]> git.neil.brown.name Git - history.git/commitdiff
Import 1.3.58 1.3.58
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:31 +0000 (15:10 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:31 +0000 (15:10 -0500)
185 files changed:
CREDITS
Documentation/Configure.help
Documentation/cdrom/optcd
MAGIC
Makefile
Rules.make
arch/alpha/config.in
arch/alpha/kernel/Makefile
arch/alpha/kernel/ksyms.c [new file with mode: 0644]
arch/i386/config.in
arch/i386/defconfig
arch/i386/kernel/Makefile
arch/i386/kernel/ksyms.c [new file with mode: 0644]
arch/i386/kernel/setup.c
arch/mips/config.in
arch/sparc/config.in
drivers/block/Config.in
drivers/block/Makefile
drivers/block/README.ide
drivers/block/cmd640.c
drivers/block/ide-cd.c
drivers/block/ide-tape.c
drivers/block/ide.c
drivers/block/ide.h
drivers/block/triton.c
drivers/cdrom/mcdx.c
drivers/cdrom/optcd.c
drivers/cdrom/optcd_isp16.h [new file with mode: 0644]
drivers/char/Config.in
drivers/char/Makefile
drivers/char/apm_bios.c
drivers/char/keyboard.c
drivers/char/mouse.c
drivers/char/tga.c
drivers/char/tpqic02.c
drivers/char/tty_io.c
drivers/char/wd501p.h
drivers/net/Config.in
drivers/net/Makefile
drivers/net/README.tunnel
drivers/net/ne.c
drivers/net/seeq8005.h
drivers/net/slhc.c
drivers/pci/pci.c
drivers/scsi/Config.in
drivers/scsi/Makefile
drivers/scsi/advansys.c [new file with mode: 0644]
drivers/scsi/advansys.h [new file with mode: 0644]
drivers/scsi/aha1542.c
drivers/scsi/aic7xxx.seq
drivers/scsi/hosts.c
drivers/scsi/scsi.c
drivers/scsi/scsi_debug.c
drivers/sound/.blurb
drivers/sound/.objects
drivers/sound/.version
drivers/sound/CHANGELOG
drivers/sound/Config.in
drivers/sound/Makefile
drivers/sound/Readme
drivers/sound/Readme.cards
drivers/sound/Readme.modules
drivers/sound/ad1848.c
drivers/sound/ad1848_mixer.h
drivers/sound/adlib_card.c
drivers/sound/aedsp16.c
drivers/sound/audio.c
drivers/sound/configure.c
drivers/sound/cs4232.c
drivers/sound/dev_table.c
drivers/sound/dev_table.h
drivers/sound/dmabuf.c
drivers/sound/experimental.txt [deleted file]
drivers/sound/gus_card.c
drivers/sound/gus_midi.c
drivers/sound/gus_vol.c
drivers/sound/gus_wave.c
drivers/sound/ics2101.c
drivers/sound/mad16.c
drivers/sound/mad16_sb_midi.c
drivers/sound/maui.c
drivers/sound/midi_synth.c
drivers/sound/midi_synth.h
drivers/sound/midibuf.c
drivers/sound/mpu401.c
drivers/sound/opl3.c
drivers/sound/os.h
drivers/sound/pas2_card.c
drivers/sound/pas2_midi.c
drivers/sound/pas2_mixer.c
drivers/sound/pas2_pcm.c
drivers/sound/patmgr.c
drivers/sound/pss.c
drivers/sound/sb16_dsp.c
drivers/sound/sb16_midi.c
drivers/sound/sb_card.c
drivers/sound/sb_dsp.c
drivers/sound/sb_midi.c
drivers/sound/sb_mixer.c
drivers/sound/sb_mixer.h
drivers/sound/sequencer.c
drivers/sound/sound_calls.h
drivers/sound/sound_config.h
drivers/sound/sound_pnp.c
drivers/sound/sound_switch.c
drivers/sound/sound_timer.c
drivers/sound/soundcard.c
drivers/sound/soundvers.h
drivers/sound/sscape.c
drivers/sound/sys_timer.c
drivers/sound/trix.c
drivers/sound/uart6850.c
drivers/sound/ulaw.h
fs/Config.in
fs/buffer.c
fs/ext/inode.c
fs/ext2/CHANGES
fs/ext2/ioctl.c
fs/ext2/super.c
fs/filesystems.c
fs/hpfs/hpfs_fs.c
fs/isofs/inode.c
fs/minix/inode.c
fs/msdos/Makefile
fs/msdos/inode.c
fs/ncpfs/dir.c
fs/ncpfs/inode.c
fs/nfs/inode.c
fs/nfs/nfsroot.c
fs/proc/Makefile
fs/proc/inode.c
fs/proc/net.c
fs/proc/procfs_syms.c [new file with mode: 0644]
fs/proc/scsi.c
fs/smbfs/inode.c
fs/smbfs/proc.c
fs/sysv/inode.c
fs/umsdos/inode.c
fs/xiafs/inode.c
include/asm-alpha/param.h
include/asm-i386/delay.h
include/linux/blk.h
include/linux/ext2_fs.h
include/linux/ext2_fs_sb.h
include/linux/ext_fs.h
include/linux/fs.h
include/linux/hpfs_fs.h
include/linux/iso_fs.h
include/linux/locks.h
include/linux/mcdx.h
include/linux/minix_fs.h
include/linux/mm.h
include/linux/msdos_fs.h
include/linux/ncp_fs.h
include/linux/nfs_fs.h
include/linux/optcd.h
include/linux/pagemap.h
include/linux/pci.h
include/linux/proc_fs.h
include/linux/quota.h
include/linux/sched.h
include/linux/smb_fs.h
include/linux/soundcard.h
include/linux/swapctl.h
include/linux/sysctl.h
include/linux/sysv_fs.h
include/linux/umsdos_fs.h
include/linux/wrapper.h [new file with mode: 0644]
include/linux/xia_fs.h
include/net/route.h
init/main.c
ipc/msg.c
ipc/util.c
kernel/ksyms.c
kernel/sched.c
kernel/sysctl.c
mm/filemap.c
mm/swap.c
mm/vmscan.c
net/Config.in
net/ipv4/proc.c
net/ipv4/tcp.c
scripts/Configure
scripts/tkparse.c
scripts/tkparse.h

diff --git a/CREDITS b/CREDITS
index 5593317e725d9167ac8583ebe4b0aa207cc2525f..c303b0edbf98f77a634425a3bac0e9191c3c433a 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -149,7 +149,7 @@ S: USA
 
 N: Andries Brouwer
 E: aeb@cwi.nl
-D: International character handling for keyboard and console
+D: random Linux hacker
 S: Bessemerstraat 21
 S: Amsterdam
 S: The Netherlands
@@ -601,7 +601,7 @@ S: Boulder, Colorado 80303
 S: USA
 
 N: H.J. Lu
-E: hjl@nynexst.com
+E: hjl@gnu.ai.mit.edu
 D: GCC + libraries hacker
 
 N: Tuomas J. Lukka
@@ -722,7 +722,7 @@ S: Muskego, Wisconsin 53150
 S: USA
 
 N: Harald Milz
-E: hm@ix.de
+E: hm@seneca.linux.de
 D: Linux Projects Map, Linux Commercial-HOWTO
 D: general Linux publicity in Germany, vacation port
 D: UUCP and CNEWS binary packages for LST
@@ -894,7 +894,8 @@ S: B2240 Zandhoven
 S: Belgium
 
 N: Martin Schulze
-E: joey@infodrom.north.de
+E: joey@linux.de
+W: http://home.pages.de/~joey/
 D: Random Linux Hacker, Linux Promoter
 D: CD-List, Books-List, Ex-FAQ
 D: Linux-Support, -Mailbox, -Stammtisch
index de9864ef069f05c920af939175bfe83c6d5e6caa..d30ce7a5bcf98bb695acc8a08e6ab311850e298a 100644 (file)
@@ -221,7 +221,7 @@ CONFIG_MAX_16M
   This is for some buggy motherboards which cannot properly deal with
   the memory above 16MB. If you have more than 16MB of RAM and
   experience weird problems, you might want to try Y, everyone else
-  says N. Note for machines with more that 64MB of RAM: in order for the
+  says N. Note for machines with more than 64MB of RAM: in order for the
   kernel to be able to use the memory above 64MB, pass the command
   line option "mem=XXXM" (where XXX is the memory size in
   megabytes) to your kernel. See the documentation of your boot loader
@@ -379,7 +379,7 @@ CONFIG_MODVERSIONS
 
 Kernel daemon support
 CONFIG_KERNELD
-  Normally when you have seleceted some drivers and/or filesystems
+  Normally when you have selected some drivers and/or filesystems
   to be created as loadable modules, you also have the responsibility
   to load the corresponding module (via insmod/modprobe) before you
   use it.  If you select Y here, the kernel will take care of this
@@ -1861,7 +1861,7 @@ CONFIG_QUOTA
   ext2 filesystem; you need the software available via ftp (user:
   anonymous) from
   sunsite.unc.edu:/pub/Linux/systm/Admin/quota_acct.tar.gz in order to
-  use it. Obviously, this is only useful for multi user systems. If
+  use it. Probably this is only useful for multi user systems. If
   unsure, say N.
 
 Standard (minix) fs support
index 514c9d9ccb126a2200b4966e1429d7187728cf38..279684c508d4e2e8f48374513d72d2580984f505 100644 (file)
@@ -43,4 +43,8 @@ try recompiling the driver with some strategically chosen #undef DEBUG_...'s
 changed into #defines (you'll find them in .../include/linux/optcd.h) and
 include the messages generated in your bug report. Good luck.
 
+I have inserted code to support multisession. It works for me, although
+it is very slow during disk detection. At this time multisession support
+is to be considered experimental. Please mail me your experiences.
+
 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
diff --git a/MAGIC b/MAGIC
index 7a5830e6f28a3d01bee7e780112dd1d49b8c9c76..5f912b28686343db3ff192ba9d28e765715f4140 100644 (file)
--- a/MAGIC
+++ b/MAGIC
@@ -74,6 +74,7 @@ Ioctl Include File            Comments
 0x06   linux/lp.h
 0x12   linux/fs.h
 0x20   linux/cm206.h
+0x22   linux/scc.h
 'A'    linux/apm_bios.h
 'C'    linux/soundcard.h
 'K'    linux/kd.h
@@ -83,7 +84,6 @@ Ioctl Include File            Comments
 'S'    linux/cdrom.h           conflict!
 'S'    linux/scsi.h            conflict!
 'T'    linux/soundcard.h       conflict!
-'T'    linux/scc.h             conflict!
 'T'    asm/termios.h           conflict!
 'V'    linux/vt.h
 'Y'    linux/cyclades.h        codes in 0x004359NN
index 14476b8e8d0544582e6139dd0dd005a76071ff23..7ff17758f9543f7d2239b88f21657dfc4e1c5f9f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 57
+SUBLEVEL = 58
 
 ARCH = i386
 
index e6ff1ce6a60cbad816350ba5fc9641841fc003a2..fa2a4daa84aaa199729b053a29ba9e2918c5ddc4 100644 (file)
@@ -146,7 +146,7 @@ $(MODINCL)/%.ver: %.c
 
 $(SYMTAB_OBJS:.o=.ver): $(TOPDIR)/include/linux/autoconf.h
 
-$(TOPDIR)/include/linux/modversions.h: $(join $(MODINCL)/,$(SYMTAB_OBJS:.o=.ver))
+$(TOPDIR)/include/linux/modversions.h: $(addprefix $(MODINCL)/,$(SYMTAB_OBJS:.o=.ver))
        @echo updating $(TOPDIR)/include/linux/modversions.h
        @(echo "#ifdef MODVERSIONS";\
        echo "#undef  CONFIG_MODVERSIONS";\
index a18f99ef58bf48f2090f1dc8f2a41369e39e36f6..2852caa8a146d386baedc8e41623b085b5eb65eb 100644 (file)
@@ -16,6 +16,7 @@ if [ "$CONFIG_MODULES" = "y" ]; then
   MODULES=y
   bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
 fi
+endmenu
 
 mainmenu_option next_comment
 comment 'General setup'
@@ -57,6 +58,7 @@ fi
 bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
 tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+endmenu
 
 source drivers/block/Config.in
 
@@ -72,6 +74,7 @@ tristate 'SCSI support' CONFIG_SCSI
 if [ "$CONFIG_SCSI" != "n" ]; then
   source drivers/scsi/Config.in
 fi
+endmenu
 
 if [ "$CONFIG_NET" = "y" ]; then
   mainmenu_option next_comment
@@ -81,6 +84,7 @@ if [ "$CONFIG_NET" = "y" ]; then
   if [ "$CONFIG_NETDEVICES" = "y" ]; then
     source drivers/net/Config.in
   fi
+  endmenu
 fi
 
 mainmenu_option next_comment
@@ -90,6 +94,7 @@ bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
 if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
   source drivers/cdrom/Config.in
 fi
+endmenu
 
 source fs/Config.in
 
@@ -102,6 +107,7 @@ tristate 'Sound card support' CONFIG_SOUND
 if [ "$CONFIG_SOUND" != "n" ]; then
   source drivers/sound/Config.in
 fi
+endmenu
 
 mainmenu_option next_comment
 comment 'Kernel hacking'
@@ -111,3 +117,4 @@ bool 'Kernel profiling support' CONFIG_PROFILE
 if [ "$CONFIG_PROFILE" = "y" ]; then
   int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
+endmenu
index 6b6bc961c0a9f7c16696a51de8052b6851e01cfb..99fddc9ed430f57abee3c8ab34f055c002cdda6e 100644 (file)
 .S.o:
        $(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
 
-OBJS  = entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \
-       bios32.o ptrace.o time.o apecs.o lca.o
+all: kernel.o head.o
+
+O_TARGET := kernel.o
+O_OBJS   := entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \
+           bios32.o ptrace.o time.o apecs.o lca.o ksyms.c
 
 all: kernel.o head.o
 
@@ -22,10 +25,4 @@ head.o: head.s
 head.s: head.S $(TOPDIR)/include/asm-alpha/system.h
        $(CPP) -traditional -o $*.s $<
 
-kernel.o: $(OBJS)
-       $(LD) -r -o kernel.o $(OBJS)
-
-dep:
-       $(CPP) -M *.c > .depend
-
 include $(TOPDIR)/Rules.make
diff --git a/arch/alpha/kernel/ksyms.c b/arch/alpha/kernel/ksyms.c
new file mode 100644 (file)
index 0000000..c8269ab
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * linux/arch/alpha/kernel/ksyms.c
+ *
+ * Export the alpha-specific functions that are needed for loadable
+ * modules.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+# include <asm/io.h>
+# include <asm/hwrpb.h>
+
+extern void bcopy (const char *src, char *dst, int len);
+extern struct hwrpb_struct *hwrpb;
+
+/* these are C runtime functions with special calling conventions: */
+extern void __divl (void);
+extern void __reml (void);
+extern void __divq (void);
+extern void __remq (void);
+extern void __divlu (void);
+extern void __remlu (void);
+extern void __divqu (void);
+extern void __remqu (void);
+
+static struct symbol_table arch_symbol_table = {
+#include <linux/symtab_begin.h>
+       /* platform dependent support */
+       X(_inb),
+       X(_inw),
+       X(_inl),
+       X(_outb),
+       X(_outw),
+       X(_outl),
+       X(bcopy),       /* generated by gcc-2.7.0 for string assignments */
+       X(hwrpb),
+       X(__divl),
+       X(__reml),
+       X(__divq),
+       X(__remq),
+       X(__divlu),
+       X(__remlu),
+       X(__divqu),
+       X(__remqu),
+       X(strlen),      /* used by ftape */
+       X(memcmp),
+       X(memmove),
+       X(__constant_c_memset),
+#include <linux/symtab_end.h>
+};
+
+void arch_syms_export(void)
+{
+       register_symtab(&arch_symbol_table);
+}
index 5110e2633f4924b672f6742ce644e8ebaadbf3a5..d7437bc401a53287d7cc725381528bce359512f5 100644 (file)
@@ -12,6 +12,7 @@ if [ "$CONFIG_MODULES" = "y" ]; then
   bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
   bool 'Kernel daemon support (e.g. autoload of modules)' CONFIG_KERNELD
 fi
+endmenu
 
 mainmenu_option next_comment
 comment 'General setup'
@@ -32,6 +33,7 @@ choice 'Processor type' \
        "386            CONFIG_M386     \
         486            CONFIG_M486     \
         Pentium        CONFIG_M586" Pentium
+endmenu
 
 source drivers/block/Config.in
 
@@ -47,6 +49,7 @@ tristate 'SCSI support' CONFIG_SCSI
 if [ "$CONFIG_SCSI" != "n" ]; then
   source drivers/scsi/Config.in
 fi
+endmenu
 
 if [ "$CONFIG_NET" = "y" ]; then
   mainmenu_option next_comment
@@ -56,6 +59,7 @@ if [ "$CONFIG_NET" = "y" ]; then
   if [ "$CONFIG_NETDEVICES" = "y" ]; then
     source drivers/net/Config.in
   fi
+  endmenu
 fi
 
 mainmenu_option next_comment
@@ -65,6 +69,7 @@ bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
 if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
   source drivers/cdrom/Config.in
 fi
+endmenu
 
 source fs/Config.in
 
@@ -77,6 +82,7 @@ tristate 'Sound card support' CONFIG_SOUND
 if [ "$CONFIG_SOUND" != "n" ]; then
   source drivers/sound/Config.in
 fi
+endmenu
 
 mainmenu_option next_comment
 comment 'Kernel hacking'
@@ -86,3 +92,4 @@ bool 'Kernel profiling support' CONFIG_PROFILE
 if [ "$CONFIG_PROFILE" = "y" ]; then
   int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
+endmenu
index d0201388509cff97cf3c38840da9835f979dcc73..d227d2f7781802b15a36cba3833aa61a26b3860b 100644 (file)
@@ -6,7 +6,7 @@
 # Loadable module support
 #
 CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
+CONFIG_MODVERSIONS=y
 # CONFIG_KERNELD is not set
 
 #
@@ -36,9 +36,9 @@ CONFIG_ST506=y
 #
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_BLK_DEV_IDE=y
-CONFIG_BLK_DEV_IDEATAPI=y
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_CMD640=y
 # CONFIG_BLK_DEV_TRITON is not set
 # CONFIG_BLK_DEV_XD is not set
 
index 1186c23064d76a5d0c00d9b78bb89da00989f0cb..daed0ea7cc2eb67e81242ebbfd2999d55838193f 100644 (file)
@@ -28,7 +28,7 @@ all: kernel.o head.o
 
 O_TARGET := kernel.o
 O_OBJS   := process.o signal.o entry.o traps.o irq.o vm86.o bios32.o \
-            ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o
+            ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o ksyms.o
 
 ifdef SMP
 
diff --git a/arch/i386/kernel/ksyms.c b/arch/i386/kernel/ksyms.c
new file mode 100644 (file)
index 0000000..0e24808
--- /dev/null
@@ -0,0 +1,17 @@
+#include <linux/module.h>
+#include <linux/smp.h>
+
+
+static struct symbol_table arch_symbol_table = {
+#include <linux/symtab_begin.h>
+       /* platform dependent support */
+#ifdef __SMP__
+       X(apic_reg),            /* Needed internally for the I386 inlines */
+#endif
+#include <linux/symtab_end.h>
+};
+
+void arch_syms_export(void)
+{
+       register_symtab(&arch_symbol_table);
+}
index 920b880cd86b55cc25e30af6343c5b5c36eff92e..435df48a280782662929a91484f4eda951905cca 100644 (file)
@@ -196,7 +196,7 @@ static const char * i486model(unsigned int nr)
 static const char * i586model(unsigned int nr)
 {
        static const char *model[] = {
-               "0", "Pentium 60/66","Pentium 75+"
+               "0", "Pentium 60/66","Pentium 75+","OverDrive PODP5V83"
        };
        if (nr < sizeof(model)/sizeof(char *))
                return model[nr];
index 19b2fbbdd0094723e70617a5eff67fc624dd506e..ac77d884e4f43d00949bb93f8e8330b09f678122 100644 (file)
@@ -47,10 +47,12 @@ bool 'Networking support' CONFIG_NET
 #  bool '   PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
 #fi
 bool 'System V IPC' CONFIG_SYSVIPC
+endmenu
 
 mainmenu_option next_comment
 comment 'Loadable module support'
 bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
+endmenu
 
 source drivers/block/Config.in
 
@@ -66,6 +68,7 @@ tristate 'SCSI support' CONFIG_SCSI
 if [ "$CONFIG_SCSI" != "n" ]; then
   source drivers/scsi/Config.in
 fi
+endmenu
 
 if [ "$CONFIG_NET" = "y" ]; then
   mainmenu_option next_comment
@@ -75,6 +78,7 @@ if [ "$CONFIG_NET" = "y" ]; then
   if [ "$CONFIG_NETDEVICES" = "y" ]; then
     source drivers/net/Config.in
   fi
+  endmenu
 fi
 
 mainmenu_option next_comment
@@ -84,6 +88,7 @@ bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
 if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
   source drivers/cdrom/Config.in
 fi
+endmenu
 
 source fs/Config.in
 
@@ -97,6 +102,7 @@ tristate 'Sound card support' CONFIG_SOUND
 if [ "$CONFIG_SOUND" != "n" ]; then
   source drivers/sound/Config.in
 fi
+endmenu
 
 mainmenu_option next_comment
 comment 'Kernel hacking'
@@ -106,3 +112,4 @@ bool 'Kernel profiling support' CONFIG_PROFILE
 if [ "$CONFIG_PROFILE" = "y" ]; then
   int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
+endmenu
index e8ad90b43aba6fad9662db4a881a80d3d873fb1e..9b4e9cdf8e8dc35c090e6954f187906d19ce4af0 100644 (file)
@@ -17,6 +17,7 @@ define_bool CONFIG_SUN_CONSOLE y
 bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
 tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+endmenu
 
 source drivers/block/Config.in
 
@@ -32,6 +33,7 @@ tristate 'SCSI support' CONFIG_SCSI
 if [ "$CONFIG_SCSI" != "n" ]; then
        source drivers/scsi/Config.in
 fi
+endmenu
 
 if [ "$CONFIG_NET" = "y" ]; then
        mainmenu_option next_comment
@@ -41,6 +43,7 @@ if [ "$CONFIG_NET" = "y" ]; then
        if [ "$CONFIG_NETDEVICES" = "y" ]; then
                source drivers/net/Config.in
        fi
+       endmenu
 fi
 
 source fs/Config.in
index b0dade40f6836bfe929127c4addf861dab46371f..e4234419066e4296078ed6ee2337f197532d624e 100644 (file)
@@ -16,11 +16,9 @@ if [ "$CONFIG_ST506" = "y" ]; then
     bool '   Use new IDE driver for primary/secondary i/f' CONFIG_BLK_DEV_IDE
   fi
   if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then
-    bool '   Include support for IDE/ATAPI CDROM or TAPE' CONFIG_BLK_DEV_IDEATAPI
-    if [ "$CONFIG_BLK_DEV_IDEATAPI" = "y" ]; then
-      bool '      Include support for IDE/ATAPI CDROM' CONFIG_BLK_DEV_IDECD
-      bool '      Include ALPHA support for IDE/ATAPI TAPE' CONFIG_BLK_DEV_IDETAPE
-    fi
+    bool '   Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD
+    bool '   Include (ALPHA) IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE
+    bool '   Special CMD640 chipset support' CONFIG_BLK_DEV_CMD640
     if [ "$CONFIG_PCI" = "y" ]; then
       bool '   PCI Triton IDE Bus Master DMA support' CONFIG_BLK_DEV_TRITON
     fi
@@ -28,3 +26,4 @@ if [ "$CONFIG_ST506" = "y" ]; then
 fi
 
 bool 'XT harddisk support' CONFIG_BLK_DEV_XD
+endmenu
index a6bfeeb7dd4a176c03a7db8b42be69170347b2bb..7da812f5504efc4b5e7d280f7872e300cb2f4ad6 100644 (file)
@@ -48,6 +48,10 @@ ifeq ($(CONFIG_BLK_DEV_TRITON),y)
 L_OBJS += triton.o
 endif
 
+ifeq ($(CONFIG_BLK_DEV_CMD640),y)
+L_OBJS += cmd640.o
+endif
+
 ifeq ($(CONFIG_BLK_DEV_IDECD),y)
 L_OBJS += ide-cd.o
 endif
index b52c9a845a9370da6905b27ec71a9b80e0531699..b040bc3760467454fae0400de98ae60199581984 100644 (file)
@@ -350,13 +350,19 @@ then use the kernel command line parameters to pass the *logical* geometry,
 as in:  hda=525,64,63
 
 If the BIOS does not support this form of drive translation, then several
-options remain, listed below in inverse order of popularity:
+options remain, listed below in order of popularity:
 
-       - boot from a floppy disk instead of the hard drive (takes 10 seconds).
        - use a partition below the 1024 cyl boundary to hold the linux
        boot files (kernel images and /boot directory), and place the rest
        of linux anywhere else on the drive.  These files can reside in a DOS
        partition, or in a tailor-made linux boot partition.
+       - use DiskManager software from OnTrack, supplied free with
+       many new hard drive purchases.
+       - use EZ-Drive software (similar to DiskManager).  Note though,
+       that LILO must *not* use the MBR when EZ-Drive is present.
+       Instead, install LILO on the first sector of your linux partition,
+       and mark it as "active" or "bootable" with fdisk.
+       - boot from a floppy disk instead of the hard drive (takes 10 seconds).
 
 If you cannot use drive translation, *and* your BIOS also restricts you to
 entering no more than 1024 cylinders in the geometry field in the CMOS setup,
index c0fbaab01c075efd06b0cc5f8d13235a0379cc26..9082404f99af693764024690aaf4f5aa262df6e4 100644 (file)
@@ -1,7 +1,7 @@
 /*
- *  linux/drivers/block/cmd640.c       Version 0.02  Nov 30, 1995
+ *  linux/drivers/block/cmd640.c       Version 0.04  Jan 11, 1996
  *
- *  Copyright (C) 1995  Linus Torvalds & author (see below)
+ *  Copyright (C) 1995-1996  Linus Torvalds & author (see below)
  */
 
 /*
  *                     read-ahead for versions 'B' and 'C' of chip by
  *                     default, some code cleanup.
  *
+ *  Version 0.03       Added reset of secondary interface,
+ *                     and black list for devices which are not compatible
+ *                     with read ahead mode. Separate function for setting
+ *                     readahead is added, possibly it will be called some
+ *                     day from ioctl processing code.
+ *
+ *  Version 0.04       Now configs/compiles separate from ide.c  -ml
+ */
+
+/*
+ *  There is a known problem with current version of this driver.
+ *  If the only device on secondary interface is CD-ROM, at some
+ *  computers it is not recognized. In all reported cases CD-ROM
+ *  was 2x or 4x speed Mitsumi drive.
+ *
+ *  The following workarounds could work:
+ * 
+ *    1. put CD-ROM as slave on primary interface
+ *
+ *    2. or define symbol at next line as 0
+ * 
  */
 
+#define CMD640_NORMAL_INIT 1
+
+#undef REALLY_SLOW_IO          /* most systems can safely undef this */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <asm/io.h>
+
+#include "ide.h"
+
+extern ide_hwif_t ide_hwifs[];
+
+int cmd640_vlb = 0;
+
 /*
  * CMD640 specific registers definition.
  */
@@ -76,7 +117,7 @@ static int   bus_speed; /* MHz */
 
 /*
  * For some unknown reasons pcibios functions which read and write registers
- * do not work with cmd640. We use direct io instead.
+ * do not always work with cmd640. We use direct io instead.
  */
 
 /* PCI method 1 access */
@@ -229,6 +270,35 @@ static int probe_for_cmd640_vlb(void) {
        return 1;
 }
 
+/*
+ * Low level reset for controller, actually it has nothing specific for
+ * CMD640, but I don't know how to use standard reset routine before
+ * we recognized any drives.
+ */
+
+static void cmd640_reset_controller(int iface_no)
+{
+       int retry_count = 600;
+       int base_port = iface_no ? 0x170 : 0x1f0;
+
+       outb_p(4, base_port + 7);
+       udelay(5);
+       outb_p(0, base_port + 7);
+
+       do {
+               udelay(5);
+               retry_count -= 1;
+       } while ((inb_p(base_port + 7) & 0x80) && retry_count);
+
+       if (retry_count == 0)
+               printk("cmd640: failed to reset controller %d\n", iface_no);
+#if 0  
+       else
+               printk("cmd640: controller %d reset [%d]\n", 
+                       iface_no, retry_count);
+#endif
+}
+
 /*
  * Probe for Cmd640x and initialize it if found
  */
@@ -282,31 +352,34 @@ int ide_probe_for_cmd640x(void)
 
        /*
         * Set the maximum allowed bus speed (it is safest until we
-        *                                    find how detect bus speed)
+        *                                    find how to detect bus speed)
         * Normally PCI bus runs at 33MHz, but often works overclocked to 40
         */
        bus_speed = (bus_type == vlb) ? 50 : 40; 
 
-#if 1  /* don't know if this is reliable yet */
        /*
         * Enable readahead for versions above 'A'
         */
        cmd_read_ahead = (cmd640_chip_version > 1);
-#else
-       cmd_read_ahead = 0;
-#endif
+
        /*
         * Setup Control Register
         */
        b = get_cmd640_reg(cmd640_key, CNTRL);  
+
+#if CMD640_NORMAL_INIT
        if (second_port)
                b |= CNTRL_ENA_2ND;
        else
                b &= ~CNTRL_ENA_2ND;
+#endif 
+
        if (cmd_read_ahead)
                b &= ~(CNTRL_DIS_RA0 | CNTRL_DIS_RA1);
        else
                b |= (CNTRL_DIS_RA0 | CNTRL_DIS_RA1);
+
+
        put_cmd640_reg(cmd640_key, CNTRL, b);
 
        /*
@@ -317,9 +390,11 @@ int ide_probe_for_cmd640x(void)
                b = cmd_read_ahead ? 0 : (DIS_RA2 | DIS_RA3);
                put_cmd640_reg(cmd640_key, ARTTIM23, b);
                put_cmd640_reg(cmd640_key, DRWTIM23, 0);
+
+               cmd640_reset_controller(1);
        }
 
-       serialized = 1;
+       ide_hwifs[0].serialized = 1;
 
        printk("ide: buggy CMD640%c interface at ", 
               'A' - 1 + cmd640_chip_version);
@@ -359,6 +434,48 @@ static int as_clocks(int a) {
        }
 }
 
+/*
+ * Sets readahead mode for specific drive
+ *  in the future it could be called from ioctl
+ */
+
+static void set_readahead_mode(int mode, int if_num, int dr_num)
+{
+       static int masks[2][2] = 
+               { 
+                       {CNTRL_DIS_RA0, CNTRL_DIS_RA1}, 
+                       {DIS_RA2,       DIS_RA3}
+               };
+
+       int port = (if_num == 0) ? CNTRL : ARTTIM23;
+       int mask = masks[if_num][dr_num];
+       byte b;
+
+       b = get_cmd640_reg(cmd640_key, port);
+       if (mode)
+               b &= mask; /* Enable readahead for specific drive */
+       else
+               b |= mask; /* Disable readahed for specific drive */
+       put_cmd640_reg(cmd640_key, port, b);
+}              
+
+static struct readahead_black_list {
+       const char*     name;
+       int             mode;   
+} drives_ra[] = {
+       { "ST3655A",    0 },
+       { NULL, 0 }
+};     
+
+static int known_drive_readahead(char* name) {
+       int i;
+
+       for (i = 0; drives_ra[i].name != NULL; i++)
+               if (strcmp(name, drives_ra[i].name) == 0)
+                       return drives_ra[i].mode;
+       return -1;
+}
+
 /*
  * Tuning of drive parameters
  */
@@ -400,7 +517,7 @@ static void cmd640_set_timing(int if_num, int dr_num, int r1, int r2) {
        }
 }
 
-struct pio_timing {
+static struct pio_timing {
        int     mc_time;        /* Minimal cycle time (ns) */
        int     av_time;        /* Address valid to DIOR-/DIOW- setup (ns) */
        int     ds_time;        /* DIOR data setup      (ns) */
@@ -413,7 +530,7 @@ struct pio_timing {
        { 20,   50,     100 }   /* PIO Mode ? */
 };
 
-struct drive_pio_info {
+static struct drive_pio_info {
        const char      *name;
        int             pio;
 } drive_pios[] = {
@@ -426,6 +543,7 @@ struct drive_pio_info {
        { "QUANTUM LPS240A", 0 },
        { "QUANTUM LPS270A", 3 },
        { "QUANTUM LPS540A", 3 },
+       { "QUANTUM FIREBALL1080A", 3 },
        { NULL, 0 }
 };
 
@@ -480,7 +598,7 @@ static void set_pio_mode(int if_num, int drv_num, int mode_num) {
        outb_p((drv_num | 0xa) << 4, p_base + 6);
        outb_p(0xef, p_base + 7);
        for (i = 0; (i < 100) && (inb (p_base + 7) & 0x80); i++)
-               delay_10ms();
+               udelay(10000);
 }
 
 void cmd640_tune_drive(ide_drive_t* drive) {
@@ -491,6 +609,7 @@ void cmd640_tune_drive(ide_drive_t* drive) {
        int mc_time, av_time, ds_time;
        struct hd_driveid* id;
        int r1, r2;
+       int mode;
 
        /*
         * Determine if drive is under cmd640 control
@@ -530,6 +649,13 @@ void cmd640_tune_drive(ide_drive_t* drive) {
                                &r1, &r2);
        set_pio_mode(interface_number, drive_number, max_pio);
        cmd640_set_timing(interface_number, drive_number, r1, r2);
+
+       /*
+        * Disable (or set) readahead mode for known drive
+        */
+       if ((mode = known_drive_readahead(id->model)) != -1) {
+               set_readahead_mode(mode, interface_number, drive_number);
+               printk("Readahead %s,", mode ? "enabled" : "disabled");
+       }
        printk ("Mode and Timing set to PIO%d (0x%x 0x%x)\n", max_pio, r1, r2);
 }
-
index 3dbdd42a2776d14ffe0b282764858b0523f05f8d..12d22d324b831b9093ba32ef0e24a8c879e9aa4c 100644 (file)
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
-#define _IDE_CD_C      /* used in blk.h */
 #include "ide.h"
 
 
index 47d2797271d14d742c98cef40d86abeebff37b09..8b36dce83611d96a71502d1b072f7d0ae5e41409 100644 (file)
 #include <asm/segment.h>
 #include <asm/io.h>
 
-#define _IDE_TAPE_C                    /* For ide_end_request in blk.h */
-
 /*
  *     Main Linux ide driver include file
  *
index d6219de37e37af1e357cbca8b2a3cf3370717993..ef8bf7fe498c6bde13dabd34477f44293835a61b 100644 (file)
@@ -1,8 +1,9 @@
 /*
- *  linux/drivers/block/ide.c  Version 5.24  Jan 4, 1996
+ *  linux/drivers/block/ide.c  Version 5.25  Jan 11, 1996
  *
  *  Copyright (C) 1994-1996  Linus Torvalds & authors (see below)
  */
+#define _IDE_C         /* needed by <linux/blk.h> */
 
 /*
  * This is the multiple IDE interface driver, as evolved from hd.c.
  *                     assembly syntax tweak to vlb_sync
  *                     removeable drive support from scuba@cs.tu-berlin.de
  *                     add transparent support for DiskManager-6.0x "Dynamic
- *                      Disk Overlay" (DDO), most of this in in genhd.c
+ *                      Disk Overlay" (DDO), most of this is in genhd.c
  *                     eliminate "multiple mode turned off" message at boot
  *  Version 4.10       fix bug in ioctl for "hdparm -c3"
  *                     fix DM6:DDO support -- now works with LILO, fdisk, ...
  *  Version 5.22       fix ide_xlate_1024() to work with/without drive->id
  *  Version 5.23       miscellaneous touch-ups
  *  Version 5.24       fix #if's for SUPPORT_CMD640
+ *  Version 5.25       more touch-ups, fix cdrom resets, ...
+ *                     cmd640.c now configs/compiles separate from ide.c
  *
  *  Driver compile-time options are in ide.h
  *
  *  To do, in likely order of completion:
- *     - make cmd640.c and umc8672.c compile separately from ide.c
+ *     - make umc8672.c compile separately from ide.c
  *     - add ALI M1443/1445 chipset support from derekn@vw.ece.cmu.edu
  *     - add ioctls to get/set interface timings on various interfaces
  *     - add Promise Caching controller support from peterd@pnd-pc.demon.co.uk
 
 #include "ide.h"
 
-#if SUPPORT_CMD640
-void cmd640_tune_drive(ide_drive_t *);
-static int cmd640_vlb = 0;
-#endif
-
        ide_hwif_t      ide_hwifs[MAX_HWIFS];           /* hwif info */
 static ide_hwgroup_t   *irq_to_hwgroup [16];
 static const byte      ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR};
 
 static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168};
 static const byte      default_irqs[MAX_HWIFS]     = {14, 15, 11, 10};
-static int             serialized = 0;         /* "serialize" option */
 static int             disallow_unmask = 0;    /* for buggy hardware */
 
 #if (DISK_RECOVERY_TIME > 0)
@@ -881,7 +878,8 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat)
        err = ide_dump_status(drive, msg, stat);
        if ((rq = HWGROUP(drive)->rq) == NULL || drive == NULL)
                return;
-       if (rq->cmd != READ && rq->cmd != WRITE) { /* retry only "normal" i/o */
+       /* retry only "normal" I/O: */
+       if (rq->cmd != READ && rq->cmd != WRITE && drive->media != ide_cdrom) {
                rq->errors = 1;
                ide_end_drive_cmd(drive, stat, err);
                return;
@@ -1346,7 +1344,7 @@ static inline void do_request (ide_hwif_t *hwif, struct request *rq)
 #if FAKE_FDISK_FOR_EZDRIVE
        if (block == 0 && drive->ezdrive) {
                block = 1;
-               printk("%s: [EZD] accessing sector 1 instead of sector 0\n", drive->name);
+               printk("%s: [EZD] accessing sector 1 in place of sector 0\n", drive->name);
        }
 #endif /* FAKE_FDISK_FOR_EZDRIVE */
        ((ide_hwgroup_t *)hwif->hwgroup)->drive = drive;
@@ -2210,8 +2208,11 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
                        printk(", DMA");
        }
        printk("\n");
-#if SUPPORT_CMD640
-       cmd640_tune_drive(drive);       /* but can we tune a fish? */
+#ifdef CONFIG_BLK_DEV_CMD640
+       {
+               extern void cmd640_tune_drive (ide_drive_t *);
+               cmd640_tune_drive(drive);       /* but can we tune a fish? */
+       }
 #endif
 }
 
@@ -2527,10 +2528,6 @@ static void init_qd6580 (void)
 #include "umc8672.c"   /* until we tidy up the interface some more */
 #endif
 
-#if SUPPORT_CMD640
-#include "cmd640.c"    /* until we tidy up the interface some more */
-#endif
-
 /*
  * stridx() returns the offset of c within s,
  * or -1 if c is '\0' or not found within s.
@@ -2699,12 +2696,15 @@ void ide_setup (char *s)
                                init_qd6580();
                                goto done;
 #endif /* SUPPORT_QD6580 */
-#if SUPPORT_CMD640
+#ifdef CONFIG_BLK_DEV_CMD640
                        case -5: /* "cmd640_vlb" */
+                               {
+                               extern int cmd640_vlb;
                                if (hw > 1) goto bad_hwif;
-                               cmd640_vlb = 1;
+                                       cmd640_vlb = 1;
+                               }
                                break;
-#endif /* SUPPORT_CMD640 */
+#endif /* CONFIG_BLK_DEV_CMD640 */
 #if SUPPORT_HT6560B
                        case -4: /* "ht6560b" */
                                if (hw > 1) goto bad_hwif;
@@ -2736,7 +2736,7 @@ void ide_setup (char *s)
                        case -2: /* "serialize" */
                        do_serialize:
                                if (hw > 1) goto bad_hwif;
-                               serialized = 1;
+                               ide_hwifs[0].serialized = 1;
                                goto done;
                        case -1: /* "noprobe" */
                                hwif->noprobe = 1;
@@ -2890,7 +2890,7 @@ static int init_irq (ide_hwif_t *hwif)
         * Check for serialization with ide1.
         * This code depends on us having already taken care of ide1.
         */
-       if (serialized && hwif->name[3] == '0' && ide_hwifs[1].present)
+       if (hwif->serialized && hwif->name[3] == '0' && ide_hwifs[1].present)
                hwgroup = ide_hwifs[1].hwgroup;
        /*
         * If this is the first interface in a group,
@@ -2941,23 +2941,14 @@ static struct file_operations ide_fops = {
 
 #ifdef CONFIG_PCI
 
-void ide_pci_access_error (int rc)
-{
-       printk("ide: pcibios access failed - %s\n", pcibios_strerror(rc));
-}
+#if SUPPORT_RZ1000
 
-#if SUPPORT_RZ1000 || SUPPORT_CMD640
-void buggy_interface_fallback (int rc)
+static void ide_pci_access_error (int rc)
 {
-       ide_pci_access_error (rc);
-       serialized = 1;
-       disallow_unmask = 1;
-       printk("serialized, disabled unmasking\n");
+       printk("ide: pcibios access failed - %s\n", pcibios_strerror(rc));
 }
-#endif /* SUPPORT_RZ1000 || SUPPORT_CMD640 */
 
-#if SUPPORT_RZ1000
-void init_rz1000 (byte bus, byte fn)
+static void init_rz1000 (byte bus, byte fn)
 {
        int rc;
        unsigned short reg;
@@ -2970,8 +2961,12 @@ void init_rz1000 (byte bus, byte fn)
        } else {
                if ((rc = pcibios_read_config_word(bus, fn, 0x40, &reg))
                 || (rc =  pcibios_write_config_word(bus, fn, 0x40, reg & 0xdfff)))
-                       buggy_interface_fallback (rc);
-               else
+               {
+                       ide_pci_access_error (rc);
+                       ide_hwifs[0].serialized = 1;
+                       disallow_unmask = 1;
+                       printk("serialized, disabled unmasking\n");
+               } else
                        printk("disabled read-ahead\n");
        }
 }
@@ -3012,7 +3007,7 @@ static void ide_init_pci (void)
        /*
         * Apparently the BIOS32 services on Intel motherboards are buggy,
         * and won't find the PCI_DEVICE_ID_INTEL_82371_1 for us.
-        * So we instead search for PCI_DEVICE_ID_INTEL_82371_0, and then add 1.
+        * So instead, we search for PCI_DEVICE_ID_INTEL_82371_0, and then add 1.
         */
        ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371_0, &ide_init_triton, 1);
 #endif
@@ -3038,8 +3033,11 @@ int ide_init (void)
        if (pcibios_present())
                ide_init_pci ();
 #endif /* CONFIG_PCI */
-#if SUPPORT_CMD640
-       ide_probe_for_cmd640x();
+#ifdef CONFIG_BLK_DEV_CMD640
+       {
+               extern void ide_probe_for_cmd640x (void);
+               ide_probe_for_cmd640x();
+       }
 #endif
 
        /*
index a7a51662d99741816add3df13990fe9580c69373..65db50d8f0604c6791dc1eeb577fd673dcd96d7e 100644 (file)
@@ -37,9 +37,6 @@
 #ifndef SUPPORT_RZ1000                 /* 1 to support RZ1000 chipset */
 #define SUPPORT_RZ1000         1       /* 0 to reduce kernel size */
 #endif
-#ifndef SUPPORT_CMD640                 /* 1 to support CMD640 chipset */
-#define SUPPORT_CMD640         1       /* 0 to reduce kernel size */
-#endif
 #ifndef SUPPORT_UMC8672                        /* 1 to support UMC8672 chipset */
 #define SUPPORT_UMC8672                1       /* 0 to reduce kernel size */
 #endif
 #define FANCY_STATUS_DUMPS     1       /* 0 to reduce kernel size */
 #endif
 
+#if defined(CONFIG_BLK_DEV_IDECD) || defined(CONFIG_BLK_DEV_IDETAPE)
+#define CONFIG_BLK_DEV_IDEATAPI 1
+#endif
+
 /*
  * IDE_DRIVE_CMD is used to implement many features of the hdparm utility
  */
@@ -393,6 +394,7 @@ typedef struct hwif_s {
        char            name[5];        /* name of interface, eg. "ide0" */
        unsigned        noprobe : 1;    /* don't probe for this interface */
        unsigned        present : 1;    /* this interface exists */
+       unsigned        serialized : 1; /* valid only for ide_hwifs[0] */
 #if (DISK_RECOVERY_TIME > 0)
        unsigned long   last_time;      /* time when previous rq was done */
 #endif
@@ -603,4 +605,3 @@ void idetape_register_chrdev (void);
 #ifdef CONFIG_BLK_DEV_TRITON
 void ide_init_triton (byte, byte);
 #endif /* CONFIG_BLK_DEV_TRITON */
-
index 07ed2bbc42ac7f3da9ea45645edceae245bc5b68..5c1d2ee3031dab6a73323b54561603708fba3fd4 100644 (file)
@@ -1,7 +1,7 @@
 /*
- *  linux/drivers/block/triton.c       Version 1.04  Dec 1, 1995
+ *  linux/drivers/block/triton.c       Version 1.05  Jan 11, 1996
  *
- *  Copyright (c) 1995  Mark Lord
+ *  Copyright (c) 1995-1996  Mark Lord
  *  May be copied or modified under the terms of the GNU General Public License
  */
 
  *
  * And, yes, Intel Zappa boards really *do* use the Triton IDE ports.
  */
-#define _TRITON_C
-#include <linux/config.h>
-#ifndef CONFIG_BLK_DEV_TRITON
-#define CONFIG_BLK_DEV_TRITON y
-#endif
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/timer.h>
@@ -127,15 +122,15 @@ const char *good_dma_drives[] = {"Micropolis 2112A"};
  * Our Physical Region Descriptor (PRD) table should be large enough
  * to handle the biggest I/O request we are likely to see.  Since requests
  * can have no more than 256 sectors, and since the typical blocksize is
- * two sectors, we can get by with a limit of 128 entries here for the
+ * two sectors, we could get by with a limit of 128 entries here for the
  * usual worst case.  Most requests seem to include some contiguous blocks,
  * further reducing the number of table entries required.
  *
- * Note that the driver reverts to PIO mode for individual requests that exceed
+ * The driver reverts to PIO mode for individual requests that exceed
  * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling
  * 100% of all crazy scenarios here is not necessary.
  *
- * As it turns out, though, we must allocate a full 4KB page for this,
+ * As it turns out though, we must allocate a full 4KB page for this,
  * so the two PRD tables (ide0 & ide1) will each get half of that,
  * allowing each to have about 256 entries (8 bytes each) from this.
  */
@@ -288,7 +283,7 @@ static int triton_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
        outl(virt_to_bus (HWIF(drive)->dmatable), dma_base + 4); /* PRD table */
        outb(reading, dma_base);                        /* specify r/w */
        outb(0x26, dma_base+2);                         /* clear status bits */
-       ide_set_handler (drive, &dma_intr, WAIT_CMD);   /* issue cmd to drive */
+       ide_set_handler(drive, &dma_intr, WAIT_CMD);    /* issue cmd to drive */
        OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
        outb(inb(dma_base)|1, dma_base);                /* begin DMA */
        return 0;
@@ -316,6 +311,48 @@ static void print_triton_drive_flags (unsigned int unit, byte flags)
        printk(" fastPIO=%s\n", ((flags&9)==1)  ? "on " : "off");
 }
 
+static void init_triton_dma (ide_hwif_t *hwif, unsigned short base)
+{
+       static unsigned long dmatable = 0;
+
+       printk("    %s: BusMaster DMA at 0x%04x-0x%04x", hwif->name, base, base+7);
+       if (check_region(base, 8)) {
+               printk(" -- ERROR, PORTS ALREADY IN USE");
+       } else {
+               request_region(base, 8, hwif->name);
+               hwif->dma_base = base;
+               if (!dmatable) {
+                       /*
+                        * Since we know we are on a PCI bus, we could
+                        * actually use __get_free_pages() here instead
+                        * of __get_dma_pages() -- no ISA limitations.
+                        */
+                       dmatable = __get_dma_pages(GFP_KERNEL, 0);
+               }
+               if (dmatable) {
+                       hwif->dmatable = (unsigned long *) dmatable;
+                       dmatable += (PRD_ENTRIES * PRD_BYTES);
+                       outl(virt_to_bus(hwif->dmatable), base + 4);
+                       hwif->dmaproc  = &triton_dmaproc;
+               }
+       }
+       printk("\n");
+}
+
+/*
+ * calc_mode() returns the ATA PIO mode number, based on the number
+ * of cycle clks passed in.  Assumes 33Mhz bus operation (30ns per clk).
+ */
+byte calc_mode (byte clks)
+{
+       if (clks == 3)  return 5;
+       if (clks == 4)  return 4;
+       if (clks <  6)  return 3;
+       if (clks <  8)  return 2;
+       if (clks < 13)  return 1;
+       return 0;
+}
+
 /*
  * ide_init_triton() prepares the IDE driver for DMA operation.
  * This routine is called once, from ide.c during driver initialization,
@@ -324,26 +361,33 @@ static void print_triton_drive_flags (unsigned int unit, byte flags)
 void ide_init_triton (byte bus, byte fn)
 {
        int rc = 0, h;
+       int dma_enabled = 0;
        unsigned short bmiba, pcicmd;
        unsigned int timings;
-       unsigned long dmatable = 0;
        extern ide_hwif_t ide_hwifs[];
 
+       printk("ide: Triton BM-IDE on PCI bus %d function %d\n", bus, fn);
        /*
         * See if IDE and BM-DMA features are enabled:
         */
        if ((rc = pcibios_read_config_word(bus, fn, 0x04, &pcicmd)))
                goto quit;
-       if ((pcicmd & 5) != 5) {
-               if ((pcicmd & 1) == 0)
-                       printk("ide: Triton IDE ports are not enabled\n");
-               else
-                       printk("ide: Triton BM-DMA feature is not enabled\n");
+       if ((pcicmd & 1) == 0)  {
+               printk("ide: Triton IDE ports are not enabled\n");
                goto quit;
        }
-#if 0
-       (void) pcibios_write_config_word(bus, fn, 0x42, 0x8037); /* for my MC2112A */
-#endif
+       if ((pcicmd & 4) == 0) {
+               printk("ide: Triton BM-DMA feature is not enabled -- upgrade your BIOS\n");
+       } else {
+               /*
+                * Get the bmiba base address
+                */
+               if ((rc = pcibios_read_config_word(bus, fn, 0x20, &bmiba)))
+                       goto quit;
+               bmiba &= 0xfff0;        /* extract port base address */
+               dma_enabled = 1;
+       }
+
        /*
         * See if ide port(s) are enabled
         */
@@ -353,52 +397,32 @@ void ide_init_triton (byte bus, byte fn)
                printk("ide: neither Triton IDE port is enabled\n");
                goto quit;
        }
-       printk("ide: Triton BM-IDE on PCI bus %d function %d\n", bus, fn);
-
-       /*
-        * Get the bmiba base address
-        */
-       if ((rc = pcibios_read_config_word(bus, fn, 0x20, &bmiba)))
-               goto quit;
-       bmiba &= 0xfff0;        /* extract port base address */
 
        /*
         * Save the dma_base port addr for each interface
         */
        for (h = 0; h < MAX_HWIFS; ++h) {
+               byte s_clks, r_clks;
                ide_hwif_t *hwif = &ide_hwifs[h];
-               unsigned short base, time;
-               if (hwif->io_base == 0x1f0 && (timings & 0x8000)) {
+               unsigned short time;
+               if (hwif->io_base == 0x1f0) {
                        time = timings & 0xffff;
-                       base = bmiba;
-               } else if (hwif->io_base == 0x170 && (timings & 0x80000000)) {
+                       if ((timings & 0x8000) == 0)    /* interface enabled? */
+                               continue;
+                       if (dma_enabled)
+                               init_triton_dma(hwif, bmiba);
+               } else if (hwif->io_base == 0x170) {
                        time = timings >> 16;
-                       base = bmiba + 8;
+                       if ((timings & 0x8000) == 0)    /* interface enabled? */
+                               continue;
+                       if (dma_enabled)
+                               init_triton_dma(hwif, bmiba + 8);
                } else
                        continue;
-               printk("    %s: BusMaster DMA at 0x%04x-0x%04x", hwif->name, base, base+7);
-               if (check_region(base, 8)) {
-                       printk(" -- ERROR, PORTS ALREADY IN USE");
-               } else {
-                       request_region(base, 8, hwif->name);
-                       hwif->dma_base = base;
-                       if (!dmatable) {
-                               /*
-                                * Since we know we are on a PCI bus, we could
-                                * actually use __get_free_pages() here instead
-                                * of __get_dma_pages() -- no ISA limitations.
-                                */
-                               dmatable = __get_dma_pages(GFP_KERNEL, 0);
-                       }
-                       if (dmatable) {
-                               hwif->dmatable = (unsigned long *) dmatable;
-                               dmatable += (PRD_ENTRIES * PRD_BYTES);
-                               outl(virt_to_bus(hwif->dmatable), base + 4);
-                               hwif->dmaproc  = &triton_dmaproc;
-                       }
-               }
-               printk("\n    %s timing: (0x%04x) sample_CLKs=%d, recovery_CLKs=%d\n",
-                hwif->name, time, ((~time>>12)&3)+2, ((~time>>8)&3)+1);
+               s_clks = ((~time >> 12) & 3) + 2;
+               r_clks = ((~time >>  8) & 3) + 1;
+               printk("    %s timing: (0x%04x) sample_CLKs=%d, recovery_CLKs=%d (PIO mode%d)\n",
+                hwif->name, time, s_clks, r_clks, calc_mode(s_clks+r_clks));
                print_triton_drive_flags (0, time & 0xf);
                print_triton_drive_flags (1, (time >> 4) & 0xf);
        }
index 1f1ef0f0c35109a28743fbca54e186ede8895fed..911186233c625a2a0d4e65f12f7956ffa7ea0271 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * The Mitsumi CDROM interface
  * Copyright (C) 1995 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: 1.5
+ * VERSION: 1.5a
  * 
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -34,7 +34,7 @@
 
 #if RCS
 static const char *mcdx_c_version
-               = "mcdx.c,v 1.19 1995/11/20 17:06:25 heiko Exp";
+               = "mcdx.c,v 1.19.2.1 1996/01/13 21:25:55 heiko Exp";
 #endif
 
 #include <linux/version.h>
@@ -768,8 +768,10 @@ mcdx_close(struct inode *ip, struct file *fp)
                /* invalidate_inodes(ip->i_rdev); */
                invalidate_buffers(ip->i_rdev);
 
+#if !MCDX_QUIET
                if (-1 == mcdx_lockdoor(stuffp, 0, 3))
                                INFO(("close() Cannot unlock the door\n"));
+#endif
 
         /* eject if wished */
         if (stuffp->eject_sw) mcdx_eject(stuffp, 1);
@@ -794,10 +796,8 @@ int check_mcdx_media_change(kdev_t full_dev)
 
 void mcdx_setup(char *str, int *pi)
 {
-#if MCDX_DEBUG
-    printk(MCDX ":: setup(%s, %d) called\n",
-           str, pi[0]);
-#endif
+       if (pi[0] > 0) mcdx_drive_map[0][0] = pi[1];
+       if (pi[0] > 1) mcdx_drive_map[0][1] = pi[2];
 }
 
 /* DIRTY PART ******************************************************/ 
@@ -1051,10 +1051,10 @@ int mcdx_init(void)
 {
        int drive;
 
-       WARN(("Version 1.5 "
-                       "mcdx.c,v 1.19 1995/11/20 17:06:25 heiko Exp\n"));
-       INFO((": Version 1.5 "
-                       "mcdx.c,v 1.19 1995/11/20 17:06:25 heiko Exp\n"));
+       WARN(("Version 1.5a "
+                       "mcdx.c,v 1.19.2.1 1996/01/13 21:25:55 heiko Exp\n"));
+       INFO((": Version 1.5a "
+                       "mcdx.c,v 1.19.2.1 1996/01/13 21:25:55 heiko Exp\n"));
 
        /* zero the pointer array */
        for (drive = 0; drive < MCDX_NDRIVES; drive++)
@@ -1245,7 +1245,7 @@ static int mcdx_transfer(struct s_drive_stuff *stuffp,
        stuffp->lock = current->pid;
 
        do {
-           int sig = 0;
+           /* int sig = 0; */
            int to = 0;
 
                /* wait for the drive become idle */
index 3e33ff1099f43a68881301b6dd6d48a8670033d3..4f5d52ea5adf3902d4424e0fef981977d7e7fd3f 100644 (file)
@@ -1,12 +1,13 @@
-/*     $Id: optcd.c,v 1.3 1995/08/24 19:54:27 root Exp root $
-       linux/drivers/block/optcd.c - Optics Storage 8000 AT CDROM driver
+/*     linux/drivers/cdrom/optcd.c - Optics Storage 8000 AT CDROM driver
+       $Id: optcd.c,v 1.20 1996/01/17 19:44:39 root Exp root $
 
        Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
 
+
        Based on Aztech CD268 CDROM driver by Werner Zimmermann and preworks
        by Eberhard Moenkeberg (emoenke@gwdg.de). ISP16 detection and
-       configuration by Eric van der Maarel (maarel@marin.nl), with some data
-       communicated by Vadim V. Model (vadim@rbrf.msk.su).
+       configuration by Eric van der Maarel (maarel@marin.nl) and
+       Vadim Model (vadim@cecmow.enet.dec.com).
 
        This program is free software; you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        You should have received a copy of the GNU General Public License
        along with this program; if not, write to the Free Software
        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+\f
+/*     Revision history
+
 
-       History
        14-5-95         v0.0    Plays sound tracks. No reading of data CDs yet.
                                Detection of disk change doesn't work.
        21-5-95         v0.1    First ALPHA version. CD can be mounted. The
                                Updated README.optcd. Submitted for
                                inclusion in 1.3.21
        29-9-95         v0.4a   Fixed bug that prevented compilation as module
+       25-10-95        v0.5    Started multisession code. Implementation
+                               copied from Werner Zimmermann, who copied it
+                               from Heiko Schlittermann's mcdx.
+       17-1-96         v0.6    Multisession works; some cleanup too.
 */
+\f
+/* Includes */
 
-#include <linux/module.h>
 
-#include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/timer.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
 #include <linux/ioport.h>
-#include <linux/major.h>
-
 #include <asm/io.h>
 
 #define MAJOR_NR OPTICS_CDROM_MAJOR
+#include <linux/blk.h>
 
-# include <linux/blk.h>
-#define optcd_port optcd       /* Needed for the modutils. */
-# include <linux/optcd.h>
-
-
-/* Some (Media)Magic */
-/* define types of drive the interface on an ISP16 card may be looking at */
-#define ISP16_DRIVE_X 0x00
-#define ISP16_SONY  0x02
-#define ISP16_PANASONIC0 0x02
-#define ISP16_SANYO0 0x02
-#define ISP16_MITSUMI  0x04
-#define ISP16_PANASONIC1 0x06
-#define ISP16_SANYO1 0x06
-#define ISP16_DRIVE_NOT_USED 0x08  /* not used */
-#define ISP16_DRIVE_SET_MASK 0xF1  /* don't change 0-bit or 4-7-bits*/
-/* ...for port */
-#define ISP16_DRIVE_SET_PORT 0xF8D
-/* set io parameters */
-#define ISP16_BASE_340  0x00
-#define ISP16_BASE_330  0x40
-#define ISP16_BASE_360  0x80
-#define ISP16_BASE_320  0xC0
-#define ISP16_IRQ_X  0x00
-#define ISP16_IRQ_5  0x04  /* shouldn't be used due to soundcard conflicts */
-#define ISP16_IRQ_7  0x08  /* shouldn't be used due to soundcard conflicts */
-#define ISP16_IRQ_3  0x0C
-#define ISP16_IRQ_9  0x10
-#define ISP16_IRQ_10  0x14
-#define ISP16_IRQ_11  0x18
-#define ISP16_DMA_X  0x03
-#define ISP16_DMA_3  0x00
-#define ISP16_DMA_5  0x00
-#define ISP16_DMA_6  0x01
-#define ISP16_DMA_7  0x02
-#define ISP16_IO_SET_MASK  0x20  /* don't change 5-bit */
-/* ...for port */
-#define ISP16_IO_SET_PORT  0xF8E
-/* enable the drive */
-#define ISP16_NO_IDE__ENABLE_CDROM_PORT  0xF90  /* ISP16 without IDE interface */
-#define ISP16_IDE__ENABLE_CDROM_PORT  0xF91  /* ISP16 with IDE interface */
-#define ISP16_ENABLE_CDROM  0x80  /* seven bit */
-
-/* the magic stuff */
-#define ISP16_CTRL_PORT  0xF8F
-#define ISP16_NO_IDE__CTRL  0xE2  /* ISP16 without IDE interface */
-#define ISP16_IDE__CTRL  0xE3  /* ISP16 with IDE interface */
-
-static short isp16_detect(void);
-static short isp16_no_ide__detect(void);
-static short isp16_with_ide__detect(void);
-static short isp16_config( int base, u_char drive_type, int irq, int dma );
-static short isp16_type; /* dependent on type of interface card */
-static u_char isp16_ctrl;
-static u_short isp16_enable_cdrom_port;
-
-
-static short optcd_port = OPTCD_PORTBASE;
-
-/* Read current status/data availability flags */
-inline static int optFlags(void) {
-       return inb(STATUS_PORT) & FL_STDT;
-}
+#include <linux/cdrom.h>
+#include <linux/optcd.h>
 
-/* Wait for status available; return TRUE on timeout */
-static int sten_low(void) {
-       int no_status;
-       unsigned long count = 0;
-       while ((no_status = (optFlags() & FL_STEN)))
-               if (++count >= BUSY_TIMEOUT)
-                       break;
-#ifdef DEBUG_DRIVE_IF
-       if (no_status)
-               printk("optcd: timeout waiting for STEN low\n");
-       else
-               printk("optcd: STEN low after %ld\n", count);
+#ifdef PROBE_ISP16
+#include "optcd_isp16.h"       /* optional ISP16 detection/configuration */
 #endif
-       return no_status;
-}
+\f
+/* Debug support */
 
-/* Wait for data available; return TRUE on timeout */
-static int dten_low(void) {
-       int no_data;
+
+/* Don't forget to add new debug flags here. */
+#if DEBUG_DRIVE_IF | DEBUG_VFS | DEBUG_CONV | DEBUG_TOC | \
+    DEBUG_BUFFERS | DEBUG_REQUEST | DEBUG_STATE | DEBUG_MULTIS
+#define DEBUG(x) debug x
+static void debug(int debug_this, const char* fmt, ...)
+{
+       char s[1024];
+       va_list args;
+
+       if (!debug_this)
+               return;
+
+       va_start(args, fmt);
+       vsprintf(s, fmt, args);
+       printk("optcd: %s\n", s);
+       va_end(args);
+}
+#else
+#define DEBUG(x)
+#endif
+\f
+/* Drive hardware/firmware characteristics
+   Identifiers in accordance with Optics Storage documentation */
+
+
+#define optcd_port optcd                       /* Needed for the modutils. */
+static short optcd_port = OPTCD_PORTBASE;      /* I/O base of drive. */
+
+/* Drive registers, read */
+#define DATA_PORT      optcd_port      /* Read data/status */
+#define STATUS_PORT    optcd_port+1    /* Indicate data/status availability */
+
+/* Drive registers, write */
+#define COMIN_PORT     optcd_port      /* For passing command/parameter */
+#define RESET_PORT     optcd_port+1    /* Write anything and wait 0.5 sec */
+#define HCON_PORT      optcd_port+2    /* Host Xfer Configuration */
+
+
+/* Command completion/status read from DATA register */
+#define ST_DRVERR              0x80
+#define ST_DOOR_OPEN           0x40
+#define ST_MIXEDMODE_DISK      0x20
+#define ST_MODE_BITS           0x1c
+#define ST_M_STOP              0x00
+#define ST_M_READ              0x04
+#define ST_M_AUDIO             0x04
+#define ST_M_PAUSE             0x08
+#define ST_M_INITIAL           0x0c
+#define ST_M_ERROR             0x10
+#define ST_M_OTHERS            0x14
+#define        ST_MODE2TRACK           0x02
+#define        ST_DSK_CHG              0x01
+#define ST_L_LOCK              0x01
+#define ST_CMD_OK              0x00
+#define ST_OP_OK               0x01
+#define ST_PA_OK               0x02
+#define ST_OP_ERROR            0x05
+#define ST_PA_ERROR            0x06
+
+
+/* Error codes (appear as command completion code from DATA register) */
+/* Player related errors */
+#define ERR_ILLCMD     0x11    /* Illegal command to player module */
+#define ERR_ILLPARM    0x12    /* Illegal parameter to player module */
+#define ERR_SLEDGE     0x13
+#define ERR_FOCUS      0x14
+#define ERR_MOTOR      0x15
+#define ERR_RADIAL     0x16
+#define ERR_PLL                0x17    /* PLL lock error */
+#define ERR_SUB_TIM    0x18    /* Subcode timeout error */
+#define ERR_SUB_NF     0x19    /* Subcode not found error */
+#define ERR_TRAY       0x1a
+#define ERR_TOC                0x1b    /* Table of Contents read error */
+#define ERR_JUMP       0x1c
+/* Data errors */
+#define ERR_MODE       0x21
+#define ERR_FORM       0x22
+#define ERR_HEADADDR   0x23    /* Header Address not found */
+#define ERR_CRC                0x24
+#define ERR_ECC                0x25    /* Uncorrectable ECC error */
+#define ERR_CRC_UNC    0x26    /* CRC error and uncorrectable error */
+#define ERR_ILLBSYNC   0x27    /* Illegal block sync error */
+#define ERR_VDST       0x28    /* VDST not found */
+/* Timeout errors */
+#define ERR_READ_TIM   0x31    /* Read timeout error */
+#define ERR_DEC_STP    0x32    /* Decoder stopped */
+#define ERR_DEC_TIM    0x33    /* Decoder interrupt timeout error */
+/* Function abort codes */
+#define ERR_KEY                0x41    /* Key -Detected abort */
+#define ERR_READ_FINISH        0x42    /* Read Finish */
+/* Second Byte diagnostic codes */
+#define ERR_NOBSYNC    0x01    /* No block sync */
+#define ERR_SHORTB     0x02    /* Short block */
+#define ERR_LONGB      0x03    /* Long block */
+#define ERR_SHORTDSP   0x04    /* Short DSP word */
+#define ERR_LONGDSP    0x05    /* Long DSP word */
+
+
+/* Status availability flags read from STATUS register */
+#define FL_EJECT       0x20
+#define FL_WAIT                0x10    /* active low */
+#define FL_EOP         0x08    /* active low */
+#define FL_STEN                0x04    /* Status available when low */
+#define FL_DTEN                0x02    /* Data available when low */
+#define FL_DRQ         0x01    /* active low */
+#define FL_RESET       0xde    /* These bits are high after a reset */
+#define FL_STDT                (FL_STEN|FL_DTEN)
+
+
+/* Transfer mode, written to HCON register */
+#define HCON_DTS       0x08
+#define HCON_SDRQB     0x04
+#define HCON_LOHI      0x02
+#define HCON_DMA16     0x01
+
+
+/* Drive command set, written to COMIN register */
+/* Quick response commands */
+#define COMDRVST       0x20    /* Drive Status Read */
+#define COMERRST       0x21    /* Error Status Read */
+#define COMIOCTLISTAT  0x22    /* Status Read; reset disk changed bit */
+#define COMINITSINGLE  0x28    /* Initialize Single Speed */
+#define COMINITDOUBLE  0x29    /* Initialize Double Speed */
+#define COMUNLOCK      0x30    /* Unlock */
+#define COMLOCK                0x31    /* Lock */
+#define COMLOCKST      0x32    /* Lock/Unlock Status */
+#define COMVERSION     0x40    /* Get Firmware Revision */
+#define COMVOIDREADMODE        0x50    /* Void Data Read Mode */
+/* Read commands */
+#define COMFETCH       0x60    /* Prefetch Data */
+#define COMREAD                0x61    /* Read */
+#define COMREADRAW     0x62    /* Read Raw Data */
+#define COMREADALL     0x63    /* Read All 2646 Bytes */
+/* Player control commands */
+#define COMLEADIN      0x70    /* Seek To Lead-in */
+#define COMSEEK                0x71    /* Seek */
+#define COMPAUSEON     0x80    /* Pause On */
+#define COMPAUSEOFF    0x81    /* Pause Off */
+#define COMSTOP                0x82    /* Stop */
+#define COMOPEN                0x90    /* Open Tray Door */
+#define COMCLOSE       0x91    /* Close Tray Door */
+#define COMPLAY                0xa0    /* Audio Play */
+#define COMPLAY_TNO    0xa2    /* Audio Play By Track Number */
+#define COMSUBQ                0xb0    /* Read Sub-q Code */
+#define COMLOCATION    0xb1    /* Read Head Position */
+/* Audio control commands */
+#define COMCHCTRL      0xc0    /* Audio Channel Control */
+/* Miscellaneous (test) commands */
+#define COMDRVTEST     0xd0    /* Write Test Bytes */
+#define COMTEST                0xd1    /* Diagnostic Test */
+\f
+/* Low level drive interface. Only here we do actual I/O
+   Waiting for status / data available */
+
+
+/* Busy wait until FLAG goes low. Return 0 on timeout. */
+inline static int flag_low(int flag, unsigned long timeout)
+{
+       int flag_high;
        unsigned long count = 0;
-       while ((no_data = (optFlags() & FL_DTEN)))
-               if (++count >= BUSY_TIMEOUT)
+
+       while ((flag_high = (inb(STATUS_PORT) & flag)))
+               if (++count >= timeout)
                        break;
-#ifdef DEBUG_DRIVE_IF
-       if (no_data)
-               printk("optcd: timeout waiting for DTEN low\n");
-       else
-               printk("optcd: DTEN low after %ld\n", count);
-#endif
-       return no_data;
+
+       DEBUG((DEBUG_DRIVE_IF, "flag_low 0x%x count %ld%s",
+               flag, count, flag_high ? " timeout" : ""));
+       return !flag_high;
 }
 
-/* Facilities for polled waiting for status or data */
-static int sleep_timeout;              /* Max amount of time still to sleep */
-static unsigned char sleep_flags;      /* Flags read last time around */
+
+/* Timed waiting for status or data */
+static int sleep_timeout;      /* max # of ticks to sleep */
 static struct wait_queue *waitq = NULL;
 static struct timer_list delay_timer = {NULL, NULL, 0, 0, NULL};
 
-/* Timer routine: wake up when either of FL_STEN or FL_DTEN goes down,
- * or when timeout expires. Otherwise wait some more.
- */
-static void sleep_timer(void) {
-       if ((sleep_flags = optFlags()) != FL_STDT) {
-               wake_up(&waitq);
-               return;
-       }
-       if (--sleep_timeout <= 0) {
+#define SET_TIMER(func, jifs) \
+       delay_timer.expires = jiffies+(jifs); \
+       delay_timer.function = (void *) (func); \
+       add_timer(&delay_timer);
+#define CLEAR_TIMER    del_timer(&delay_timer)
+
+
+/* Timer routine: wake up when desired flag goes low,
+   or when timeout expires. */
+static void sleep_timer(void)
+{
+       int flags = inb(STATUS_PORT) & FL_STDT;
+
+       if (flags == FL_STDT && --sleep_timeout > 0) {
+               SET_TIMER(sleep_timer, HZ/100); /* multi-statement macro */
+       } else
                wake_up(&waitq);
-               return;
-       }
-       SET_TIMER(sleep_timer, 1);
 }
 
-/* Sleep until any of FL_STEN or FL_DTEN go down, or until timeout.
- * sleep_timeout must be set first.
- */
-static int sleep_status(void) {
-#ifdef DEBUG_DRIVE_IF
-       printk("optcd: sleeping %d on status\n", sleep_timeout);
-#endif
-       if (sleep_timeout <= 0)         /* timeout immediately */
-               return FL_STDT;
-       if ((sleep_flags = optFlags()) == FL_STDT) {
-               SET_TIMER(sleep_timer, 1);
+
+/* Sleep until FLAG goes low. Return 0 on timeout or wrong flag low. */
+static int sleep_flag_low(int flag, unsigned long timeout)
+{
+       int flag_high;
+
+       DEBUG((DEBUG_DRIVE_IF, "sleep_flag_low"));
+
+       sleep_timeout = timeout;
+       flag_high = inb(STATUS_PORT) & flag;
+       if (flag_high && sleep_timeout > 0) {
+               SET_TIMER(sleep_timer, HZ/100);
                sleep_on(&waitq);
+               flag_high = inb(STATUS_PORT) & flag;
        }
-#ifdef DEBUG_DRIVE_IF
-       printk("optcd: woken up with %d to go, flags %d\n",
-               sleep_timeout, sleep_flags);
-#endif
-       return sleep_flags;
-}
 
-/* Sleep until status available; return TRUE on timeout */
-inline static int sleep_sten_low(void) {
-       int flags;
-       sleep_timeout = SLEEP_TIMEOUT;
-       flags = sleep_status();
-#ifdef DEBUG_DRIVE_IF
-       if (!(flags & FL_DTEN))
-               printk("optcd: DTEN while waiting for STEN\n");
-#endif
-       return flags & FL_STEN;
+       DEBUG((DEBUG_DRIVE_IF, "flag 0x%x count %ld%s",
+               flag, timeout, flag_high ? " timeout" : ""));
+       return !flag_high;
 }
+\f
+/* Low level drive interface. Only here we do actual I/O
+   Sending commands and parameters */
+
+
+/* Errors in the command protocol */
+#define ERR_IF_CMD_TIMEOUT     0x100
+#define ERR_IF_ERR_TIMEOUT     0x101
+#define ERR_IF_RESP_TIMEOUT    0x102
+#define ERR_IF_DATA_TIMEOUT    0x103
+#define ERR_IF_NOSTAT          0x104
 
-/* Sleep until data available; return TRUE on timeout */
-inline static int sleep_dten_low(void) {
-       int flags;
-       sleep_timeout = SLEEP_TIMEOUT;
-       flags = sleep_status();
-#ifdef DEBUG_DRIVE_IF
-       if (!(flags & FL_STEN))
-               printk("optcd: STEN while waiting for DTEN\n");
-#endif
-       return flags & FL_DTEN;
-}
 
 /* Send command code. Return <0 indicates error */
-static int optSendCmd(int cmd) {
+static int send_cmd(int cmd)
+{
        unsigned char ack;
-#if defined(DEBUG_DRIVE_IF)||defined(DEBUG_COMMANDS)
-       printk("optcd: executing command 0x%02x\n", cmd);
-#endif
+
+       DEBUG((DEBUG_DRIVE_IF, "sending command 0x%02x\n", cmd));
+
        outb(HCON_DTS, HCON_PORT);      /* Enable Suspend Data Transfer */
        outb(cmd, COMIN_PORT);          /* Send command code */
-       if (sten_low())                 /* Wait for status available */
+       if (!flag_low(FL_STEN, BUSY_TIMEOUT))   /* Wait for status */
                return -ERR_IF_CMD_TIMEOUT;
        ack = inb(DATA_PORT);           /* read command acknowledge */
-#ifdef DEBUG_DRIVE_IF
-       printk("optcd: acknowledge code 0x%02x\n", ack);
-#endif
        outb(HCON_SDRQB, HCON_PORT);    /* Disable Suspend Data Transfer */
        return ack==ST_OP_OK ? 0 : -ack;
 }
 
+
 /* Send command parameters. Return <0 indicates error */
-static int optSendParams(struct opt_Play_msf *params) {
+static int send_params(struct cdrom_msf *params)
+{
        unsigned char ack;
-#if defined(DEBUG_DRIVE_IF)||defined(DEBUG_COMMANDS)
-       printk("optcd: params %02x:%02x:%02x %02x:%02x:%02x\n",
-               params->start.min, params->start.sec, params->start.frame,
-               params->end.min, params->end.sec, params->end.frame);
-#endif
-       outb(params -> start.min, COMIN_PORT);
-       outb(params -> start.sec, COMIN_PORT);
-       outb(params -> start.frame, COMIN_PORT);
-       outb(params -> end.min, COMIN_PORT);
-       outb(params -> end.sec, COMIN_PORT);
-       outb(params -> end.frame, COMIN_PORT);
-       if (sten_low())                 /* Wait for status available */
+
+       DEBUG((DEBUG_DRIVE_IF, "sending parameters"
+               " %02x:%02x:%02x"
+               " %02x:%02x:%02x",
+               params->cdmsf_min0,
+               params->cdmsf_sec0,
+               params->cdmsf_frame0,
+               params->cdmsf_min1,
+               params->cdmsf_sec1,
+               params->cdmsf_frame1));
+
+       outb(params->cdmsf_min0, COMIN_PORT);
+       outb(params->cdmsf_sec0, COMIN_PORT);
+       outb(params->cdmsf_frame0, COMIN_PORT);
+       outb(params->cdmsf_min1, COMIN_PORT);
+       outb(params->cdmsf_sec1, COMIN_PORT);
+       outb(params->cdmsf_frame1, COMIN_PORT);
+       if (!flag_low(FL_STEN, BUSY_TIMEOUT))   /* Wait for status */
                return -ERR_IF_CMD_TIMEOUT;
        ack = inb(DATA_PORT);           /* read command acknowledge */
-#ifdef DEBUG_DRIVE_IF
-       printk("optcd: acknowledge code 0x%02x\n", ack);
-#endif
        return ack==ST_PA_OK ? 0 : -ack;
 }
 
-/* Return execution status for quick response commands, i.e. busy wait.
- * Return value <0 indicates timeout.
- */
-static int optGetExecStatus(void) {
-       unsigned char exec_status;
-       if (sten_low())                 /* Wait for status available */
+
+/* Send parameters for SEEK command. Return <0 indicates error */
+static int send_seek_params(struct cdrom_msf *params)
+{
+       unsigned char ack;
+
+       DEBUG((DEBUG_DRIVE_IF, "sending seek parameters"
+               " %02x:%02x:%02x",
+               params->cdmsf_min0,
+               params->cdmsf_sec0,
+               params->cdmsf_frame0));
+
+       outb(params->cdmsf_min0, COMIN_PORT);
+       outb(params->cdmsf_sec0, COMIN_PORT);
+       outb(params->cdmsf_frame0, COMIN_PORT);
+       if (!flag_low(FL_STEN, BUSY_TIMEOUT))   /* Wait for status */
                return -ERR_IF_CMD_TIMEOUT;
-       exec_status = inb(DATA_PORT);   /* read command execution status */
-#ifdef DEBUG_DRIVE_IF
-       printk("optcd: returned execution status: 0x%02x\n", exec_status);
-#endif
-       return exec_status;
+       ack = inb(DATA_PORT);           /* read command acknowledge */
+       return ack==ST_PA_OK ? 0 : -ack;
 }
 
-/* Return execution status for slow commands. Only use when no data is
- * expected. Return value <0 indicates timeout.
- */
-static int optSleepTillExecStatus(void) {
+
+/* Wait for command execution status. Choice between busy waiting
+   and sleeping. Return value <0 indicates timeout. */
+inline static int get_exec_status(int busy_waiting)
+{
        unsigned char exec_status;
-       if (sleep_sten_low())           /* Wait for status available */
+
+       if (busy_waiting
+           ? !flag_low(FL_STEN, BUSY_TIMEOUT)
+           : !sleep_flag_low(FL_STEN, SLEEP_TIMEOUT))
                return -ERR_IF_CMD_TIMEOUT;
-       exec_status = inb(DATA_PORT);   /* read command execution status */
-#ifdef DEBUG_DRIVE_IF
-       printk("optcd: returned execution status: 0x%02x\n", exec_status);
-#endif
+
+       exec_status = inb(DATA_PORT);
+       DEBUG((DEBUG_DRIVE_IF, "returned exec status 0x%02x", exec_status));
        return exec_status;
 }
 
-/* Fetch status that has previously been waited for. <0 means not available */
-inline static int optStatus(void) {
-       unsigned char status;
-       if (optFlags() & FL_STEN)
-               return -ERR_IF_NOSTAT;
-       status = inb(DATA_PORT);
-#ifdef DEBUG_DRIVE_IF
-       printk("optcd: read status: 0x%02x\n", status);
-#endif
-       return status;
-}
 
-/* Wait for extra byte of data that a command returns */
-static int optGetData(void) {
+/* Wait busy for extra byte of data that a command returns.
+   Return value <0 indicates timeout. */
+inline static int get_data(int short_timeout)
+{
        unsigned char data;
-       if (sten_low())
+
+       if (!flag_low(FL_STEN, short_timeout ? FAST_TIMEOUT : BUSY_TIMEOUT))
                return -ERR_IF_DATA_TIMEOUT;
+
        data = inb(DATA_PORT);
-#ifdef DEBUG_DRIVE_IF
-       printk("optcd: read data: 0x%02x\n", data);
-#endif
+       DEBUG((DEBUG_DRIVE_IF, "returned data 0x%02x", data));
        return data;
 }
 
-/* Read data that has previously been waited for. */
-inline static void optReadData(char *buf, int n) {
-       insb(DATA_PORT, buf, n);
-}
-
-/* Flush status and data fifos */
-inline static void optFlushData(void) {
-       while (optFlags() != FL_STDT)
-               inb(DATA_PORT);
-}
 
-/* Write something to RESET_PORT and wait. Return TRUE upon success. */
-static int optResetDrive(void) {
+/* Returns 0 if failed */
+static int reset_drive(void)
+{
        unsigned long count = 0;
        int flags;
-#ifdef DEBUG_DRIVE_IF
-       printk("optcd: reset drive\n");
-#endif
+
+       DEBUG((DEBUG_DRIVE_IF, "reset drive"));
+
        outb(0, RESET_PORT);
        while (++count < RESET_WAIT)
                inb(DATA_PORT);
+
        count = 0;
        while ((flags = (inb(STATUS_PORT) & FL_RESET)) != FL_RESET)
                if (++count >= BUSY_TIMEOUT)
                        break;
-#ifdef DEBUG_DRIVE_IF
-       if (flags == FL_RESET)
-               printk("optcd: drive reset\n");
-       else
-               printk("optcd: reset failed\n");
-#endif
+
+       DEBUG((DEBUG_DRIVE_IF, "reset %s",
+               flags == FL_RESET ? "succeeded" : "failed"));
+
        if (flags != FL_RESET)
                return 0;               /* Reset failed */
        outb(HCON_SDRQB, HCON_PORT);    /* Disable Suspend Data Transfer */
@@ -356,345 +431,620 @@ static int optResetDrive(void) {
 }
 
 
+/* Facilities for asynchronous operation */
+
+/* Read status/data availability flags FL_STEN and FL_DTEN */
+inline static int stdt_flags(void)
+{
+       return inb(STATUS_PORT) & FL_STDT;
+}
+
+
+/* Fetch status that has previously been waited for. <0 means not available */
+inline static int fetch_status(void)
+{
+       unsigned char status;
+
+       if (inb(STATUS_PORT) & FL_STEN)
+               return -ERR_IF_NOSTAT;
+
+       status = inb(DATA_PORT);
+       DEBUG((DEBUG_DRIVE_IF, "fetched exec status 0x%02x", status));
+       return status;
+}
+
+
+/* Fetch data that has previously been waited for. */
+inline static void fetch_data(char *buf, int n)
+{
+       insb(DATA_PORT, buf, n);
+       DEBUG((DEBUG_DRIVE_IF, "fetched 0x%x bytes", n));
+}
+
+
+/* Flush status and data fifos */
+inline static void flush_data(void)
+{
+       while ((inb(STATUS_PORT) & FL_STDT) != FL_STDT)
+               inb(DATA_PORT);
+       DEBUG((DEBUG_DRIVE_IF, "flushed fifos"));
+}
+\f
 /* Command protocol */
 
-/* Send a simple command and wait for response */
-inline static int optCmd(int cmd) {
-       int ack = optSendCmd(cmd);
+
+/* Send a simple command and wait for response. Command codes < COMFETCH
+   are quick response commands */
+inline static int exec_cmd(int cmd)
+{
+       int ack = send_cmd(cmd);
        if (ack < 0)
                return ack;
-       if (cmd < COMFETCH)             /* Quick response command */
-               return optGetExecStatus();
-       else                            /* Slow command */
-               return optSleepTillExecStatus();
+       return get_exec_status(cmd < COMFETCH);
 }
 
-/* Send a command with parameters and wait for response */
-inline static int optPlayCmd(int cmd, struct opt_Play_msf *params) {
-       int ack = optSendCmd(cmd);
+
+/* Send a command with parameters. Don't wait for the response,
+ * which consists of data blocks read from the CD. */
+inline static int exec_read_cmd(int cmd, struct cdrom_msf *params)
+{
+       int ack = send_cmd(cmd);
        if (ack < 0)
                return ack;
-       if ((ack = optSendParams(params)) < 0)
-               return ack;
-       return optSleepTillExecStatus();
+       return send_params(params);
 }
 
-/* Send a command with parameters. Don't wait for the response,
- * which consists of the data blocks read. */
-inline static int optReadCmd(int cmd, struct opt_Play_msf *params) {
-       int ack = optSendCmd(cmd);
+
+/* Send a seek command with parameters and wait for response */
+inline static int exec_seek_cmd(int cmd, struct cdrom_msf *params)
+{
+       int ack = send_cmd(cmd);
+       if (ack < 0)
+               return ack;
+       ack = send_seek_params(params);
        if (ack < 0)
                return ack;
-       return optSendParams(params);
+       return 0;
 }
 
 
+/* Send a command with parameters and wait for response */
+inline static int exec_long_cmd(int cmd, struct cdrom_msf *params)
+{
+       int ack = exec_read_cmd(cmd, params);
+       if (ack < 0)
+               return ack;
+       return get_exec_status(0);
+}
+\f
 /* Address conversion routines */
 
+
 /* Binary to BCD (2 digits) */
-inline static unsigned char bin2bcd(unsigned char p) {
-#ifdef DEBUG_CONV
-       if (p > 99)
-               printk("optcd: error bin2bcd %d\n", p);
-#endif
-       return (p % 10) | ((p / 10) << 4);
+inline static void single_bin2bcd(u_char *p)
+{
+       DEBUG((DEBUG_CONV, "bin2bcd %02d", *p));
+       *p = (*p % 10) | ((*p / 10) << 4);
 }
 
-/* Linear address to minute, second, frame form */
-static void hsg2msf(long hsg, struct msf *msf) {
-       hsg += 150;
-       msf -> min = hsg / 4500;
-       hsg %= 4500;
-       msf -> sec = hsg / 75;
-       msf -> frame = hsg % 75;
-#ifdef DEBUG_CONV
-       if (msf -> min >= 70)
-               printk("optcd: Error hsg2msf address Minutes\n");
-       if (msf -> sec >= 60)
-               printk("optcd: Error hsg2msf address Seconds\n");
-       if (msf -> frame >= 75)
-               printk("optcd: Error hsg2msf address Frames\n");
-#endif
-       msf -> min = bin2bcd(msf -> min);       /* convert to BCD */
-       msf -> sec = bin2bcd(msf -> sec);
-       msf -> frame = bin2bcd(msf -> frame);
+
+/* Convert entire msf struct */
+static void bin2bcd(struct cdrom_msf *msf)
+{
+       single_bin2bcd(&msf->cdmsf_min0);
+       single_bin2bcd(&msf->cdmsf_sec0);
+       single_bin2bcd(&msf->cdmsf_frame0);
+       single_bin2bcd(&msf->cdmsf_min1);
+       single_bin2bcd(&msf->cdmsf_sec1);
+       single_bin2bcd(&msf->cdmsf_frame1);
+}
+
+
+/* Linear block address to minute, second, frame form */
+static void lba2msf(int lba, struct cdrom_msf *msf)
+{
+       DEBUG((DEBUG_CONV, "lba2msf %d", lba));
+       lba += CD_MSF_OFFSET;
+       msf->cdmsf_min0 = lba / 4500; lba %= 4500;
+       msf->cdmsf_sec0 = lba / 75;
+       msf->cdmsf_frame0 = lba % 75;
+       msf->cdmsf_min1 = 0;
+       msf->cdmsf_sec1 = 0;
+       msf->cdmsf_frame1 = 0;
+       bin2bcd(msf);
 }
 
+
 /* Two BCD digits to binary */
-inline static int bcd2bin(unsigned char bcd) {
+inline static u_char bcd2bin(u_char bcd)
+{
+       DEBUG((DEBUG_CONV, "bcd2bin %x%02x", bcd));
        return (bcd >> 4) * 10 + (bcd & 0x0f);
 }
 
-/* Minute, second, frame address to linear address */
-static long msf2hsg(struct msf *mp) {
-#ifdef DEBUG_CONV
-       if (mp -> min >= 70)
-               printk("optcd: Error msf2hsg address Minutes\n");
-       if (mp -> sec >= 60)
-               printk("optcd: Error msf2hsg address Seconds\n");
-       if (mp -> frame >= 75)
-               printk("optcd: Error msf2hsg address Frames\n");
-#endif
-       return bcd2bin(mp -> frame)
-               + bcd2bin(mp -> sec) * 75
-               + bcd2bin(mp -> min) * 4500
-               - 150;
+
+union cd_addr {
+       struct {
+               u_char  minute;
+               u_char  second;
+               u_char  frame;
+       } msf;
+       int     lba;
+};
+
+
+static void msf2lba(union cd_addr *addr)
+{
+       addr->lba = addr->msf.minute * 4500
+                   + addr->msf.second * 75
+                   + addr->msf.frame - CD_MSF_OFFSET;
+}
+
+
+/* Minute, second, frame address BCD to binary or to linear address,
+   depending on MODE */
+static void msf_bcd2bin(union cd_addr *addr)
+{
+       addr->msf.minute = bcd2bin(addr->msf.minute);
+       addr->msf.second = bcd2bin(addr->msf.second);
+       addr->msf.frame = bcd2bin(addr->msf.frame);
 }
+\f
+/* High level drive commands */
 
 
-/* Drive status and table of contents */
+static int audio_status = CDROM_AUDIO_NO_STATUS;
+static char toc_uptodate = 0;
 
-static int optAudioStatus = CDROM_AUDIO_NO_STATUS;
-static char optDiskChanged = 1;
-static char optTocUpToDate = 0;
-static struct opt_DiskInfo DiskInfo;
-static struct opt_Toc Toc[MAX_TRACKS];
+/* Get drive status, flagging completion of audio play and disk changes. */
+static int drive_status(void)
+{
+       int status;
 
-/* Get CDROM status, flagging completion of audio play and disk changes. */
-static int optGetStatus(void) {
-       int st;
-       if ((st = optCmd(COMIOCTLISTAT)) < 0)
-               return st;
-       if (st == 0xff)
+       status = exec_cmd(COMIOCTLISTAT);
+       DEBUG((DEBUG_DRIVE_IF, "IOCTLISTAT: %03x", status));
+       if (status < 0)
+               return status;
+       if (status == 0xff)     /* No status available */
                return -ERR_IF_NOSTAT;
-       if (((st & ST_MODE_BITS) != ST_M_AUDIO) &&
-               (optAudioStatus == CDROM_AUDIO_PLAY)) {
-               optAudioStatus = CDROM_AUDIO_COMPLETED;
+
+       if (((status & ST_MODE_BITS) != ST_M_AUDIO) &&
+               (audio_status == CDROM_AUDIO_PLAY)) {
+               audio_status = CDROM_AUDIO_COMPLETED;
        }
-       if (st & ST_DSK_CHG) {
-               optDiskChanged = 1;
-               optTocUpToDate = 0;
-               optAudioStatus = CDROM_AUDIO_NO_STATUS;
+
+       if (status & ST_DSK_CHG) {
+               toc_uptodate = 0;
+               audio_status = CDROM_AUDIO_NO_STATUS;
        }
-       return st;
+
+       return status;
 }
 
-/*
- * Read the current Q-channel info. Also used for reading the
- * table of contents.
- */
-static int optGetQChannelInfo(struct opt_Toc *qp) {
-       int st;
-#ifdef DEBUG_TOC
-       printk("optcd: starting optGetQChannelInfo\n");
-#endif
-       if ((st = optGetStatus()) < 0)
-               return st;
-       if ((st = optCmd(COMSUBQ)) < 0)
-               return st;
-       if ((qp -> ctrl_addr = st = optGetData()), st < 0) return st;
-       if ((qp -> track = st = optGetData()), st < 0) return st;
-       if ((qp -> pointIndex = st = optGetData()), st < 0) return st;
-       if ((qp -> trackTime.min = st = optGetData()), st < 0) return st;
-       if ((qp -> trackTime.sec = st = optGetData()), st < 0) return st;
-       if ((qp -> trackTime.frame = st = optGetData()), st < 0) return st;
-       if ((st = optGetData()) < 0) return st;         /* byte not used */
-       if ((qp -> diskTime.min = st = optGetData()), st < 0) return st;
-       if ((qp -> diskTime.sec = st = optGetData()), st < 0) return st;
-       if ((qp -> diskTime.frame = st = optGetData()), st < 0) return st;
-#ifdef DEBUG_TOC
-       printk("optcd: exiting optGetQChannelInfo\n");
-#endif
+
+/* Read the current Q-channel info. Also used for reading the
+   table of contents. qp->cdsc_format must be set on entry to
+   indicate the desired address format */
+static int get_q_channel(struct cdrom_subchnl *qp)
+{
+       int status, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10;
+
+       status = drive_status();
+       if (status < 0)
+               return status;
+       qp->cdsc_audiostatus = audio_status;
+
+       status = exec_cmd(COMSUBQ);
+       if (status < 0)
+               return status;
+
+       d1 = get_data(0);
+       if (d1 < 0)
+               return d1;
+       qp->cdsc_adr = d1;
+       qp->cdsc_ctrl = d1 >> 4;
+
+       d2 = get_data(0);
+       if (d2 < 0)
+               return d2;
+       qp->cdsc_trk = bcd2bin(d2);
+
+       d3 = get_data(0);
+       if (d3 < 0)
+               return d3;
+       qp->cdsc_ind = bcd2bin(d3);
+
+       d4 = get_data(0);
+       if (d4 < 0)
+               return d4;
+       qp->cdsc_reladdr.msf.minute = d4;
+
+       d5 = get_data(0);
+       if (d5 < 0)
+               return d5;
+       qp->cdsc_reladdr.msf.second = d5;
+
+       d6 = get_data(0);
+       if (d6 < 0)
+               return d6;
+       qp->cdsc_reladdr.msf.frame = d6;
+
+       d7 = get_data(0);
+       if (d7 < 0)
+               return d7;
+       /* byte not used */
+
+       d8 = get_data(0);
+       if (d8 < 0)
+               return d8;
+       qp->cdsc_absaddr.msf.minute = d8;
+
+       d9 = get_data(0);
+       if (d9 < 0)
+               return d9;
+       qp->cdsc_absaddr.msf.second = d9;
+
+       d10 = get_data(0);
+       if (d10 < 0)
+               return d10;
+       qp->cdsc_absaddr.msf.frame = d10;
+
+       DEBUG((DEBUG_TOC, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
+               d1, d2, d3, d4, d5, d6, d7, d8, d9, d10));
+
+       msf_bcd2bin((union cd_addr *)/*%%*/&qp->cdsc_absaddr);
+       msf_bcd2bin((union cd_addr *)/*%%*/&qp->cdsc_reladdr);
+       if (qp->cdsc_format == CDROM_LBA) {
+               msf2lba((union cd_addr *)/*%%*/&qp->cdsc_absaddr);
+               msf2lba((union cd_addr *)/*%%*/&qp->cdsc_reladdr);
+       }
+
        return 0;
 }
+\f
+/* Table of contents handling */
 
-#define QINFO_FIRSTTRACK       0xa0
-#define QINFO_LASTTRACK                0xa1
-#define QINFO_DISKLENGTH       0xa2
 
-static int optGetDiskInfo(void) {
-       int st, limit;
-       unsigned char test = 0;
-       struct opt_Toc qInfo;
-#ifdef DEBUG_TOC
-       printk("optcd: starting optGetDiskInfo\n");
-#endif
-       optDiskChanged = 0;
-       if ((st = optCmd(COMLEADIN)) < 0)
-               return st;
-       for (limit = 300; (limit > 0) && (test != 0x0f); limit--) {
-               if ((st = optGetQChannelInfo(&qInfo)) < 0)
-                       return st;
-               switch (qInfo.pointIndex) {
-               case QINFO_FIRSTTRACK:
-                       DiskInfo.first = bcd2bin(qInfo.diskTime.min);
-#ifdef DEBUG_TOC
-                       printk("optcd: got first: %d\n", DiskInfo.first);
-#endif
-                       test |= 0x01;
-                       break;
-               case QINFO_LASTTRACK:
-                       DiskInfo.last = bcd2bin(qInfo.diskTime.min);
-#ifdef DEBUG_TOC
-                       printk("optcd: got last: %d\n", DiskInfo.last);
-#endif
-                       test |= 0x02;
-                       break;
-               case QINFO_DISKLENGTH:
-                       DiskInfo.diskLength.min = qInfo.diskTime.min;
-                       DiskInfo.diskLength.sec = qInfo.diskTime.sec-2;
-                       DiskInfo.diskLength.frame = qInfo.diskTime.frame;
-#ifdef DEBUG_TOC
-                       printk("optcd: got length: %x:%x.%x\n",
-                               DiskInfo.diskLength.min,
-                               DiskInfo.diskLength.sec,
-                               DiskInfo.diskLength.frame);
+/* Errors in table of contents */
+#define ERR_TOC_MISSINGINFO    0x120
+#define ERR_TOC_MISSINGENTRY   0x121
+
+
+struct msf {
+       u_char  minute;
+       u_char  second;
+       u_char  frame;
+};
+
+struct cdrom_disk_info {
+       unsigned char   first;
+       unsigned char   last;
+       struct msf      disk_length;
+       struct msf      first_track;
+       /* Multisession info: */
+       unsigned char   next;
+       struct msf      next_session;
+       struct msf      last_session;
+       unsigned char   multi;
+       unsigned char   xa;
+       unsigned char   audio;
+};
+static struct cdrom_disk_info disk_info;
+
+#define MAX_TRACKS             111
+static struct cdrom_subchnl toc[MAX_TRACKS];
+
+#define QINFO_FIRSTTRACK       100 /* bcd2bin(0xa0) */
+#define QINFO_LASTTRACK                101 /* bcd2bin(0xa1) */
+#define QINFO_DISKLENGTH       102 /* bcd2bin(0xa2) */
+#define QINFO_NEXTSESSION      110 /* bcd2bin(0xb0) */
+
+#define I_FIRSTTRACK   0x01
+#define I_LASTTRACK    0x02
+#define I_DISKLENGTH   0x04
+#define I_NEXTSESSION  0x08
+#define I_ALL  (I_FIRSTTRACK | I_LASTTRACK | I_DISKLENGTH)
+
+
+#if DEBUG_TOC
+void toc_debug_info(int i)
+{
+       printk("#%3d ctl %1x, adr %1x, track %2d index %3d"
+               "  %2d:%02d.%02d %2d:%02d.%02d\n",
+               i, toc[i].cdsc_ctrl, toc[i].cdsc_adr,
+               toc[i].cdsc_trk, toc[i].cdsc_ind,
+               toc[i].cdsc_reladdr.msf.minute,
+               toc[i].cdsc_reladdr.msf.second,
+               toc[i].cdsc_reladdr.msf.frame,
+               toc[i].cdsc_absaddr.msf.minute,
+               toc[i].cdsc_absaddr.msf.second,
+               toc[i].cdsc_absaddr.msf.frame);
+}
 #endif
-                       test |= 0x04;
-                       break;
-               default:
-                       if ((test & 0x01)       /* Got no of first track */
-                        && (qInfo.pointIndex == DiskInfo.first)) {
-                               /* StartTime of First Track */
-                               DiskInfo.firstTrack.min = qInfo.diskTime.min;
-                               DiskInfo.firstTrack.sec = qInfo.diskTime.sec;
-                               DiskInfo.firstTrack.frame = qInfo.diskTime.frame;
-#ifdef DEBUG_TOC
-                       printk("optcd: got start: %x:%x.%x\n",
-                               DiskInfo.firstTrack.min,
-                               DiskInfo.firstTrack.sec,
-                               DiskInfo.firstTrack.frame);
+
+
+static int read_toc(void)
+{
+       int status, limit, count;
+       unsigned char got_info = 0;
+       struct cdrom_subchnl q_info;
+#if DEBUG_TOC
+       int i;
 #endif
-                               test |= 0x08;
+
+       DEBUG((DEBUG_TOC, "starting read_toc"));
+
+       count = 0;
+       for (limit = 60; limit > 0; limit--) {
+               int index;
+
+               q_info.cdsc_format = CDROM_MSF;
+               status = get_q_channel(&q_info);
+               if (status < 0)
+                       return status;
+
+               index = q_info.cdsc_ind;
+               if (index > 0 && index < MAX_TRACKS
+                   && q_info.cdsc_trk == 0 && toc[index].cdsc_ind == 0) {
+                       toc[index] = q_info;
+                       DEBUG((DEBUG_TOC, "got %d", index));
+                       if (index < 100)
+                               count++;
+
+                       switch (q_info.cdsc_ind) {
+                       case QINFO_FIRSTTRACK:
+                               got_info |= I_FIRSTTRACK;
+                               break;
+                       case QINFO_LASTTRACK:
+                               got_info |= I_LASTTRACK;
+                               break;
+                       case QINFO_DISKLENGTH:
+                               got_info |= I_DISKLENGTH;
+                               break;
+                       case QINFO_NEXTSESSION:
+                               got_info |= I_NEXTSESSION;
+                               break;
                        }
                }
+
+               if ((got_info & I_ALL) == I_ALL
+                   && toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
+                      >= toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
+                       break;
+       }
+
+       /* Construct disk_info from TOC */
+       if (disk_info.first == 0) {
+               disk_info.first = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
+               disk_info.first_track.minute =
+                       toc[disk_info.first].cdsc_absaddr.msf.minute;
+               disk_info.first_track.second =
+                       toc[disk_info.first].cdsc_absaddr.msf.second;
+               disk_info.first_track.frame =
+                       toc[disk_info.first].cdsc_absaddr.msf.frame;
        }
-#ifdef DEBUG_TOC
-       printk("optcd: exiting optGetDiskInfo\n");
+       disk_info.last = toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute;
+       disk_info.disk_length.minute =
+                       toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.minute;
+       disk_info.disk_length.second =
+                       toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.second-2;
+       disk_info.disk_length.frame =
+                       toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.frame;
+       disk_info.next_session.minute =
+                       toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.minute;
+       disk_info.next_session.second =
+                       toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.second;
+       disk_info.next_session.frame =
+                       toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.frame;
+       disk_info.next = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
+       disk_info.last_session.minute =
+                       toc[disk_info.next].cdsc_absaddr.msf.minute;
+       disk_info.last_session.second =
+                       toc[disk_info.next].cdsc_absaddr.msf.second;
+       disk_info.last_session.frame =
+                       toc[disk_info.next].cdsc_absaddr.msf.frame;
+       toc[disk_info.last + 1].cdsc_absaddr.msf.minute =
+                       disk_info.disk_length.minute;
+       toc[disk_info.last + 1].cdsc_absaddr.msf.second =
+                       disk_info.disk_length.second;
+       toc[disk_info.last + 1].cdsc_absaddr.msf.frame =
+                       disk_info.disk_length.frame;
+#if DEBUG_TOC
+       for (i = 1; i <= disk_info.last + 1; i++)
+               toc_debug_info(i);
+       toc_debug_info(QINFO_FIRSTTRACK);
+       toc_debug_info(QINFO_LASTTRACK);
+       toc_debug_info(QINFO_DISKLENGTH);
+       toc_debug_info(QINFO_NEXTSESSION);
 #endif
-       if (test != 0x0f)
+
+       DEBUG((DEBUG_TOC, "exiting read_toc, got_info %x, count %d",
+               got_info, count));
+       if ((got_info & I_ALL) != I_ALL
+           || toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
+              < toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
                return -ERR_TOC_MISSINGINFO;
        return 0;
 }
 
-static int optGetToc(void) {   /* Presumes we have got DiskInfo */
-       int st, count, px, limit;
-       struct opt_Toc qInfo;
-#ifdef DEBUG_TOC
-       int i;
-       printk("optcd: starting optGetToc\n");
-#endif
-       for (count = 0; count < MAX_TRACKS; count++)
-               Toc[count].pointIndex = 0;
-       if ((st = optCmd(COMLEADIN)) < 0)
-               return st;
-       st = 0;
-       count = DiskInfo.last + 3;
-       for (limit = 300; (limit > 0) && (count > 0); limit--) {
-               if ((st = optGetQChannelInfo(&qInfo)) < 0)
+
+#ifdef MULTISESSION
+static int get_multi_disk_info(void)
+{
+       int sessions, status;
+       struct cdrom_msf multi_index;
+
+
+       for (sessions = 2; sessions < 10 /* %%for now */; sessions++) {
+               int count;
+
+               for (count = 100; count < MAX_TRACKS; count++) 
+                       toc[count].cdsc_ind = 0;
+
+               multi_index.cdmsf_min0 = disk_info.next_session.minute;
+               multi_index.cdmsf_sec0 = disk_info.next_session.second;
+               multi_index.cdmsf_frame0 = disk_info.next_session.frame;
+               if (multi_index.cdmsf_sec0 >= 20)
+                       multi_index.cdmsf_sec0 -= 20;
+               else {
+                       multi_index.cdmsf_sec0 += 40;
+                       multi_index.cdmsf_min0--;
+               }
+               DEBUG((DEBUG_MULTIS, "Try %d: %2d:%02d.%02d", sessions,
+                       multi_index.cdmsf_min0,
+                       multi_index.cdmsf_sec0,
+                       multi_index.cdmsf_frame0));
+               bin2bcd(&multi_index);
+               multi_index.cdmsf_min1 = 0;
+               multi_index.cdmsf_sec1 = 0;
+               multi_index.cdmsf_frame1 = 1;
+
+               status = exec_read_cmd(COMREAD, &multi_index);
+               if (status < 0) {
+                       DEBUG((DEBUG_TOC, "exec_read_cmd COMREAD: %02x",
+                               -status));
                        break;
-               px = bcd2bin(qInfo.pointIndex);
-               if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
-                       if (Toc[px].pointIndex == 0) {
-                               Toc[px] = qInfo;
-                               count--;
-                       }
+               }
+               status = sleep_flag_low(FL_DTEN, MULTI_SEEK_TIMEOUT) ?
+                               0 : -ERR_TOC_MISSINGINFO;
+               flush_data();
+               if (status < 0) {
+                       DEBUG((DEBUG_TOC, "sleep_flag_low: %02x", -status));
+                       break;
+               }
+
+               status = read_toc();
+               if (status < 0) {
+                       DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
+                       break;
+               }
+
+               disk_info.multi = 1;
        }
-       Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
-#ifdef DEBUG_TOC
-       printk("optcd: exiting optGetToc\n");
-       for (i = 1; i <= DiskInfo.last + 1; i++)
-               printk("i = %3d ctl-adr = %02x track %2d px "
-                       "%02x %02x:%02x.%02x %02x:%02x.%02x\n",
-                       i, Toc[i].ctrl_addr,
-                       Toc[i].track,
-                       Toc[i].pointIndex,
-                       Toc[i].trackTime.min,
-                       Toc[i].trackTime.sec,
-                       Toc[i].trackTime.frame,
-                       Toc[i].diskTime.min,
-                       Toc[i].diskTime.sec,
-                       Toc[i].diskTime.frame);
-       for (i = 100; i < 103; i++)
-               printk("i = %3d ctl-adr = %02x track %2d px "
-                       "%02x %02x:%02x.%02x %02x:%02x.%02x\n",
-                       i, Toc[i].ctrl_addr,
-                       Toc[i].track,
-                       Toc[i].pointIndex,
-                       Toc[i].trackTime.min,
-                       Toc[i].trackTime.sec,
-                       Toc[i].trackTime.frame,
-                       Toc[i].diskTime.min,
-                       Toc[i].diskTime.sec,
-                       Toc[i].diskTime.frame);
-#endif
-       return count ? -ERR_TOC_MISSINGENTRY : 0;
+
+       exec_cmd(COMSTOP);
+
+       if (status < 0)
+               return -EIO;
+       return 0;
 }
+#endif MULTISESSION
 
-static int optUpdateToc(void) {
-#ifdef DEBUG_TOC
-       printk("optcd: starting optUpdateToc\n");
-#endif
-       if (optTocUpToDate)
+
+static int update_toc(void)
+{
+       int status, count;
+
+       if (toc_uptodate)
                return 0;
-       if (optGetDiskInfo() < 0)
+
+       DEBUG((DEBUG_TOC, "starting update_toc"));
+
+       disk_info.first = 0;
+       for (count = 0; count < MAX_TRACKS; count++) 
+               toc[count].cdsc_ind = 0;
+
+       status = exec_cmd(COMLEADIN);
+       if (status < 0)
                return -EIO;
-       if (optGetToc() < 0)
+
+       status = read_toc();
+       if (status < 0) {
+               DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
                return -EIO;
-       optTocUpToDate = 1;
-#ifdef DEBUG_TOC
-       printk("optcd: exiting optUpdateToc\n");
-#endif
+       }
+
+        /* Audio disk detection. Look at first track. */
+       disk_info.audio =
+               (toc[disk_info.first].cdsc_ctrl & CDROM_DATA_TRACK) ? 0 : 1;
+
+       /* XA detection */
+       disk_info.xa = drive_status() & ST_MODE2TRACK;
+
+       /* Multisession detection: if we want this, define MULTISESSION */
+       disk_info.multi = 0;
+#ifdef MULTISESSION
+       if (disk_info.xa)
+               get_multi_disk_info();  /* Here disk_info.multi is set */
+#endif MULTISESSION
+       if (disk_info.multi)
+               printk("optcd: Multisession support experimental, "
+                       "see linux/Documentation/cdrom/optcd\n");
+
+       DEBUG((DEBUG_TOC, "exiting update_toc"));
+
+       toc_uptodate = 1;
        return 0;
 }
+\f
+/* Request handling */
+
 
+#define CURRENT_VALID \
+       (CURRENT && MAJOR(CURRENT -> rq_dev) == MAJOR_NR \
+        && CURRENT -> cmd == READ && CURRENT -> sector != -1)
 
-/* Buffers */
 
-#define OPT_BUF_SIZ            16
-#define OPT_BLOCKSIZE          2048
-#define OPT_BLOCKSIZE_RAW      2336
-#define OPT_BLOCKSIZE_ALL      2646
-#define OPT_NOBUF              -1
+#define BLOCKSIZE      2048
+#define BLOCKSIZE_RAW  2336
+#define BLOCKSIZE_ALL  2646
+#define N_BUFS         16
+#define NOBUF          -1
+
 
 /* Buffer for block size conversion. */
-static char opt_buf[OPT_BLOCKSIZE*OPT_BUF_SIZ];
-static volatile int opt_buf_bn[OPT_BUF_SIZ], opt_next_bn;
-static volatile int opt_buf_in = 0, opt_buf_out = OPT_NOBUF;
+static char buf[BLOCKSIZE * N_BUFS];
+static volatile int buf_bn[N_BUFS], next_bn;
+static volatile int buf_in = 0, buf_out = NOBUF;
 
-inline static void opt_invalidate_buffers(void) {
+inline static void opt_invalidate_buffers(void)
+{
        int i;
-#ifdef DEBUG_BUFFERS
-       printk("optcd: executing opt_invalidate_buffers\n");
-#endif
-       for (i = 0; i < OPT_BUF_SIZ; i++)
-               opt_buf_bn[i] = OPT_NOBUF;
-       opt_buf_out = OPT_NOBUF;
+
+       DEBUG((DEBUG_BUFFERS, "executing opt_invalidate_buffers"));
+
+       for (i = 0; i < N_BUFS; i++)
+               buf_bn[i] = NOBUF;
+       buf_out = NOBUF;
 }
 
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-static void opt_transfer(void) {
-#if (defined DEBUG_BUFFERS) || (defined DEBUG_REQUEST)
-       printk("optcd: executing opt_transfer\n");
+
+/* Take care of the different block sizes between cdrom and Linux.
+   When Linux gets variable block sizes this will probably go away. */
+static void transfer(void)
+{
+#if DEBUG_BUFFERS | DEBUG_REQUEST
+       printk("optcd: executing transfer\n");
 #endif
+
        if (!CURRENT_VALID)
                return;
        while (CURRENT -> nr_sectors) {
                int bn = CURRENT -> sector / 4;
                int i, offs, nr_sectors;
-               for (i = 0; i < OPT_BUF_SIZ && opt_buf_bn[i] != bn; ++i);
-#ifdef DEBUG_REQUEST
-               printk("optcd: found %d\n", i);
-#endif
-               if (i >= OPT_BUF_SIZ) {
-                       opt_buf_out = OPT_NOBUF;
+               for (i = 0; i < N_BUFS && buf_bn[i] != bn; ++i);
+
+               DEBUG((DEBUG_REQUEST, "found %d", i));
+
+               if (i >= N_BUFS) {
+                       buf_out = NOBUF;
                        break;
                }
+
                offs = (i * 4 + (CURRENT -> sector & 3)) * 512;
                nr_sectors = 4 - (CURRENT -> sector & 3);
-               if (opt_buf_out != i) {
-                       opt_buf_out = i;
-                       if (opt_buf_bn[i] != bn) {
-                               opt_buf_out = OPT_NOBUF;
+
+               if (buf_out != i) {
+                       buf_out = i;
+                       if (buf_bn[i] != bn) {
+                               buf_out = NOBUF;
                                continue;
                        }
                }
+
                if (nr_sectors > CURRENT -> nr_sectors)
                        nr_sectors = CURRENT -> nr_sectors;
-               memcpy(CURRENT -> buffer, opt_buf + offs, nr_sectors * 512);
+               memcpy(CURRENT -> buffer, buf + offs, nr_sectors * 512);
                CURRENT -> nr_sectors -= nr_sectors;
                CURRENT -> sector += nr_sectors;
                CURRENT -> buffer += nr_sectors * 512;
@@ -704,216 +1054,219 @@ static void opt_transfer(void) {
 
 /* State machine for reading disk blocks */
 
-enum opt_state_e {
-       OPT_S_IDLE,     /* 0 */
-       OPT_S_START,    /* 1 */
-       OPT_S_READ,     /* 2 */
-       OPT_S_DATA,     /* 3 */
-       OPT_S_STOP,     /* 4 */
-       OPT_S_STOPPING  /* 5 */
+enum state_e {
+       S_IDLE,         /* 0 */
+       S_START,        /* 1 */
+       S_READ,         /* 2 */
+       S_DATA,         /* 3 */
+       S_STOP,         /* 4 */
+       S_STOPPING      /* 5 */
 };
 
-static volatile enum opt_state_e opt_state = OPT_S_IDLE;
-#ifdef DEBUG_STATE
-static volatile enum opt_state_e opt_state_old = OPT_S_STOP;
-static volatile int opt_st_old = 0;
-static volatile long opt_state_n = 0;
+static volatile enum state_e state = S_IDLE;
+#if DEBUG_STATE
+static volatile enum state_e state_old = S_STOP;
+static volatile int flags_old = 0;
+static volatile long state_n = 0;
 #endif
 
-static volatile int opt_transfer_is_active = 0;
-static volatile int opt_error = 0;     /* do something with this?? */
-static int optTries;                   /* ibid?? */
 
-static void opt_poll(void) {
-       static int optTimeout;
-       static volatile int opt_read_count = 1;
-       int st = 0;
-       int loop_ctl = 1;
+static volatile int transfer_is_active = 0;
+static volatile int error = 0; /* %% do something with this?? */
+static int tries;              /* ibid?? */
+
+static void poll(void)
+{
+       static int timeout;
+       static volatile int read_count = 1;
+       int flags;
+       int loop_again = 1;
+       int status = 0;
        int skip = 0;
 
-       if (opt_error) {
-               printk("optcd: I/O error 0x%02x\n", opt_error);
+       if (error) {
+               printk("optcd: I/O error 0x%02x\n", error);
                opt_invalidate_buffers();
-#ifdef WARN_IF_READ_FAILURE
-               if (optTries == 5)
-                       printk("optcd: read block %d failed; audio disk?\n",
-                               opt_next_bn);
-#endif
-               if (!optTries--) {
+               if (!tries--) {
                        printk("optcd: read block %d failed; Giving up\n",
-                              opt_next_bn);
-                       if (opt_transfer_is_active) {
-                               optTries = 0;
-                               loop_ctl = 0;
-                       }
+                              next_bn);
+                       if (transfer_is_active)
+                               loop_again = 0;
                        if (CURRENT_VALID)
                                end_request(0);
-                       optTries = 5;
+                       tries = 5;
                }
-               opt_error = 0;
-               opt_state = OPT_S_STOP;
+               error = 0;
+               state = S_STOP;
        }
 
-       while (loop_ctl)
+       while (loop_again)
        {
-               loop_ctl = 0; /* each case must flip this back to 1 if we want
+               loop_again = 0; /* each case must flip this back to 1 if we want
                                 to come back up here */
-#ifdef DEBUG_STATE
-               if (opt_state == opt_state_old)
-                       opt_state_n++;
+
+#if DEBUG_STATE
+               if (state == state_old)
+                       state_n++;
                else {
-                       opt_state_old = opt_state;
-                       if (++opt_state_n > 1)
+                       state_old = state;
+                       if (++state_n > 1)
                                printk("optcd: %ld times in previous state\n",
-                                       opt_state_n);
-                       printk("optcd: state %d\n", opt_state);
-                       opt_state_n = 0;
+                                       state_n);
+                       printk("optcd: state %d\n", state);
+                       state_n = 0;
                }
 #endif
-               switch (opt_state) {
-               case OPT_S_IDLE:
+
+               switch (state) {
+               case S_IDLE:
                        return;
-               case OPT_S_START:
-                       if (optSendCmd(COMDRVST))
+               case S_START:
+                       if (send_cmd(COMDRVST))
                                return;
-                       opt_state = OPT_S_READ;
-                       optTimeout = 3000;
+                       state = S_READ;
+                       timeout = READ_TIMEOUT;
                        break;
-               case OPT_S_READ: {
-                       struct opt_Play_msf msf;
+               case S_READ: {
+                       struct cdrom_msf msf;
                        if (!skip) {
-                               if ((st = optStatus()) < 0)
+                               status = fetch_status();
+                               if (status < 0)
                                        break;
-                               if (st & ST_DSK_CHG) {
-                                       optDiskChanged = 1;
-                                       optTocUpToDate = 0;
+                               if (status & ST_DSK_CHG) {
+                                       toc_uptodate = 0;
                                        opt_invalidate_buffers();
                                }
                        }
                        skip = 0;
-                       if ((st & ST_DOOR_OPEN) || (st & ST_DRVERR)) {
-                               optDiskChanged = 1;
-                               optTocUpToDate = 0;
-                               printk((st & ST_DOOR_OPEN)
+                       if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
+                               toc_uptodate = 0;
+                               printk((status & ST_DOOR_OPEN)
                                       ? "optcd: door open\n"
                                       : "optcd: disk removed\n");
-                               if (opt_transfer_is_active) {
-                                       opt_state = OPT_S_START;
-                                       loop_ctl = 1;
+                               if (transfer_is_active) {
+                                       state = S_START;
+                                       loop_again = 1;
                                        break;
                                }
-                               opt_state = OPT_S_IDLE;
+                               state = S_IDLE;
                                while (CURRENT_VALID)
                                        end_request(0);
                                return;
                        }
                        if (!CURRENT_VALID) {
-                               opt_state = OPT_S_STOP;
-                               loop_ctl = 1;
+                               state = S_STOP;
+                               loop_again = 1;
                                break;
                        }
-                       opt_next_bn = CURRENT -> sector / 4;
-                       hsg2msf(opt_next_bn, &msf.start);
-                       opt_read_count = OPT_BUF_SIZ;
-                       msf.end.min = 0;
-                       msf.end.sec = 0;
-                       msf.end.frame = opt_read_count;
-#ifdef DEBUG_REQUEST
-                       printk("optcd: reading %x:%x.%x %x:%x.%x\n",
-                               msf.start.min,
-                               msf.start.sec,
-                               msf.start.frame,
-                               msf.end.min,
-                               msf.end.sec,
-                               msf.end.frame);
-                       printk("optcd: opt_next_bn:%d opt_buf_in:%d opt_buf_out:%d opt_buf_bn:%d\n",
-                               opt_next_bn,
-                               opt_buf_in,
-                               opt_buf_out,
-                               opt_buf_bn[opt_buf_in]);
-#endif
-                       optReadCmd(COMREAD, &msf);
-                       opt_state = OPT_S_DATA;
-                       optTimeout = READ_TIMEOUT;
+                       next_bn = CURRENT -> sector / 4;
+                       lba2msf(next_bn, &msf);
+                       read_count = N_BUFS;
+                       msf.cdmsf_frame1 = read_count; /* Not BCD! */
+
+                       DEBUG((DEBUG_REQUEST, "reading %x:%x.%x %x:%x.%x",
+                               msf.cdmsf_min0,
+                               msf.cdmsf_sec0,
+                               msf.cdmsf_frame0,
+                               msf.cdmsf_min1,
+                               msf.cdmsf_sec1,
+                               msf.cdmsf_frame1));
+                       DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d"
+                               " buf_out:%d buf_bn:%d",
+                               next_bn,
+                               buf_in,
+                               buf_out,
+                               buf_bn[buf_in]));
+
+                       exec_read_cmd(COMREAD, &msf);
+                       state = S_DATA;
+                       timeout = READ_TIMEOUT;
                        break;
                }
-               case OPT_S_DATA:
-                       st = optFlags() & (FL_STEN|FL_DTEN);
-#ifdef DEBUG_STATE
-                       if (st != opt_st_old) {
-                               opt_st_old = st;
-                               printk("optcd: st:%x\n", st);
+               case S_DATA:
+                       flags = stdt_flags() & (FL_STEN|FL_DTEN);
+
+#if DEBUG_STATE
+                       if (flags != flags_old) {
+                               flags_old = flags;
+                               printk("optcd: flags:%x\n", flags);
                        }
-                       if (st == FL_STEN)
-                               printk("timeout cnt: %d\n", optTimeout);
-#endif
-                       switch (st) {
-                       case FL_DTEN:
-#ifdef WARN_IF_READ_FAILURE
-                               if (optTries == 5)
-                                       printk("optcd: read block %d failed; audio disk?\n",
-                                              opt_next_bn);
+                       if (flags == FL_STEN)
+                               printk("timeout cnt: %d\n", timeout);
 #endif
-                               if (!optTries--) {
-                                       printk("optcd: read block %d failed; Giving up\n",
-                                              opt_next_bn);
-                                       if (opt_transfer_is_active) {
-                                               optTries = 0;
+
+                       switch (flags) {
+                       case FL_DTEN:           /* only STEN low */
+                               if (!tries--) {
+                                       printk("optcd: read block %d failed; "
+                                               "Giving up\n", next_bn);
+                                       if (transfer_is_active) {
+                                               tries = 0;
                                                break;
                                        }
                                        if (CURRENT_VALID)
                                                end_request(0);
-                                       optTries = 5;
+                                       tries = 5;
                                }
-                               opt_state = OPT_S_START;
-                               optTimeout = READ_TIMEOUT;
-                               loop_ctl = 1;
-                       case (FL_STEN|FL_DTEN):
+                               state = S_START;
+                               timeout = READ_TIMEOUT;
+                               loop_again = 1;
+                       case (FL_STEN|FL_DTEN):  /* both high */
                                break;
-                       default:
-                               optTries = 5;
-                               if (!CURRENT_VALID && opt_buf_in == opt_buf_out) {
-                                       opt_state = OPT_S_STOP;
-                                       loop_ctl = 1;
+                       default:        /* DTEN low */
+                               tries = 5;
+                               if (!CURRENT_VALID && buf_in == buf_out) {
+                                       state = S_STOP;
+                                       loop_again = 1;
                                        break;
                                }
-                               if (opt_read_count<=0)
-                                       printk("optcd: warning - try to read 0 frames\n");
-                               while (opt_read_count) {
-                                       opt_buf_bn[opt_buf_in] = OPT_NOBUF;
-                                       if (dten_low()) { /* should be no waiting here!?? */
-                                               printk("read_count:%d CURRENT->nr_sectors:%ld opt_buf_in:%d\n",
-                                                       opt_read_count,
+                               if (read_count<=0)
+                                       printk("optcd: warning - try to read"
+                                               " 0 frames\n");
+                               while (read_count) {
+                                       buf_bn[buf_in] = NOBUF;
+                                       if (!flag_low(FL_DTEN, BUSY_TIMEOUT)) {
+                                       /* should be no waiting here!?? */
+                                               printk("read_count:%d "
+                                                  "CURRENT->nr_sectors:%ld "
+                                                  "buf_in:%d\n",
+                                                       read_count,
                                                        CURRENT->nr_sectors,
-                                                       opt_buf_in);
-                                               printk("opt_transfer_is_active:%x\n",
-                                                       opt_transfer_is_active);
-                                               opt_read_count = 0;
-                                               opt_state = OPT_S_STOP;
-                                               loop_ctl = 1;
+                                                       buf_in);
+                                               printk("transfer active: %x\n",
+                                                       transfer_is_active);
+                                               read_count = 0;
+                                               state = S_STOP;
+                                               loop_again = 1;
                                                end_request(0);
                                                break;
                                        }
-                                       optReadData(opt_buf+OPT_BLOCKSIZE*opt_buf_in, OPT_BLOCKSIZE);
-                                       opt_read_count--;
-#ifdef DEBUG_REQUEST
-                                       printk("OPT_S_DATA; ---I've read data- read_count: %d\n",
-                                              opt_read_count);
-                                       printk("opt_next_bn:%d  opt_buf_in:%d opt_buf_out:%d  opt_buf_bn:%d\n",
-                                              opt_next_bn,
-                                              opt_buf_in,
-                                              opt_buf_out,
-                                              opt_buf_bn[opt_buf_in]);
-#endif
-                                       opt_buf_bn[opt_buf_in] = opt_next_bn++;
-                                       if (opt_buf_out == OPT_NOBUF)
-                                               opt_buf_out = opt_buf_in;
-                                       opt_buf_in = opt_buf_in + 1 ==
-                                               OPT_BUF_SIZ ? 0 : opt_buf_in + 1;
+                                       fetch_data(buf+
+                                           BLOCKSIZE*buf_in,
+                                           BLOCKSIZE);
+                                       read_count--;
+
+                                       DEBUG((DEBUG_REQUEST,
+                                               "S_DATA; ---I've read data- "
+                                               "read_count: %d",
+                                               read_count));
+                                       DEBUG((DEBUG_REQUEST,
+                                               "next_bn:%d  buf_in:%d "
+                                               "buf_out:%d  buf_bn:%d",
+                                               next_bn,
+                                               buf_in,
+                                               buf_out,
+                                               buf_bn[buf_in]));
+
+                                       buf_bn[buf_in] = next_bn++;
+                                       if (buf_out == NOBUF)
+                                               buf_out = buf_in;
+                                       buf_in = buf_in + 1 ==
+                                               N_BUFS ? 0 : buf_in + 1;
                                }
-                               if (!opt_transfer_is_active) {
+                               if (!transfer_is_active) {
                                        while (CURRENT_VALID) {
-                                               opt_transfer();
+                                               transfer();
                                                if (CURRENT -> nr_sectors == 0)
                                                        end_request(1);
                                                else
@@ -922,442 +1275,663 @@ static void opt_poll(void) {
                                }
 
                                if (CURRENT_VALID
-                                   && (CURRENT -> sector / 4 < opt_next_bn ||
+                                   && (CURRENT -> sector / 4 < next_bn ||
                                    CURRENT -> sector / 4 >
-                                    opt_next_bn + OPT_BUF_SIZ)) {
-                                       opt_state = OPT_S_STOP;
-                                       loop_ctl = 1;
+                                    next_bn + N_BUFS)) {
+                                       state = S_STOP;
+                                       loop_again = 1;
                                        break;
                                }
-                               optTimeout = READ_TIMEOUT;
-                               if (opt_read_count == 0) {
-                                       opt_state = OPT_S_STOP;
-                                       loop_ctl = 1;
+                               timeout = READ_TIMEOUT;
+                               if (read_count == 0) {
+                                       state = S_STOP;
+                                       loop_again = 1;
                                        break;
                                }
                        }
                        break;
-               case OPT_S_STOP:
-                       if (opt_read_count != 0)
+               case S_STOP:
+                       if (read_count != 0)
                                printk("optcd: discard data=%x frames\n",
-                                       opt_read_count);
-                       while (opt_read_count != 0) {
-                               optFlushData();
-                               opt_read_count--;
-                       }
-                       if (optSendCmd(COMDRVST))
+                                       read_count);
+                       flush_data();
+                       if (send_cmd(COMDRVST))
                                return;
-                       opt_state = OPT_S_STOPPING;
-                       optTimeout = 1000;
+                       state = S_STOPPING;
+                       timeout = STOP_TIMEOUT;
                        break;
-               case OPT_S_STOPPING:
-                       if ((st = optStatus()) < 0 && optTimeout)
+               case S_STOPPING:
+                       status = fetch_status();
+                       if (status < 0 && timeout)
                                        break;
-                       if ((st != -1) && (st & ST_DSK_CHG)) {
-                               optDiskChanged = 1;
-                               optTocUpToDate = 0;
+                       if ((status >= 0) && (status & ST_DSK_CHG)) {
+                               toc_uptodate = 0;
                                opt_invalidate_buffers();
                        }
                        if (CURRENT_VALID) {
-                               if (st != -1) {
-                                       opt_state = OPT_S_READ;
-                                       loop_ctl = 1;
+                               if (status >= 0) {
+                                       state = S_READ;
+                                       loop_again = 1;
                                        skip = 1;
                                        break;
                                } else {
-                                       opt_state = OPT_S_START;
-                                       optTimeout = 1;
+                                       state = S_START;
+                                       timeout = 1;
                                }
                        } else {
-                               opt_state = OPT_S_IDLE;
+                               state = S_IDLE;
                                return;
                        }
                        break;
                default:
-                       printk("optcd: invalid state %d\n", opt_state);
+                       printk("optcd: invalid state %d\n", state);
                        return;
                } /* case */
        } /* while */
 
-       if (!optTimeout--) {
-               printk("optcd: timeout in state %d\n", opt_state);
-               opt_state = OPT_S_STOP;
-               if (optCmd(COMSTOP) < 0)
+       if (!timeout--) {
+               printk("optcd: timeout in state %d\n", state);
+               state = S_STOP;
+               if (exec_cmd(COMSTOP) < 0)
                        return;
        }
 
-       SET_TIMER(opt_poll, 1);
+       SET_TIMER(poll, HZ/100);
 }
 
 
-static void do_optcd_request(void) {
-#ifdef DEBUG_REQUEST
-       printk("optcd: do_optcd_request(%ld+%ld)\n",
-              CURRENT -> sector, CURRENT -> nr_sectors);
-#endif
-       opt_transfer_is_active = 1;
+static void do_optcd_request(void)
+{
+       DEBUG((DEBUG_REQUEST, "do_optcd_request(%ld+%ld)",
+              CURRENT -> sector, CURRENT -> nr_sectors));
+
+       if (disk_info.audio) {
+               printk("optcd: Error: tried to mount an Audio CD\n");
+               end_request(0);
+               return;
+       }
+
+       transfer_is_active = 1;
        while (CURRENT_VALID) {
                if (CURRENT->bh) {
                        if (!buffer_locked(CURRENT->bh))
                                panic(DEVICE_NAME ": block not locked");
                }
-               opt_transfer(); /* First try to transfer block from buffers */
+               transfer();     /* First try to transfer block from buffers */
                if (CURRENT -> nr_sectors == 0) {
                        end_request(1);
                } else {        /* Want to read a block not in buffer */
-                       opt_buf_out = OPT_NOBUF;
-                       if (opt_state == OPT_S_IDLE) {
-                               /* Should this block the request queue?? */
-                               if (optUpdateToc() < 0) {
+                       buf_out = NOBUF;
+                       if (state == S_IDLE) {
+                               /* %% Should this block the request queue?? */
+                               if (update_toc() < 0) {
                                        while (CURRENT_VALID)
                                                end_request(0);
                                        break;
                                }
                                /* Start state machine */
-                               opt_state = OPT_S_START;
-                               optTries = 5;
-                               SET_TIMER(opt_poll, 1); /* why not start right away?? */
+                               state = S_START;
+                               tries = 5;
+                               /* %% why not start right away?? */
+                               SET_TIMER(poll, HZ/100);
                        }
                        break;
                }
        }
-       opt_transfer_is_active = 0;
-#ifdef DEBUG_REQUEST
-       printk("opt_next_bn:%d  opt_buf_in:%d opt_buf_out:%d  opt_buf_bn:%d\n",
-              opt_next_bn, opt_buf_in, opt_buf_out, opt_buf_bn[opt_buf_in]);
-       printk("optcd: do_optcd_request ends\n");
-#endif
+       transfer_is_active = 0;
+
+       DEBUG((DEBUG_REQUEST, "next_bn:%d  buf_in:%d buf_out:%d  buf_bn:%d",
+              next_bn, buf_in, buf_out, buf_bn[buf_in]));
+       DEBUG((DEBUG_REQUEST, "do_optcd_request ends"));
 }
+\f
+/* IOCTLs */
 
 
-/* VFS calls */
+static char auto_eject = 0;
 
-static int opt_ioctl(struct inode *ip, struct file *fp,
-                       unsigned int cmd, unsigned long arg) {
-       static struct opt_Play_msf opt_Play;    /* pause position */
-       int err;
-#ifdef DEBUG_VFS
-       printk("optcd: starting opt_ioctl, command 0x%x\n", cmd);
-#endif
-       if (!ip)
+static int cdrompause(void)
+{
+       int status;
+
+       if (audio_status != CDROM_AUDIO_PLAY)
                return -EINVAL;
-       if (optGetStatus() < 0)
-               return -EIO;
-       if ((err = optUpdateToc()) < 0)
-               return err;
 
-       switch (cmd) {
-       case CDROMPAUSE: {
-               struct opt_Toc qInfo;
-
-               if (optAudioStatus != CDROM_AUDIO_PLAY)
-                       return -EINVAL;
-               if (optGetQChannelInfo(&qInfo) < 0) {
-                       /* didn't get q channel info */
-                       optAudioStatus = CDROM_AUDIO_NO_STATUS;
-                       return 0;
-               }
-               opt_Play.start = qInfo.diskTime;        /* restart point */
-               if (optCmd(COMPAUSEON) < 0)
-                       return -EIO;
-               optAudioStatus = CDROM_AUDIO_PAUSED;
-               break;
-       }
-       case CDROMRESUME:
-               if (optAudioStatus != CDROM_AUDIO_PAUSED)
-                       return -EINVAL;
-               if (optPlayCmd(COMPLAY, &opt_Play) < 0) {
-                       optAudioStatus = CDROM_AUDIO_ERROR;
-                       return -EIO;
-               }
-               optAudioStatus = CDROM_AUDIO_PLAY;
-               break;
-       case CDROMPLAYMSF: {
-               int st;
-               struct cdrom_msf msf;
-
-               if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof msf)))
-                       return st;
-               memcpy_fromfs(&msf, (void *) arg, sizeof msf);
-               opt_Play.start.min = bin2bcd(msf.cdmsf_min0);
-               opt_Play.start.sec = bin2bcd(msf.cdmsf_sec0);
-               opt_Play.start.frame = bin2bcd(msf.cdmsf_frame0);
-               opt_Play.end.min = bin2bcd(msf.cdmsf_min1);
-               opt_Play.end.sec = bin2bcd(msf.cdmsf_sec1);
-               opt_Play.end.frame = bin2bcd(msf.cdmsf_frame1);
-               if (optPlayCmd(COMPLAY, &opt_Play) < 0) {
-                       optAudioStatus = CDROM_AUDIO_ERROR;
-                       return -EIO;
-               }
-               optAudioStatus = CDROM_AUDIO_PLAY;
-               break;
+       status = exec_cmd(COMPAUSEON);
+       if (status < 0) {
+               DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEON: %02x", -status));
+               return -EIO;
        }
-       case CDROMPLAYTRKIND: {
-               int st;
-               struct cdrom_ti ti;
-
-               if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof ti)))
-                       return st;
-               memcpy_fromfs(&ti, (void *) arg, sizeof ti);
-               if (ti.cdti_trk0 < DiskInfo.first
-                       || ti.cdti_trk0 > DiskInfo.last
-                       || ti.cdti_trk1 < ti.cdti_trk0)
-                       return -EINVAL;
-               if (ti.cdti_trk1 > DiskInfo.last)
-                       ti.cdti_trk1 = DiskInfo.last;
-               opt_Play.start = Toc[ti.cdti_trk0].diskTime;
-               opt_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
-#ifdef DEBUG_VFS
-               printk("optcd: play %02x:%02x.%02x to %02x:%02x.%02x\n",
-                       opt_Play.start.min,
-                       opt_Play.start.sec,
-                       opt_Play.start.frame,
-                       opt_Play.end.min,
-                       opt_Play.end.sec,
-                       opt_Play.end.frame);
-#endif
-               if (optPlayCmd(COMPLAY, &opt_Play) < 0) {
-                       optAudioStatus = CDROM_AUDIO_ERROR;
-                       return -EIO;
-               }
-               optAudioStatus = CDROM_AUDIO_PLAY;
-               break;
+       audio_status = CDROM_AUDIO_PAUSED;
+       return 0;
+}
+
+
+static int cdromresume(void)
+{
+       int status;
+
+       if (audio_status != CDROM_AUDIO_PAUSED)
+               return -EINVAL;
+
+       status = exec_cmd(COMPAUSEOFF);
+       if (status < 0) {
+               DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEOFF: %02x", -status));
+               audio_status = CDROM_AUDIO_ERROR;
+               return -EIO;
        }
-       case CDROMREADTOCHDR: {         /* Read the table of contents header. */
-               int st;
-               struct cdrom_tochdr tocHdr;
-
-               if ((st = verify_area(VERIFY_WRITE,(void *)arg,sizeof tocHdr)))
-                       return st;
-               if (!optTocUpToDate)
-                       optGetDiskInfo();
-               tocHdr.cdth_trk0 = DiskInfo.first;
-               tocHdr.cdth_trk1 = DiskInfo.last;
-               memcpy_tofs((void *) arg, &tocHdr, sizeof tocHdr);
-               break;
+       audio_status = CDROM_AUDIO_PLAY;
+       return 0;
+}
+
+
+static int cdromplaymsf(unsigned long arg)
+{
+       int status;
+       struct cdrom_msf msf;
+
+       status = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
+       if (status)
+               return status;
+       memcpy_fromfs(&msf, (void *) arg, sizeof msf);
+
+       bin2bcd(&msf);
+       status = exec_long_cmd(COMPLAY, &msf);
+       if (status < 0) {
+               DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
+               audio_status = CDROM_AUDIO_ERROR;
+               return -EIO;
        }
-       case CDROMREADTOCENTRY: {       /* Read a table of contents entry. */
-               int st;
-               struct cdrom_tocentry entry;
-               struct opt_Toc *tocPtr;
-
-               if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof entry)))
-                       return st;
-               if ((st = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry)))
-                       return st;
-               memcpy_fromfs(&entry, (void *) arg, sizeof entry);
-               if (!optTocUpToDate)
-                       optGetDiskInfo();
-               if (entry.cdte_track == CDROM_LEADOUT)
-                       tocPtr = &Toc[DiskInfo.last + 1];
-               else if (entry.cdte_track > DiskInfo.last
-                       || entry.cdte_track < DiskInfo.first)
-                       return -EINVAL;
-               else
-                       tocPtr = &Toc[entry.cdte_track];
-               entry.cdte_adr = tocPtr -> ctrl_addr;
-               entry.cdte_ctrl = tocPtr -> ctrl_addr >> 4;
-               switch (entry.cdte_format) {
-               case CDROM_LBA:
-                       entry.cdte_addr.lba = msf2hsg(&tocPtr -> diskTime);
-                       break;
-               case CDROM_MSF:
-                       entry.cdte_addr.msf.minute =
-                               bcd2bin(tocPtr -> diskTime.min);
-                       entry.cdte_addr.msf.second =
-                               bcd2bin(tocPtr -> diskTime.sec);
-                       entry.cdte_addr.msf.frame =
-                               bcd2bin(tocPtr -> diskTime.frame);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               memcpy_tofs((void *) arg, &entry, sizeof entry);
-               break;
+
+       audio_status = CDROM_AUDIO_PLAY;
+       return 0;
+}
+
+
+static int cdromplaytrkind(unsigned long arg)
+{
+       int status;
+       struct cdrom_ti ti;
+       struct cdrom_msf msf;
+
+       status = verify_area(VERIFY_READ, (void *) arg, sizeof ti);
+       if (status)
+               return status;
+       memcpy_fromfs(&ti, (void *) arg, sizeof ti);
+
+       if (ti.cdti_trk0 < disk_info.first
+           || ti.cdti_trk0 > disk_info.last
+           || ti.cdti_trk1 < ti.cdti_trk0)
+               return -EINVAL;
+       if (ti.cdti_trk1 > disk_info.last)
+               ti.cdti_trk1 = disk_info.last;
+
+       msf.cdmsf_min0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.minute;
+       msf.cdmsf_sec0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.second;
+       msf.cdmsf_frame0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.frame;
+       msf.cdmsf_min1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.minute;
+       msf.cdmsf_sec1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.second;
+       msf.cdmsf_frame1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.frame;
+
+       DEBUG((DEBUG_VFS, "play %02d:%02d.%02d to %02d:%02d.%02d",
+               msf.cdmsf_min0,
+               msf.cdmsf_sec0,
+               msf.cdmsf_frame0,
+               msf.cdmsf_min1,
+               msf.cdmsf_sec1,
+               msf.cdmsf_frame1));
+
+       bin2bcd(&msf);
+       status = exec_long_cmd(COMPLAY, &msf);
+       if (status < 0) {
+               DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
+               audio_status = CDROM_AUDIO_ERROR;
+               return -EIO;
        }
-       case CDROMSTOP:
-               optCmd(COMSTOP);
-               optAudioStatus = CDROM_AUDIO_NO_STATUS;
-               break;
-       case CDROMSTART:
-               optCmd(COMCLOSE);       /* What else can we do? */
-               break;
-       case CDROMEJECT:
-               optCmd(COMUNLOCK);
-               optCmd(COMOPEN);
-               break;
-       case CDROMVOLCTRL: {
-               int st;
-               struct cdrom_volctrl volctrl;
-
-               if ((st = verify_area(VERIFY_READ, (void *) arg,
-                               sizeof(volctrl))))
-                       return st;
-               memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
-               opt_Play.start.min = 0x10;
-               opt_Play.start.sec = 0x32;
-               opt_Play.start.frame = volctrl.channel0;
-               opt_Play.end.min = volctrl.channel1;
-               opt_Play.end.sec = volctrl.channel2;
-               opt_Play.end.frame = volctrl.channel3;
-               if (optPlayCmd(COMCHCTRL, &opt_Play) < 0)
-                       return -EIO;
-               break;
+
+       audio_status = CDROM_AUDIO_PLAY;
+       return 0;
+}
+
+
+static int cdromreadtochdr(unsigned long arg)
+{
+       int status;
+       struct cdrom_tochdr tochdr;
+
+       status = verify_area(VERIFY_WRITE, (void *) arg, sizeof tochdr);
+       if (status)
+               return status;
+
+       tochdr.cdth_trk0 = disk_info.first;
+       tochdr.cdth_trk1 = disk_info.last;
+
+       memcpy_tofs((void *) arg, &tochdr, sizeof tochdr);
+       return 0;
+}
+
+
+static int cdromreadtocentry(unsigned long arg)
+{
+       int status;
+       struct cdrom_tocentry entry;
+       struct cdrom_subchnl *tocptr;
+
+       status = verify_area(VERIFY_READ, (void *) arg, sizeof entry);
+       if (status)
+               return status;
+       status = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry);
+       if (status)
+               return status;
+       memcpy_fromfs(&entry, (void *) arg, sizeof entry);
+
+       if (entry.cdte_track == CDROM_LEADOUT)
+               tocptr = &toc[disk_info.last + 1];
+       else if (entry.cdte_track > disk_info.last
+               || entry.cdte_track < disk_info.first)
+               return -EINVAL;
+       else
+               tocptr = &toc[entry.cdte_track];
+
+       entry.cdte_adr = tocptr->cdsc_adr;
+       entry.cdte_ctrl = tocptr->cdsc_ctrl;
+       entry.cdte_addr.msf.minute = tocptr->cdsc_absaddr.msf.minute;
+       entry.cdte_addr.msf.second = tocptr->cdsc_absaddr.msf.second;
+       entry.cdte_addr.msf.frame = tocptr->cdsc_absaddr.msf.frame;
+       /* %% What should go into entry.cdte_datamode? */
+
+       if (entry.cdte_format == CDROM_LBA)
+               msf2lba((union cd_addr *)/*%%*/&entry.cdte_addr);
+       else if (entry.cdte_format != CDROM_MSF)
+               return -EINVAL;
+
+       memcpy_tofs((void *) arg, &entry, sizeof entry);
+       return 0;
+}
+
+
+static int cdromvolctrl(unsigned long arg)
+{
+       int status;
+       struct cdrom_volctrl volctrl;
+       struct cdrom_msf msf;
+
+       status = verify_area(VERIFY_READ, (void *) arg, sizeof volctrl);
+       if (status)
+               return status;
+       memcpy_fromfs(&volctrl, (char *) arg, sizeof volctrl);
+
+       msf.cdmsf_min0 = 0x10;
+       msf.cdmsf_sec0 = 0x32;
+       msf.cdmsf_frame0 = volctrl.channel0;
+       msf.cdmsf_min1 = volctrl.channel1;
+       msf.cdmsf_sec1 = volctrl.channel2;
+       msf.cdmsf_frame1 = volctrl.channel3;
+
+       status = exec_long_cmd(COMCHCTRL, &msf);
+       if (status < 0) {
+               DEBUG((DEBUG_VFS, "exec_long_cmd COMCHCTRL: %02x", -status));
+               return -EIO;
        }
-       case CDROMSUBCHNL: {    /* Get subchannel info */
-               int st;
-               struct cdrom_subchnl subchnl;
-               struct opt_Toc qInfo;
-
-               if ((st = verify_area(VERIFY_READ,
-                               (void *) arg, sizeof subchnl)))
-                       return st;
-               if ((st = verify_area(VERIFY_WRITE,
-                               (void *) arg, sizeof subchnl)))
-                       return st;
-               memcpy_fromfs(&subchnl, (void *) arg, sizeof subchnl);
-               if (optGetQChannelInfo(&qInfo) < 0)
-                       return -EIO;
-               subchnl.cdsc_audiostatus = optAudioStatus;
-               subchnl.cdsc_adr = qInfo.ctrl_addr;
-               subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
-               subchnl.cdsc_trk = bcd2bin(qInfo.track);
-               subchnl.cdsc_ind = bcd2bin(qInfo.pointIndex);
-               switch (subchnl.cdsc_format) {
-               case CDROM_LBA:
-                       subchnl.cdsc_absaddr.lba = msf2hsg(&qInfo.diskTime);
-                       subchnl.cdsc_reladdr.lba = msf2hsg(&qInfo.trackTime);
-                       break;
-               case CDROM_MSF:
-                       subchnl.cdsc_absaddr.msf.minute =
-                               bcd2bin(qInfo.diskTime.min);
-                       subchnl.cdsc_absaddr.msf.second =
-                               bcd2bin(qInfo.diskTime.sec);
-                       subchnl.cdsc_absaddr.msf.frame =
-                               bcd2bin(qInfo.diskTime.frame);
-                       subchnl.cdsc_reladdr.msf.minute =
-                               bcd2bin(qInfo.trackTime.min);
-                       subchnl.cdsc_reladdr.msf.second =
-                               bcd2bin(qInfo.trackTime.sec);
-                       subchnl.cdsc_reladdr.msf.frame =
-                               bcd2bin(qInfo.trackTime.frame);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               memcpy_tofs((void *) arg, &subchnl, sizeof subchnl);
-               break;
+       return 0;
+}
+
+
+static int cdromsubchnl(unsigned long arg)
+{
+       int status;
+       struct cdrom_subchnl subchnl;
+
+       status = verify_area(VERIFY_READ, (void *) arg, sizeof subchnl);
+       if (status)
+               return status;
+       status = verify_area(VERIFY_WRITE, (void *) arg, sizeof subchnl);
+       if (status)
+               return status;
+       memcpy_fromfs(&subchnl, (void *) arg, sizeof subchnl);
+
+       if (subchnl.cdsc_format != CDROM_LBA
+           && subchnl.cdsc_format != CDROM_MSF)
+               return -EINVAL;
+
+       status = get_q_channel(&subchnl);
+       if (status < 0) {
+               DEBUG((DEBUG_VFS, "get_q_channel: %02x", -status));
+               return -EIO;
        }
-       case CDROMREADMODE1: {
-               int st;
-               struct cdrom_msf msf;
-               char buf[OPT_BLOCKSIZE];
-
-               if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof msf)))
-                       return st;
-               if ((st = verify_area(VERIFY_WRITE,(void *)arg,OPT_BLOCKSIZE)))
-                       return st;
-               memcpy_fromfs(&msf, (void *) arg, sizeof msf);
-               opt_Play.start.min = bin2bcd(msf.cdmsf_min0);
-               opt_Play.start.sec = bin2bcd(msf.cdmsf_sec0);
-               opt_Play.start.frame = bin2bcd(msf.cdmsf_frame0);
-               opt_Play.end.min = 0;
-               opt_Play.end.sec = 0;
-               opt_Play.end.frame = 1; /* read only one frame */
-               st = optReadCmd(COMREAD, &opt_Play);
-#ifdef DEBUG_VFS
-               printk("optcd: COMREAD status 0x%x\n", st);
-#endif
-               sleep_dten_low();       /* error checking here?? */
-               optReadData(buf, OPT_BLOCKSIZE);
-               memcpy_tofs((void *) arg, &buf, OPT_BLOCKSIZE);
-               break;
+
+       memcpy_tofs((void *) arg, &subchnl, sizeof subchnl);
+       return 0;
+}
+
+
+static int cdromread(unsigned long arg, int blocksize, int cmd)
+{
+       int status;
+       struct cdrom_msf msf;
+       char buf[BLOCKSIZE_ALL];
+
+       status = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
+       if (status)
+               return status;
+       status = verify_area(VERIFY_WRITE, (void *) arg, blocksize);
+       if (status)
+               return status;
+       memcpy_fromfs(&msf, (void *) arg, sizeof msf);
+
+       bin2bcd(&msf);
+       msf.cdmsf_min1 = 0;
+       msf.cdmsf_sec1 = 0;
+       msf.cdmsf_frame1 = 1;   /* read only one frame */
+       status = exec_read_cmd(cmd, &msf);
+
+       DEBUG((DEBUG_VFS, "read cmd status 0x%x", status));
+
+       if (!sleep_flag_low(FL_DTEN, SLEEP_TIMEOUT))
+               return -EIO;
+       fetch_data(buf, blocksize);
+
+       memcpy_tofs((void *) arg, &buf, blocksize);
+       return 0;
+}
+
+
+static int cdromseek(unsigned long arg)
+{
+       int status;
+       struct cdrom_msf msf;
+
+       status = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
+       if (status)
+               return status;
+       memcpy_fromfs(&msf, (void *) arg, sizeof msf);
+
+       bin2bcd(&msf);
+       status = exec_seek_cmd(COMSEEK, &msf);
+
+       DEBUG((DEBUG_VFS, "COMSEEK status 0x%x", status));
+
+       if (status < 0)
+               return -EIO;
+       return 0;
+}
+
+
+#ifdef MULTISESSION
+static int cdrommultisession(unsigned long arg)
+{
+       int status;
+       struct cdrom_multisession ms;
+
+       status = verify_area(VERIFY_READ, (void*) arg, sizeof ms);
+       if (status)
+               return status;
+       status = verify_area(VERIFY_WRITE, (void*) arg, sizeof ms);
+       if (status)
+               return status;
+       memcpy_fromfs(&ms, (void*) arg, sizeof ms);
+
+       ms.addr.msf.minute = disk_info.last_session.minute;
+       ms.addr.msf.second = disk_info.last_session.second;
+       ms.addr.msf.frame = disk_info.last_session.frame;
+
+       if (ms.addr_format != CDROM_LBA
+          && ms.addr_format != CDROM_MSF)
+               return -EINVAL;
+       if (ms.addr_format == CDROM_LBA)
+               msf2lba((union cd_addr *)/*%%*/&ms.addr);
+
+       ms.xa_flag = disk_info.xa;
+
+       memcpy_tofs((void*) arg, &ms,
+               sizeof(struct cdrom_multisession));
+
+#if DEBUG_MULTIS
+       if (ms.addr_format == CDROM_MSF)
+                       printk("optcd: multisession xa:%d, msf:%02d:%02d.%02d\n",
+                       ms.xa_flag,
+                       ms.addr.msf.minute,
+                       ms.addr.msf.second,
+                       ms.addr.msf.frame);
+       else
+               printk("optcd: multisession %d, lba:0x%08x [%02d:%02d.%02d])\n",
+                       ms.xa_flag,
+                       ms.addr.lba,
+                       disk_info.last_session.minute,
+                       disk_info.last_session.second,
+                       disk_info.last_session.frame);
+#endif DEBUG_MULTIS
+
+       return 0;
+}
+#endif MULTISESSION
+
+
+static int cdromreset(void)
+{
+       if (state != S_IDLE) {
+               error = 1;
+               tries = 0;
        }
-       case CDROMMULTISESSION:
-               return -EINVAL; /* unluckily, not implemented yet */
 
-       default:
+       toc_uptodate = 0;
+       opt_invalidate_buffers();
+       audio_status = CDROM_AUDIO_NO_STATUS;
+
+       if (!reset_drive())
+               return -EIO;
+       return 0;
+}
+\f
+/* VFS calls */
+
+
+static int opt_ioctl(struct inode *ip, struct file *fp,
+                     unsigned int cmd, unsigned long arg)
+{
+       int err;
+
+       DEBUG((DEBUG_VFS, "starting opt_ioctl"));
+
+       if (!ip)
                return -EINVAL;
+
+       if (cmd == CDROMRESET)
+               return cdromreset();
+
+       if (state != S_IDLE)
+               return -EBUSY;
+
+       err = drive_status();
+       if (err < 0) {
+               DEBUG((DEBUG_VFS, "drive_status: %02x", -err));
+               return -EIO;
        }
-#ifdef DEBUG_VFS
-       printk("optcd: exiting opt_ioctl\n");
+       err = update_toc();
+       if (err < 0) {
+               DEBUG((DEBUG_VFS, "update_toc: %02x", -err));
+               return -EIO;
+       }
+
+       DEBUG((DEBUG_VFS, "ioctl cmd 0x%x", cmd));
+
+       switch (cmd) {
+       case CDROMPAUSE:        return cdrompause();
+       case CDROMRESUME:       return cdromresume();
+       case CDROMPLAYMSF:      return cdromplaymsf(arg);
+       case CDROMPLAYTRKIND:   return cdromplaytrkind(arg);
+       case CDROMREADTOCHDR:   return cdromreadtochdr(arg);
+       case CDROMREADTOCENTRY: return cdromreadtocentry(arg);
+
+       case CDROMSTOP:         err = exec_cmd(COMSTOP);
+                               if (err < 0) {
+                                       DEBUG((DEBUG_VFS,
+                                               "exec_cmd COMSTOP: %02x",
+                                               -err));
+                                       return -EIO;
+                               }
+                               audio_status = CDROM_AUDIO_NO_STATUS;
+                               break;
+       case CDROMSTART:        err = exec_cmd(COMCLOSE);  /* What else? */
+                               if (err < 0) {
+                                       DEBUG((DEBUG_VFS,
+                                               "exec_cmd COMCLOSE: %02x",
+                                               -err));
+                                       return -EIO;
+                               }
+                               break;
+       case CDROMEJECT:        err = exec_cmd(COMUNLOCK);
+                               if (err < 0) {
+                                       DEBUG((DEBUG_VFS,
+                                               "exec_cmd COMUNLOCK: %02x",
+                                               -err));
+                                       return -EIO;
+                               }
+                               err = exec_cmd(COMOPEN);
+                               if (err < 0) {
+                                       DEBUG((DEBUG_VFS,
+                                               "exec_cmd COMOPEN: %02x",
+                                               -err));
+                                       return -EIO;
+                               }
+                               break;
+
+       case CDROMVOLCTRL:      return cdromvolctrl(arg);
+       case CDROMSUBCHNL:      return cdromsubchnl(arg);
+
+       case CDROMREADAUDIO:    return -EINVAL; /* not implemented */
+       case CDROMEJECT_SW:     auto_eject = (char) arg;
+                               break;
+
+#ifdef MULTISESSION
+       case CDROMMULTISESSION: return cdrommultisession(arg);
 #endif
+
+       case CDROM_GET_UPC:     return -EINVAL; /* not implemented */
+       case CDROMVOLREAD:      return -EINVAL; /* not implemented */
+
+       case CDROMREADRAW:
+                       return cdromread(arg, BLOCKSIZE_RAW, COMREADRAW);
+       case CDROMREADCOOKED:
+                       return cdromread(arg, BLOCKSIZE, COMREAD);
+       case CDROMSEEK:         return cdromseek(arg);
+       case CDROMPLAYBLK:      return -EINVAL; /* not implemented */
+       default:                return -EINVAL;
+       }
        return 0;
 }
 
-static int optPresent = 0;
-static int opt_open_count = 0;
+
+static int open_count = 0;
 
 /* Open device special file; check that a disk is in. */
-static int opt_open(struct inode *ip, struct file *fp) {
-#ifdef DEBUG_VFS
-       printk("optcd: starting opt_open\n");
-#endif
-       if (!optPresent)
-               return -ENXIO;          /* no hardware */
-       if (!opt_open_count && opt_state == OPT_S_IDLE) {
-               int st;
+static int opt_open(struct inode *ip, struct file *fp)
+{
+       DEBUG((DEBUG_VFS, "starting opt_open"));
+
+       if (!open_count++ && state == S_IDLE) {
+               int status;
+
                opt_invalidate_buffers();
-               if ((st = optGetStatus()) < 0)
+               status = drive_status();
+               if (status < 0) {
+                       DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
                        return -EIO;
-               if (st & ST_DOOR_OPEN) {
-                       optCmd(COMCLOSE);                       /* close door */
-                       if ((st = optGetStatus()) < 0)          /* try again */
+               }
+               DEBUG((DEBUG_VFS, "status: %02x", status));
+               if (status & ST_DOOR_OPEN) {
+                       status = exec_cmd(COMCLOSE);    /* close door */
+                       if (status < 0) {
+                               DEBUG((DEBUG_VFS,
+                                       "exec_cmd COMCLOSE: %02x", -status));
+                       }
+                       status = drive_status();        /* try again */
+                       if (status < 0) {
+                               DEBUG((DEBUG_VFS,
+                                       "drive_status: %02x", -status));
                                return -EIO;
+                       }
+                       DEBUG((DEBUG_VFS, "status: %02x", status));
                }
-               if (st & (ST_DOOR_OPEN|ST_DRVERR)) {
+               if (status & (ST_DOOR_OPEN|ST_DRVERR)) {
                        printk("optcd: no disk or door open\n");
                        return -EIO;
                }
-               if (optUpdateToc() < 0)
+               status = exec_cmd(COMLOCK);             /* Lock door */
+               if (status < 0) {
+                       DEBUG((DEBUG_VFS, "exec_cmd COMLOCK: %02x", -status));
+               }
+               status = update_toc();  /* Read table of contents */
+               if (status < 0) {
+                       DEBUG((DEBUG_VFS, "update_toc: %02x", -status));
                        return -EIO;
+               }
        }
-       opt_open_count++;
        MOD_INC_USE_COUNT;
-       optCmd(COMLOCK);                /* Lock door */
-#ifdef DEBUG_VFS
-       printk("optcd: exiting opt_open\n");
-#endif
+
+       DEBUG((DEBUG_VFS, "exiting opt_open"));
+
        return 0;
 }
 
+
 /* Release device special file; flush all blocks from the buffer cache */
-static void opt_release(struct inode *ip, struct file *fp) {
-#ifdef DEBUG_VFS
-       printk("optcd: executing opt_release\n");
-       printk("inode: %p, inode -> i_rdev: 0x%x, file: %p\n",
-               ip, ip -> i_rdev, fp);
-#endif
-       if (!--opt_open_count) {
+static void opt_release(struct inode *ip, struct file *fp)
+{
+       int status;
+
+       DEBUG((DEBUG_VFS, "executing opt_release"));
+       DEBUG((DEBUG_VFS, "inode: %p, inode -> i_rdev: 0x%x, file: %p\n",
+               ip, ip -> i_rdev, fp));
+
+       if (!--open_count) {
                opt_invalidate_buffers();
                sync_dev(ip -> i_rdev);
                invalidate_buffers(ip -> i_rdev);
+               status = exec_cmd(COMUNLOCK);   /* Unlock door */
+               if (status < 0) {
+                       DEBUG((DEBUG_VFS, "exec_cmd COMUNLOCK: %02x", -status));
+               }
+               if (auto_eject) {
+                       status = exec_cmd(COMOPEN);
+                       DEBUG((DEBUG_VFS, "exec_cmd COMOPEN: %02x", -status));
+               }
                CLEAR_TIMER;
-               optCmd(COMUNLOCK);      /* Unlock door */
        }
        MOD_DEC_USE_COUNT;
 }
+\f
+/* Driver initialisation */
 
 
-/* Initialisation */
-
-static int version_ok(void) {
+/* Returns 1 if a drive is detected with a version string
+   starting with "DOLPHIN". Otherwise 0. */
+static int version_ok(void)
+{
        char devname[100];
-       int count, i, ch;
+       int count, i, ch, status;
 
-       if (optCmd(COMVERSION) < 0)
+       status = exec_cmd(COMVERSION);
+       if (status < 0) {
+               DEBUG((DEBUG_VFS, "exec_cmd COMVERSION: %02x", -status));
                return 0;
-       if ((count = optGetData()) < 0)
+       }
+       if ((count = get_data(1)) < 0) {
+               DEBUG((DEBUG_VFS, "get_data(1): %02x", -count));
                return 0;
+       }
        for (i = 0, ch = -1; count > 0; count--) {
-               if ((ch = optGetData()) < 0)
+               if ((ch = get_data(1)) < 0) {
+                       DEBUG((DEBUG_VFS, "get_data(1): %02x", -ch));
                        break;
+               }
                if (i < 99)
                        devname[i++] = ch;
        }
        devname[i] = '\0';
        if (ch < 0)
                return 0;
+
        printk("optcd: Device %s detected\n", devname);
        return ((devname[0] == 'D')
             && (devname[1] == 'O')
@@ -1386,17 +1960,57 @@ static struct file_operations opt_fops = {
 };
 
 
+/* Flag indicates if ISP16 detection and initialisation should be skipped */
+#define skip_isp16_init        noisp16         /* Needed for the modutils. */
+static int skip_isp16_init = 0;
+
 /* Get kernel parameter when used as a kernel driver */
-void optcd_setup(char *str, int *ints) {
+void optcd_setup(char *str, int *ints)
+{
        if (ints[0] > 0)
                optcd_port = ints[1];
+       if (!strcmp(str ,"noisp16"))
+               skip_isp16_init = 1;
+}
+
+
+#ifdef PROBE_ISP16
+/* If ISP16 I/O ports not already reserved, probe for an ISP16 interface card,
+   and enable SONY mode with no interrupts and no DMA.
+   (As far as I know, all Optics 8000 AT drives come with a SONY interface.
+   Interrupts and DMA are not supported).
+   Returns false only if ISP16 detected but couldn't be initialised. */
+static int probe_isp16(void)
+{
+       if (skip_isp16_init)
+               return 1;
+
+       if (check_region(ISP16_DRIVE_SET_PORT, 5))
+               return 1;
+
+       if (isp16_detect() < 0 ) {
+               printk( "No ISP16 cdrom interface found.\n" );
+               return 1;
+       }
+
+       isp16_sound_config();   /* Enable playing through speakers */
+
+       printk( "ISP16 cdrom interface detected.\n");
+       if (isp16_cdi_config(optcd_port, ISP16_SONY, 0, 0) < 0) {
+               printk( "ISP16 configure error.\n" );
+               return 0;
+       }
+       return 1;
 }
+#endif PROBE_ISP16
 
-/*
- * Test for presence of drive and initialize it. Called at boot time.
- */
 
-int optcd_init(void) {
+/* Test for presence of drive and initialize it. Called at boot time
+   or during module initialisation. */
+int optcd_init(void)
+{
+       int status;
+
        if (optcd_port <= 0) {
                printk("optcd: no Optics Storage CDROM Initialization\n");
                return -EIO;
@@ -1407,29 +2021,12 @@ int optcd_init(void) {
                return -EIO;
        }
 
-       if (!check_region(ISP16_DRIVE_SET_PORT, 5)) {
-       /* If someone else has'nt already reserved these ports,
-          probe for an ISP16 interface card, and enable SONY mode
-          with no interrupts and no DMA. (As far as I know, all optics
-          drives come with a SONY interface.) */
-  if ( (isp16_type=isp16_detect()) < 0 )
-    printk( "No ISP16 cdrom interface found.\n" );
-  else {
-    u_char expected_drive;
-
-    printk( "ISP16 cdrom interface (%s optional IDE) detected.\n",
-      (isp16_type==2)?"with":"without" );
-
-    expected_drive = (isp16_type?ISP16_SANYO1:ISP16_SANYO0);
-
-    if ( isp16_config( optcd_port, ISP16_SONY, 0, 0 ) < 0 ) {
-      printk( "ISP16 cdrom interface has not been properly configured.\n" );
-      return -EIO;
-    }
-  }
-       }
+#ifdef PROBE_ISP16
+       if (!probe_isp16())
+               return -EIO;
+#endif
 
-       if (!optResetDrive()) {
+       if (!reset_drive()) {
                printk("optcd: drive at 0x%x not ready\n", optcd_port);
                return -EIO;
        }
@@ -1437,8 +2034,10 @@ int optcd_init(void) {
                printk("optcd: unknown drive detected; aborting\n");
                return -EIO;
        }
-       if (optCmd(COMINITDOUBLE) < 0) {
+       status = exec_cmd(COMINITDOUBLE);
+       if (status < 0) {
                printk("optcd: cannot init double speed mode\n");
+               DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status));
                return -EIO;
        }
        if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0)
@@ -1446,22 +2045,26 @@ int optcd_init(void) {
                printk("optcd: unable to get major %d\n", MAJOR_NR);
                return -EIO;
        }
+
        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
        read_ahead[MAJOR_NR] = 4;
        request_region(optcd_port, 4, "optcd");
-       optPresent = 1;
-       printk("optcd: 8000 AT CDROM at 0x%x\n", optcd_port);
+
+       printk("optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
        return 0;
 }
 
+
 #ifdef MODULE
 int init_module(void)
 {
        return optcd_init();
 }
 
-void cleanup_module(void) {
-       if ((unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL)) {
+
+void cleanup_module(void)
+{
+       if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
                printk("optcd: what's that: can't unregister\n");
                return;
        }
@@ -1469,191 +2072,3 @@ void cleanup_module(void) {
        printk("optcd: module released.\n");
 }
 #endif MODULE
-
-
-/*
- * -- ISP16 detection and configuration
- *
- *    Copyright (c) 1995, Eric van der Maarel <maarel@marin.nl>
- *
- *    Version 0.5
- *
- *    Detect cdrom interface on ISP16 soundcard.
- *    Configure cdrom interface.
- *
- *    Algorithm for the card with no IDE support option taken
- *    from the CDSETUP.SYS driver for MSDOS,
- *    by OPTi Computers, version 2.03.
- *    Algorithm for the IDE supporting ISP16 as communicated
- *    to me by Vadim Model and Leo Spiekman.
- *
- *    Use, modifification or redistribution of this software is
- *    allowed under the terms of the GPL.
- *
- */
-
-
-#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
-#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
-
-static short
-isp16_detect(void)
-{
-
-  if ( !( isp16_with_ide__detect() < 0 ) )
-    return(2);
-  else
-    return( isp16_no_ide__detect() );
-}
-
-static short
-isp16_no_ide__detect(void)
-{
-  u_char ctrl;
-  u_char enable_cdrom;
-  u_char io;
-  short i = -1;
-
-  isp16_ctrl = ISP16_NO_IDE__CTRL;
-  isp16_enable_cdrom_port = ISP16_NO_IDE__ENABLE_CDROM_PORT;
-
-  /* read' and write' are a special read and write, respectively */
-
-  /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */
-  ctrl = ISP16_IN( ISP16_CTRL_PORT ) & 0xFC;
-  ISP16_OUT( ISP16_CTRL_PORT, ctrl );
-
-  /* read' 3,4 and 5-bit from the cdrom enable port */
-  enable_cdrom = ISP16_IN( ISP16_NO_IDE__ENABLE_CDROM_PORT ) & 0x38;
-
-  if ( !(enable_cdrom & 0x20) ) {  /* 5-bit not set */
-    /* read' last 2 bits of ISP16_IO_SET_PORT */
-    io = ISP16_IN( ISP16_IO_SET_PORT ) & 0x03;
-    if ( ((io&0x01)<<1) == (io&0x02) ) {  /* bits are the same */
-      if ( io == 0 ) {  /* ...the same and 0 */
-        i = 0;
-        enable_cdrom |= 0x20;
-      }
-      else {  /* ...the same and 1 */  /* my card, first time 'round */
-        i = 1;
-        enable_cdrom |= 0x28;
-      }
-      ISP16_OUT( ISP16_NO_IDE__ENABLE_CDROM_PORT, enable_cdrom );
-    }
-    else {  /* bits are not the same */
-      ISP16_OUT( ISP16_CTRL_PORT, ctrl );
-      return(i); /* -> not detected: possibly incorrect conclusion */
-    }
-  }
-  else if ( enable_cdrom == 0x20 )
-    i = 0;
-  else if ( enable_cdrom == 0x28 )  /* my card, already initialised */
-    i = 1;
-
-  ISP16_OUT( ISP16_CTRL_PORT, ctrl );
-
-  return(i);
-}
-
-static short
-isp16_with_ide__detect(void)
-{
-  u_char ctrl;
-  u_char tmp;
-
-  isp16_ctrl = ISP16_IDE__CTRL;
-  isp16_enable_cdrom_port = ISP16_IDE__ENABLE_CDROM_PORT;
-
-  /* read' and write' are a special read and write, respectively */
-
-  /* read' ISP16_CTRL_PORT and save */
-  ctrl = ISP16_IN( ISP16_CTRL_PORT );
-
-  /* write' zero to the ctrl port and get response */
-  ISP16_OUT( ISP16_CTRL_PORT, 0 );
-  tmp = ISP16_IN( ISP16_CTRL_PORT );
-
-  if ( tmp != 2 )  /* isp16 with ide option not detected */
-    return(-1);
-
-  /* restore ctrl port value */
-  ISP16_OUT( ISP16_CTRL_PORT, ctrl );
-  
-  return(2);
-}
-
-static short
-isp16_config( int base, u_char drive_type, int irq, int dma )
-{
-  u_char base_code;
-  u_char irq_code;
-  u_char dma_code;
-  u_char i;
-
-  if ( (drive_type == ISP16_MITSUMI) && (dma != 0) )
-    printk( "Mitsumi cdrom drive has no dma support.\n" );
-
-  switch (base) {
-  case 0x340: base_code = ISP16_BASE_340; break;
-  case 0x330: base_code = ISP16_BASE_330; break;
-  case 0x360: base_code = ISP16_BASE_360; break;
-  case 0x320: base_code = ISP16_BASE_320; break;
-  default:
-    printk( "Base address 0x%03X not supported by cdrom interface on ISP16.\n", base );
-    return(-1);
-  }
-  switch (irq) {
-  case 0: irq_code = ISP16_IRQ_X; break; /* disable irq */
-  case 5: irq_code = ISP16_IRQ_5;
-          printk( "Irq 5 shouldn't be used by cdrom interface on ISP16,"
-            " due to possible conflicts with the soundcard.\n");
-          break;
-  case 7: irq_code = ISP16_IRQ_7;
-          printk( "Irq 7 shouldn't be used by cdrom interface on ISP16,"
-            " due to possible conflicts with the soundcard.\n");
-          break;
-  case 3: irq_code = ISP16_IRQ_3; break;
-  case 9: irq_code = ISP16_IRQ_9; break;
-  case 10: irq_code = ISP16_IRQ_10; break;
-  case 11: irq_code = ISP16_IRQ_11; break;
-  default:
-    printk( "Irq %d not supported by cdrom interface on ISP16.\n", irq );
-    return(-1);
-  }
-  switch (dma) {
-  case 0: dma_code = ISP16_DMA_X; break;  /* disable dma */
-  case 1: printk( "Dma 1 cannot be used by cdrom interface on ISP16,"
-            " due to conflict with the soundcard.\n");
-          return(-1); break;
-  case 3: dma_code = ISP16_DMA_3; break;
-  case 5: dma_code = ISP16_DMA_5; break;
-  case 6: dma_code = ISP16_DMA_6; break;
-  case 7: dma_code = ISP16_DMA_7; break;
-  default:
-    printk( "Dma %d not supported by cdrom interface on ISP16.\n", dma );
-    return(-1);
-  }
-
-  if ( drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
-    drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
-    drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
-    drive_type != ISP16_DRIVE_X ) {
-    printk( "Drive type (code 0x%02X) not supported by cdrom"
-     " interface on ISP16.\n", drive_type );
-    return(-1);
-  }
-
-  /* set type of interface */
-  i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK;  /* clear some bits */
-  ISP16_OUT( ISP16_DRIVE_SET_PORT, i|drive_type );
-
-  /* enable cdrom on interface with ide support */
-  if ( isp16_type > 1 )
-    ISP16_OUT( isp16_enable_cdrom_port, ISP16_ENABLE_CDROM );
-
-  /* set base address, irq and dma */
-  i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK;  /* keep some bits */
-  ISP16_OUT( ISP16_IO_SET_PORT, i|base_code|irq_code|dma_code );
-
-  return(0);
-}
diff --git a/drivers/cdrom/optcd_isp16.h b/drivers/cdrom/optcd_isp16.h
new file mode 100644 (file)
index 0000000..f6bb76d
--- /dev/null
@@ -0,0 +1,337 @@
+/* linux/drivers/cdrom/optcd_isp16.h - ISP16 CDROM interface configuration
+   $Id: optcd_isp16.h,v 1.3 1996/01/15 18:43:11 root Exp root $
+
+   Extracts from linux/drivers/cdrom/sjcd.c
+   For copyrights see linux/drivers/cdrom/optcd.c
+*/
+
+
+/* Some (Media)Magic */
+/* define types of drive the interface on an ISP16 card may be looking at */
+#define ISP16_DRIVE_X 0x00
+#define ISP16_SONY  0x02
+#define ISP16_PANASONIC0 0x02
+#define ISP16_SANYO0 0x02
+#define ISP16_MITSUMI  0x04
+#define ISP16_PANASONIC1 0x06
+#define ISP16_SANYO1 0x06
+#define ISP16_DRIVE_NOT_USED 0x08  /* not used */
+#define ISP16_DRIVE_SET_MASK 0xF1  /* don't change 0-bit or 4-7-bits*/
+/* ...for port */
+#define ISP16_DRIVE_SET_PORT 0xF8D
+/* set io parameters */
+#define ISP16_BASE_340  0x00
+#define ISP16_BASE_330  0x40
+#define ISP16_BASE_360  0x80
+#define ISP16_BASE_320  0xC0
+#define ISP16_IRQ_X  0x00
+#define ISP16_IRQ_5  0x04  /* shouldn't be used due to soundcard conflicts */
+#define ISP16_IRQ_7  0x08  /* shouldn't be used due to soundcard conflicts */
+#define ISP16_IRQ_3  0x0C
+#define ISP16_IRQ_9  0x10
+#define ISP16_IRQ_10  0x14
+#define ISP16_IRQ_11  0x18
+#define ISP16_DMA_X  0x03
+#define ISP16_DMA_3  0x00
+#define ISP16_DMA_5  0x00
+#define ISP16_DMA_6  0x01
+#define ISP16_DMA_7  0x02
+#define ISP16_IO_SET_MASK  0x20  /* don't change 5-bit */
+/* ...for port */
+#define ISP16_IO_SET_PORT  0xF8E
+/* enable the card */
+#define ISP16_C928__ENABLE_PORT  0xF90  /* ISP16 with OPTi 82C928 chip */
+#define ISP16_C929__ENABLE_PORT  0xF91  /* ISP16 with OPTi 82C929 chip */
+#define ISP16_ENABLE_CDROM  0x80  /* seven bit */
+
+/* the magic stuff */
+#define ISP16_CTRL_PORT  0xF8F
+#define ISP16_C928__CTRL  0xE2  /* ISP16 with OPTi 82C928 chip */
+#define ISP16_C929__CTRL  0xE3  /* ISP16 with OPTi 82C929 chip */
+
+static short isp16_detect(void);
+static short isp16_c928__detect(void);
+static short isp16_c929__detect(void);
+static short isp16_cdi_config( int base, u_char drive_type, int irq, int dma );
+static void isp16_sound_config( void );
+static short isp16_type; /* dependent on type of interface card */
+static u_char isp16_ctrl;
+static u_short isp16_enable_port;
+
+/*static int sjcd_present = 0;*/
+static u_char special_mask = 0;
+
+static unsigned char defaults[ 16 ] = {
+  0xA8, 0xA8, 0x18, 0x18, 0x18, 0x18, 0x8E, 0x8E,
+  0x03, 0x00, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00
+};
+/* ------------- */
+/*
+ * -- ISP16 detection and configuration
+ *
+ *    Copyright (c) 1995, Eric van der Maarel <maarel@marin.nl>
+ *
+ *    Version 0.5
+ *
+ *    Detect cdrom interface on ISP16 soundcard.
+ *    Configure cdrom interface.
+ *    Configure sound interface.
+ *
+ *    Algorithm for the card with OPTi 82C928 taken
+ *    from the CDSETUP.SYS driver for MSDOS,
+ *    by OPTi Computers, version 2.03.
+ *    Algorithm for the card with OPTi 82C929 as communicated
+ *    to me by Vadim Model and Leo Spiekman.
+ *
+ *    Use, modifification or redistribution of this software is
+ *    allowed under the terms of the GPL.
+ *
+ */
+
+
+#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
+#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
+
+static short
+isp16_detect(void)
+{
+
+  if ( !( isp16_c929__detect() < 0 ) )
+    return(2);
+  else
+    return( isp16_c928__detect() );
+}
+
+static short
+isp16_c928__detect(void)
+{
+  u_char ctrl;
+  u_char enable_cdrom;
+  u_char io;
+  short i = -1;
+
+  isp16_ctrl = ISP16_C928__CTRL;
+  isp16_enable_port = ISP16_C928__ENABLE_PORT;
+
+  /* read' and write' are a special read and write, respectively */
+
+  /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */
+  ctrl = ISP16_IN( ISP16_CTRL_PORT ) & 0xFC;
+  ISP16_OUT( ISP16_CTRL_PORT, ctrl );
+
+  /* read' 3,4 and 5-bit from the cdrom enable port */
+  enable_cdrom = ISP16_IN( ISP16_C928__ENABLE_PORT ) & 0x38;
+
+  if ( !(enable_cdrom & 0x20) ) {  /* 5-bit not set */
+    /* read' last 2 bits of ISP16_IO_SET_PORT */
+    io = ISP16_IN( ISP16_IO_SET_PORT ) & 0x03;
+    if ( ((io&0x01)<<1) == (io&0x02) ) {  /* bits are the same */
+      if ( io == 0 ) {  /* ...the same and 0 */
+        i = 0;
+        enable_cdrom |= 0x20;
+      }
+      else {  /* ...the same and 1 */  /* my card, first time 'round */
+        i = 1;
+        enable_cdrom |= 0x28;
+      }
+      ISP16_OUT( ISP16_C928__ENABLE_PORT, enable_cdrom );
+    }
+    else {  /* bits are not the same */
+      ISP16_OUT( ISP16_CTRL_PORT, ctrl );
+      return(i); /* -> not detected: possibly incorrect conclusion */
+    }
+  }
+  else if ( enable_cdrom == 0x20 )
+    i = 0;
+  else if ( enable_cdrom == 0x28 )  /* my card, already initialised */
+    i = 1;
+
+  ISP16_OUT( ISP16_CTRL_PORT, ctrl );
+
+  return(i);
+}
+
+static short
+isp16_c929__detect(void)
+{
+  u_char ctrl;
+  u_char tmp;
+
+  isp16_ctrl = ISP16_C929__CTRL;
+  isp16_enable_port = ISP16_C929__ENABLE_PORT;
+
+  /* read' and write' are a special read and write, respectively */
+
+  /* read' ISP16_CTRL_PORT and save */
+  ctrl = ISP16_IN( ISP16_CTRL_PORT );
+
+  /* write' zero to the ctrl port and get response */
+  ISP16_OUT( ISP16_CTRL_PORT, 0 );
+  tmp = ISP16_IN( ISP16_CTRL_PORT );
+
+  if ( tmp != 2 )  /* isp16 with 82C929 not detected */
+    return(-1);
+
+  /* restore ctrl port value */
+  ISP16_OUT( ISP16_CTRL_PORT, ctrl );
+  
+  return(2);
+}
+
+static short
+isp16_cdi_config( int base, u_char drive_type, int irq, int dma )
+{
+  u_char base_code;
+  u_char irq_code;
+  u_char dma_code;
+  u_char i;
+
+  if ( (drive_type == ISP16_MITSUMI) && (dma != 0) )
+    printk( "Mitsumi cdrom drive has no dma support.\n" );
+
+  switch (base) {
+  case 0x340: base_code = ISP16_BASE_340; break;
+  case 0x330: base_code = ISP16_BASE_330; break;
+  case 0x360: base_code = ISP16_BASE_360; break;
+  case 0x320: base_code = ISP16_BASE_320; break;
+  default:
+    printk( "Base address 0x%03X not supported by cdrom interface on ISP16.\n", base );
+    return(-1);
+  }
+  switch (irq) {
+  case 0: irq_code = ISP16_IRQ_X; break; /* disable irq */
+  case 5: irq_code = ISP16_IRQ_5;
+          printk( "Irq 5 shouldn't be used by cdrom interface on ISP16,"
+            " due to possible conflicts with the soundcard.\n");
+          break;
+  case 7: irq_code = ISP16_IRQ_7;
+          printk( "Irq 7 shouldn't be used by cdrom interface on ISP16,"
+            " due to possible conflicts with the soundcard.\n");
+          break;
+  case 3: irq_code = ISP16_IRQ_3; break;
+  case 9: irq_code = ISP16_IRQ_9; break;
+  case 10: irq_code = ISP16_IRQ_10; break;
+  case 11: irq_code = ISP16_IRQ_11; break;
+  default:
+    printk( "Irq %d not supported by cdrom interface on ISP16.\n", irq );
+    return(-1);
+  }
+  switch (dma) {
+  case 0: dma_code = ISP16_DMA_X; break;  /* disable dma */
+  case 1: printk( "Dma 1 cannot be used by cdrom interface on ISP16,"
+            " due to conflict with the soundcard.\n");
+          return(-1); break;
+  case 3: dma_code = ISP16_DMA_3; break;
+  case 5: dma_code = ISP16_DMA_5; break;
+  case 6: dma_code = ISP16_DMA_6; break;
+  case 7: dma_code = ISP16_DMA_7; break;
+  default:
+    printk( "Dma %d not supported by cdrom interface on ISP16.\n", dma );
+    return(-1);
+  }
+
+  if ( drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
+    drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
+    drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
+    drive_type != ISP16_DRIVE_X ) {
+    printk( "Drive type (code 0x%02X) not supported by cdrom"
+     " interface on ISP16.\n", drive_type );
+    return(-1);
+  }
+
+  /* set type of interface */
+  i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK;  /* clear some bits */
+  ISP16_OUT( ISP16_DRIVE_SET_PORT, i|drive_type );
+
+  /* enable cdrom on interface with 82C929 chip */
+  if ( isp16_type > 1 )
+    ISP16_OUT( isp16_enable_port, ISP16_ENABLE_CDROM );
+
+  /* set base address, irq and dma */
+  i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK;  /* keep some bits */
+  ISP16_OUT( ISP16_IO_SET_PORT, i|base_code|irq_code|dma_code );
+
+  return(0);
+}
+
+static void isp16_sound_config( void )
+{
+  int i;
+  u_char saved;
+
+  saved = ISP16_IN( 0xF8D ) & 0x8F;
+    
+  ISP16_OUT( 0xF8D, 0x40 );
+
+  /*
+   * Now we should wait for a while...
+   */
+  for( i = 16*1024; i--; );
+  
+  ISP16_OUT( 0xF8D, saved );
+
+  ISP16_OUT( 0xF91, 0x1B );
+
+  for( i = 5*64*1024; i != 0; i-- )
+    if( !( inb( 0x534 ) & 0x80 ) ) break;
+
+  if( i > 0 ) {
+    saved = ( inb( 0x534 ) & 0xE0 ) | 0x0A;
+    outb( saved, 0x534 );
+
+    special_mask = ( inb( 0x535 ) >> 4 ) & 0x08;
+
+    saved = ( inb( 0x534 ) & 0xE0 ) | 0x0C;
+    outb( saved, 0x534 );
+
+    switch( inb( 0x535 ) ) {
+      case 0x09:
+      case 0x0A:
+        special_mask |= 0x05;
+        break;
+      case 0x8A:
+        special_mask = 0x0F;
+        break;
+      default:
+        i = 0;
+    }
+  }
+  if ( i == 0 ) {
+    printk( "Strange MediaMagic, but\n" );
+  }
+  else {
+    printk( "Conf:" );
+    saved = inb( 0x534 ) & 0xE0;
+    for( i = 0; i < 16; i++ ) {
+      outb( 0x20 | ( u_char )i, 0x534 );
+      outb( defaults[i], 0x535 );
+    }
+    for ( i = 0; i < 16; i++ ) {
+      outb( 0x20 | ( u_char )i, 0x534 );
+      saved = inb( 0x535 );
+      printk( " %02X", saved );
+    }
+    printk( "\n" );
+  }
+
+  ISP16_OUT( 0xF91, 0xA0 | special_mask );
+
+  /*
+   * The following have no explaination yet.
+   */
+  ISP16_OUT( 0xF90, 0xA2 );
+  ISP16_OUT( 0xF92, 0x03 );
+
+  /*
+   * Turn general sound on and set total volume.
+   */
+  ISP16_OUT( 0xF93, 0x0A );
+
+/*
+  outb( 0x04, 0x224 );
+  saved = inb( 0x225 );
+  outb( 0x04, 0x224 );
+  outb( saved, 0x225 );
+*/
+
+}
index 8a37d4a49ecf9114155a20fb5225bc507dee2dbb..b19439cd1c823f36cdaf153d2783b047515c1eaa 100644 (file)
@@ -48,3 +48,4 @@ if [ "$CONFIG_WATCHDOG" = "y" ]; then
      bool '   Software Watchdog' CONFIG_SOFT_WATCHDOG
   fi
 fi
+endmenu
index 33fa7f454d75955fb74d00e5ace6a5a8243469ad..1f079551d15213da5366c1afbb7076850cd011f5 100644 (file)
@@ -95,6 +95,7 @@ endif
 ifdef CONFIG_SOFT_WATCHDOG
 L_OBJS += softdog.o
 M = y
+# This is not modularized, so if configured then "mouse.c" will be resident
 endif
 
 ifdef CONFIG_QIC02_TAPE
@@ -106,16 +107,20 @@ LX_OBJS += apm_bios.o
 endif
 
 ifdef M
-L_OBJS += mouse.o
+LX_OBJS += mouse.o
 else
   ifdef MM
-  M_OBJS += mouse.o
+  MX_OBJS += mouse.o
   endif
 endif
-  
-ifdef CONFIG_SCC
+
+ifeq ($(CONFIG_SCC),y)
 L_OBJS += scc.o
-endif
+else
+  ifeq ($(CONFIG_SCC),m)
+  M_OBJS += scc.o
+  endif
+endif  
 
 ifdef CONFIG_TGA_CONSOLE
 L_OBJS += tga.o
index 6196f170efc9861295484b26cabef99585e30083..5e24d1bc3c602ce954caaba2aac99ae5cf76d325 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/* -*- linux-c -*-
  * APM BIOS driver for Linux
  * Copyright 1994, 1995 Stephen Rothwell (Stephen.Rothwell@pd.necisa.oz.au)
  *
  *
  * October 1995, Rik Faith (faith@cs.unc.edu):
  *    Minor enhancements and updates (to the patch set) for 1.3.x
+ *    Documentation
+ * January 1996, Rik Faith (faith@cs.unc.edu):
+ *    Make /proc/apm easy to format (bump driver version)
+ *
  *
  * Reference:
  *
@@ -24,9 +28,9 @@
  *   Intel Order Number 241704-001.  Microsoft Part Number 781-110-X01.
  *
  * [This document is available free from Intel by calling 800.628.8686 (fax
- * 916.356.6100) or 800.548.4725.  It is also available from Microsoft by
- * calling 206.882.8080; and is ftpable from
- * ftp://ftp.intel.com/pub/IAL/software_specs/apmv11.doc]
+ * 916.356.6100) or 800.548.4725; or via anonymous ftp from
+ * ftp://ftp.intel.com/pub/IAL/software_specs/apmv11.doc.  It is also
+ * available from Microsoft by calling 206.882.8080.]
  *
  */
 
@@ -288,7 +292,7 @@ static struct apm_bios_struct *     user_list = NULL;
 
 static struct timer_list       apm_timer;
 
-static char                    driver_version[] = "0.6b";
+static char                    driver_version[] = "0.7";/* no spaces */
 
 #ifdef APM_DEBUG
 static char *  apm_event_name[] = {
@@ -882,69 +886,91 @@ static int do_open(struct inode * inode, struct file * filp)
 int apm_proc(char *buf)
 {
        char *          p;
-       char *          power_stat;
-       char *          bat_stat;
        unsigned short  bx;
        unsigned short  cx;
        unsigned short  dx;
        unsigned short  error;
+       unsigned short  ac_line_status = 0xff;
+       unsigned short  battery_status = 0xff;
+       unsigned short  battery_flag   = 0xff;
+       unsigned short  percentage     = -1;
+       int             time_units     = -1;
+       char            *units         = "?";
 
        if (apm_bios_info.version == 0)
                return 0;
        p = buf;
-       p += sprintf(p, "BIOS version: %d.%d\nFlags: 0x%02x\n",
-                    (apm_bios_info.version >> 8) & 0xff,
-                    apm_bios_info.version & 0xff,
-                    apm_bios_info.flags);
-       if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) == 0)
-               return p - buf;
-       p += sprintf(p, "Entry %x:%lx cseg16 %x dseg %x",
-                    apm_bios_info.cseg, apm_bios_info.offset,
-                    apm_bios_info.cseg_16, apm_bios_info.dseg);
-       if (apm_bios_info.version > 0x100)
-               p += sprintf(p, " cseg len %x, dseg len %x",
-                            apm_bios_info.cseg_len, apm_bios_info.dseg_len);
-       *p++ = '\n';
-       error = apm_get_power_status(&bx, &cx, &dx);
-       if (error) {
-               strcpy(p, "Power status not available\n");
-               p += strlen(p);
-               return p - buf;
-       }
-       switch ((bx >> 8) & 0xff) {
-       case 0: power_stat = "off line"; break;
-       case 1: power_stat = "on line"; break;
-       case 2: power_stat = "on backup power"; break;
-       default: power_stat = "unknown"; break;
-       }
-       switch (bx & 0xff) {
-       case 0: bat_stat = "high"; break;
-       case 1: bat_stat = "low"; break;
-       case 2: bat_stat = "critical"; break;
-       case 3: bat_stat = "charging"; break;
-       default: bat_stat = "unknown"; break;
-       }
-       p += sprintf(p, "AC: %s\nBattery status: %s\nBattery life: ",
-                    power_stat, bat_stat);
-       if ((cx & 0xff) == 0xff) {
-               strcpy(p, "unknown");
-               p += strlen(p);
-       } else
-               p += sprintf(p, "%d%%", cx & 0xff);
-       *p++ = '\n';
-       if (apm_bios_info.version > 0x100) {
-               p += sprintf(p, "Battery flag: 0x%02x\nBattery life: ",
-                            (cx >> 8) & 0xff);
-               if (dx == 0xffff) {
-                       strcpy(p, "unknown");
-                       p += strlen(p);
+
+       if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) != 0) {
+               if (!(error = apm_get_power_status(&bx, &cx, &dx))) {
+                       ac_line_status = (bx >> 8) & 0xff;
+                       battery_status = bx & 0xff;
+                       if ((cx & 0xff) != 0xff)
+                               percentage = cx & 0xff;
+       
+                       if (apm_bios_info.version > 0x100) {
+                               battery_flag = (cx >> 8) & 0xff;
+                               if (dx != 0xffff) {
+                                       if ((dx & 0x8000) == 0x8000) {
+                                               units = "min";
+                                               time_units = dx & 0x7ffe;
+                                       } else {
+                                               units = "sec";
+                                               time_units = dx & 0x7fff;
+                                       }
+                               }
+                       }
                }
-               else
-                       p += sprintf(p, "%d %s", dx & 0x7fff,
-                                    ((dx & 0x8000) == 0)
-                                    ? "seconds" : "minutes");
-               *p++ = '\n';
        }
+       /* Arguments, with symbols from linux/apm_bios.h.  Information is
+          from the Get Power Status (0x0a) call unless otherwise noted.
+
+          0) Linux driver version (this will change if format changes)
+          1) APM BIOS Version.  Usually 1.0 or 1.1.
+          2) APM flags from APM Installation Check (0x00):
+             bit 0: APM_16_BIT_SUPPORT
+             bit 1: APM_32_BIT_SUPPORT
+             bit 2: APM_IDLE_SLOWS_CLOCK
+             bit 3: APM_BIOS_DISABLED
+             bit 4: APM_BIOS_DISENGAGED
+          3) AC line status
+             0x00: Off-line
+             0x01: On-line
+             0x02: On backup power (APM BIOS 1.1 only)
+             0xff: Unknown
+          4) Battery status
+             0x00: High
+             0x01: Low
+             0x02: Critical
+             0x03: Charging
+             0xff: Unknown
+          5) Battery flag
+             bit 0: High
+             bit 1: Low
+             bit 2: Critical
+             bit 3: Charging
+             bit 7: No system battery
+             0xff: Unknown
+          6) Remaining battery life (percentage of charge):
+             0-100: valid
+             -1: Unknown
+          7) Remaining battery life (time units):
+             Number of remaining minutes or seconds
+             -1: Unknown
+          8) min = minutes; sec = seconds */
+           
+       p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+                    driver_version,
+                    (apm_bios_info.version >> 8) & 0xff,
+                    apm_bios_info.version & 0xff,
+                    apm_bios_info.flags,
+                    ac_line_status,
+                    battery_status,
+                    battery_flag,
+                    percentage,
+                    time_units,
+                    units );
+
        return p - buf;
 }
 
@@ -1000,12 +1026,12 @@ static int apm_setup(void)
                set_limit(gdt[APM_DS >> 3], 64 * 1024);
        } else {
                set_limit(gdt[APM_CS >> 3], apm_bios_info.cseg_len);
-               /*
-                * This is not clear from the spec, but at least one
-                * machine needs this to be a 64k segment.
-                */
+               /* This is not clear from the spec, but at least one
+                  machine needs CS_16 to be a 64k segment, and the DEC
+                  Hinote Ultra CT475 (and others?) needs DS to be a 64k
+                  segment. */
                set_limit(gdt[APM_CS_16 >> 3], 64 * 1024);
-               set_limit(gdt[APM_DS >> 3], apm_bios_info.dseg_len);
+               set_limit(gdt[APM_DS >> 3], 64 * 1024);
                apm_bios_info.version = 0x0101;
                error = apm_driver_version(&apm_bios_info.version);
                if (error != 0)
@@ -1047,10 +1073,12 @@ static int apm_setup(void)
                               (cx >> 8) & 0xff);
                        if (dx == 0xffff)
                                printk("unknown\n");
-                       else
-                               printk("%d %s\n", dx & 0x7fff,
-                                      ((dx & 0x8000) == 0)
-                                      ? "seconds" : "minutes");
+                       else {
+                               if ((dx & 0x8000)) 
+                                       printk("%d minutes\n", dx & 0x7ffe );
+                               else
+                                       printk("%d seconds\n", dx & 0x7fff );
+                       }
                }
        }
 
index 330b2732ea6678b84d9447f3feaf0620701e52bb..1279e397a1ab066ddea9aae3d304422b92d11101 100644 (file)
@@ -87,12 +87,6 @@ extern void change_console(unsigned int new_console);
 extern void scrollback(int);
 extern void scrollfront(int);
 
-#ifdef __i386__
-#define fake_keyboard_interrupt() __asm__ __volatile__("int $0x21")
-#else
-#define fake_keyboard_interrupt() do ; while (0)
-#endif
-
 unsigned char kbd_read_mask = 0x01;    /* modified by psaux.c */
 
 /*
@@ -128,6 +122,8 @@ static struct tty_struct * tty = NULL;
 static volatile unsigned char reply_expected = 0;
 static volatile unsigned char acknowledge = 0;
 static volatile unsigned char resend = 0;
+/* used by kbd_bh - set by keyboard_interrupt */
+static volatile unsigned char do_poke_blanked_console = 0;
 
 extern void compute_shiftstate(void);
 
@@ -384,6 +380,7 @@ static void keyboard_interrupt(int irq, struct pt_regs *regs)
                prev_scancode = 0;
                goto end_kbd_intr;
        }
+       do_poke_blanked_console = 1;
        add_keyboard_randomness(scancode);
 
        tty = ttytab[fg_console];
@@ -1178,11 +1175,10 @@ static void kbd_bh(void * unused)
                }
                want_console = -1;
        }
-       poke_blanked_console();
-       cli();
-       if ((inb_p(0x64) & kbd_read_mask) == 0x01)
-               fake_keyboard_interrupt();
-       sti();
+       if (do_poke_blanked_console) { /* do not unblank for a LED change */
+               do_poke_blanked_console = 0;
+               poke_blanked_console();
+       }
 }
 
 int kbd_init(void)
index dacc86aa1ed7516f7cde32304fdd629c26414f69..a9ed83043c67b83dfc5596db632f4e529861f1b9 100644 (file)
@@ -104,6 +104,14 @@ void cleanup_module(void)
 
 #endif
 
+static struct symbol_table mouse_syms = {
+/* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */
+#include <linux/symtab_begin.h>
+       X(mouse_register),
+       X(mouse_deregister),
+#include <linux/symtab_end.h>
+};
+
 int mouse_init(void)
 {
 #ifndef MODULE
@@ -128,5 +136,6 @@ int mouse_init(void)
                 MOUSE_MAJOR);
                return -EIO;
        }
-       return 0;
+
+       return register_symtab(&mouse_syms);
 }
index d43e40cd06d8faa3e257ac07303a52005b4e0a11..f8ba50b12363e47365dc60a4fbe185201b898a29 100644 (file)
@@ -421,6 +421,9 @@ set_get_cmap(unsigned char * arg, int set) {
  * dummy routines for the VESA blanking code, which is VGA only,
  * so we don't have to carry that stuff around for the TGA...
  */
+void vesa_powerdown(void)
+{
+}
 void vesa_blank(void)
 {
 }
index ce4b8747fac47f8846d935b85e3e19c9ca21d799..bf18465a14f7aa15e37649c2fad06f2f906bae6f 100644 (file)
  * Also, be careful to avoid IO conflicts with other devices!
  */
 
-#include <linux/autoconf.h>
-
 
 /*
 #define TDEBUG
index dcf53d7d899b71d229ab4a63a28b21f6358e217b..cd26ac67c90848c68485cdc5b0bc51e8308026e5 100644 (file)
 #include "vt_kern.h"
 #include "selection.h"
 
+#ifdef CONFIG_KERNELD
+#include <linux/kerneld.h>
+#endif
+
 #define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
 #define TTY_DEV MKDEV(TTYAUX_MAJOR,0)
 
@@ -211,8 +215,17 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
        int     retval = 0;
        struct  tty_ldisc o_ldisc;
 
-       if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS) ||
-           !(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED))
+       if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS))
+               return -EINVAL;
+#ifdef CONFIG_KERNELD
+       /* Eduardo Blanco <ejbs@cs.cs.com.uy> */
+       if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) {
+               char modname [20];
+               sprintf(modname, "tty-ldisc-%d", ldisc);
+               request_module (modname);
+       }
+#endif
+       if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED))
                return -EINVAL;
 
        if (tty->ldisc.num == ldisc)
index 9796609281437771ad047d64ec9c682021e6a267..002021ed3cb24f2357888744b2d1929515d9cdaa 100644 (file)
@@ -18,6 +18,8 @@
  *     Release 0.04.
  *
  */
+
+#include <linux/config.h>
  
 #define WATCHDOG_MINOR         130     /* Watchdog timer     */
 #define TEMP_MINOR             131     /* Temperature Sensor */
index eb70644fd944de297d7faf93d14ed8ec3e0debbd..9cbfa39d7cf081240fe090724c4c62b216c48617 100644 (file)
@@ -10,7 +10,7 @@ tristate 'PPP (point-to-point) support' CONFIG_PPP
 if [ ! "$CONFIG_PPP" = "n" ]; then
   comment 'CCP compressors for PPP are only built as modules.'
 fi
-bool 'Z8530 SCC kiss emulation driver for AX.25' CONFIG_SCC
+tristate 'Z8530 SCC kiss emulation driver for AX.25' CONFIG_SCC
 tristate 'PLIP (parallel port) support' CONFIG_PLIP
 tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
 bool 'Do you want to be offered ALPHA test drivers' CONFIG_NET_ALPHA
index bf226b783c183bb25caf359c11876e7f98052ed9..bc8da3e895919de6be1f5e335ee04e6f8cdc1549 100644 (file)
@@ -352,10 +352,10 @@ endif
 # If anything built-in uses slhc, then build it into the kernel also.
 # If not, but a module uses it, build as a module.
 ifdef CONFIG_SLHC_BUILTIN
-L_OBJS += slhc.o
+LX_OBJS += slhc.o
 else
   ifdef CONFIG_SLHC_MODULE
-  M_OBJS += slhc.o
+  MX_OBJS += slhc.o
   endif
 endif
 
index 9736b484f8e8f1434599a7dac84c063d37a18366..455022738aeb2f7d098deaf07e0c6e4717199afc 100644 (file)
@@ -113,9 +113,9 @@ address on network B, and machine B is simply acting as a proxy
 for machine A.  Machine A needs it's tunnel address to be on network 
 B so that when packets from machine B are unwrapped, the Linux 
 routing system knows that the address is a local one.  Due to a 
-feature of Linux, any packets recieved locally, bound for another
+feature of Linux, any packets received locally, bound for another
 local address, are simply routed through the loopback interface.
-This means that the tunnel device should never recieve packets.  Even
+This means that the tunnel device should never receive packets.  Even
 on machine B, it is the ethernet interface that is receiving wrapped
 packets, and once they are unwrapped they go back out the ethernet
 interface.  This could cause Linux to generate ICMP redirect messages
index ae22a6a4843dd3a02a6cd73ca5d3ae28a3ab1c1d..4da4efb7cee5192b7d21948556d8b218981b508b 100644 (file)
@@ -22,6 +22,7 @@
                          sanity checks and bad clone support optional.
     Paul Gortmaker     : new reset code, reset card after probe at boot.
     Paul Gortmaker     : multiple card support for module users.
+    Paul Gortmaker     : Support for PCI ne2k clones, similar to lance.c
 
 */
 
@@ -32,10 +33,12 @@ static const char *version =
 
 
 #include <linux/module.h>
-
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/bios32.h>
 #include <asm/system.h>
 #include <asm/io.h>
 
@@ -90,6 +93,9 @@ bad_clone_list[] = {
 #define NESM_START_PG  0x40    /* First page of TX buffer */
 #define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
 
+/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
+static unsigned char pci_irq_line = 0;
+
 int ne_probe(struct device *dev);
 static int ne_probe1(struct device *dev, int ioaddr);
 
@@ -131,16 +137,56 @@ struct netdev_entry netcard_drv =
 {"ne", ne_probe1, NE_IO_EXTENT, netcard_portlist};
 #else
 
+/*  Note that this probe only picks up one card at a time, even for multiple
+    PCI ne2k cards. Use "ether=0,0,eth1" if you have a second PCI ne2k card.
+    This keeps things consistent regardless of the bus type of the card. */
+
 int ne_probe(struct device *dev)
 {
     int i;
     int base_addr = dev ? dev->base_addr : 0;
 
+    /* First check any supplied i/o locations. User knows best. <cough> */
     if (base_addr > 0x1ff)     /* Check a single specified location. */
        return ne_probe1(dev, base_addr);
     else if (base_addr != 0)   /* Don't probe at all. */
        return ENXIO;
 
+    /* Then look for any installed PCI clones */
+#if defined(CONFIG_PCI)
+    if (pcibios_present()) {
+       int pci_index;
+       for (pci_index = 0; pci_index < 8; pci_index++) {
+               unsigned char pci_bus, pci_device_fn;
+               unsigned int pci_ioaddr;
+
+               /* Currently only Realtek are making PCI ne2k clones. */
+               if (pcibios_find_device (PCI_VENDOR_ID_REALTEK,
+                               PCI_DEVICE_ID_REALTEK_8029, pci_index,
+                               &pci_bus, &pci_device_fn) != 0)
+                       break;  /* OK, now try to probe for std. ISA card */
+               pcibios_read_config_byte(pci_bus, pci_device_fn,
+                               PCI_INTERRUPT_LINE, &pci_irq_line);
+               pcibios_read_config_dword(pci_bus, pci_device_fn,
+                               PCI_BASE_ADDRESS_0, &pci_ioaddr);
+               /* Strip the I/O address out of the returned value */
+               pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
+               /* Avoid already found cards from previous ne_probe() calls */
+               if (check_region(pci_ioaddr, NE_IO_EXTENT))
+                       continue;
+               printk("ne.c: PCI BIOS reports ne2000 clone at i/o %#x, irq %d.\n",
+                               pci_ioaddr, pci_irq_line);
+               if (ne_probe1(dev, pci_ioaddr) != 0) {  /* Shouldn't happen. */
+                       printk(KERN_ERR "ne.c: Probe of PCI card at %#x failed.\n", pci_ioaddr);
+                       break;  /* Hrmm, try to probe for ISA card... */
+               }
+               pci_irq_line = 0;
+               return 0;
+       }
+    }
+#endif  /* defined(CONFIG_PCI) */
+
+    /* Last resort. The semi-risky ISA auto-probe. */
     for (i = 0; netcard_portlist[i]; i++) {
        int ioaddr = netcard_portlist[i];
        if (check_region(ioaddr, NE_IO_EXTENT))
@@ -291,6 +337,10 @@ static int ne_probe1(struct device *dev, int ioaddr)
        dev = init_etherdev(0, 0);
     }
 
+    if (pci_irq_line) {
+       dev->irq = pci_irq_line;
+    }
+
     if (dev->irq < 2) {
        autoirq_setup(0);
        outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */
index abd06abd7f36af5a2dcc6812bd8da5b6a29fcef3..7122340c447916fa0cdaeadb75e8a28530b1d59f 100644 (file)
 #define        SEEQCFG2_SLOTSEL        (0x0040)        /* 0= standard IEEE802.3, 1= smaller,faster, non-standard */
 #define SEEQCFG2_NO_PREAM      (0x0080)        /* 1= user supplies Xmit preamble bytes */
 #define SEEQCFG2_ADDR_LEN      (0x0100)        /* 1= 2byte addresses */
-#define SEEQCFG2_REC_CRC       (0x0200)        /* 0= recieved packets will have CRC stripped from them */
+#define SEEQCFG2_REC_CRC       (0x0200)        /* 0= received packets will have CRC stripped from them */
 #define SEEQCFG2_XMIT_NO_CRC   (0x0400)        /* dont xmit CRC with each packet (user supplies it) */
 #define SEEQCFG2_LOOPBACK      (0x0800)
 #define SEEQCFG2_CTRLO         (0x1000)
@@ -133,7 +133,7 @@ struct seeq_pkt_hdr {
                        unused:1,
                        data_follows:1,         /* if not set, process this as a header and pointer only */
                        chain_cont:1,           /* if set, more headers in chain                only cmd bit valid in recv header */
-                       xmit_recv:1;            /* if set, a xmit packet, else a recieve packet.*/
+                       xmit_recv:1;            /* if set, a xmit packet, else a receive packet.*/
        unsigned char   status;
 };
 
index d046fd870e49ff08f2fbec53de8ffd5ba3356280..aad76ed91c3749f6f07cf7b04251f78c9e1404fe 100644 (file)
@@ -90,6 +90,8 @@ static unsigned char *encode(unsigned char *cp, unsigned short n);
 static long decode(unsigned char **cpp);
 static unsigned char * put16(unsigned char *cp, unsigned short x);
 static unsigned short pull16(unsigned char **cpp);
+static void export_slhc_syms(void);
+static has_exported = 0;
 
 /* Initialize compression data structure
  *     slots must be in range 0 to 255 (zero meaning no compression)
@@ -101,6 +103,9 @@ slhc_init(int rslots, int tslots)
        register struct cstate *ts;
        struct slcompress *comp;
 
+       if (!has_exported)
+               export_slhc_syms();
+
        comp = (struct slcompress *)kmalloc(sizeof(struct slcompress),
                                            GFP_KERNEL);
        if (! comp)
@@ -727,11 +732,31 @@ void slhc_o_status(struct slcompress *comp)
        }
 }
 
+static struct symbol_table slhc_syms = {
+/* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */
+#include <linux/symtab_begin.h>
+        /* VJ header compression */
+        X(slhc_init),
+        X(slhc_free),
+        X(slhc_remember),
+        X(slhc_compress),
+        X(slhc_uncompress),
+        X(slhc_toss),
+#include <linux/symtab_end.h>
+};
+
+static void export_slhc_syms(void)
+{
+       register_symtab(&slhc_syms);
+       has_exported = 1;
+}
+
 #ifdef MODULE
 
 int init_module(void)
 {
        printk("CSLIP: code copyright 1989 Regents of the University of California\n");
+       export_slhc_syms();
        return 0;
 }
 
index fbf16a23017dc98f463afb7c932afefdb8f2c5b0..16ebfd198c8a3f5e132898d1e4f0eb7e951284f8 100644 (file)
@@ -85,6 +85,7 @@ struct pci_dev_info dev_info[] = {
        DEVICE( MATROX,         MATROX_MGA_IMP, "MGA Impression"),
        DEVICE( CT,             CT_65545,       "65545"),
        DEVICE( FD,             FD_36C70,       "TMC-18C30"),
+       DEVICE( SI,             SI_6201,        "6201"),
        DEVICE( SI,             SI_6202,        "6202"),
        DEVICE( SI,             SI_503,         "85C503"),
        DEVICE( SI,             SI_501,         "85C501"),
index fca4734d7c412193728241d3548bf60205c6e536..9d2eb2e70d92e0d32cfa508bc10f1c6c7a243d53 100644 (file)
@@ -14,11 +14,12 @@ bool 'Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
 mainmenu_option next_comment
 comment 'SCSI low-level drivers'
 
+dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
 dep_tristate 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X $CONFIG_SCSI
 dep_tristate 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 $CONFIG_SCSI
 dep_tristate 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 $CONFIG_SCSI
 dep_tristate 'Adaptec AHA274X/284X/294X support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI
-dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC
+dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG.SCSI
 dep_tristate 'EATA-DMA (DPT, NEC, ATT, Olivetti) support' CONFIG_SCSI_EATA_DMA $CONFIG_SCSI
 dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI
 dep_tristate 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F $CONFIG_SCSI
@@ -37,3 +38,4 @@ dep_tristate '7000FASST SCSI support' CONFIG_SCSI_7000FASST $CONFIG_SCSI
 dep_tristate 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA $CONFIG_SCSI
 dep_tristate 'NCR53c406a SCSI support' CONFIG_SCSI_NCR53C406A $CONFIG_SCSI
 #dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI
+endmenu
index 2358418e49f1df737168b00a0fc1975c856c2c0b..6423151e7ca18697e4e1a3a000186f863a6d3ea0 100644 (file)
@@ -33,6 +33,7 @@ endif
 
 ifeq ($(CONFIG_SCSI),y)
 L_OBJS += hosts.o scsi.o scsi_ioctl.o constants.o scsicam.o scsi_proc.o
+LX_OBJS += scsi_syms.o
 else
   ifeq ($(CONFIG_SCSI),m)
     MX_OBJS += scsi_syms.o
@@ -72,6 +73,14 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_SCSI_ADVANSYS),y)
+L_OBJS += advansys.o
+else
+       ifeq ($(CONFIG_SCSI_ADVANSYS),m)
+       M_OBJS += advansys.o
+       endif
+endif
+
 ifeq ($(CONFIG_SCSI_QLOGIC),y)
 L_OBJS += qlogic.o
 else
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
new file mode 100644 (file)
index 0000000..34dd617
--- /dev/null
@@ -0,0 +1,9061 @@
+/* $Id: advansys.c,v 1.11 1996/01/16 22:39:19 bobf Exp bobf $ */
+/*
+ * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
+ * 
+ * Copyright (c) 1995-1996 Advanced System Products, Inc.
+ * All Rights Reserved.
+ *
+ * This driver may be modified and freely distributed provided that
+ * the above copyright message and this comment are included in the
+ * distribution. The latest version of this driver is available at
+ * the AdvanSys FTP and BBS sites listed below.
+ *
+ * Please send questions, comments, bug reports to:
+ * bobf@advansys.com (Bob Frey)
+ */
+
+/* The driver has been tested with Linux 1.2.1 and 1.3.57 kernels. */
+#define ASC_VERSION "1.2"      /* AdvanSys Driver Version */
+
+/*
+
+  Documentation for the AdvanSys Driver
+
+  A. Adapters Supported by this Driver
+  B. Linux 1.2.X - Directions for Adding the AdvanSys Driver
+  C. Linux 1.3.X - Directions for Adding the AdvanSys Driver
+  D. Source Comments
+  E. Driver Compile Time Options and Debugging
+  F. Driver LILO Option
+  G. Release History
+  H. Known Problems or Issues
+  I. Credits
+  J. AdvanSys Contact Information
+
+
+  A. 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.
+     
+     The CDB counts below indicate the number of SCSI CDB (Command
+     Descriptor Block) requests that can be stored in the RISC chip
+     cache and board LRAM. The driver detect routine will display the
+     number of CDBs available for each adapter detected. This value
+     can be lowered in the BIOS by changing the 'Host Queue Size'
+     adapter setting.
+
+     Connectivity Products:
+       ABP920 - Bus-Master PCI 16 CDB
+       ABP930 - Bus-Master PCI 16 CDB
+       ABP5140 - Bus-Master PnP ISA 16 CDB
+   
+     Single Channel Products:
+       ABP542 - Bus-Master ISA 240 CDB
+       ABP5150 - Bus-Master ISA 240 CDB *
+       ABP742 - Bus-Master EISA 240 CDB
+       ABP842 - Bus-Master VL 240 CDB
+       ABP940 - Bus-Master PCI 240 CDB
+   
+     Dual Channel Products:
+       ABP950 - Dual Channel Bus-Master PCI 240 CDB Per Channel
+       ABP852 - Dual Channel Bus-Master VL 240 CDB Per Channel
+       ABP752 - Dual Channel Bus-Master EISA 240 CDB Per Channel
+
+     * This board is shipped by HP with the 4020i CD-R drive. It has
+       no BIOS so it cannot control a boot device, but it can control
+       any secondary devices.
+  B. Linux 1.2.X - Directions for Adding the AdvanSys Driver
+     There are two source files: advansys.h and advansys.c. Copy
+     both of these files to the directory /usr/src/linux/drivers/scsi.
+    
+     1. Add the following line to /usr/src/linux/arch/i386/config.in
+        after "comment 'SCSI low-level drivers'":
+    
+          bool 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS y
+    
+     2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c
+        after "#include "hosts.h"":
+    
+          #ifdef CONFIG_SCSI_ADVANSYS
+          #include "advansys.h"
+          #endif
+    
+        and after "static Scsi_Host_Template builtin_scsi_hosts[] =":
+    
+          #ifdef CONFIG_SCSI_ADVANSYS
+          ADVANSYS,
+          #endif
+    
+     3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile:
+    
+          ifdef CONFIG_SCSI_ADVANSYS
+          SCSI_SRCS := $(SCSI_SRCS) advansys.c
+          SCSI_OBJS := $(SCSI_OBJS) advansys.o
+          else
+          SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) advansys.o
+          endif
+
+     4. (Optional) If you would like to enable the LILO command line
+        and /etc/lilo.conf 'advansys' option, make the following changes.
+        This option can be used to disable I/O port scanning or to limit
+        I/O port scanning to specific addresses. Refer to the 'Driver
+        LILO Option' section below. Add the following lines to
+        /usr/src/linux/init/main.c in the prototype section:
+
+          extern void advansys_setup(char *str, int *ints);
+
+        and add the following lines to the bootsetups[] array.
+
+          #ifdef CONFIG_SCSI_ADVANSYS
+             { "advansys=", advansys_setup },
+          #endif
+
+     5. If you have the HP 4020i CD-R driver and Linux 1.2.X you should
+        add a fix to the CD-ROM target driver. This fix will allow
+        you to mount CDs with the iso9660 file system. Linux 1.3.X
+        already has this fix. In the file /usr/src/linux/drivers/scsi/sr.c
+        and function get_sectorsize() after the line:
+
+        if(scsi_CDs[i].sector_size == 0) scsi_CDs[i].sector_size = 2048;
+
+        add the following line:
+
+        if(scsi_CDs[i].sector_size == 2340) scsi_CDs[i].sector_size = 2048;
+
+     6. In the directory /usr/src/linux run 'make config' to configure
+        the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to
+        make the kernel. If the AdvanSys driver is not configured, then
+        a loadable module can be built by running 'make modules' and
+        'make modules_install'. Use 'insmod' and 'rmmod' to install
+        and remove advansys.o.
+  C. Linux 1.3.X - Directions for Adding the AdvanSys Driver
+
+     There are two source files: advansys.h and advansys.c. Copy
+     both of these files to the directory /usr/src/linux/drivers/scsi.
+   
+     1. Add the following line to /usr/src/linux/drivers/scsi/Config.in
+        after "comment 'SCSI low-level drivers'":
+   
+          dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
+   
+     2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c
+        after "#include "hosts.h"":
+   
+          #ifdef CONFIG_SCSI_ADVANSYS
+          #include "advansys.h"
+          #endif
+   
+        and after "static Scsi_Host_Template builtin_scsi_hosts[] =":
+   
+          #ifdef CONFIG_SCSI_ADVANSYS
+          ADVANSYS,
+          #endif
+   
+     3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile:
+   
+          ifeq ($(CONFIG_SCSI_ADVANSYS),y)
+          L_OBJS += advansys.o
+          else
+            ifeq ($(CONFIG_SCSI_ADVANSYS),m)
+            M_OBJS += advansys.o
+            endif
+          endif
+   
+     4. Add the following line to /usr/src/linux/include/linux/proc_fs.h
+        in the enum scsi_directory_inos array:
+   
+          PROC_SCSI_ADVANSYS,
+   
+     5. (Optional) If you would like to enable the LILO command line
+        and /etc/lilo.conf 'advansys' option, make the following changes.
+        This option can be used to disable I/O port scanning or to limit
+        I/O port scanning to specific addresses. Refer to the 'Driver
+        LILO Option' section below. Add the following lines to
+        /usr/src/linux/init/main.c in the prototype section:
+   
+          extern void advansys_setup(char *str, int *ints);
+   
+        and add the following lines to the bootsetups[] array.
+   
+          #ifdef CONFIG_SCSI_ADVANSYS
+             { "advansys=", advansys_setup },
+          #endif
+   
+     6. In the directory /usr/src/linux run 'make config' to configure
+        the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to
+        make the kernel. If the AdvanSys driver is not configured, then
+        a loadable module can be built by running 'make modules' and
+        'make modules_install'. Use 'insmod' and 'rmmod' to install
+        and remove advansys.o.
+
+  D. Source Comments
+     1. Use tab stops set to 4 for the source files. For vi use 'se tabstops=4'.
+     2. This driver should be maintained in multiple files. But to make
+        it easier to include with Linux and to follow Linux conventions,
+        the whole driver is maintained in the source files advansys.h and
+        advansys.c. In this file logical sections of the driver begin with
+        a comment that contains '---'. The following are the logical sections
+        of the driver below.
+           --- Linux Version
+           --- Linux Include Files 
+           --- Driver Options
+           --- Asc Library Constants and Macros
+           --- Debugging Header
+           --- Driver Constants
+           --- Driver Macros
+           --- Driver Structures
+           --- Driver Data
+           --- Driver Function Prototypes
+           --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
+           --- Loadable Driver Support
+           --- Miscellaneous Driver Functions
+           --- Functions Required by the Asc Library
+           --- Tracing and Debugging Functions
+           --- Asc 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 Constants and Macros
+           --- Asc Library Functions
+  E. Driver Compile Time Options and Debugging
+     In this source file the following constants can be defined. They are
+     defined in the source below. Both of these options are enabled by
+     default.
+     1. ADVANSYS_DEBUG - enable for debugging and assertions
+        The amount of debugging output can be controlled with the global
+        variable 'asc_dbglvl'. The higher the number the more output. By
+        default the debug level is 0.
+        
+        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
+        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
+        and set the debug level to 2.
+
+           linux advansys=0x330,0x0,0x0,0x0,0xdeb2
+
+        If the driver is built as a loadable module this variable can be
+        defined when the driver is loaded. The following insmod command
+        will set the debug level to one.
+  
+           insmod advansys.o asc_dbglvl=1
+        Debugging Message Levels:
+           0: Errors Only
+           1: High-Level Tracing
+           2-N: Verbose Tracing
+        I don't know the approved way for turning on printk()s to the
+        console. Here's a program I use to do this. Debug output is
+        logged in /var/adm/messages.
+          main()
+          {
+                  syscall(103, 7, 0, 0);
+          }
+        I found that increasing LOG_BUF_LEN to 40960 in kernel/printk.c
+        prevents most level 1 debug messages from being lost.
+     2. ADVANSYS_STATS - enable statistics and tracing
+        For Linux 1.2.X if ADVANSYS_STATS_1_2_PRINT is defined every
+        10,000 I/O operations the driver will print statistics to the
+        console. This value can be changed by modifying the constant
+        used in advansys_queuecommand(). ADVANSYS_STATS_1_2_PRINT is
+        off by default.
+
+        For Linux 1.3.X statistics can be accessed by reading the
+        /proc/scsi/advansys/[0-9] files.
+
+        Note: these statistics are currently maintained on a global driver
+        basis and not per board.
+
+  F. Driver LILO Option
+     If init/main.c is modified as described in the 'Directions for Adding
+     the AdvanSys Driver to Linux' section (B.4.) above, the driver will
+     recognize the 'advansys' LILO command line and /etc/lilo.conf option.
+     This option can be used 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.
+
+     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
+
+     For a loadable module the same effect can be achieved by setting
+     the 'asc_iopflag' variable and 'asc_ioport' array when loading
+     the driver, e.g.
+
+           insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330
+
+     If ADVANSYS_DEBUG is defined a 5th (ASC_NUM_BOARD_SUPPORTED + 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.
+
+  G. Release History
+
+     12/23/95 BETA-1.0:
+         First Release
+
+     12/28/95 BETA-1.1:
+         1. Prevent advansys_detect() from being called twice.
+         2. Add LILO 0xdeb[0-f] option to set 'asc_dbglvl'.
+
+     1/12/96 1.2:
+         1. Prevent re-entrancy in the interrupt handler which
+            resulted in the driver hanging Linux.
+         2. Fix problem that prevented ABP-940 cards from being
+            recognized on some PCI motherboards.
+         3. Add support for the ABP-5140 PnP ISA card.
+         4. Fix check condition return status.
+         5. Add conditionally compiled code for Linux 1.3.X.
+        
+  H. Known Problems or Issues
+
+     1. The setting for 'cmd_per_lun' needs to be changed. It is currently
+        less then what the AdvanSys boards can queue. Because the target and
+        mid-level Linux drivers base memory allocation on 'cmd_per_lun' (as
+        well as 'sg_tablesize') memory use gets out of hand with a large
+        'cmd_per_lun'. 'cmd_per_lun' should be per device instead of per
+        adapter. When the driver is compiled as a loadable module both
+        'cmd_per_lun' and 'sg_tablesize' are tuned down to try to prevent
+        memory allocation errors.
+
+     2. For the first scsi command sent to a device the driver increases
+        the timeout value. This gives the driver more time to perform
+        its own initialization for the board and each device. The timeout
+        value is only changed on the first scsi command for each device
+        and never thereafter.
+
+  I. Credits
+
+     Nathan Hartwell (mage@cdc3.cdc.net) provided the directions and
+     and basis for the Linux 1.3.X changes which were included in the
+     1.2 release.
+
+  J. AdvanSys Contact Information
+     Mail:                   Advanced System Products, Inc.
+                             1150 Ringwood Court
+                             San Jose, CA 95131 USA
+     Operator:               1-408-383-9400
+     FAX:                    1-408-383-9612
+     Tech Support:           1-800-525-7440
+     BBS:                    1-408-383-9540 (9600,N,8,1)
+     Interactive FAX:        1-408-383-9753
+     Customer Direct Sales:  1-800-883-1099
+     Tech Support E-Mail:    support@advansys.com
+     Linux Support E-Mail:   bobf@advansys.com
+     FTP Site:               ftp.advansys.com (login: anonymous)
+     Web Site:               http://www.advansys.com
+
+*/
+
+
+/*
+ * --- Linux Version
+ */
+
+/*
+ * The driver can be used in Linux 1.2.X or 1.3.X.
+ */
+#if !defined(LINUX_1_2) && !defined(LINUX_1_3)
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif /* LINUX_VERSION_CODE */
+#if LINUX_VERSION_CODE > 65536 + 3 * 256
+#define LINUX_1_3
+#else /* LINUX_VERSION_CODE */
+#define LINUX_1_2
+#endif /* LINUX_VERSION_CODE */
+#endif /* !defined(LINUX_1_2) && !defined(LINUX_1_3) */
+
+
+/*
+ * --- Linux Include Files 
+ */
+
+#ifdef MODULE
+#ifdef LINUX_1_3
+#include <linux/autoconf.h>
+#endif /* LINUX_1_3 */ 
+#include <linux/module.h>
+#endif /* MODULE */
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/head.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/config.h>
+#ifdef LINUX_1_3
+#include <linux/proc_fs.h>
+#endif /* LINUX_1_3 */ 
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#ifdef LINUX_1_2
+#include "../block/blk.h"
+#else /* LINUX_1_3 */ 
+#include <linux/blk.h>
+#include <linux/stat.h>
+#endif /* LINUX_1_3 */ 
+#include "scsi.h"
+#include "hosts.h"
+#include "sd.h"
+#include "advansys.h"
+
+
+/*
+ * --- Driver Options
+ */
+#define ADVANSYS_DEBUG /* Enable for debugging and assertions. */
+#define ADVANSYS_STATS /* Enable for statistics and tracing. */
+#ifdef LINUX_1_2
+#undef ADVANSYS_STATS_1_2_PRINT /* Enable to print statistics to console. */
+#endif /* LINUX_1_2 */
+
+
+/*
+ * --- Asc Library Constants and Macros
+ */
+
+#define ASC_LIB_VERSION_MAJOR  1
+#define ASC_LIB_VERSION_MINOR  16
+#define ASC_LIB_SERIAL_NUMBER  53
+
+typedef unsigned char uchar;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+
+typedef int         BOOL;
+
+#ifndef NULL
+#define NULL     (0)
+#endif
+
+#ifndef TRUE
+#define TRUE     (1)
+#endif
+
+#ifndef FALSE
+#define FALSE    (0)
+#endif
+
+#define  REG     register
+
+#define rchar    REG char
+#define rshort   REG short
+#define rint     REG int
+#define rlong    REG long
+
+#define ruchar   REG uchar
+#define rushort  REG ushort
+#define ruint    REG uint
+#define rulong   REG ulong
+
+#define NULLPTR   ( void *)0
+#define FNULLPTR  ( void dosfar *)0UL
+#define EOF      (-1)
+#define EOS      '\0'
+#define ERR      (-1)
+#define UB_ERR   (uchar)(0xFF)
+#define UW_ERR   (uint)(0xFFFF)
+#define UL_ERR   (ulong)(0xFFFFFFFFUL)
+
+#define iseven_word( val )  ( ( ( ( uint )val) & ( uint )0x0001 ) == 0 )
+#define isodd_word( val )   ( ( ( ( uint )val) & ( uint )0x0001 ) != 0 )
+#define toeven_word( val )  ( ( ( uint )val ) & ( uint )0xFFFE )
+
+#define biton( val, bits )   ((( uint )( val >> bits ) & (uint)0x0001 ) != 0 )
+#define bitoff( val, bits )  ((( uint )( val >> bits ) & (uint)0x0001 ) == 0 )
+#define lbiton( val, bits )  ((( ulong )( val >> bits ) & (ulong)0x00000001UL ) != 0 )
+#define lbitoff( val, bits ) ((( ulong )( val >> bits ) & (ulong)0x00000001UL ) == 0 )
+
+#define  absh( val )    ( ( val ) < 0 ? -( val ) : ( val ) )
+
+#define  swapbyte( ch )  ( ( ( (ch) << 4 ) | ( (ch) >> 4 ) ) )
+
+#ifndef GBYTE
+#define GBYTE       (0x40000000UL)
+#endif
+
+#ifndef MBYTE
+#define MBYTE       (0x100000UL)
+#endif
+
+#ifndef KBYTE
+#define KBYTE       (0x400)
+#endif
+
+#define HI_BYTE(x) ( *( ( BYTE *)(&x)+1 ) )
+#define LO_BYTE(x) ( *( ( BYTE *)&x ) )
+
+#define HI_WORD(x) ( *( ( WORD *)(&x)+1 ) )
+#define LO_WORD(x) ( *( ( WORD *)&x ) )
+
+#ifndef MAKEWORD
+#define MAKEWORD(lo, hi)    ((WORD) (((WORD) lo) | ((WORD) hi << 8)))
+#endif
+
+#ifndef MAKELONG
+#define MAKELONG(lo, hi)    ((DWORD) (((DWORD) lo) | ((DWORD) hi << 16)))
+#endif
+
+#define SwapWords(dWord)        ((DWORD) ((dWord >> 16) | (dWord << 16)))
+#define SwapBytes(word)         ((WORD) ((word >> 8) | (word << 8)))
+
+#define BigToLittle(dWord) \
+    ((DWORD) (SwapWords(MAKELONG(SwapBytes(LO_WORD(dWord)), SwapBytes(HI_WORD(dWord))))))
+#define LittleToBig(dWord)      BigToLittle(dWord)
+
+#define Lptr
+#define dosfar
+#define far
+#define PortAddr                       unsigned short
+#define Ptr2Func               ulong
+
+#define inp(port)              inb(port)
+#define inpw(port)             inw(port)
+#define outp(port, byte)    outb((byte), (port))
+#define outpw(port, word)   outw((word), (port))
+
+#define ASC_MAX_SG_QUEUE       5
+#define ASC_MAX_SG_LIST                (1 + ((ASC_SG_LIST_PER_Q) * (ASC_MAX_SG_QUEUE)))
+
+#define CC_INIT_INQ_DISPLAY     FALSE
+
+#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_LINK_BUSY_Q         FALSE
+
+#define CC_TARGET_MODE         FALSE
+
+#define CC_SCAM                FALSE
+
+#define CC_LITTLE_ENDIAN_HOST  TRUE
+
+#ifndef CC_TEST_LRAM_ENDIAN
+
+#if CC_LITTLE_ENDIAN_HOST
+#define CC_TEST_LRAM_ENDIAN     FALSE
+#else
+#define CC_TEST_LRAM_ENDIAN     TRUE
+#endif
+
+#endif
+
+#define CC_STRUCT_ALIGNED      TRUE
+
+#define CC_MEMORY_MAPPED_IO    FALSE
+
+#ifndef CC_TARGET_MODE
+#define CC_TARGET_MODE         FALSE
+#endif
+
+#ifndef CC_STRUCT_ALIGNED
+#define CC_STRUCT_ALIGNED      FALSE
+#endif
+
+#ifndef CC_LITTLE_ENDIAN_HOST
+#define CC_LITTLE_ENDIAN_HOST  TRUE
+#endif
+
+#if !CC_LITTLE_ENDIAN_HOST
+
+#ifndef CC_TEST_LRAM_ENDIAN
+#define CC_TEST_LRAM_ENDIAN    TRUE
+#endif
+
+#endif
+
+#ifndef CC_MEMORY_MAPPED_IO
+#define CC_MEMORY_MAPPED_IO    FALSE
+#endif
+
+#ifndef CC_WRITE_IO_COUNT
+#define CC_WRITE_IO_COUNT      FALSE
+#endif
+
+#ifndef CC_CLEAR_DMA_REMAIN
+#define CC_CLEAR_DMA_REMAIN    FALSE
+#endif
+
+#define ASC_CS_TYPE  unsigned short
+
+#ifndef asc_ptr_type
+#define asc_ptr_type
+#endif
+
+#ifndef CC_SCAM
+#define CC_SCAM  FALSE
+#endif
+
+#ifndef ASC_GET_PTR2FUNC
+#define ASC_GET_PTR2FUNC( fun )  ( Ptr2Func )( fun )
+#endif
+
+#define FLIP_BYTE_NIBBLE( x )    ( ((x<<4)& 0xFF) | (x>>4) )
+
+#define ASC_IS_ISA          (0x0001)
+#define ASC_IS_ISAPNP       (0x0081)
+#define ASC_IS_EISA         (0x0002)
+#define ASC_IS_PCI          (0x0004)
+#define ASC_IS_PCMCIA       (0x0008)
+#define ASC_IS_PNP          (0x0010)
+#define ASC_IS_MCA          (0x0020)
+#define ASC_IS_VL           (0x0040)
+
+#define ASC_ISA_PNP_PORT_ADDR  (0x279)
+#define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800)
+
+#define ASC_IS_WIDESCSI_16  (0x0100)
+#define ASC_IS_WIDESCSI_32  (0x0200)
+
+#define ASC_IS_BIG_ENDIAN   (0x8000)
+
+#define ASC_CHIP_MIN_VER_VL      (0x01)
+#define ASC_CHIP_MAX_VER_VL      (0x07)
+
+#define ASC_CHIP_MIN_VER_PCI     (0x09)
+#define ASC_CHIP_MAX_VER_PCI     (0x0F)
+#define ASC_CHIP_VER_PCI_BIT     (0x08)
+
+#define ASC_CHIP_MIN_VER_ISA     (0x11)
+#define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
+#define ASC_CHIP_MAX_VER_ISA     (0x27)
+#define ASC_CHIP_VER_ISA_BIT     (0x30)
+#define ASC_CHIP_VER_ISAPNP_BIT  (0x20)
+
+#define ASC_CHIP_VER_ASYN_BUG    (0x21)
+
+#define ASC_CHIP_MIN_VER_EISA (0x41)
+#define ASC_CHIP_MAX_VER_EISA (0x47)
+#define ASC_CHIP_VER_EISA_BIT (0x40)
+
+#define ASC_MAX_VL_DMA_ADDR     (0x07FFFFFFL)
+#define ASC_MAX_VL_DMA_COUNT    (0x07FFFFFFL)
+
+#define ASC_MAX_PCI_DMA_ADDR    (0xFFFFFFFFL)
+#define ASC_MAX_PCI_DMA_COUNT   (0xFFFFFFFFL)
+
+#define ASC_MAX_ISA_DMA_ADDR    (0x00FFFFFFL)
+#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
+
+#define ASC_SCSI_ID_BITS  3
+#define ASC_SCSI_TIX_TYPE     uchar
+#define ASC_ALL_DEVICE_BIT_SET  0xFF
+
+#ifdef ASC_WIDESCSI_16
+
+#undef  ASC_SCSI_ID_BITS
+#define ASC_SCSI_ID_BITS  4
+#define ASC_ALL_DEVICE_BIT_SET  0xFFFF
+
+#endif
+
+#ifdef ASC_WIDESCSI_32
+
+#undef  ASC_SCSI_ID_BITS
+#define ASC_SCSI_ID_BITS  5
+#define ASC_ALL_DEVICE_BIT_SET  0xFFFFFFFFL
+
+#endif
+
+#if ASC_SCSI_ID_BITS == 3
+
+#define ASC_SCSI_BIT_ID_TYPE  uchar
+#define ASC_MAX_TID       7
+#define ASC_MAX_LUN       7
+#define ASC_SCSI_WIDTH_BIT_SET  0xFF
+
+#elif ASC_SCSI_ID_BITS == 4
+
+#define ASC_SCSI_BIT_ID_TYPE   ushort
+#define ASC_MAX_TID         15
+#define ASC_MAX_LUN         7
+#define ASC_SCSI_WIDTH_BIT_SET  0xFFFF
+
+#elif ASC_SCSI_ID_BITS == 5
+
+#define ASC_SCSI_BIT_ID_TYPE    ulong
+#define ASC_MAX_TID         31
+#define ASC_MAX_LUN         7
+#define ASC_SCSI_WIDTH_BIT_SET  0xFFFFFFFF
+
+#else
+
+#error  ASC_SCSI_ID_BITS definition is wrong
+
+#endif
+
+#define ASC_MAX_SENSE_LEN   32
+#define ASC_MIN_SENSE_LEN   14
+
+#define ASC_MAX_CDB_LEN     12
+
+#define SCSICMD_TestUnitReady     0x00
+#define SCSICMD_Rewind            0x01
+#define SCSICMD_Rezero            0x01
+#define SCSICMD_RequestSense      0x03
+#define SCSICMD_Format            0x04
+#define SCSICMD_FormatUnit        0x04
+#define SCSICMD_Read6             0x08
+#define SCSICMD_Write6            0x0A
+#define SCSICMD_Seek6             0x0B
+#define SCSICMD_Inquiry           0x12
+#define SCSICMD_Verify6           0x13
+#define SCSICMD_ModeSelect6       0x15
+#define SCSICMD_ModeSense6        0x1A
+
+#define SCSICMD_StartStopUnit     0x1B
+#define SCSICMD_LoadUnloadTape    0x1B
+#define SCSICMD_ReadCapacity      0x25
+#define SCSICMD_Read10            0x28
+#define SCSICMD_Write10           0x2A
+#define SCSICMD_Seek10            0x2B
+#define SCSICMD_Erase10           0x2C
+#define SCSICMD_WriteAndVerify10  0x2E
+#define SCSICMD_Verify10          0x2F
+
+#define SCSICMD_ModeSelect10      0x55
+#define SCSICMD_ModeSense10       0x5A
+
+#define SCSI_TYPE_DASD     0x00
+#define SCSI_TYPE_SASD     0x01
+#define SCSI_TYPE_PRN      0x02
+#define SCSI_TYPE_PROC     0x03
+
+#define SCSI_TYPE_WORM     0x04
+#define SCSI_TYPE_CDROM    0x05
+#define SCSI_TYPE_SCANNER  0x06
+#define SCSI_TYPE_OPTMEM   0x07
+#define SCSI_TYPE_MED_CHG  0x08
+#define SCSI_TYPE_COMM     0x09
+#define SCSI_TYPE_UNKNOWN  0x1F
+#define SCSI_TYPE_NO_DVC   0xFF
+
+#define ASC_SCSIDIR_NOCHK    0x00
+
+#define ASC_SCSIDIR_T2H      0x08
+
+#define ASC_SCSIDIR_H2T      0x10
+
+#define ASC_SCSIDIR_NODATA   0x18
+
+#define SCSI_SENKEY_NO_SENSE      0x00
+#define SCSI_SENKEY_UNDEFINED     0x01
+#define SCSI_SENKEY_NOT_READY     0x02
+#define SCSI_SENKEY_MEDIUM_ERR    0x03
+#define SCSI_SENKEY_HW_ERR        0x04
+#define SCSI_SENKEY_ILLEGAL       0x05
+#define SCSI_SENKEY_ATTENSION     0x06
+#define SCSI_SENKEY_PROTECTED     0x07
+#define SCSI_SENKEY_BLANK         0x08
+#define SCSI_SENKEY_V_UNIQUE      0x09
+#define SCSI_SENKEY_CPY_ABORT     0x0A
+#define SCSI_SENKEY_ABORT         0x0B
+#define SCSI_SENKEY_EQUAL         0x0C
+#define SCSI_SENKEY_VOL_OVERFLOW  0x0D
+#define SCSI_SENKEY_MISCOMP       0x0E
+#define SCSI_SENKEY_RESERVED      0x0F
+
+#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 ) )
+
+#define PUT_CDB1( x )   ( ( uchar )( ( uint )( x ) >> 8 ) )
+
+#define SS_GOOD              0x00
+#define SS_CHK_CONDITION     0x02
+#define SS_CONDITION_MET     0x04
+#define SS_TARGET_BUSY       0x08
+#define SS_INTERMID          0x10
+#define SS_INTERMID_COND_MET 0x14
+
+#define SS_RSERV_CONFLICT    0x18
+#define SS_CMD_TERMINATED    0x22
+
+#define SS_QUEUE_FULL        0x28
+
+#define MS_CMD_DONE    0x00
+#define MS_EXTEND      0x01
+#define MS_SDTR_LEN    0x03
+#define MS_SDTR_CODE   0x01
+
+#define M1_SAVE_DATA_PTR        0x02
+#define M1_RESTORE_PTRS         0x03
+#define M1_DISCONNECT           0x04
+#define M1_INIT_DETECTED_ERR    0x05
+#define M1_ABORT                0x06
+#define M1_MSG_REJECT           0x07
+#define M1_NO_OP                0x08
+#define M1_MSG_PARITY_ERR       0x09
+#define M1_LINK_CMD_DONE        0x0A
+#define M1_LINK_CMD_DONE_WFLAG  0x0B
+#define M1_BUS_DVC_RESET        0x0C
+#define M1_ABORT_TAG            0x0D
+#define M1_CLR_QUEUE            0x0E
+#define M1_INIT_RECOVERY        0x0F
+#define M1_RELEASE_RECOVERY     0x10
+#define M1_KILL_IO_PROC         0x11
+
+#define M2_QTAG_MSG_SIMPLE      0x20
+#define M2_QTAG_MSG_HEAD        0x21
+#define M2_QTAG_MSG_ORDERED     0x22
+#define M2_IGNORE_WIDE_RESIDUE  0x23
+
+typedef struct {
+       uchar               peri_dvc_type:5;
+       uchar               peri_qualifier:3;
+} ASC_SCSI_INQ0;
+
+typedef struct {
+       uchar               dvc_type_modifier:7;
+       uchar               rmb:1;
+} ASC_SCSI_INQ1;
+
+typedef struct {
+       uchar               ansi_apr_ver:3;
+       uchar               ecma_ver:3;
+       uchar               iso_ver:2;
+} ASC_SCSI_INQ2;
+
+typedef struct {
+       uchar               rsp_data_fmt:4;
+
+       uchar               res:2;
+       uchar               TemIOP:1;
+       uchar               aenc:1;
+} ASC_SCSI_INQ3;
+
+typedef struct {
+       uchar               StfRe:1;
+       uchar               CmdQue:1;
+       uchar               Reserved:1;
+       uchar               Linked:1;
+       uchar               Sync:1;
+       uchar               WBus16:1;
+       uchar               WBus32:1;
+       uchar               RelAdr:1;
+} ASC_SCSI_INQ7;
+
+typedef struct {
+       ASC_SCSI_INQ0       byte0;
+       ASC_SCSI_INQ1       byte1;
+       ASC_SCSI_INQ2       byte2;
+       ASC_SCSI_INQ3       byte3;
+       uchar               add_len;
+       uchar               res1;
+       uchar               res2;
+       ASC_SCSI_INQ7       byte7;
+       uchar               vendor_id[8];
+       uchar               product_id[16];
+       uchar               product_rev_level[4];
+} ASC_SCSI_INQUIRY;
+
+typedef struct asc_req_sense {
+       uchar               err_code:7;
+       uchar               info_valid:1;
+       uchar               segment_no;
+       uchar               sense_key:4;
+       uchar               reserved_bit:1;
+       uchar               sense_ILI:1;
+       uchar               sense_EOM:1;
+       uchar               file_mark:1;
+       uchar               info1[4];
+       uchar               add_sense_len;
+       uchar               cmd_sp_info[4];
+       uchar               asc;
+       uchar               ascq;
+
+       uchar               fruc;
+       uchar               sks_byte0:7;
+       uchar               sks_valid:1;
+       uchar               sks_bytes[2];
+       uchar               notused[2];
+       uchar               ex_sense_code;
+       uchar               info2[4];
+} ASC_REQ_SENSE;
+
+#define ASC_SG_LIST_PER_Q   7
+
+#define QS_FREE        0x00
+#define QS_READY       0x01
+#define QS_DISC1       0x02
+#define QS_DISC2       0x04
+#define QS_BUSY        0x08
+
+#define QS_ABORTED     0x40
+#define QS_DONE        0x80
+
+#define QC_NO_CALLBACK   0x01
+
+#define QC_SG_SWAP_QUEUE 0x02
+#define QC_SG_HEAD       0x04
+#define QC_DATA_IN       0x08
+#define QC_DATA_OUT      0x10
+
+#define QC_URGENT        0x20
+#define QC_MSG_OUT       0x40
+#define QC_REQ_SENSE     0x80
+
+#define QCSG_SG_XFER_LIST  0x02
+#define QCSG_SG_XFER_MORE  0x04
+#define QCSG_SG_XFER_END   0x08
+
+#define QD_IN_PROGRESS       0x00
+#define QD_NO_ERROR          0x01
+#define QD_ABORTED_BY_HOST   0x02
+#define QD_WITH_ERROR        0x04
+#define QD_INVALID_REQUEST   0x80
+#define QD_INVALID_HOST_NUM  0x81
+#define QD_INVALID_DEVICE    0x82
+#define QD_ERR_INTERNAL      0xFF
+
+#define QHSTA_NO_ERROR               0x00
+#define QHSTA_M_SEL_TIMEOUT          0x11
+#define QHSTA_M_DATA_OVER_RUN        0x12
+#define QHSTA_M_DATA_UNDER_RUN       0x12
+#define QHSTA_M_UNEXPECTED_BUS_FREE  0x13
+#define QHSTA_M_BAD_BUS_PHASE_SEQ    0x14
+
+#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
+#define QHSTA_D_ASC_DVC_ERROR_CODE_SET  0x22
+#define QHSTA_D_HOST_ABORT_FAILED       0x23
+#define QHSTA_D_EXE_SCSI_Q_FAILED       0x24
+#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
+
+#define QHSTA_D_ASPI_NO_BUF_POOL        0x26
+
+#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_TARGET_STATUS_BUSY  0x45
+#define QHSTA_M_BAD_TAG_CODE        0x46
+
+#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY  0x47
+
+#define QHSTA_D_LRAM_CMP_ERROR        0x81
+#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
+
+#define ASC_FLAG_SCSIQ_REQ        0x01
+#define ASC_FLAG_BIOS_SCSIQ_REQ   0x02
+#define ASC_FLAG_BIOS_ASYNC_IO    0x04
+#define ASC_FLAG_SRB_LINEAR_ADDR  0x08
+
+#define ASC_FLAG_WIN16            0x10
+#define ASC_FLAG_WIN32            0x20
+
+#define ASC_FLAG_DOS_VM_CALLBACK  0x80
+
+#define ASC_TAG_FLAG_ADD_ONE_BYTE     0x10
+#define ASC_TAG_FLAG_ISAPNP_ADD_BYTES 0x40
+
+#define ASC_SCSIQ_CPY_BEG              4
+#define ASC_SCSIQ_SGHD_CPY_BEG         2
+
+#define ASC_SCSIQ_B_FWD                0
+#define ASC_SCSIQ_B_BWD                1
+
+#define ASC_SCSIQ_B_STATUS             2
+#define ASC_SCSIQ_B_QNO                3
+
+#define ASC_SCSIQ_B_CNTL               4
+#define ASC_SCSIQ_B_SG_QUEUE_CNT       5
+
+#define ASC_SCSIQ_D_DATA_ADDR          8
+#define ASC_SCSIQ_D_DATA_CNT          12
+#define ASC_SCSIQ_B_SENSE_LEN         20
+#define ASC_SCSIQ_DONE_INFO_BEG       22
+#define ASC_SCSIQ_D_SRBPTR            22
+#define ASC_SCSIQ_B_TARGET_IX         26
+#define ASC_SCSIQ_B_CDB_LEN           28
+#define ASC_SCSIQ_B_TAG_CODE          29
+#define ASC_SCSIQ_W_VM_ID             30
+#define ASC_SCSIQ_DONE_STATUS         32
+#define ASC_SCSIQ_HOST_STATUS         33
+#define ASC_SCSIQ_SCSI_STATUS         34
+#define ASC_SCSIQ_CDB_BEG             36
+#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
+#define ASC_SCSIQ_DW_REMAIN_XFER_CNT  60
+#define ASC_SCSIQ_B_SG_WK_QP          49
+#define ASC_SCSIQ_B_SG_WK_IX          50
+#define ASC_SCSIQ_W_REQ_COUNT         52
+#define ASC_SCSIQ_B_LIST_CNT          6
+#define ASC_SCSIQ_B_CUR_LIST_CNT      7
+
+#define ASC_SGQ_B_SG_CNTL             4
+#define ASC_SGQ_B_SG_HEAD_QP          5
+#define ASC_SGQ_B_SG_LIST_CNT         6
+#define ASC_SGQ_B_SG_CUR_LIST_CNT     7
+#define ASC_SGQ_LIST_BEG              8
+
+#define ASC_DEF_SCSI1_QNG    2
+#define ASC_MAX_SCSI1_QNG    2
+#define ASC_DEF_SCSI2_QNG    16
+#define ASC_MAX_SCSI2_QNG    32
+
+#define ASC_TAG_CODE_MASK    0x23
+
+#define ASC_STOP_REQ_RISC_STOP      0x01
+
+#define ASC_STOP_ACK_RISC_STOP      0x03
+
+#define ASC_STOP_CLEAN_UP_BUSY_Q    0x10
+#define ASC_STOP_CLEAN_UP_DISC_Q    0x20
+#define ASC_STOP_HOST_REQ_RISC_HALT 0x40
+#define ASC_STOP_SEND_INT_TO_HOST   0x80
+
+#define ASC_TIDLUN_TO_IX( tid, lun )  ( ASC_SCSI_TIX_TYPE )( (tid) + ((lun)<<ASC_SCSI_ID_BITS) )
+
+#define ASC_TID_TO_TARGET_ID( tid )   ( ASC_SCSI_BIT_ID_TYPE )( 0x01 << (tid) )
+#define ASC_TIX_TO_TARGET_ID( tix )   ( 0x01 << ( (tix) & ASC_MAX_TID ) )
+#define ASC_TIX_TO_TID( tix )  ( (tix) & ASC_MAX_TID )
+#define ASC_TID_TO_TIX( tid )  ( (tid) & ASC_MAX_TID )
+#define ASC_TIX_TO_LUN( tix )  ( ( (tix) >> ASC_SCSI_ID_BITS ) & ASC_MAX_LUN )
+
+#define ASC_QNO_TO_QADDR( q_no )      ( (ASC_QADR_BEG)+( ( int )(q_no) << 6 ) )
+
+typedef struct asc_scisq_1 {
+       uchar               status;
+       uchar               q_no;
+       uchar               cntl;
+       uchar               sg_queue_cnt;
+
+       uchar               target_id;
+       uchar               target_lun;
+
+       ulong               data_addr;
+       ulong               data_cnt;
+       ulong               sense_addr;
+       uchar               sense_len;
+       uchar               user_def;
+} ASC_SCSIQ_1;
+
+typedef struct asc_scisq_2 {
+       ulong               srb_ptr;
+       uchar               target_ix;
+
+       uchar               flag;
+       uchar               cdb_len;
+       uchar               tag_code;
+
+       ushort              vm_id;
+} ASC_SCSIQ_2;
+
+typedef struct asc_scsiq_3 {
+       uchar               done_stat;
+       uchar               host_stat;
+       uchar               scsi_stat;
+       uchar               scsi_msg;
+} ASC_SCSIQ_3;
+
+typedef struct asc_scsiq_4 {
+       uchar               cdb[ASC_MAX_CDB_LEN];
+       uchar               y_first_sg_list_qp;
+       uchar               y_working_sg_qp;
+       uchar               y_working_sg_ix;
+       uchar               y_cntl;
+       ushort              x_req_count;
+       ushort              x_reconnect_rtn;
+       ulong               x_saved_data_addr;
+       ulong               x_saved_data_cnt;
+} ASC_SCSIQ_4;
+
+typedef struct asc_q_done_info {
+       ASC_SCSIQ_2         d2;
+       ASC_SCSIQ_3         d3;
+       uchar               q_status;
+       uchar               q_no;
+       uchar               cntl;
+       uchar               sense_len;
+       uchar               user_def;
+       uchar               res;
+       ulong               remain_bytes;
+} ASC_QDONE_INFO;
+
+typedef struct asc_sg_list {
+       ulong               addr;
+       ulong               bytes;
+} ASC_SG_LIST;
+
+typedef struct asc_sg_head {
+       uchar               entry_cnt;
+
+       uchar               queue_cnt;
+
+       uchar               entry_to_copy;
+       uchar               res;
+       ASC_SG_LIST         sg_list[ASC_MAX_SG_LIST];
+} ASC_SG_HEAD;
+
+#define ASC_MIN_SG_LIST   2
+
+typedef struct asc_min_sg_head {
+       uchar               entry_cnt;
+
+       uchar               queue_cnt;
+
+       uchar               entry_to_copy;
+       uchar               res;
+       ASC_SG_LIST         sg_list[ASC_MIN_SG_LIST];
+} ASC_MIN_SG_HEAD;
+
+#define QCX_SORT        (0x0001)
+#define QCX_COALEASE    (0x0002)
+
+#if CC_LINK_BUSY_Q
+typedef struct asc_ext_scsi_q {
+       ulong               lba;
+       ushort              lba_len;
+       struct asc_scsi_q dosfar *next;
+       struct asc_scsi_q dosfar *join;
+       ushort              cntl;
+       ushort              buffer_id;
+       uchar               q_required;
+       uchar               res;
+} ASC_EXT_SCSI_Q;
+
+#endif
+
+typedef struct asc_scsi_q {
+       ASC_SCSIQ_1         q1;
+       ASC_SCSIQ_2         q2;
+       uchar dosfar       *cdbptr;
+
+       ASC_SG_HEAD dosfar *sg_head;
+
+#if CC_LINK_BUSY_Q
+       ASC_EXT_SCSI_Q      ext;
+#endif
+
+} ASC_SCSI_Q;
+
+typedef struct asc_scsi_req_q {
+       ASC_SCSIQ_1         r1;
+       ASC_SCSIQ_2         r2;
+       uchar dosfar       *cdbptr;
+       ASC_SG_HEAD dosfar *sg_head;
+
+#if CC_LINK_BUSY_Q
+       ASC_EXT_SCSI_Q      ext;
+#endif
+
+       uchar dosfar       *sense_ptr;
+
+       ASC_SCSIQ_3         r3;
+       uchar               cdb[ASC_MAX_CDB_LEN];
+       uchar               sense[ASC_MIN_SENSE_LEN];
+} ASC_SCSI_REQ_Q;
+
+typedef struct asc_risc_q {
+       uchar               fwd;
+       uchar               bwd;
+       ASC_SCSIQ_1         i1;
+       ASC_SCSIQ_2         i2;
+       ASC_SCSIQ_3         i3;
+       ASC_SCSIQ_4         i4;
+} ASC_RISC_Q;
+
+typedef struct asc_sg_list_q {
+
+       uchar               seq_no;
+       uchar               q_no;
+       uchar               cntl;
+       uchar               sg_head_qp;
+       uchar               sg_list_cnt;
+       uchar               sg_cur_list_cnt;
+
+} ASC_SG_LIST_Q;
+
+typedef struct asc_risc_sg_list_q {
+       uchar               fwd;
+       uchar               bwd;
+       ASC_SG_LIST_Q       sg;
+       ASC_SG_LIST         sg_list[7];
+} ASC_RISC_SG_LIST_Q;
+
+#define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP  0x1000000UL
+#define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP  1024
+
+#define ASCQ_ERR_NO_ERROR             0
+#define ASCQ_ERR_IO_NOT_FOUND         1
+#define ASCQ_ERR_LOCAL_MEM            2
+#define ASCQ_ERR_CHKSUM               3
+#define ASCQ_ERR_START_CHIP           4
+#define ASCQ_ERR_INT_TARGET_ID        5
+#define ASCQ_ERR_INT_LOCAL_MEM        6
+#define ASCQ_ERR_HALT_RISC            7
+#define ASCQ_ERR_GET_ASPI_ENTRY       8
+#define ASCQ_ERR_CLOSE_ASPI           9
+#define ASCQ_ERR_HOST_INQUIRY         0x0A
+#define ASCQ_ERR_SAVED_SRB_BAD        0x0B
+#define ASCQ_ERR_QCNTL_SG_LIST        0x0C
+#define ASCQ_ERR_Q_STATUS             0x0D
+#define ASCQ_ERR_WR_SCSIQ             0x0E
+#define ASCQ_ERR_PC_ADDR              0x0F
+#define ASCQ_ERR_SYN_OFFSET           0x10
+#define ASCQ_ERR_SYN_XFER_TIME        0x11
+#define ASCQ_ERR_LOCK_DMA             0x12
+#define ASCQ_ERR_UNLOCK_DMA           0x13
+#define ASCQ_ERR_VDS_CHK_INSTALL      0x14
+#define ASCQ_ERR_MICRO_CODE_HALT      0x15
+#define ASCQ_ERR_SET_LRAM_ADDR        0x16
+#define ASCQ_ERR_CUR_QNG              0x17
+#define ASCQ_ERR_SG_Q_LINKS           0x18
+#define ASCQ_ERR_SCSIQ_PTR            0x19
+#define ASCQ_ERR_ISR_RE_ENTRY         0x1A
+#define ASCQ_ERR_CRITICAL_RE_ENTRY    0x1B
+#define ASCQ_ERR_ISR_ON_CRITICAL      0x1C
+#define ASCQ_ERR_SG_LIST_ODD_ADDRESS  0x1D
+#define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E
+#define ASCQ_ERR_SCSIQ_NULL_PTR       0x1F
+#define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR   0x20
+#define ASCQ_ERR_GET_NUM_OF_FREE_Q    0x21
+#define ASCQ_ERR_SEND_SCSI_Q          0x22
+#define ASCQ_ERR_HOST_REQ_RISC_HALT   0x23
+#define ASCQ_ERR_RESET_SDTR           0x24
+
+#define ASC_WARN_NO_ERROR             0x0000
+#define ASC_WARN_IO_PORT_ROTATE       0x0001
+#define ASC_WARN_EEPROM_CHKSUM        0x0002
+#define ASC_WARN_IRQ_MODIFIED         0x0004
+#define ASC_WARN_AUTO_CONFIG          0x0008
+#define ASC_WARN_CMD_QNG_CONFLICT     0x0010
+
+#define ASC_WARN_EEPROM_RECOVER       0x0020
+#define ASC_WARN_CFG_MSW_RECOVER      0x0040
+
+#define ASC_IERR_WRITE_EEPROM         0x0001
+#define ASC_IERR_MCODE_CHKSUM         0x0002
+#define ASC_IERR_SET_PC_ADDR          0x0004
+#define ASC_IERR_START_STOP_CHIP      0x0008
+
+#define ASC_IERR_IRQ_NO               0x0010
+
+#define ASC_IERR_SET_IRQ_NO           0x0020
+#define ASC_IERR_CHIP_VERSION         0x0040
+#define ASC_IERR_SET_SCSI_ID          0x0080
+#define ASC_IERR_GET_PHY_ADDR         0x0100
+#define ASC_IERR_BAD_SIGNATURE        0x0200
+#define ASC_IERR_NO_BUS_TYPE          0x0400
+#define ASC_IERR_SCAM                 0x0800
+#define ASC_IERR_SET_SDTR             0x1000
+#define ASC_IERR_RW_LRAM              0x8000
+
+#define ASC_DEF_IRQ_NO  10
+#define ASC_MAX_IRQ_NO  15
+#define ASC_MIN_IRQ_NO  10
+
+#define ASC_MIN_REMAIN_Q        (0x02)
+#define ASC_DEF_MAX_TOTAL_QNG   (0x40)
+
+#define ASC_MIN_TAG_Q_PER_DVC   (0x04)
+#define ASC_DEF_TAG_Q_PER_DVC   (0x04)
+
+#define ASC_MIN_FREE_Q        ASC_MIN_REMAIN_Q
+
+#define ASC_MIN_TOTAL_QNG     (( ASC_MAX_SG_QUEUE )+( ASC_MIN_FREE_Q ))
+
+#define ASC_MAX_TOTAL_QNG 240
+#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
+
+#define ASC_MAX_INRAM_TAG_QNG   16
+
+typedef struct asc_dvc_cfg {
+       ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
+
+       ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
+       ASC_SCSI_BIT_ID_TYPE disc_enable;
+       uchar               res;
+       uchar               chip_scsi_id:4;
+
+       uchar               isa_dma_speed:4;
+
+       uchar               isa_dma_channel;
+       uchar               chip_version;
+       ushort              pci_device_id;
+       ushort              lib_serial_no;
+       ushort              lib_version;
+       ushort              mcode_date;
+       ushort              mcode_version;
+       uchar               sdtr_data[ASC_MAX_TID + 1];
+       uchar               max_tag_qng[ASC_MAX_TID + 1];
+       uchar dosfar       *overrun_buf;
+
+} ASC_DVC_CFG;
+
+#define ASC_DEF_DVC_CNTL       0xFFFF
+#define ASC_DEF_CHIP_SCSI_ID   7
+#define ASC_DEF_ISA_DMA_SPEED  4
+
+#define ASC_INIT_STATE_NULL          0x0000
+#define ASC_INIT_STATE_BEG_GET_CFG   0x0001
+#define ASC_INIT_STATE_END_GET_CFG   0x0002
+#define ASC_INIT_STATE_BEG_SET_CFG   0x0004
+#define ASC_INIT_STATE_END_SET_CFG   0x0008
+#define ASC_INIT_STATE_BEG_LOAD_MC   0x0010
+#define ASC_INIT_STATE_END_LOAD_MC   0x0020
+#define ASC_INIT_STATE_BEG_INQUIRY   0x0040
+#define ASC_INIT_STATE_END_INQUIRY   0x0080
+#define ASC_INIT_RESET_SCSI_DONE     0x0100
+
+#define ASC_PCI_DEVICE_ID_REV_A      0x1100
+#define ASC_PCI_DEVICE_ID_REV_B      0x1200
+
+#define ASC_BUG_FIX_ADD_ONE_BYTE     0x0001
+
+#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
+
+#define ASC_MIN_TAGGED_CMD  7
+
+typedef struct asc_dvc_var {
+       PortAddr            iop_base;
+       ushort              err_code;
+       ushort              dvc_cntl;
+       ushort              bug_fix_cntl;
+       ushort              bus_type;
+       Ptr2Func            isr_callback;
+       Ptr2Func            exe_callback;
+
+       ASC_SCSI_BIT_ID_TYPE init_sdtr;
+
+       ASC_SCSI_BIT_ID_TYPE sdtr_done;
+
+       ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
+
+       ASC_SCSI_BIT_ID_TYPE unit_not_ready;
+
+       ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
+
+       ASC_SCSI_BIT_ID_TYPE start_motor;
+       uchar               scsi_reset_wait;
+       uchar               chip_no;
+
+       char                is_in_int;
+       uchar               max_total_qng;
+
+       uchar               cur_total_qng;
+
+       uchar               in_critical_cnt;
+
+       uchar               irq_no;
+       uchar               last_q_shortage;
+
+       ushort              init_state;
+       uchar               cur_dvc_qng[ASC_MAX_TID + 1];
+       uchar               max_dvc_qng[ASC_MAX_TID + 1];
+
+       ASC_SCSI_Q dosfar  *scsiq_busy_head[ASC_MAX_TID + 1];
+       ASC_SCSI_Q dosfar  *scsiq_busy_tail[ASC_MAX_TID + 1];
+
+       ulong               int_count;
+       ulong               req_count;
+       ulong               busy_count;
+
+       ASC_DVC_CFG dosfar *cfg;
+       Ptr2Func            saved_ptr2func;
+       ulong               reserved2;
+       ulong               reserved3;
+       ulong               max_dma_count;
+       ASC_SCSI_BIT_ID_TYPE no_scam;
+       ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
+} ASC_DVC_VAR;
+
+typedef int         (dosfar * ASC_ISR_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_QDONE_INFO dosfar *);
+typedef int         (dosfar * ASC_EXE_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
+
+typedef struct asc_dvc_inq_info {
+       uchar               type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
+} ASC_DVC_INQ_INFO;
+
+typedef struct asc_cap_info {
+       ulong               lba;
+       ulong               blk_size;
+} ASC_CAP_INFO;
+
+typedef struct asc_cap_info_array {
+       ASC_CAP_INFO        cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
+} ASC_CAP_INFO_ARRAY;
+
+#define ASC_IOADR_TABLE_MAX_IX  11
+#define ASC_IOADR_GAP   0x10
+#define ASC_SEARCH_IOP_GAP 0x10
+#define ASC_MIN_IOP_ADDR   ( PortAddr )0x0100
+#define ASC_MAX_IOP_ADDR   ( PortAddr )0x3F0
+
+#define ASC_IOADR_1     ( PortAddr )0x0110
+#define ASC_IOADR_2     ( PortAddr )0x0130
+#define ASC_IOADR_3     ( PortAddr )0x0150
+#define ASC_IOADR_4     ( PortAddr )0x0190
+#define ASC_IOADR_5     ( PortAddr )0x0210
+#define ASC_IOADR_6     ( PortAddr )0x0230
+#define ASC_IOADR_7     ( PortAddr )0x0250
+#define ASC_IOADR_8     ( PortAddr )0x0330
+#define ASC_IOADR_DEF   ASC_IOADR_8
+
+#define ASC_SYN_XFER_NO   8
+#define ASC_MAX_SDTR_PERIOD_INDEX  7
+#define ASC_SYN_MAX_OFFSET   0x0F
+#define ASC_DEF_SDTR_OFFSET  0x0F
+#define ASC_DEF_SDTR_INDEX   0x00
+
+#define SYN_XFER_NS_0  25
+#define SYN_XFER_NS_1  30
+#define SYN_XFER_NS_2  35
+#define SYN_XFER_NS_3  40
+#define SYN_XFER_NS_4  50
+#define SYN_XFER_NS_5  60
+#define SYN_XFER_NS_6  70
+#define SYN_XFER_NS_7  85
+
+#define ASC_SDTR_PERIOD_IX_MIN  7
+
+#define SYN_XMSG_WLEN  3
+
+typedef struct sdtr_xmsg {
+       uchar               msg_type;
+       uchar               msg_len;
+       uchar               msg_req;
+       uchar               xfer_period;
+       uchar               req_ack_offset;
+       uchar               res;
+} SDTR_XMSG;
+
+#define ASC_MCNTL_NO_SEL_TIMEOUT  ( ushort )0x0001
+#define ASC_MCNTL_NULL_TARGET     ( ushort )0x0002
+
+#define ASC_CNTL_INITIATOR         ( ushort )0x0001
+#define ASC_CNTL_BIOS_GT_1GB       ( ushort )0x0002
+#define ASC_CNTL_BIOS_GT_2_DISK    ( ushort )0x0004
+#define ASC_CNTL_BIOS_REMOVABLE    ( ushort )0x0008
+#define ASC_CNTL_NO_SCAM           ( ushort )0x0010
+#define ASC_CNTL_NO_PCI_FIX_ASYN_XFER ( ushort )0x0020
+
+#define ASC_CNTL_INT_MULTI_Q       ( ushort )0x0080
+
+#define ASC_CNTL_NO_LUN_SUPPORT    ( ushort )0x0040
+
+#define ASC_CNTL_NO_VERIFY_COPY    ( ushort )0x0100
+#define ASC_CNTL_RESET_SCSI        ( ushort )0x0200
+#define ASC_CNTL_INIT_INQUIRY      ( ushort )0x0400
+#define ASC_CNTL_INIT_VERBOSE      ( ushort )0x0800
+
+#define ASC_CNTL_SCSI_PARITY       ( ushort )0x1000
+#define ASC_CNTL_BURST_MODE        ( ushort )0x2000
+
+#define ASC_CNTL_USE_8_IOP_BASE    ( ushort )0x4000
+
+#define ASC_EEP_DVC_CFG_BEG_VL    2
+#define ASC_EEP_MAX_DVC_ADDR_VL   15
+
+#define ASC_EEP_DVC_CFG_BEG      32
+#define ASC_EEP_MAX_DVC_ADDR     45
+
+#define ASC_EEP_DEFINED_WORDS    10
+#define ASC_EEP_MAX_ADDR         63
+#define ASC_EEP_RES_WORDS         0
+#define ASC_EEP_MAX_RETRY        20
+#define ASC_MAX_INIT_BUSY_RETRY   8
+
+#define ASC_EEP_ISA_PNP_WSIZE    16
+
+typedef struct asceep_config {
+       ushort              cfg_lsw;
+       ushort              cfg_msw;
+
+       uchar               init_sdtr;
+       uchar               disc_enable;
+
+       uchar               use_cmd_qng;
+
+       uchar               start_motor;
+       uchar               max_total_qng;
+       uchar               max_tag_qng;
+       uchar               bios_scan;
+
+       uchar               power_up_wait;
+
+       uchar               no_scam;
+       uchar               chip_scsi_id:4;
+
+       uchar               isa_dma_speed:4;
+
+       uchar               sdtr_data[ASC_MAX_TID + 1];
+
+       uchar               adapter_info[6];
+
+       ushort              cntl;
+
+       ushort              chksum;
+} ASCEEP_CONFIG;
+
+#define ASC_EEP_CMD_READ          0x80
+#define ASC_EEP_CMD_WRITE         0x40
+#define ASC_EEP_CMD_WRITE_ABLE    0x30
+#define ASC_EEP_CMD_WRITE_DISABLE 0x00
+
+#define ASC_OVERRUN_BSIZE  0x00000048UL
+
+#define ASCV_MSGOUT_BEG         0x0000
+#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
+#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
+
+#define ASCV_MSGIN_BEG          (ASCV_MSGOUT_BEG+8)
+#define ASCV_MSGIN_SDTR_PERIOD  (ASCV_MSGIN_BEG+3)
+#define ASCV_MSGIN_SDTR_OFFSET  (ASCV_MSGIN_BEG+4)
+
+#define ASCV_SDTR_DATA_BEG      (ASCV_MSGIN_BEG+8)
+#define ASCV_SDTR_DONE_BEG      (ASCV_SDTR_DATA_BEG+8)
+#define ASCV_MAX_DVC_QNG_BEG    ( ushort )0x0020
+
+#define ASCV_ASCDVC_ERR_CODE_W  ( ushort )0x0030
+#define ASCV_MCODE_CHKSUM_W   ( ushort )0x0032
+#define ASCV_MCODE_SIZE_W     ( ushort )0x0034
+#define ASCV_STOP_CODE_B      ( ushort )0x0036
+#define ASCV_DVC_ERR_CODE_B   ( ushort )0x0037
+
+#define ASCV_OVERRUN_PADDR_D  ( ushort )0x0038
+#define ASCV_OVERRUN_BSIZE_D  ( ushort )0x003C
+
+#define ASCV_HALTCODE_W       ( ushort )0x0040
+#define ASCV_CHKSUM_W         ( ushort )0x0042
+#define ASCV_MC_DATE_W        ( ushort )0x0044
+#define ASCV_MC_VER_W         ( ushort )0x0046
+#define ASCV_NEXTRDY_B        ( ushort )0x0048
+#define ASCV_DONENEXT_B       ( ushort )0x0049
+#define ASCV_USE_TAGGED_QNG_B ( ushort )0x004A
+#define ASCV_SCSIBUSY_B       ( ushort )0x004B
+#define ASCV_CDBCNT_B         ( ushort )0x004C
+#define ASCV_CURCDB_B         ( ushort )0x004D
+#define ASCV_RCLUN_B          ( ushort )0x004E
+#define ASCV_BUSY_QHEAD_B     ( ushort )0x004F
+#define ASCV_DISC1_QHEAD_B    ( ushort )0x0050
+
+#define ASCV_DISC_ENABLE_B    ( ushort )0x0052
+#define ASCV_CAN_TAGGED_QNG_B ( ushort )0x0053
+#define ASCV_HOSTSCSI_ID_B    ( ushort )0x0055
+#define ASCV_MCODE_CNTL_B     ( ushort )0x0056
+#define ASCV_NULL_TARGET_B    ( ushort )0x0057
+
+#define ASCV_FREE_Q_HEAD_W    ( ushort )0x0058
+#define ASCV_DONE_Q_TAIL_W    ( ushort )0x005A
+#define ASCV_FREE_Q_HEAD_B    ( ushort )(ASCV_FREE_Q_HEAD_W+1)
+#define ASCV_DONE_Q_TAIL_B    ( ushort )(ASCV_DONE_Q_TAIL_W+1)
+
+#define ASCV_HOST_FLAG_B      ( ushort )0x005D
+
+#define ASCV_TOTAL_READY_Q_B  ( ushort )0x0064
+#define ASCV_VER_SERIAL_B     ( ushort )0x0065
+#define ASCV_HALTCODE_SAVED_W ( ushort )0x0066
+#define ASCV_WTM_FLAG_B       ( ushort )0x0068
+#define ASCV_RISC_FLAG_B      ( ushort )0x006A
+#define ASCV_REQ_SG_LIST_QP   ( ushort )0x006B
+
+#define ASC_HOST_FLAG_IN_ISR        0x01
+#define ASC_HOST_FLAG_ACK_INT       0x02
+
+#define ASC_RISC_FLAG_GEN_INT      0x01
+#define ASC_RISC_FLAG_REQ_SG_LIST  0x02
+
+#define IOP_CTRL         (0x0F)
+#define IOP_STATUS       (0x0E)
+#define IOP_INT_ACK      IOP_STATUS
+
+#define IOP_REG_IFC      (0x0D)
+
+#define IOP_SYN_OFFSET   (0x0B)
+#define IOP_REG_PC       (0x0C)
+#define IOP_RAM_ADDR     (0x0A)
+#define IOP_RAM_DATA     (0x08)
+#define IOP_EEP_DATA     (0x06)
+#define IOP_EEP_CMD      (0x07)
+
+#define IOP_VERSION      (0x03)
+#define IOP_CONFIG_HIGH  (0x04)
+#define IOP_CONFIG_LOW   (0x02)
+#define IOP_ASPI_ID_LOW  (0x01)
+#define IOP_ASPI_ID_HIGH (0x00)
+
+#define IOP_REG_DC1      (0x0E)
+#define IOP_REG_DC0      (0x0C)
+#define IOP_REG_SB       (0x0B)
+#define IOP_REG_DA1      (0x0A)
+#define IOP_REG_DA0      (0x08)
+#define IOP_REG_SC       (0x09)
+#define IOP_DMA_SPEED    (0x07)
+#define IOP_REG_FLAG     (0x07)
+#define IOP_FIFO_H       (0x06)
+#define IOP_FIFO_L       (0x04)
+#define IOP_REG_ID       (0x05)
+#define IOP_REG_QP       (0x03)
+#define IOP_REG_IH       (0x02)
+#define IOP_REG_IX       (0x01)
+#define IOP_REG_AX       (0x00)
+
+#define IFC_REG_LOCK      (0x00)
+#define IFC_REG_UNLOCK    (0x09)
+
+#define IFC_WR_EN_FILTER  (0x10)
+#define IFC_RD_NO_EEPROM  (0x10)
+#define IFC_SLEW_RATE     (0x20)
+#define IFC_ACT_NEG       (0x40)
+#define IFC_INP_FILTER    (0x80)
+
+#define IFC_INIT_DEFAULT  ( IFC_ACT_NEG | IFC_REG_UNLOCK )
+
+#define SC_SEL   (0x80)
+#define SC_BSY   (0x40)
+#define SC_ACK   (0x20)
+#define SC_REQ   (0x10)
+#define SC_ATN   (0x08)
+#define SC_IO    (0x04)
+#define SC_CD    (0x02)
+#define SC_MSG   (0x01)
+
+#define AscGetVarFreeQHead( port )       AscReadLramWord( port, ASCV_FREE_Q_HEAD_W )
+#define AscGetVarDoneQTail( port )       AscReadLramWord( port, ASCV_DONE_Q_TAIL_W )
+#define AscPutVarFreeQHead( port, val )  AscWriteLramWord( port, ASCV_FREE_Q_HEAD_W, val )
+#define AscPutVarDoneQTail( port, val )  AscWriteLramWord( port, ASCV_DONE_Q_TAIL_W, val )
+
+#define AscGetRiscVarFreeQHead( port )        AscReadLramByte( port, ASCV_NEXTRDY_B )
+#define AscGetRiscVarDoneQTail( port )        AscReadLramByte( port, ASCV_DONENEXT_B )
+#define AscPutRiscVarFreeQHead( port, val )   AscWriteLramByte( port, ASCV_NEXTRDY_B, val )
+#define AscPutRiscVarDoneQTail( port, val )   AscWriteLramByte( port, ASCV_DONENEXT_B, val )
+
+#define AscGetChipIFC( port )               inp( (port)+IOP_REG_IFC )
+#define AscPutChipIFC( port, data )         outp( (port)+IOP_REG_IFC, data )
+
+#define AscGetChipLramAddr( port )          ( ushort )inpw( ( PortAddr )((port)+IOP_RAM_ADDR) )
+#define AscSetChipLramAddr( port, addr )    outpw( ( PortAddr )( (port)+IOP_RAM_ADDR ), addr )
+#define AscPutChipLramData( port, data )    outpw( (port)+IOP_RAM_DATA, data )
+#define AscGetChipLramData( port )          inpw( (port)+IOP_RAM_DATA )
+
+#define AscWriteChipSyn( port, data )       outp( (port)+IOP_SYN_OFFSET, data )
+#define AscReadChipSyn( port )              inp( (port)+IOP_SYN_OFFSET )
+
+#define AscWriteChipIH( port, data )        outpw( (port)+IOP_REG_IH, data )
+#define AscReadChipIH( port )               inpw( (port)+IOP_REG_IH )
+
+#define AscWriteChipScsiID( port, data )    outp( (port)+IOP_REG_ID, data )
+#define AscReadChipScsiID( port )           inp( (port)+IOP_REG_ID )
+
+#define AscGetChipDmaSpeed( port )         ( uchar )inp( (port)+IOP_DMA_SPEED )
+#define AscSetChipDmaSpeed( port, data )   outp( (port)+IOP_DMA_SPEED, data )
+#define AscGetChipQP( port )               ( uchar )inp( (port)+IOP_REG_QP )
+#define AscSetPCAddr( port, data )         outpw( (port)+IOP_REG_PC, data )
+#define AscGetPCAddr( port )               inpw( (port)+IOP_REG_PC )
+#define AscGetChipVerNo( port )            ( uchar )inp( (port)+IOP_VERSION )
+
+#define AscGetChipEEPCmd( port )           ( uchar )inp( (port)+IOP_EEP_CMD )
+#define AscSetChipEEPCmd( port, data )     outp( (port)+IOP_EEP_CMD, data )
+#define AscGetChipEEPData( port )          inpw( (port)+IOP_EEP_DATA )
+#define AscSetChipEEPData( port, data )    outpw( (port)+IOP_EEP_DATA, data )
+
+#define AscGetChipControl( port )          ( uchar )inp( (port)+IOP_CTRL )
+#define AscSetChipControl( port, cc_val )  outp( (port)+IOP_CTRL, cc_val )
+
+#define AscGetChipStatus( port )           ( ASC_CS_TYPE )inpw( (port)+IOP_STATUS )
+#define AscSetChipStatus( port, cs_val )   outpw( (port)+IOP_STATUS, cs_val )
+
+#define AscGetChipCfgLsw( port )           ( ushort )inpw( (port)+IOP_CONFIG_LOW )
+#define AscGetChipCfgMsw( port )           ( ushort )inpw( (port)+IOP_CONFIG_HIGH )
+#define AscSetChipCfgLsw( port, data )     outpw( (port)+IOP_CONFIG_LOW, data )
+#define AscSetChipCfgMsw( port, data )     outpw( (port)+IOP_CONFIG_HIGH, data )
+
+#define AscIsIntPending( port )           ( AscGetChipStatus( port ) & CSW_INT_PENDING )
+#define AscGetChipScsiID( port )          ( ( AscGetChipCfgLsw( port ) >> 8 ) & ASC_MAX_TID )
+
+#define ASC_HALT_EXTMSG_IN     ( ushort )0x8000
+#define ASC_HALT_CHK_CONDITION ( ushort )0x8100
+#define ASC_HALT_SS_QUEUE_FULL ( ushort )0x8200
+#define ASC_HALT_SDTR_REJECTED ( ushort )0x4000
+
+#define ASC_MAX_QNO        0xF8
+#define ASC_DATA_SEC_BEG   ( ushort )0x0080
+#define ASC_DATA_SEC_END   ( ushort )0x0080
+#define ASC_CODE_SEC_BEG   ( ushort )0x0080
+#define ASC_CODE_SEC_END   ( ushort )0x0080
+#define ASC_QADR_BEG       (0x4000)
+#define ASC_QADR_USED      ( ushort )( ASC_MAX_QNO * 64 )
+#define ASC_QADR_END       ( ushort )0x7FFF
+#define ASC_QLAST_ADR      ( ushort )0x7FC0
+#define ASC_QBLK_SIZE      0x40
+#define ASC_BIOS_DATA_QBEG 0xF8
+
+#define ASC_MIN_ACTIVE_QNO 0x01
+
+#define ASC_QLINK_END      0xFF
+#define ASC_EEPROM_WORDS   0x10
+#define ASC_MAX_MGS_LEN    0x10
+
+#define ASC_BIOS_ADDR_DEF  0xDC00
+#define ASC_BIOS_SIZE      0x3800
+#define ASC_BIOS_RAM_OFF   0x3800
+#define ASC_BIOS_RAM_SIZE  0x800
+#define ASC_BIOS_MIN_ADDR  0xC000
+#define ASC_BIOS_MAX_ADDR  0xEC00
+#define ASC_BIOS_BANK_SIZE 0x0400
+
+#define ASC_MCODE_START_ADDR  0x0080
+
+#define ASC_CFG0_HOST_INT_ON    0x0020
+#define ASC_CFG0_BIOS_ON        0x0040
+#define ASC_CFG0_VERA_BURST_ON  0x0080
+#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    0xF0C0
+
+#define CSW_TEST1             ( ASC_CS_TYPE )0x8000
+#define CSW_AUTO_CONFIG       ( ASC_CS_TYPE )0x4000
+#define CSW_RESERVED1         ( ASC_CS_TYPE )0x2000
+#define CSW_IRQ_WRITTEN       ( ASC_CS_TYPE )0x1000
+#define CSW_33MHZ_SELECTED    ( ASC_CS_TYPE )0x0800
+#define CSW_TEST2             ( ASC_CS_TYPE )0x0400
+#define CSW_TEST3             ( ASC_CS_TYPE )0x0200
+#define CSW_RESERVED2         ( ASC_CS_TYPE )0x0100
+#define CSW_DMA_DONE          ( ASC_CS_TYPE )0x0080
+#define CSW_FIFO_RDY          ( ASC_CS_TYPE )0x0040
+
+#define CSW_EEP_READ_DONE     ( ASC_CS_TYPE )0x0020
+
+#define CSW_HALTED            ( ASC_CS_TYPE )0x0010
+#define CSW_SCSI_RESET_ACTIVE ( ASC_CS_TYPE )0x0008
+
+#define CSW_PARITY_ERR        ( ASC_CS_TYPE )0x0004
+#define CSW_SCSI_RESET_LATCH  ( ASC_CS_TYPE )0x0002
+
+#define CSW_INT_PENDING       ( ASC_CS_TYPE )0x0001
+
+#define CIW_INT_ACK      ( ASC_CS_TYPE )0x0100
+#define CIW_TEST1        ( ASC_CS_TYPE )0x0200
+#define CIW_TEST2        ( ASC_CS_TYPE )0x0400
+#define CIW_SEL_33MHZ    ( ASC_CS_TYPE )0x0800
+
+#define CIW_IRQ_ACT      ( ASC_CS_TYPE )0x1000
+
+#define CC_CHIP_RESET   ( uchar )0x80
+#define CC_SCSI_RESET   ( uchar )0x40
+#define CC_HALT         ( uchar )0x20
+#define CC_SINGLE_STEP  ( uchar )0x10
+#define CC_DMA_ABLE     ( uchar )0x08
+#define CC_TEST         ( uchar )0x04
+#define CC_BANK_ONE     ( uchar )0x02
+#define CC_DIAG         ( uchar )0x01
+
+#define ASC_1000_ID0W      0x04C1
+#define ASC_1000_ID0W_FIX  0x00C1
+#define ASC_1000_ID1B      0x25
+
+#define ASC_EISA_BIG_IOP_GAP   (0x1C30-0x0C50)
+#define ASC_EISA_SMALL_IOP_GAP (0x0020)
+#define ASC_EISA_MIN_IOP_ADDR  (0x0C30)
+#define ASC_EISA_MAX_IOP_ADDR  (0xFC50)
+#define ASC_EISA_REV_IOP_MASK  (0x0C83)
+#define ASC_EISA_PID_IOP_MASK  (0x0C80)
+#define ASC_EISA_CFG_IOP_MASK  (0x0C86)
+
+#define ASC_GET_EISA_SLOT( iop )  ( PortAddr )( (iop) & 0xF000 )
+
+#define ASC_EISA_ID_740    0x01745004UL
+#define ASC_EISA_ID_750    0x01755004UL
+
+#define INS_HALTINT        ( ushort )0x6281
+#define INS_HALT           ( ushort )0x6280
+#define INS_SINT           ( ushort )0x6200
+#define INS_RFLAG_WTM      ( ushort )0x7380
+
+#define ASC_MC_SAVE_CODE_WSIZE  0x500
+#define ASC_MC_SAVE_DATA_WSIZE  0x40
+
+typedef struct asc_mc_saved {
+       ushort              data[ASC_MC_SAVE_DATA_WSIZE];
+       ushort              code[ASC_MC_SAVE_CODE_WSIZE];
+} ASC_MC_SAVED;
+
+int                 AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
+int                 AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
+void                AscWaitEEPRead(void);
+void                AscWaitEEPWrite(void);
+ushort              AscReadEEPWord(PortAddr, uchar);
+ushort              AscWriteEEPWord(PortAddr, uchar, ushort);
+ushort              AscGetEEPConfig(PortAddr, ASCEEP_CONFIG dosfar *, ushort);
+int                 AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG dosfar *, ushort);
+int                 AscSetEEPConfig(PortAddr, ASCEEP_CONFIG dosfar *, ushort);
+ushort              AscEEPSum(PortAddr, uchar, uchar);
+
+int                 AscStartChip(PortAddr);
+int                 AscStopChip(PortAddr);
+void                AscSetChipIH(PortAddr, ushort);
+int                 AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
+
+int                 AscIsChipHalted(PortAddr);
+
+void                AscSetChipCfgDword(PortAddr, ulong);
+ulong               AscGetChipCfgDword(PortAddr);
+
+void                AscAckInterrupt(PortAddr);
+void                AscDisableInterrupt(PortAddr);
+void                AscEnableInterrupt(PortAddr);
+void                AscSetBank(PortAddr, uchar);
+uchar               AscGetBank(PortAddr);
+int                 AscResetChipAndScsiBus(PortAddr);
+ushort              AscGetIsaDmaChannel(PortAddr);
+ushort              AscSetIsaDmaChannel(PortAddr, ushort);
+uchar               AscSetIsaDmaSpeed(PortAddr, uchar);
+uchar               AscGetIsaDmaSpeed(PortAddr);
+
+uchar               AscReadLramByte(PortAddr, ushort);
+ushort              AscReadLramWord(PortAddr, ushort);
+ulong               AscReadLramDWord(PortAddr, ushort);
+void                AscWriteLramWord(PortAddr, ushort, ushort);
+void                AscWriteLramDWord(PortAddr, ushort, ulong);
+void                AscWriteLramByte(PortAddr, ushort, uchar);
+int                 AscVerWriteLramDWord(PortAddr, ushort, ulong);
+int                 AscVerWriteLramWord(PortAddr, ushort, ushort);
+int                 AscVerWriteLramByte(PortAddr, ushort, uchar);
+
+ulong               AscMemSumLramWord(PortAddr, ushort, int);
+void                AscMemWordSetLram(PortAddr, ushort, ushort, int);
+void                AscMemWordCopyToLram(PortAddr, ushort, ushort dosfar *, int);
+void                AscMemDWordCopyToLram(PortAddr, ushort, ulong dosfar *, int);
+void                AscMemWordCopyFromLram(PortAddr, ushort, ushort dosfar *, int);
+int                 AscMemWordCmpToLram(PortAddr, ushort, ushort dosfar *, int);
+
+ushort              AscInitAscDvcVar(ASC_DVC_VAR asc_ptr_type *);
+ulong               AscLoadMicroCode(PortAddr, ushort,
+                                                                        ushort dosfar *, ushort);
+ushort              AscInitFromEEP(ASC_DVC_VAR asc_ptr_type *);
+ushort              AscInitFromAscDvcVar(ASC_DVC_VAR asc_ptr_type *);
+ushort              AscInitMicroCodeVar(ASC_DVC_VAR asc_ptr_type * asc_dvc);
+
+void dosfar         AscInitPollIsrCallBack(ASC_DVC_VAR asc_ptr_type *,
+                                                                                  ASC_QDONE_INFO dosfar *);
+int                 AscTestExternalLram(ASC_DVC_VAR asc_ptr_type *);
+ushort              AscTestLramEndian(PortAddr);
+
+uchar               AscMsgOutSDTR(PortAddr, uchar, uchar);
+
+uchar               AscCalSDTRData(uchar, uchar);
+void                AscSetChipSDTR(PortAddr, uchar, uchar);
+int                 AscInitChipAllSynReg(ASC_DVC_VAR asc_ptr_type *, uchar);
+uchar               AscGetSynPeriodIndex(uchar);
+uchar               AscSynIndexToPeriod(uchar);
+uchar               AscAllocFreeQueue(PortAddr, uchar);
+uchar               AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
+int                 AscRiscHaltedAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong);
+int                 AscRiscHaltedAbortTIX(ASC_DVC_VAR asc_ptr_type *, uchar);
+int                 AscRiscHaltedAbortALL(ASC_DVC_VAR asc_ptr_type *);
+int                 AscHostReqRiscHalt(PortAddr);
+int                 AscStopQueueExe(PortAddr);
+int                 AscStartQueueExe(PortAddr);
+int                 AscCleanUpDiscQueue(PortAddr);
+int                 AscCleanUpBusyQueue(PortAddr);
+int                 _AscAbortTidBusyQueue(ASC_DVC_VAR asc_ptr_type *,
+                                                                                 ASC_QDONE_INFO dosfar *, uchar);
+int                 _AscAbortSrbBusyQueue(ASC_DVC_VAR asc_ptr_type *,
+                                                                                 ASC_QDONE_INFO dosfar *, ulong);
+int                 AscWaitTixISRDone(ASC_DVC_VAR asc_ptr_type *, uchar);
+int                 AscWaitISRDone(ASC_DVC_VAR asc_ptr_type *);
+ulong               AscGetOnePhyAddr(ASC_DVC_VAR asc_ptr_type *, uchar dosfar *, ulong);
+
+int                 AscSendScsiQueue(ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                                                        ASC_SCSI_Q dosfar * scsiq,
+                                                                        uchar n_q_required);
+int                 AscPutReadyQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *, uchar);
+int                 AscPutReadySgListQueue(ASC_DVC_VAR asc_ptr_type *,
+                                                                                  ASC_SCSI_Q dosfar *, uchar);
+int                 AscAbortScsiIO(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
+void                AscExeScsiIO(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
+int                 AscSetChipSynRegAtID(PortAddr, uchar, uchar);
+int                 AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
+ushort              AscInitLram(ASC_DVC_VAR asc_ptr_type *);
+int                 AscReInitLram(ASC_DVC_VAR asc_ptr_type *);
+ushort              AscInitQLinkVar(ASC_DVC_VAR asc_ptr_type *);
+int                 AscSetLibErrorCode(ASC_DVC_VAR asc_ptr_type *, ushort);
+int                 _AscWaitQDone(PortAddr, ASC_SCSI_Q dosfar *);
+
+int                 AscEnterCritical(void);
+void                AscLeaveCritical(int);
+
+int                 AscIsrChipHalted(ASC_DVC_VAR asc_ptr_type *);
+uchar               _AscCopyLramScsiDoneQ(PortAddr, ushort,
+                                                                                 ASC_QDONE_INFO dosfar *, ulong);
+int                 AscIsrQDone(ASC_DVC_VAR asc_ptr_type *);
+ushort              AscIsrExeBusyQueue(ASC_DVC_VAR asc_ptr_type *, uchar);
+int                 AscScsiSetupCmdQ(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *,
+                                                                        uchar dosfar *, ulong);
+
+int                 AscScsiInquiry(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *,
+                                                                  uchar dosfar *, int);
+int                 AscScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *);
+int                 AscScsiStartStopUnit(ASC_DVC_VAR asc_ptr_type *,
+                                                                                ASC_SCSI_REQ_Q dosfar *, uchar);
+int                 AscScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *,
+                                                                               ASC_SCSI_REQ_Q dosfar *,
+                                                                               uchar dosfar *);
+
+ulong dosfar       *swapfarbuf4(uchar dosfar *);
+int                 PollQueueDone(ASC_DVC_VAR asc_ptr_type *,
+                                                                 ASC_SCSI_REQ_Q dosfar *,
+                                                                 int);
+int                 PollScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *,
+                                                                                ASC_SCSI_REQ_Q dosfar *,
+                                                                                ASC_CAP_INFO dosfar *);
+int                 PollScsiInquiry(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_REQ_Q dosfar *,
+                                                                       uchar dosfar *, int);
+int                 PollScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *,
+                                                                                 ASC_SCSI_REQ_Q dosfar *);
+int                 PollScsiStartUnit(ASC_DVC_VAR asc_ptr_type *,
+                                                                         ASC_SCSI_REQ_Q dosfar *);
+int                 InitTestUnitReady(ASC_DVC_VAR asc_ptr_type *,
+                                                                         ASC_SCSI_REQ_Q dosfar *);
+void                AscDispInquiry(uchar, uchar, ASC_SCSI_INQUIRY dosfar *);
+int                 AscPollQDone(ASC_DVC_VAR asc_ptr_type *,
+                                                                ASC_SCSI_REQ_Q dosfar *, int);
+
+int                 AscSetBIOSBank(PortAddr, int, ushort);
+int                 AscSetVlBIOSBank(PortAddr, int);
+int                 AscSetEisaBIOSBank(PortAddr, int);
+int                 AscSetIsaBIOSBank(PortAddr, int);
+
+int                 AscIsBiosEnabled(PortAddr, ushort);
+void                AscResetScsiBus(PortAddr);
+void                AscClrResetScsiBus(PortAddr);
+
+void                AscSingleStepChip(PortAddr);
+uchar               AscSetChipScsiID(PortAddr, uchar);
+ushort              AscGetChipBiosAddress(PortAddr, ushort);
+ushort              AscSetChipBiosAddress(PortAddr, ushort, ushort);
+uchar               AscGetChipVersion(PortAddr, ushort);
+ushort              AscGetChipBusType(PortAddr);
+
+PortAddr            AscSearchIOPortAddr11(PortAddr);
+PortAddr            AscSearchIOPortAddr100(PortAddr);
+int                 AscFindSignature(PortAddr);
+void                AscToggleIRQAct(PortAddr);
+int                 AscResetChip(PortAddr);
+void                AscClrResetChip(PortAddr);
+
+short               itos(ushort, uchar dosfar *, short, short);
+int                 insnchar(uchar dosfar *, short, short, ruchar, short);
+void                itoh(ushort, ruchar dosfar *);
+void                btoh(uchar, ruchar dosfar *);
+void                ltoh(ulong, ruchar dosfar *);
+uchar dosfar       *todstr(ushort, uchar dosfar *);
+uchar dosfar       *tohstr(ushort, uchar dosfar *);
+uchar dosfar       *tobhstr(uchar, uchar dosfar *);
+uchar dosfar       *tolhstr(ulong, uchar dosfar *);
+
+void                AscSetISAPNPWaitForKey(void);
+uchar               AscGetChipIRQ(PortAddr, ushort);
+uchar               AscSetChipIRQ(PortAddr, uchar, ushort);
+uchar               AscGetChipScsiCtrl(PortAddr);
+
+ushort              AscGetEisaChipCfg(PortAddr);
+ushort              AscGetEisaChipGpReg(PortAddr);
+ushort              AscSetEisaChipCfg(PortAddr, ushort);
+ushort              AscSetEisaChipGpReg(PortAddr, ushort);
+
+ulong               AscGetEisaProductID(PortAddr);
+PortAddr            AscSearchIOPortAddrEISA(PortAddr);
+
+int                 AscPollQTailSync(PortAddr);
+int                 AscPollQHeadSync(PortAddr);
+int                 AscWaitQTailSync(PortAddr);
+
+int                 _AscRestoreMicroCode(PortAddr, ASC_MC_SAVED dosfar *);
+
+int                 AscSCAM(ASC_DVC_VAR asc_ptr_type *);
+
+ushort              SwapByteOfWord(ushort word_val);
+ulong               SwapWordOfDWord(ulong dword_val);
+ulong               AdjEndianDword(ulong dword_val);
+
+int                 AscAdjEndianScsiQ(ASC_SCSI_Q dosfar *);
+int                 AscAdjEndianQDoneInfo(ASC_QDONE_INFO dosfar *);
+
+extern int          DvcEnterCritical(void);
+extern void         DvcLeaveCritical(int);
+
+extern void         DvcInPortWords(PortAddr, ushort dosfar *, int);
+extern void         DvcOutPortWords(PortAddr, ushort dosfar *, int);
+extern void         DvcOutPortDWords(PortAddr, ulong dosfar *, int);
+
+extern void         DvcSleepMilliSecond(ulong);
+extern void         DvcDisplayString(uchar dosfar *);
+extern ulong        DvcGetPhyAddr(uchar dosfar * buf_addr, ulong buf_len);
+extern ulong        DvcGetSGList(ASC_DVC_VAR asc_ptr_type *, uchar dosfar *, ulong,
+                                                                ASC_SG_HEAD dosfar *);
+
+extern void         DvcSCAMDelayMS(ulong);
+extern int          DvcDisableCPUInterrupt(void);
+extern void         DvcRestoreCPUInterrupt(int);
+
+void                DvcPutScsiQ(PortAddr, ushort, ushort dosfar *, int);
+void                DvcGetQinfo(PortAddr, ushort, ushort dosfar *, int);
+
+PortAddr            AscSearchIOPortAddr(PortAddr, ushort);
+ushort              AscInitGetConfig(ASC_DVC_VAR asc_ptr_type *);
+ushort              AscInitSetConfig(ASC_DVC_VAR asc_ptr_type *);
+ushort              AscInitAsc1000Driver(ASC_DVC_VAR asc_ptr_type *);
+int                 AscInitScsiTarget(ASC_DVC_VAR asc_ptr_type *,
+                                                                         ASC_DVC_INQ_INFO dosfar *,
+                                                                         uchar dosfar *,
+                                                                         ASC_CAP_INFO_ARRAY dosfar *,
+                                                                         ushort);
+int                 AscInitPollBegin(ASC_DVC_VAR asc_ptr_type *);
+int                 AscInitPollEnd(ASC_DVC_VAR asc_ptr_type *);
+int                 AscInitPollTarget(ASC_DVC_VAR asc_ptr_type *,
+                                                                         ASC_SCSI_REQ_Q dosfar *,
+                                                                         ASC_SCSI_INQUIRY dosfar *,
+                                                                         ASC_CAP_INFO dosfar *);
+int                 AscExeScsiQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q dosfar *);
+
+int                 AscISR(ASC_DVC_VAR asc_ptr_type *);
+void                AscISR_AckInterrupt(ASC_DVC_VAR asc_ptr_type *);
+int                 AscISR_CheckQDone(ASC_DVC_VAR asc_ptr_type *,
+                                                                         ASC_QDONE_INFO dosfar *,
+                                                                         uchar dosfar *);
+
+int                 AscStartUnit(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_TIX_TYPE);
+int                 AscStopUnit(
+                                                                  ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                                                  ASC_SCSI_TIX_TYPE target_ix
+);
+
+uint                AscGetNumOfFreeQueue(ASC_DVC_VAR asc_ptr_type *, uchar, uchar);
+int                 AscSgListToQueue(int);
+int                 AscQueueToSgList(int);
+int                 AscSetDvcErrorCode(ASC_DVC_VAR asc_ptr_type *, uchar);
+
+int                 AscAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong);
+int                 AscResetDevice(ASC_DVC_VAR asc_ptr_type *, uchar);
+int                 AscResetSB(ASC_DVC_VAR asc_ptr_type *);
+
+void                AscEnableIsaDma(uchar);
+void                AscDisableIsaDma(uchar);
+
+ulong               AscGetMaxDmaAddress(ushort);
+ulong               AscGetMaxDmaCount(ushort);
+
+int                 AscSaveMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *);
+int                 AscRestoreOldMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *);
+int                 AscRestoreNewMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SAVED dosfar *);
+
+/*
+ * --- Debugging Header
+ */
+
+#ifdef ADVANSYS_DEBUG
+#define STATIC
+#else /* ADVANSYS_DEBUG */
+#define STATIC static
+#endif /* ADVANSYS_DEBUG */
+
+
+/*
+ * --- Driver Constants and Macros
+ */
+
+#define ASC_NUM_BOARD_SUPPORTED 4
+#define ASC_NUM_BUS                            4
+
+/* Reference Scsi_Host hostdata */
+#define ASC_BOARD(host) ((struct asc_board *) &(host)->hostdata)
+
+#define NO_ISA_DMA     0xff            /* No ISA DMA Channel Used */
+
+#ifndef min
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#endif /* min */
+
+/* Asc Library return codes */
+#define ASC_TRUE               1
+#define ASC_FALSE              0
+#define ASC_NOERROR            1
+#define ASC_BUSY               0
+#define ASC_ERROR              (-1)
+
+/* 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)
+
+/* asc_enqueue() flags */
+#define ASC_FRONT              1
+#define ASC_BACK               2
+
+/* PCI configuration declarations */
+
+#define ASC_PCI_REV_A_INIT             0x01
+#define ASC_PCI_REV_A_DONE             0x02
+#define ASC_PCI_REV_B_INIT             0x04
+#define ASC_PCI_REV_B_DONE             0x08
+
+#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
+
+/* 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
+
+/* DISPLAY CONTROLLER */
+#define PCI_SUB_CLASS_VGA_CONTROLLER                   0x00
+#define PCI_SUB_CLASS_XGA_CONTROLLER                   0x01
+#define PCI_SUB_CLASS_OTHER_DISPLAY_CONTROLLER 0x80
+
+/* MULTIMEDIA CONTROLLER */
+#define PCI_SUB_CLASS_VIDEO_DEVICE                             0x00
+#define PCI_SUB_CLASS_AUDIO_DEVICE                             0x01
+#define PCI_SUB_CLASS_OTHER_MULTIMEDIA_DEVICE  0x80
+
+/* MEMORY CONTROLLER */
+#define PCI_SUB_CLASS_RAM_CONTROLLER                   0x00
+#define PCI_SUB_CLASS_FLASH_CONTROLLER                 0x01
+#define PCI_SUB_CLASS_OTHER_MEMORY_CONTROLLER  0x80
+
+/* 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
+
+#define PCI_MAX_SLOT                   0x1F
+#define PCI_MAX_BUS                            0xFF
+#define ASC_PCI_VENDORID               0x10CD
+#define PCI_IOADDRESS_MASK             0xFFFE
+
+/* PCI IO Port Addresses to generate special cycle */
+
+#define PCI_CONFIG_ADDRESS_MECH1               0x0CF8
+#define PCI_CONFIG_DATA_MECH1                  0x0CFC
+
+#define PCI_CONFIG_FORWARD_REGISTER            0x0CFA  /* 0=type 0; 1=type 1; */
+
+#define PCI_CONFIG_BUS_NUMBER_MASK             0x00FF0000
+#define PCI_CONFIG_DEVICE_FUNCTION_MASK        0x0000FF00
+#define PCI_CONFIG_REGISTER_NUMBER_MASK        0x000000F8
+
+#define PCI_DEVICE_FOUND                               0x0000
+#define PCI_DEVICE_NOT_FOUND                   0xffff
+
+#define SUBCLASS_OFFSET        0x0A
+#define CLASSCODE_OFFSET       0x0B
+#define VENDORID_OFFSET                0x00
+#define DEVICEID_OFFSET                0x02
+
+/*
+ * --- Driver Macros
+ */
+
+#ifndef ADVANSYS_STATS
+#define ASC_STATS(counter)
+#define ASC_STATS_ADD(counter, count)
+#else /* ADVANSYS_STATS */
+#define ASC_STATS(counter)                             asc_stats.counter++
+#define ASC_STATS_ADD(counter, count)  asc_stats.counter += (count)
+#endif /* ADVANSYS_STATS */
+
+#ifndef ADVANSYS_DEBUG
+
+#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_DVC_VAR(lvl, v)
+#define        ASC_DBG_PRT_DVC_CFG(lvl, c)
+#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)
+#define ASC_ASSERT(a)
+
+#else /* ADVANSYS_DEBUG */
+
+/*
+ * Debugging Message Levels:
+ * 0: Errors Only
+ * 1: High-Level Tracing
+ * 2-N: Verbose Tracing
+ */
+
+#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)); \
+               } \
+       }
+
+#define        ASC_DBG3(lvl, s, a1, a2, a3) \
+       { \
+               if (asc_dbglvl >= (lvl)) { \
+                       printk((s), (a1), (a2), (a3)); \
+               } \
+       }
+
+#define        ASC_DBG4(lvl, s, a1, a2, a3, a4) \
+       { \
+               if (asc_dbglvl >= (lvl)) { \
+                       printk((s), (a1), (a2), (a3), (a4)); \
+               } \
+       }
+
+#define        ASC_DBG_PRT_SCSI_HOST(lvl, s) \
+       { \
+               if (asc_dbglvl >= (lvl)) { \
+                       asc_prt_scsi_host(s); \
+               } \
+       }
+
+#define        ASC_DBG_PRT_DVC_VAR(lvl, v) \
+       { \
+               if (asc_dbglvl >= (lvl)) { \
+                       asc_prt_dvc_var(v); \
+               } \
+       }
+
+#define        ASC_DBG_PRT_DVC_CFG(lvl, c) \
+       { \
+               if (asc_dbglvl >= (lvl)) { \
+                       asc_prt_dvc_cfg(c); \
+               } \
+       }
+
+#define        ASC_DBG_PRT_SCSI_Q(lvl, scsiqp) \
+       { \
+               if (asc_dbglvl >= (lvl)) { \
+                       asc_prt_scsi_q(scsiqp); \
+               } \
+       }
+
+#define        ASC_DBG_PRT_QDONE_INFO(lvl, qdone) \
+       { \
+               if (asc_dbglvl >= (lvl)) { \
+                       asc_prt_qdone_info(qdone); \
+               } \
+       }
+
+#define        ASC_DBG_PRT_HEX(lvl, name, start, length) \
+       { \
+               if (asc_dbglvl >= (lvl)) { \
+                       asc_prt_hex((name), (start), (length)); \
+               } \
+       }
+
+#define        ASC_DBG_PRT_CDB(lvl, cdb, len) \
+               ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
+
+#define        ASC_DBG_PRT_SENSE(lvl, sense, len) \
+               ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
+
+#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
+               ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
+
+#define ASC_ASSERT(a) \
+       { \
+               if (!(a)) { \
+                       printk("ASC_ASSERT() Failure: file %s, line %d\n", \
+                               __FILE__, __LINE__); \
+               } \
+       }
+#endif /* ADVANSYS_DEBUG */
+
+
+/*
+ * --- Driver Structures
+ */
+
+/*
+ * 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.
+ */
+struct asc_board {
+       /* Asc Library */
+       ASC_DVC_VAR                      board;                                 /* Board configuration */
+       ASC_DVC_CFG                      cfg;                                   /* Device configuration */
+       uchar                            overrun_buf[ASC_OVERRUN_BSIZE];
+       /* Queued Commands */
+       ASC_SCSI_BIT_ID_TYPE pending_tidmask;           /* Pending command mask */
+       Scsi_Cmnd                        *pending[ASC_MAX_TID];
+       /* Target Initialization */
+       ASC_SCSI_BIT_ID_TYPE init_tidmask;                      /* Target initialized mask */
+       ASC_SCSI_REQ_Q           scsireqq;
+       ASC_CAP_INFO             cap_info;
+       ASC_SCSI_INQUIRY         inquiry;
+};
+
+/*
+ * PCI configuration structures
+ */
+typedef struct _PCI_DATA_
+{
+       uchar   type;
+       uchar   bus;
+       uchar   slot;
+       uchar   func;
+       uchar   offset;
+} PCI_DATA;
+
+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;
+
+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;
+
+#ifdef ADVANSYS_STATS
+struct asc_stats {
+       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;              /* # calls to advansys_interrupt() */
+       ulong   callback;               /* # calls asc_isr_callback() */
+       ulong   cont_cnt;               /* # non-scatter-gather I/O requests received */
+       ulong   cont_xfer;              /* contiguous transfer total (512 byte units) */
+       ulong   sg_cnt;                 /* # scatter-gather I/O requests received */
+       ulong   sg_elem;                /* scatter-gather element total */
+       ulong   sg_xfer;                /* scatter-gather tranfer total (512 byte units) */
+       ulong   error;                  /* # AscExeScsiQueue() ASC_ERROR returns. */
+       /*
+        * Number of times interrupts disabled in advansys_queuecommand() and
+        * asc_isr_callback(), respectively. For the former indicates how many
+        * times commands were pending when a new command was received.
+        */
+       ulong   cmd_disable;
+       ulong   intr_disable;
+       /*
+        * Number of times asc_enqueue() called. Indicates how many ASC_BUSY
+        * returns have occurred.
+        */
+       ulong   enqueue;
+       ulong   dequeue;                /* # calls to asc_dequeue(). */
+       /*
+        * Number of times asc_rmqueue() called and the specified command
+        * was found and removed.
+        */
+       ulong   rmqueue;
+} asc_stats;
+#endif /* ADVANSYS_STATS */
+
+
+/*
+ * --- Driver Data
+ */
+
+#ifdef LINUX_1_3
+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 /* LINUX_1_3 */
+
+STATIC int asc_board_count; /* Number of boards detected in system. */
+STATIC struct Scsi_Host        *asc_host[ASC_NUM_BOARD_SUPPORTED];
+STATIC Scsi_Cmnd *asc_scsi_done; /* Commands needing done function call. */
+
+STATIC ushort asc_bus[ASC_NUM_BUS] = {
+       ASC_IS_ISA,
+       ASC_IS_VL,
+       ASC_IS_EISA,
+       ASC_IS_PCI,
+};
+
+/*
+ * Used with the LILO 'advansys' option to eliminate or
+ * limit I/O port probing at boot time, cf. advansys_setup().
+ */
+int asc_iopflag = ASC_FALSE;
+int asc_ioport[ASC_NUM_BOARD_SUPPORTED] = { 0, 0, 0, 0 };
+
+#ifdef ADVANSYS_DEBUG
+char *
+asc_bus_name[ASC_NUM_BUS] = {
+       "ASC_IS_ISA",
+       "ASC_IS_VL",
+       "ASC_IS_EISA",
+       "ASC_IS_PCI",
+};
+
+int            asc_dbglvl = 0;
+#endif /* ADVANSYS_DEBUG */
+
+
+/*
+ * --- Driver Function Prototypes
+ *
+ * advansys.h contains function prototypes for functions global to Linux.
+ */
+
+#ifdef LINUX_1_3
+STATIC int                     asc_proc_copy(off_t, off_t, char *, int , char *, int);
+#endif /* LINUX_1_3 */
+STATIC void            advansys_interrupt(int, struct pt_regs *);
+STATIC void            advansys_command_done(Scsi_Cmnd *);
+STATIC int                     asc_execute_scsi_cmnd(Scsi_Cmnd *);
+STATIC void            asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
+STATIC void                    asc_execute_pending(struct Scsi_Host *);
+STATIC int                     asc_init_dev(ASC_DVC_VAR *, Scsi_Cmnd *);
+STATIC int                     asc_srch_pci_dev(PCI_DEVICE *);
+STATIC uchar           asc_scan_method(PCI_DEVICE *);
+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_enqueue(struct Scsi_Host *, Scsi_Cmnd *, int, int);
+STATIC Scsi_Cmnd       *asc_dequeue(struct Scsi_Host *, int);
+STATIC int                     asc_rmqueue(struct Scsi_Host *, Scsi_Cmnd *, int);
+
+/* XXX - Asc Library Routines not supposed to be used directly */
+ushort                         AscGetChipBiosAddress(PortAddr, ushort);
+int             AscFindSignature(PortAddr);
+
+#ifdef ADVANSYS_STATS
+STATIC int             asc_prt_stats(char *, int);
+STATIC int             asc_prt_stats_line(char *, int, char *fmt, ...);
+#endif /* ADVANSYS_STATS */
+#ifdef ADVANSYS_DEBUG
+STATIC void    asc_prt_scsi_host(struct Scsi_Host *);
+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);
+STATIC int             interrupts_enabled(void);
+#endif /* ADVANSYS_DEBUG */
+
+
+/*
+ * --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
+ */
+
+#ifdef LINUX_1_3
+/*
+ * advansys_proc_info() - /proc/scsi/advansys/[0-ASC_NUM_BOARD_SUPPORTED]
+ *
+ * *buffer: I/O buffer
+ * **start: if inout == FALSE pointer into buffer where user read should start
+ * offset: current offset into /proc/scsi/advansys 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
+ * /proc/scsi/advansys file.
+ */
+int
+advansys_proc_info(char *buffer, char **start, off_t offset, int length, 
+                                  int hostno, int inout)
+{
+       struct Scsi_Host        *shp;
+       int                                     i;
+       char                            *cp;
+       int                                     cplen;
+       int                                     cnt;
+       int                                     totcnt;
+       int                                     leftlen;
+       char                            *curbuf;
+       off_t                           advoffset;
+    Scsi_Device                        *scd;
+       char                            prtbuf[480];    /* 6 lines */
+
+       ASC_DBG(1, "advansys_proc_info: begin\n");
+
+       /*
+        * User write not supported.
+        */
+       if (inout == TRUE) {
+               return(-ENOSYS);
+       }
+
+       /*
+        * User read of /proc/scsi/advansys 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);
+       }
+       shp = asc_host[i];
+
+       /* Always copy read data to the beginning of the buffer. */
+       *start = buffer;
+
+       curbuf = buffer;
+       advoffset = 0;
+       totcnt = 0;
+       leftlen = length;
+
+       /* Get board information. */
+       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;
+
+       /*
+        * Get and copy information for each device attached to the board.
+        */
+       cp = &prtbuf[0];
+       sprintf(cp, "\nDevices attached to SCSI Host %d:\n", shp->host_no);
+       cplen = strlen(cp);
+       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;
+
+       cp = &prtbuf[0];
+    for (scd = scsi_devices; scd; scd = scd->next) {
+               if (scd->host == shp) {
+               proc_print_scsidevice(scd, cp, &cplen, 0);
+                       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;
+               }
+    }
+    
+#ifdef ADVANSYS_STATS
+       /*
+        * prtbuf[] has about 6 lines worth of space. If the statistics ever
+        * get longer than 6 lines, prtbuf[] should be increased in size. If
+        * prtbuf[] is too small it will not be overwritten. Instead the user
+        * just won't get all of the available statistics.
+        */
+       cp = &prtbuf[0];
+       cplen = asc_prt_stats(cp, sizeof(prtbuf));
+       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 */
+
+       ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
+
+       return totcnt;
+}
+#endif /* LINUX_1_3 */
+
+
+/*
+ * 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().
+ */
+int
+advansys_detect(Scsi_Host_Template *tpnt)
+{
+       static int                      detect_called = ASC_FALSE;
+       int                                     iop;
+       int                                     bus;
+       struct Scsi_Host        *shp;
+       ASC_DVC_VAR                     *boardp;
+       int                                     ioport = 0;
+       PCI_DEVICE                      pciDevice;
+       PCI_CONFIG_SPACE        pciConfig;
+       int                                     ret;
+       extern PortAddr         _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX];
+
+
+       if (detect_called == ASC_FALSE) {
+               detect_called = ASC_TRUE;
+       } else {
+               printk("AdvanSys SCSI: advansys_detect() mulitple calls ignored\n");
+               return 0;
+       }
+
+       ASC_DBG(1, "advansys_detect: begin\n");
+
+#ifdef LINUX_1_3
+       tpnt->proc_dir = &proc_scsi_advansys;
+#endif /* LINUX_1_3 */
+
+#ifdef ADVANSYS_STATS
+       memset(&asc_stats, 0, sizeof(asc_stats));
+#endif /* ADVANSYS_STATS */
+
+       asc_board_count = 0;
+
+       /*
+        * 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, "asdvansys_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;
+
+       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;
+
+               while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) {
+
+                       ASC_DBG1(2, "advansys_detect: asc_board_count %d\n",
+                               asc_board_count);
+
+                       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;
+
+                       case ASC_IS_EISA:
+                               iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
+                               break;
+
+                       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;
+
+                       default:
+                               ASC_DBG(0, "advansys_detect: unknown bus type\n");
+                               break;
+                       }
+                       ASC_DBG1(1, "advansys_detect: iop %x\n", iop);
+
+                       /*
+                        * Adapter not found, try next bus type.
+                        */
+                       if (iop == 0) {
+                               break;
+                       }
+
+                       /*
+                        * Adapter found.
+                        *
+                        * Register the adapter, get its configuration, and
+                        * initialize it.
+                        */
+                       ASC_DBG(2, "advansys_detect: scsi_register()\n");
+                       shp = scsi_register(tpnt, sizeof(struct asc_board));
+
+                       /* Save a pointer to the Scsi_host of each found board. */
+                       asc_host[asc_board_count++] = shp;
+
+                       /* Initialize private per board data */
+                       memset(ASC_BOARD(shp), 0, sizeof(struct asc_board));
+                       boardp = &ASC_BOARD(shp)->board;
+                       boardp->cfg = &ASC_BOARD(shp)->cfg;
+                       boardp->cfg->overrun_buf = &ASC_BOARD(shp)->overrun_buf[0];
+                       boardp->iop_base = iop;
+
+                       /*
+                        * Set the board bus type and PCI IRQ for AscInitGetConfig().
+                        */
+                       boardp->bus_type = asc_bus[bus];
+                       switch (boardp->bus_type) {
+                       case ASC_IS_ISA:
+                               shp->unchecked_isa_dma = TRUE;
+                               break;
+                       case ASC_IS_EISA:
+                               shp->unchecked_isa_dma = FALSE;
+                               break;
+                       case ASC_IS_VL:
+                               shp->unchecked_isa_dma = FALSE;
+                               break;
+                       case ASC_IS_PCI:
+                               shp->irq = boardp->irq_no = pciConfig.irqLine;
+                               boardp->cfg->pci_device_id = pciConfig.deviceID;
+                               shp->unchecked_isa_dma = FALSE;
+                               break;
+                       default:
+                               ASC_DBG(0, "advansys_detect: unknown adapter type");
+                               shp->unchecked_isa_dma = TRUE;
+                               break;
+                       }
+
+                       /*
+                        * Get the board configuration.  AscInitGetConfig() may change
+                        * the board's bus_type value. The asc_bus[bus] value should no
+                        * longer be used.
+                        */
+                       ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n");
+                       switch(ret = AscInitGetConfig(boardp)) {
+                       case 0: /* No error */
+                               break;
+                       case ASC_WARN_IO_PORT_ROTATE:
+                               ASC_DBG(0, "AscInitGetConfig: I/O port address modified\n");
+                               break;
+                       case ASC_WARN_EEPROM_CHKSUM:
+                               ASC_DBG(0, "AscInitGetConfig: EEPROM checksum error\n");
+                               break;
+                       case ASC_WARN_IRQ_MODIFIED:
+                               ASC_DBG(0, "AscInitGetConfig: IRQ modified\n");
+                               break;
+                       case ASC_WARN_CMD_QNG_CONFLICT:
+                               ASC_DBG(0,
+                                       "AscInitGetConfig: Tag queuing enabled w/o disconnects\n");
+                               break;
+                       default:
+                               ASC_DBG1(0, "AscInitGetConfig: Unknown warning: %x\n", ret);
+                               break;
+                       }
+                       if (boardp->err_code != 0) {
+                               ASC_DBG2(0,
+                                       "AscInitGetConfig: error: init_state %x, err_code %x\n",
+                                       boardp->init_state, boardp->err_code);
+                               scsi_unregister(shp);
+                               asc_board_count--;
+                               continue;
+                       }
+
+                       /*
+                        * Modify board configuration.
+                        */
+                       boardp->isr_callback = (Ptr2Func) asc_isr_callback;
+                       boardp->exe_callback = (Ptr2Func) NULL;
+
+                       ASC_DBG(2, "advansys_detect: AscInitSetConfig()\n");
+                       switch (ret = AscInitSetConfig(boardp)) {
+                       case 0: /* No error. */
+                               break;
+                       case ASC_WARN_IO_PORT_ROTATE:
+                               ASC_DBG(0, "AscInitSetConfig: I/O port address modified\n");
+                               break;
+                       case ASC_WARN_EEPROM_CHKSUM:
+                               ASC_DBG(0, "AscInitSetConfig: EEPROM checksum error\n");
+                               break;
+                       case ASC_WARN_IRQ_MODIFIED:
+                               ASC_DBG(0, "AscInitSetConfig: IRQ modified\n");
+                               break;
+                       case ASC_WARN_CMD_QNG_CONFLICT:
+                               ASC_DBG(0, "AscInitSetConfig: Tag queuing w/o disconnects\n");
+                               break;
+                       default:
+                               ASC_DBG1(0, "AscInitSetConfig: Unknown warning: %x\n", ret);
+                               break;
+                       }
+                       if (boardp->err_code != 0) {
+                               ASC_DBG2(0,
+                                       "AscInitSetConfig: error: init_state %x, err_code %x\n",
+                                       boardp->init_state, boardp->err_code);
+                               scsi_unregister(shp);
+                               asc_board_count--;
+                               continue;
+                       }
+
+                       /*
+                        * Finish initializing the 'Scsi_Host' structure.
+                        */
+
+                       /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
+                       if (boardp->bus_type != ASC_IS_PCI) {
+                               shp->irq = boardp->irq_no;
+                       }
+
+                       shp->io_port = boardp->iop_base;
+                       shp->n_io_port = ASC_IOADR_GAP;
+                       shp->this_id = boardp->cfg->chip_scsi_id;
+
+                       /* Maximum number of queues this adapter can handle. */
+                       shp->can_queue = boardp->max_total_qng;
+
+                       /*
+                        * XXX - Command queuing limits are maintained per target
+                        * by AdvanSys adapters. Set 'cmd_per_lun' to the minimum
+                        * value of the all the target settings for the adapter.
+                        *
+                        * For now set 'cmd_per_lun' to 'max_total_qng'. This
+                        * value should be adjusted every time a new device is
+                        * found in asc_init_dev().
+                        *
+                        * XXX - memory allocation is done by the mid-level scsi
+                        * driver based on 'cmd_per_lun'. If 'sg_tablesize' is too large
+                        * allocation failures can occur in scsi_register_host().
+                        * A 'Scsi_Cmnd' structure is pre-allocated for each command
+                        * also DMA memory is reserved. Set it artificially low for now.
+                        *
+                        * shp->cmd_per_lun = boardp->max_total_qng;
+                        */
+#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);
+                       
+                       /* Maximum number of scatter-gather elements adapter can handle. */
+                       /*
+                        * XXX - memory allocation is done by the mid-level scsi
+                        * driver based on sg_tablesize. If 'sg_tablesize' is too large
+                        * allocation failures can occur in scsi_register_host().
+                        */
+#ifdef MODULE
+                       shp->sg_tablesize = 8;
+#else /* MODULE */
+                       shp->sg_tablesize = ASC_MAX_SG_LIST;
+#endif /* MODULE */
+                       ASC_DBG1(1, "advansys_detect: sg_tablesize: %d\n",
+                               shp->sg_tablesize);
+
+                       /* BIOS start address. */
+                       shp->base = (char *) ((ulong) AscGetChipBiosAddress(
+                                                                                               boardp->iop_base,
+                                                                                               boardp->bus_type));
+
+                       /*
+                        * Register Board Resources - I/O Port, DMA, IRQ
+                        */
+
+                       /* Register I/O port range */
+                       ASC_DBG(2, "advansys_detect: request_region()\n");
+                       request_region(shp->io_port, shp->n_io_port, "advansys");
+
+                       /* Register DMA channel for ISA bus. */
+                       if ((boardp->bus_type & ASC_IS_ISA) == 0) {
+                               shp->dma_channel = NO_ISA_DMA;
+                       } else {
+                               shp->dma_channel = boardp->cfg->isa_dma_channel;
+                               if ((ret = request_dma(shp->dma_channel, "advansys")) != 0) {
+                                       ASC_DBG2(0, "advansys_detect: request_dma() %d failed %d\n",
+                                               shp->dma_channel, ret);
+                                       release_region(shp->io_port, shp->n_io_port);
+                                       scsi_unregister(shp);
+                                       asc_board_count--;
+                                       continue;
+                               }
+                               AscEnableIsaDma(shp->dma_channel);
+                       }
+
+                       /* Register IRQ Number. */
+                       ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq);
+                       if ((ret = request_irq(shp->irq, advansys_interrupt,
+                                                               SA_INTERRUPT, "advansys")) != 0) {
+                               ASC_DBG1(0, "advansys_detect: request_irq() failed %d\n", ret);
+                               release_region(shp->io_port, shp->n_io_port);
+                               if (shp->dma_channel != NO_ISA_DMA) {
+                                       free_dma(shp->dma_channel);
+                               }
+                               scsi_unregister(shp);
+                               asc_board_count--;
+                               continue;
+                       }
+
+                       /*
+                        * Initialize board RISC chip and enable interrupts.
+                        */
+                       ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()\n");
+                       if (AscInitAsc1000Driver(boardp)) {
+                               ASC_DBG2(0,
+                                       "AscInitAsc1000Driver: error: init_state %x, err_code %x\n",
+                                       boardp->init_state, boardp->err_code);
+                               release_region(shp->io_port, shp->n_io_port);
+                               if (shp->dma_channel != NO_ISA_DMA) {
+                                       free_dma(shp->dma_channel);
+                               }
+                               free_irq(shp->irq);
+                               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.
+ */
+int
+advansys_release(struct Scsi_Host *shp)
+{
+       ASC_DBG(1, "advansys_release: begin\n");
+       free_irq(shp->irq);
+       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);
+       scsi_unregister(shp);
+       ASC_DBG(1, "advansys_release: end\n");
+       return 0;
+}
+
+/*
+ * advansys_info()
+ *
+ * Return suitable for printing on the console with the argument
+ * adapter's configuration information.
+ */
+const char *
+advansys_info(struct Scsi_Host *shp)
+{
+       static char     info[128];
+       ASC_DVC_VAR             *boardp;
+       char                    *busname;
+
+       boardp = &ASC_BOARD(shp)->board;
+       ASC_DBG(1, "advansys_info: begin\n");
+       if (boardp->bus_type & ASC_IS_ISA) {
+               sprintf(info,
+                       "AdvanSys SCSI %s: ISA (%u CDB): BIOS %X, IO %X-%X, IRQ %u, DMA %u",
+                       ASC_VERSION, ASC_BOARD(shp)->board.max_total_qng,
+                       (unsigned) shp->base, shp->io_port,
+                       shp->io_port + (shp->n_io_port - 1), shp->irq, shp->dma_channel);
+       } else {
+               switch (boardp->bus_type) {
+               case ASC_IS_EISA:
+                       busname = "EISA";
+                       break;
+               case ASC_IS_VL:
+                       busname = "VL";
+                       break;
+               case ASC_IS_PCI:
+                       busname = "PCI";
+                       break;
+               default:
+                       busname = "?";
+                       ASC_DBG1(0, "advansys_info: unknown bus type %d\n",
+                               boardp->bus_type);
+                       break;
+               }
+               /* No DMA channel for non-ISA busses. */
+               sprintf(info,
+                       "AdvanSys SCSI %s: %s (%u CDB): BIOS %X, IO %X-%X, IRQ %u",
+                       ASC_VERSION, busname, ASC_BOARD(shp)->board.max_total_qng,
+                       (unsigned) shp->base, shp->io_port,
+                       shp->io_port + (shp->n_io_port - 1), shp->irq);
+       }
+       ASC_DBG(1, "advansys_info: end\n");
+       return info;
+}
+
+/*
+ * advansys_command()
+ *
+ * Polled-I/O. Apparently host driver shouldn't return until
+ * command is finished.
+ *
+ * XXX - Can host driver block here instead of spinning on command status?
+ */
+int
+advansys_command(Scsi_Cmnd *scp)
+{
+       ASC_DBG1(1, "advansys_command: scp %x\n", (unsigned) scp);
+       ASC_STATS(command);
+       scp->SCp.Status = 0; /* Set to a known state */
+       advansys_queuecommand(scp, advansys_command_done);
+       while (scp->SCp.Status == 0) {
+               continue;
+       }
+       ASC_DBG1(1, "advansys_command: result %x\n", scp->result);
+       return scp->result;
+}
+
+/*
+ * advansys_queuecommand()
+ *
+ * This function always returns 0. Command return status is saved
+ * in the 'scp' result field.
+ */
+int
+advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
+{
+       struct Scsi_Host                *shp;
+       int                                             flags = 0;
+       int                                             interrupts_disabled;
+
+       ASC_STATS(queuecommand);
+       shp = scp->host;
+
+#ifdef LINUX_1_2
+       /*
+        * For LINUX_1_3, if statistics are enabled they can be accessed
+        * by reading /proc/scsi/advansys/[0-9].
+        */
+#ifdef ADVANSYS_STATS_1_2_PRINT
+       /* Display statistics every 10000 commands. */
+       if ((asc_stats.queuecommand % 10000) == 0) {
+               printk("\n");
+               (void) asc_prt_stats(NULL, 0);
+               printk("\n");
+       }
+#endif /* ADVANSYS_STATS_1_2_PRINT */
+#endif /* LINUX_1_2 */
+
+       /*
+        * If there are any pending commands for this board before trying
+        * to execute them, disable interrupts to preserve request ordering.
+        *
+        * The typical case will be no pending commands and interrupts
+        * not disabled.
+        */
+       if (ASC_BOARD(shp)->pending_tidmask == 0) {
+               interrupts_disabled = ASC_FALSE;
+       } else {
+               ASC_STATS(cmd_disable);
+               /* Disable interrupts */
+               interrupts_disabled = ASC_TRUE;
+               save_flags(flags);
+               cli();
+               ASC_DBG1(1, "advansys_queuecommand: asc_execute_pending() %x\n",
+                       ASC_BOARD(shp)->pending_tidmask);
+               asc_execute_pending(shp);
+       }
+
+       /*
+        * Save the function pointer to Linux mid-level 'done' function and
+        * execute the command.
+        */
+       scp->scsi_done = done;
+       if (asc_execute_scsi_cmnd(scp) == ASC_BUSY) {
+               if (interrupts_disabled == ASC_FALSE) {
+                       save_flags(flags);
+                       cli();
+                       interrupts_disabled = ASC_TRUE;
+               }
+               asc_enqueue(shp, scp, scp->target, ASC_BACK);
+       }
+
+       if (interrupts_disabled == ASC_TRUE) {
+               restore_flags(flags);
+       }
+
+       return 0;
+}
+
+/*
+ * advansys_abort()
+ *
+ * Abort the specified command and reset the device
+ * associated with the command 'scp'.
+ */
+int
+advansys_abort(Scsi_Cmnd *scp)
+{
+       ASC_DVC_VAR             *boardp;
+       int                             flags;
+       int                             ret;
+
+       ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp);
+       save_flags(flags);
+       cli();
+       ASC_STATS(abort);
+       if (scp->host == NULL) {
+               scp->result = HOST_BYTE(DID_ERROR);
+               ret = SCSI_ABORT_ERROR;
+       } else if (asc_rmqueue(scp->host, scp, scp->target) == ASC_TRUE) {
+               scp->result = HOST_BYTE(DID_ABORT);
+               ret = SCSI_ABORT_SUCCESS;
+               (void) AscResetDevice(&ASC_BOARD(scp->host)->board, scp->target);
+       } else {
+               /* Must enable interrupts for AscAbortSRB() */
+               sti();
+               boardp = &ASC_BOARD(scp->host)->board;
+               scp->result = HOST_BYTE(DID_ABORT);
+               switch (AscAbortSRB(boardp, (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;
+               }
+               (void) AscResetDevice(boardp, scp->target);
+       }
+       restore_flags(flags);
+       ASC_DBG1(1, "advansys_abort: ret %d\n", ret);
+       return ret;
+}
+
+/*
+ * advansys_reset()
+ *
+ * Reset all devices and the SCSI bus for the board
+ * associated with 'scp'.
+ */
+int
+advansys_reset(Scsi_Cmnd *scp)
+{
+       ASC_DVC_VAR             *boardp;
+       int                             flags;
+       Scsi_Cmnd               *tscp;
+       int                             i;
+       int                             ret;
+
+       ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp);
+       save_flags(flags);
+       cli();
+       ASC_STATS(reset);
+       if (scp->host == NULL) {
+               scp->result = HOST_BYTE(DID_ERROR);
+               ret = SCSI_RESET_ERROR;
+       } else {
+               /* Remove any pending commands, set DID_RESET, and done them.  */
+               for (i = 0; i < ASC_MAX_TID; i++) {
+                       while ((tscp = asc_dequeue(scp->host, i)) != NULL) {
+                               tscp->result = HOST_BYTE(DID_RESET);
+                               tscp->scsi_done(tscp);
+                       }
+               }
+               /* Must enable interrupts for AscResetSB() */
+               sti();
+               boardp = &ASC_BOARD(scp->host)->board;
+               scp->result = HOST_BYTE(DID_RESET);
+               switch (AscResetSB(boardp)) {
+               case ASC_TRUE:
+                       ASC_DBG(1, "advansys_abort: AscResetSB() TRUE\n");
+                       ret = SCSI_RESET_SUCCESS;
+                       break;
+               case ASC_ERROR:
+               default:
+                       ASC_DBG(1, "advansys_abort: AscResetSB() ERROR\n");
+                       ret = SCSI_RESET_ERROR;
+                       break;
+               }
+       }
+       restore_flags(flags);
+       ASC_DBG1(1, "advansys_reset: ret %d", ret);
+       return ret;
+}
+
+/*
+ * 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
+#ifdef LINUX_1_2
+advansys_biosparam(Disk *dp, int dep, int ip[])
+#else /* LINUX_1_3 */
+advansys_biosparam(Disk *dp, kdev_t dep, int ip[])
+#endif /* LINUX_1_3 */
+{
+       ASC_DBG(1, "advansys_biosparam: begin\n");
+       ASC_STATS(biosparam);
+       if ((ASC_BOARD(dp->device->host)->board.dvc_cntl & ASC_CNTL_BIOS_GT_1GB) &&
+               dp->capacity > 0x200000) {
+                       ip[0] = 255;
+                       ip[1] = 64;
+       } 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.
+ *
+ * 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_BOARD_SUPPORTED + 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
+ * ...
+ */
+void
+advansys_setup(char *str, int *ints)
+{
+       int     i;
+
+       if (asc_iopflag == ASC_TRUE) {
+               printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n");
+               return;
+       }
+
+       asc_iopflag = ASC_TRUE;
+
+       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 */
+       }
+
+#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 */
+
+       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]);
+       }
+}
+
+
+/*
+ * --- Loadable Driver Support
+ */
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = ADVANSYS;
+# include "scsi_module.c"
+#endif /* MODULE */
+
+
+/*
+ * --- Miscellaneous Driver Functions
+ */
+
+#ifdef LINUX_1_3
+/*
+ * asc_proc_copy() 
+ *
+ * Copy proc information to a read buffer considering 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)
+{
+       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 = 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 = 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;
+}
+#endif /* LINUX_1_3 */
+
+/*
+ * First-level interrupt handler.
+ */
+STATIC void
+advansys_interrupt(int irq, struct pt_regs *regs)
+{
+       int                     i;
+       int                     flags;
+       Scsi_Cmnd       *scp;
+       Scsi_Cmnd       *tscp;
+
+       /* Disable interrupts, if the aren't already disabled. */
+       save_flags(flags);
+       cli();
+
+       ASC_DBG(1, "advansys_interrupt: begin\n");
+       ASC_STATS(interrupt);
+       /*
+        * Check for interrupts on all boards.
+        * AscISR() will call asc_isr_callback().
+        */
+       for (i = 0; i < asc_board_count; i++) {
+               while (AscIsIntPending(asc_host[i]->io_port)) {
+                       ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
+                       AscISR(&ASC_BOARD(asc_host[i])->board);
+               }
+       }
+       ASC_DBG(1, "advansys_interrupt: end\n");
+
+       /*
+        * While interrupts are still disabled save the list of requests that
+        * need their done function called. After re-enabling interrupts call
+        * the done function which may re-enable interrupts anyway.
+        */
+       if ((scp = asc_scsi_done) != NULL) {
+               asc_scsi_done = NULL;
+       }
+
+       /* Re-enable interrupts, if they were enabled on entry. */
+       restore_flags(flags);
+
+       while (scp) {
+               tscp = (Scsi_Cmnd *) scp->host_scribble;
+               scp->scsi_done(scp);
+               scp = tscp;
+       }
+
+       return;
+}
+
+/*
+ * 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;
+}
+
+/*
+ * 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 done
+ * function has been called. 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_DVC_VAR             *boardp;
+       ASC_SCSI_Q              scsiq;
+       ASC_SG_HEAD             sghead;
+       int                             ret;
+
+       ASC_DBG2(1, "asc_execute_scsi_cmnd: scp %x, done %x\n",
+               (unsigned) scp, (unsigned) scp->scsi_done);
+
+       boardp = &ASC_BOARD(scp->host)->board;
+
+       /*
+        * If this is the first command, then initialize the device. If
+        * no device is found set 'DID_BAD_TARGET' and return.
+        */
+       if ((ASC_BOARD(scp->host)->init_tidmask &
+                ASC_TIX_TO_TARGET_ID(scp->target)) == 0) {
+               if (asc_init_dev(boardp, scp) == ASC_FALSE) {
+                       scp->result = HOST_BYTE(DID_BAD_TARGET);
+                       scp->scsi_done(scp);
+                       return ASC_ERROR;
+               }
+               ASC_BOARD(scp->host)->init_tidmask |= ASC_TIX_TO_TARGET_ID(scp->target);
+       }
+
+       memset(&scsiq, 0, sizeof(ASC_SCSI_Q));
+
+       /*
+        * Point the ASC_SCSI_Q to the 'Scsi_Cmnd'.
+        */
+       scsiq.q2.srb_ptr = (ulong) scp;
+
+       /*
+        * Build the ASC_SCSI_Q request.
+        */
+       scsiq.cdbptr = &scp->cmnd[0];
+       scsiq.q2.cdb_len = scp->cmd_len;
+       scsiq.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
+       scsiq.q1.target_lun = scp->lun;
+       scsiq.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun);
+       scsiq.q1.sense_addr = (ulong) &scp->sense_buffer[0];
+       scsiq.q1.sense_len = sizeof(scp->sense_buffer);
+       scsiq.q2.tag_code = M2_QTAG_MSG_SIMPLE;
+
+       /*
+        * 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(cont_cnt);
+               /* request_buffer is already a real address. */
+               scsiq.q1.data_addr = (ulong) scp->request_buffer;
+               scsiq.q1.data_cnt = scp->request_bufflen;
+               ASC_STATS_ADD(cont_xfer, (scp->request_bufflen + 511) >> 9);
+               scsiq.q1.sg_queue_cnt = 0;
+               scsiq.sg_head = NULL;
+       } else {
+               /*
+                * CDB scatter-gather request list.
+                */
+               int                                     sgcnt;
+               struct scatterlist      *slp;
+
+               if (scp->use_sg > ASC_MAX_SG_LIST) {
+                       ASC_DBG2(0, "asc_execute_scsi_cmnd: use_sg %d > %d\n",
+                               scp->use_sg, ASC_MAX_SG_LIST);
+                       scp->result = HOST_BYTE(DID_ERROR);
+                       scp->scsi_done(scp);
+                       return ASC_ERROR;
+               }
+
+               ASC_STATS(sg_cnt);
+
+               /*
+                * Allocate a ASC_SG_HEAD structure and set the ASC_SCSI_Q
+                * to point to it.
+                */
+               memset(&sghead, 0, sizeof(ASC_SG_HEAD));
+
+               scsiq.q1.cntl |= QC_SG_HEAD;
+               scsiq.sg_head = &sghead;
+               scsiq.q1.data_cnt = 0;
+               scsiq.q1.data_addr = 0;
+               sghead.entry_cnt = scsiq.q1.sg_queue_cnt = scp->use_sg;
+               ASC_STATS_ADD(sg_elem, sghead.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++) {
+                       sghead.sg_list[sgcnt].addr = (ulong) slp->address;
+                       sghead.sg_list[sgcnt].bytes = slp->length;
+                       ASC_STATS_ADD(sg_xfer, (slp->length + 511) >> 9);
+               }
+       }
+
+       ASC_DBG_PRT_SCSI_Q(2, &scsiq);
+       ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
+
+       switch (ret = AscExeScsiQueue(boardp, &scsiq)) {
+       case ASC_NOERROR:
+               ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue() ASC_NOERROR\n");
+               break;
+       case ASC_BUSY:
+               /* Caller must enqueue request and retry later. */
+               break;
+       case ASC_ERROR:
+               ASC_DBG1(0,
+                       "asc_execute_scsi_cmnd: AscExeScsiQueue() ASC_ERROR err_code %x\n",
+                       boardp->err_code);
+               ASC_STATS(error);
+               scp->result = HOST_BYTE(DID_ERROR);
+               scp->scsi_done(scp);
+               break;
+       }
+
+       ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
+       return ret;
+}
+
+/*
+ * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
+ */
+void
+asc_isr_callback(ASC_DVC_VAR *boardp, ASC_QDONE_INFO *qdonep)
+{
+       Scsi_Cmnd                       *scp;
+       struct Scsi_Host        *shp;
+       int                                     flags;
+       Scsi_Cmnd                       **scpp;
+
+       ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+       ASC_DBG2(1, "asc_isr_callback: boardp %x, qdonep %x\n",
+               (unsigned) boardp, (unsigned) qdonep);
+       ASC_STATS(callback);
+       ASC_DBG_PRT_QDONE_INFO(2, qdonep);
+
+       /*
+        * 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);
+
+       shp = scp->host;
+       ASC_ASSERT(shp);
+       ASC_DBG1(1, "asc_isr_callback: shp %x\n", (unsigned) shp);
+
+       /*
+        * '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;
+
+       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 left shifted status byte definitions. For instance
+                                * target drivers use CHECK_CONDITION, defined to 0x1, instead
+                                * of the SCSI defined check condition value of 0x2.
+                                */
+                               scp->result = DRIVER_BYTE(DRIVER_SENSE) |
+                                       STATUS_BYTE(qdonep->d3.scsi_stat); 
+                       } else {
+                               scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); 
+                       }
+                       break;
+
+               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;
+
+       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;
+
+       default:
+               ASC_DBG1(0, "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;
+       }
+
+       /*
+        * Before calling 'scsi_done' for the current 'Scsi_Cmnd' and possibly
+        * triggering more commands to be issued, try to start any pending
+        * commands.
+        */
+       if (ASC_BOARD(shp)->pending_tidmask != 0) {
+               /*
+                * If there are any pending commands for this board before trying
+                * to execute them, disable interrupts to preserve request ordering.
+                */
+               ASC_STATS(intr_disable);
+               save_flags(flags);
+               cli();
+               ASC_DBG1(1, "asc_isr_callback: asc_execute_pending() %x\n",
+                       ASC_BOARD(shp)->pending_tidmask);
+               asc_execute_pending(shp);
+               restore_flags(flags);
+       }
+
+       /* 
+        * Because interrupts may be enabled by the 'Scsi_Cmnd' done function,
+        * add the command to the end of the global done list. The done function
+        * for the command will be called in advansys_interrupt().
+        */
+       for (scpp = &asc_scsi_done; *scpp;
+            scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) {
+               ;
+       }
+       *scpp = scp;
+       scp->host_scribble = NULL;
+       return;
+}
+
+/*
+ * Execute as many pending requests as possible for the
+ * board specified by 'Scsi_Host'.
+ */
+STATIC void
+asc_execute_pending(struct Scsi_Host *shp)
+{
+       ASC_SCSI_BIT_ID_TYPE    scan_tidmask;
+       Scsi_Cmnd                               *scp;
+       int                                             i;
+
+       ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+       /*
+        * Execute pending commands for devices attached to
+        * the current board in round-robin fashion.
+        */
+       scan_tidmask = ASC_BOARD(shp)->pending_tidmask;
+       do {
+               for (i = 0; i < ASC_MAX_TID; i++) {
+                       if (scan_tidmask & ASC_TIX_TO_TARGET_ID(i)) {
+                               if ((scp = asc_dequeue(shp, i)) == NULL) {
+                                       scan_tidmask &= ~ASC_TIX_TO_TARGET_ID(i);
+                               } else if (asc_execute_scsi_cmnd(scp) == ASC_BUSY) {
+                                       scan_tidmask &= ~ASC_TIX_TO_TARGET_ID(i);
+                                       /* Put the request back at front of the list. */
+                                       asc_enqueue(shp, scp, i, ASC_FRONT);
+                               }
+                       }
+               }
+       } while (scan_tidmask);
+       return;
+}
+
+/*
+ * asc_init_dev()
+ *
+ * Perform one-time initialization of a device.
+ */
+STATIC int
+asc_init_dev(ASC_DVC_VAR *boardp, Scsi_Cmnd *scp)
+{
+       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);
+
+       /* Return true for the board's target id. */
+       if (boardp->cfg->chip_scsi_id == scp->target) {
+               return ASC_TRUE;
+       }
+
+       /*
+        * XXX - Host drivers should not modify the timeout field.
+        * But on the first command only add some extra time to
+        * allow the driver to complete its initialization for the
+        * device.
+        */
+       scp->timeout += 2000;   /* Add 5 seconds to the request timeout. */
+
+       /* Set-up AscInitPollTarget() arguments. */
+       scsireqq = &ASC_BOARD(scp->host)->scsireqq;
+       memset(scsireqq, 0, sizeof(ASC_SCSI_REQ_Q));
+       cap_info = &ASC_BOARD(scp->host)->cap_info;
+       memset(cap_info, 0, sizeof(ASC_CAP_INFO));
+       inquiry = &ASC_BOARD(scp->host)->inquiry;
+       memset(inquiry, 0, sizeof(ASC_SCSI_INQUIRY));
+
+       /*
+        * 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 = boardp->use_tagged_qng;
+    save_can_tagged_qng = boardp->cfg->can_tagged_qng;
+
+       ASC_DBG(2, "asc_init_dev: AscInitPollBegin()\n");
+       if (AscInitPollBegin(boardp)) {
+               ASC_DBG(0, "asc_init_dev: AscInitPollBegin() failed\n");
+               return ASC_FALSE;
+       }
+
+       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(boardp, 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 (boardp->use_tagged_qng & tidmask) {
+                       ASC_DBG1(1, "asc_init_dev: command queuing enabled: %d\n",
+                               boardp->max_dvc_qng[scp->target]);
+               } else {
+                       ASC_DBG(1, "asc_init_dev: command queuing disabled\n");
+               }
+               if (boardp->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 (boardp->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_DBG(0, "asc_init_dev: AscInitPollTarget() ASC_ERROR\n");
+               break;
+       default:
+               ASC_DBG1(0, "asc_init_dev: AscInitPollTarget() unknown ret %d\n", ret);
+               break;
+       }
+
+       /* XXX - 'Or' in original tag bits. */
+       boardp->use_tagged_qng |= save_use_tagged_qng;
+       boardp->cfg->can_tagged_qng |= save_can_tagged_qng;
+
+       ASC_DBG(2, "asc_init_dev: AscInitPollEnd()\n");
+       AscInitPollEnd(boardp);
+
+#ifdef ASC_SET_CMD_PER_LUN
+       /*
+        * XXX - Refer to the comment in advansys_detect()
+        * regarding cmd_per_lun.
+        */
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               if (boardp->max_dvc_qng[i] < scp->host->cmd_per_lun) {
+                       scp->host->cmd_per_lun = boardp->max_dvc_qng[i];
+               }
+       }
+#endif /* ASC_SET_CMD_PER_LUN */
+
+       return found;
+}
+
+/*
+ * Search for an AdvanSys PCI device in the PCI configuration space.
+ */
+STATIC int
+asc_srch_pci_dev(PCI_DEVICE *pciDevice)
+{
+       int ret;
+       static int scan = 1;
+
+       ASC_DBG(2, "asc_srch_pci_dev: begin\n");
+
+       if (scan) {
+               pciDevice->type = asc_scan_method(pciDevice);
+               scan = 0;
+               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'.
+ */
+STATIC uchar
+asc_scan_method(PCI_DEVICE *pciDevice)
+{
+       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.
+ */
+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_REV_A) ||
+                               (deviceid == ASC_PCI_DEVICE_ID_REV_B))) {
+                               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'.
+ */
+STATIC void
+asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig)
+{
+       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(4, "asc_get_pci_cfg: counter %d\n", counter);
+}
+
+/*
+ * Read a word (16 bits) from the PCI configuration space.
+ *
+ * The configuration mechanism is checked for the correct access method.
+ */
+STATIC ushort
+asc_get_cfg_word(PCI_DATA *pciData)
+{
+       ushort tmp;
+       ulong address;
+       ulong lbus = pciData->bus;
+       ulong lslot = pciData->slot;
+       ulong lfunc = pciData->func;
+       uchar t2CFA, t2CF8;
+       ushort t1CF8, t1CFA, t1CFC, t1CFE;
+
+       ASC_DBG4(4, "asc_get_cfg_word: type %d, bus %lu, slot %lu, func %lu\n",
+               pciData->type, lbus, lslot, lfunc);
+
+       /*
+        * check type of configuration mechanism
+        */
+       if (pciData->type == 2) {
+               /*
+                * save these registers so we can restore them after we are done
+                */
+               t2CFA = inp(0xCFA);     /* save PCI bus register */
+               t2CF8 = inp(0xCF8);     /* save config space enable register */
+
+               /*
+                * go out and 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));
+       } else {
+               /*
+                * type 1 configuration mechanism
+                *
+                * save the CONFIG_ADDRESS and CONFIG_DATA register values
+                */
+               t1CFC = inpw(0xCFC);
+               t1CFE = inpw(0xCFE);
+               t1CF8 = inpw(0xCF8);
+               t1CFA = inpw(0xCFA);
+
+               /*
+                * 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 the address to CONFIG_ADDRESS
+                */
+               outl(address, 0xCF8);
+
+               /*
+                * read in the word from CONFIG_DATA
+                */
+               tmp = (ushort) ((inl(0xCFC) >>
+                                ((pciData->offset & 2) * 8)) & 0xFFFF);
+       }
+       ASC_DBG1(4, "asc_get_cfg_word: config data: %x\n", tmp);
+       return tmp;
+}
+
+/*
+ * Reads a byte from the PCI configuration space.
+ *
+ * The configuration mechanism is checked for the correct access method.
+ */
+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;
+       ushort t1CF8, t1CFA, t1CFC, t1CFE;
+
+       ASC_DBG1(4, "asc_get_cfg_byte: type: %d\n", pciData->type);
+
+       /*
+        * check type of configuration mechanism
+        */
+       if (pciData->type == 2) {
+               /*
+                * save these registers so we can restore them after we are done
+                */
+               t2CFA = inp(0xCFA);     /* save PCI bus register */
+               t2CF8 = inp(0xCF8);     /* save config space enable register */
+
+               /*
+                * go out and 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 = inp(0xC000 | ((pciData->slot << 8) + pciData->offset));
+
+               /*
+                * restore the registers used for our transaction
+                */
+               outp(0xCF8, t2CF8);     /* restore the enable register */
+               outp(0xCFA, t2CFA);     /* restore PCI bus register */
+       } else {
+               /*
+                * type 1 configuration mechanism
+                *
+                * save the CONFIG_ADDRESS and CONFIG_DATA register values
+                */
+               t1CFC = inpw(0xCFC);
+               t1CFE = inpw(0xCFE);
+               t1CF8 = inpw(0xCF8);
+               t1CFA = inpw(0xCFA);
+
+               /*
+                * 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 the address to CONFIG_ADDRESS
+                */
+               outl(address, 0xCF8);
+
+               /*
+                * read in the word from CONFIG_DATA
+                */
+               tmp = (uchar) ((inl(0xCFC) >> ((pciData->offset & 3) * 8)) & 0xFF);
+       }
+       ASC_DBG1(4, "asc_get_cfg_byte: config data: %x\n", tmp);
+       return tmp;
+}
+
+/*
+ * Add a 'Scsi_Cmnd' to the end of specified 'Scsi_Host' 
+ * target device pending command list. Set 'pending_tidmask'
+ * to indicate a command is queued for the device.
+ *
+ * 'flag' may be either ASC_FRONT or ASC_BACK.
+ *
+ * The 'Scsi_Cmnd' host_scribble field is used as a next pointer.
+ */
+STATIC void
+asc_enqueue(struct Scsi_Host *shp, Scsi_Cmnd *scp, int tid, int flag)
+{
+       Scsi_Cmnd       **scpp;
+
+       ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+       ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
+       ASC_STATS(enqueue);
+       if (flag == ASC_FRONT) {
+               scp->host_scribble = (unsigned char *) ASC_BOARD(shp)->pending[tid];
+               ASC_BOARD(shp)->pending[tid] = (Scsi_Cmnd *) scp;
+       } else { /* ASC_BACK */
+               for (scpp = &ASC_BOARD(shp)->pending[tid]; *scpp;
+                        scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) {
+                       ;
+               }
+               *scpp = scp;
+               scp->host_scribble = NULL;
+       }
+       ASC_BOARD(shp)->pending_tidmask |= ASC_TIX_TO_TARGET_ID(tid);
+}
+
+/*
+ * Return first pending 'Scsi_Cmnd' on the specified 'Scsi_Host'
+ * for the specified target device. Clear the 'pending_tidmask'
+ * bit for the device if no more commands are left queued for it.
+ *
+ * The 'Scsi_Cmnd' host_scribble field is used as a next pointer.
+ */
+STATIC Scsi_Cmnd *
+asc_dequeue(struct Scsi_Host *shp, int tid)
+{
+       Scsi_Cmnd       *scp;
+
+       ASC_STATS(dequeue);
+       ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+       if ((scp = ASC_BOARD(shp)->pending[tid]) != NULL) {
+               ASC_BOARD(shp)->pending[tid] = (Scsi_Cmnd *) scp->host_scribble;
+       }
+       if (ASC_BOARD(shp)->pending[tid] == NULL) {
+               ASC_BOARD(shp)->pending_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid);
+       }
+       return scp;
+}
+
+/*
+ * Remove the specified 'Scsi_Cmnd' from the specified 'Scsi_Host'
+ * for the specified target device. Clear the 'pending_tidmask'
+ * bit for the device if no more commands are left queued for it.
+ *
+ * The 'Scsi_Cmnd' host_scribble field is used as a next pointer.
+ *
+ * Return ASC_TRUE if the command was found and removed, otherwise
+ * return ASC_FALSE if the command was not found.
+ */
+STATIC int
+asc_rmqueue(struct Scsi_Host *shp, Scsi_Cmnd *scp, int tid)
+{
+       Scsi_Cmnd       **scpp;
+       int                     ret;
+
+       ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+       ret = ASC_FALSE;
+       for (scpp = &ASC_BOARD(shp)->pending[tid];
+            *scpp; scpp = (Scsi_Cmnd **) &(*scpp)->host_scribble) {
+               if (*scpp == scp) {
+                       *scpp = (Scsi_Cmnd *) scp->host_scribble;       
+                       scp->host_scribble = NULL;
+                       ASC_STATS(rmqueue);
+                       ret = ASC_TRUE;
+               }
+       }
+       if (ASC_BOARD(shp)->pending[tid] == NULL) {
+               ASC_BOARD(shp)->pending_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid);
+       }
+       return ret;
+}
+
+
+/*
+ * --- 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.
+ */
+void
+DvcSleepMilliSecond(ulong n)
+{
+       ulong i;
+
+       ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", n);
+       for (i = 0; i < n; i++) {
+               udelay(1000);
+       }
+}
+
+void
+DvcDisplayString(uchar *s)
+{
+       printk(s);
+}
+
+int
+DvcEnterCritical(void)
+{
+       int     flags;
+
+       save_flags(flags);
+       cli();
+       return flags;
+}
+
+void
+DvcLeaveCritical(int flags)
+{
+       restore_flags(flags);
+}
+
+/*
+ * Convert a virtual address to a virtual address.
+ *
+ * Apparently Linux is loaded V=R (virtual equals real). Just return
+ * the virtual address.
+ */
+ulong
+DvcGetPhyAddr(uchar *buf_addr, ulong buf_len)
+{
+       ulong phys_addr;
+
+       phys_addr = (ulong) buf_addr;
+       return phys_addr;
+}
+
+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;
+       asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr;
+       asc_sg_head_ptr->sg_list[0].bytes = buf_size;
+       return buf_size;
+}
+
+/*
+ * 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
+ */
+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;
+               }
+               AscPutChipLramData(iop_base, *outbuf);
+       }
+}
+
+/*
+ * 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
+ */
+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 = AscGetChipLramData(iop_base);
+       }
+       ASC_DBG_PRT_HEX(2, "DvcGetQinfo", (uchar *) inbuf, 2 * words);
+}
+
+/*
+ * void        DvcOutPortWords(ushort iop_base, ushort &outbuf, int words)
+ *
+ * Calling/Exit State:
+ *     none
+ *
+ * Description:
+ *     output a buffer to an i/o port address
+ */
+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)
+ *
+ * Calling/Exit State:
+ *     none
+ *
+ * Description:
+ *     input a buffer from an i/o port address
+ */
+void
+DvcInPortWords(ushort iop_base, ushort *inbuf, int words)
+{
+       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
+ */
+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;
+}
+
+
+/*
+ * --- Tracing and Debugging Functions
+ */
+
+#ifdef ADVANSYS_STATS
+
+#define ASC_PRT_STATS_NEXT() \
+       if (cp) { \
+               totlen += len; \
+               leftlen -= len; \
+               if (leftlen == 0) { \
+                       return totlen; \
+               } \
+               cp += len; \
+       }
+
+/*
+ * asc_prt_stats()
+ *
+ * Note: no single line should be greater than 160 characters, cf.
+ * asc_prt_stats_line().
+ *
+ * Return the number of characters copied into 'cp'. No more than
+ * 'cplen' characters will be copied to 'cp'.
+ */
+STATIC int
+asc_prt_stats(char *cp, int cplen)
+{
+       struct asc_stats        *s;
+       int                                     leftlen;
+       int                                     totlen;
+       int                                     len;
+
+       s = &asc_stats;
+       leftlen = cplen;
+       totlen = len = 0;
+
+       len = asc_prt_stats_line(cp, leftlen,
+"\nAdvanSys SCSI Host Driver Statistics:\n");
+       ASC_PRT_STATS_NEXT();
+       
+       len = asc_prt_stats_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_STATS_NEXT();
+
+       len = asc_prt_stats_line(cp, leftlen,
+" interrupt %lu, callback %lu, cmd_disable %lu, intr_disable %lu,\n",
+               s->interrupt, s->callback, s->cmd_disable, s->intr_disable);
+       ASC_PRT_STATS_NEXT();
+
+       len = asc_prt_stats_line(cp, leftlen,
+" error %lu, enqueue %lu, dequeue %lu, rmqueue %lu,\n",
+               s->error, s->enqueue, s->dequeue, s->rmqueue);
+       ASC_PRT_STATS_NEXT();
+
+       if (s->cont_cnt > 0) {
+               len = asc_prt_stats_line(cp, leftlen,
+" cont_cnt %lu, cont_xfer %lu: avg_xfer=%lu kb\n",
+                       s->cont_cnt, s->cont_xfer, (s->cont_xfer/2)/s->cont_cnt);
+               ASC_PRT_STATS_NEXT();
+       }
+
+       if (s->sg_cnt > 0) {
+               len = asc_prt_stats_line(cp, leftlen,
+" sg_cnt %lu, sg_elem %lu, sg_xfer %lu: avg_elem=%lu, avg_size=%lu kb\n",
+                       s->sg_cnt, s->sg_elem, s->sg_xfer,
+                       s->sg_elem/s->sg_cnt, (s->sg_xfer/2)/s->sg_cnt);
+               ASC_PRT_STATS_NEXT();
+       }
+
+       return totlen;
+}
+
+/*
+ * asc_prt_stats_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 160 bytes the stack
+ * will be corrupted. 's[]' is defined to be 160 bytes.
+ */
+int
+asc_prt_stats_line(char *buf, int buflen, char *fmt, ...)
+{
+       va_list         args;
+       int                     ret;
+       char            s[160];         /* 2 lines */
+
+       va_start(args, fmt);
+       ret = vsprintf(s, fmt, args);
+       if (buf == NULL) {
+               (void) printk(s);
+               ret = 0;
+       } else {
+               ret = min(buflen, ret);
+               memcpy(buf, s, ret);
+       }
+       va_end(args);
+       return ret;
+}
+#endif /* ADVANSYS_STATS */
+
+#ifdef ADVANSYS_DEBUG
+/*
+ * asc_prt_scsi_host()
+ */
+STATIC void 
+asc_prt_scsi_host(struct Scsi_Host *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,
+               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);
+
+       printk("hostdata (struct asc_board)\n");
+       asc_prt_dvc_var(&ASC_BOARD(s)->board);
+       asc_prt_dvc_cfg(&ASC_BOARD(s)->cfg);
+       printk(" overrun_buf %x\n", (unsigned) &ASC_BOARD(s)->overrun_buf[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);
+
+       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(
+" int_count %ld, req_count %ld, busy_count %ld, cfg %x, saved_ptr2func %x\n",
+               h->int_count, h->req_count, h->busy_count, (unsigned) h->cfg,
+               (unsigned) h->saved_ptr2func);
+}
+
+/*
+ * asc_prt_dvc_cfg()
+ */
+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);
+
+       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 %d, lib_version %d, mcode_date %d,\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_scsi_q()
+ */
+STATIC void 
+asc_prt_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_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_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)+4]);
+                       break;
+               case 2:
+                       printk(" %2.2X%2.2X",
+                               (unsigned) s[i+(j*4)+4],
+                               (unsigned) s[i+(j*4)+5]);
+                       break;
+               case 3:
+                       printk(" %2.2X%2.2X%2.2X",
+                               (unsigned) s[i+(j*4)+4],
+                               (unsigned) s[i+(j*4)+5],
+                               (unsigned) s[i+(j*4)+6]);
+                       break;
+               }
+
+               printk("\n");
+       }
+}
+
+/*
+ * 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_DEBUG */
+
+
+/*
+ * --- Asc Library Functions
+ */
+
+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));
+}
+
+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));
+}
+
+ushort
+AscGetChipBiosAddress(
+                                                PortAddr iop_base,
+                                                ushort bus_type
+)
+{
+       ushort              cfg_lsw;
+       ushort              bios_addr;
+
+       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);
+       }
+       cfg_lsw = AscGetChipCfgLsw(iop_base);
+       bios_addr = (ushort) (((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) + ASC_BIOS_MIN_ADDR);
+       return (bios_addr);
+}
+
+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));
+}
+
+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);
+       } else 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);
+       } else {
+               return (0);
+       }
+}
+
+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;
+}
+
+ulong
+AscLoadMicroCode(
+                                       PortAddr iop_base,
+                                       ushort s_addr,
+                                       ushort dosfar * 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);
+}
+
+uchar               _hextbl_[16] =
+{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'};
+
+uchar               _isa_pnp_inited = 0;
+
+PortAddr            _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] =
+{
+       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
+};
+
+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);
+}
+
+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 (AscFindSignature(iop_base)) {
+                       return (iop_base);
+               }
+       }
+       return (0);
+}
+
+int
+AscFindSignature(
+                                       PortAddr iop_base
+)
+{
+       ushort              sig_word;
+
+       if ((inp((PortAddr) (iop_base + 1)) & 0xFF) == (uchar) ASC_1000_ID1B) {
+               sig_word = inpw(iop_base);
+               if ((sig_word == (ushort) ASC_1000_ID0W) ||
+                       (sig_word == (ushort) ASC_1000_ID0W_FIX)) {
+                       return (1);
+               }
+       }
+       return (0);
+}
+
+void
+AscToggleIRQAct(
+                                  PortAddr iop_base
+)
+{
+       AscSetChipStatus(iop_base, CIW_IRQ_ACT);
+       AscSetChipStatus(iop_base, 0);
+       return;
+}
+
+#if CC_INIT_INQ_DISPLAY
+
+#endif
+
+void
+AscSetISAPNPWaitForKey(
+                                                 void)
+{
+
+       outp(ASC_ISA_PNP_PORT_ADDR, 0x02);
+       outp(ASC_ISA_PNP_PORT_WRITE, 0x02);
+       return;
+}
+
+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);
+       } else {
+
+               cfg_lsw = AscGetChipCfgLsw(iop_base);
+
+               if ((bus_type & ASC_IS_VL) != 0) {
+
+                       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)));
+               }
+               chip_irq = (uchar) (((cfg_lsw >> 2) & 0x03));
+               if (chip_irq == 3)
+                       chip_irq += (uchar) 2;
+               return ((uchar) (chip_irq + ASC_MIN_IRQ_NO));
+       }
+}
+
+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));
+
+       } else 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));
+       } else {
+
+               return (0);
+       }
+}
+
+uchar
+AscGetChipScsiCtrl(
+                                         PortAddr iop_base
+)
+{
+       uchar               sc;
+
+       AscSetBank(iop_base, 1);
+       sc = inp(iop_base + IOP_REG_SC);
+       AscSetBank(iop_base, 0);
+       return (sc);
+}
+
+extern uchar        _sdtr_period_tbl_[];
+
+int
+AscIsrChipHalted(
+                                       ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+       SDTR_XMSG           sdtr_xmsg;
+       SDTR_XMSG           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;
+
+       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_EXTMSG_IN) {
+
+               AscMemWordCopyFromLram(iop_base,
+                                                          ASCV_MSGIN_BEG,
+                                                          (ushort dosfar *) & sdtr_xmsg,
+                                                          (ushort) (sizeof (SDTR_XMSG) >> 1));
+               if ((sdtr_xmsg.msg_type == MS_EXTEND) &&
+                       (sdtr_xmsg.msg_len == MS_SDTR_LEN)) {
+                       sdtr_accept = TRUE;
+                       if (sdtr_xmsg.msg_req == MS_SDTR_CODE) {
+                               if (sdtr_xmsg.req_ack_offset > ASC_SYN_MAX_OFFSET) {
+
+                                       sdtr_accept = FALSE;
+                                       sdtr_xmsg.req_ack_offset = ASC_SYN_MAX_OFFSET;
+                               }
+                               sdtr_data = AscCalSDTRData(sdtr_xmsg.xfer_period,
+                                                                                  sdtr_xmsg.req_ack_offset);
+                               if (sdtr_xmsg.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_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);
+                               } 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;
+                                               AscSetChipSDTR(iop_base, sdtr_data, tid_no);
+                                       } else {
+
+                                               q_cntl |= QC_MSG_OUT;
+
+                                               AscMsgOutSDTR(iop_base,
+                                                                         sdtr_xmsg.xfer_period,
+                                                                         sdtr_xmsg.req_ack_offset);
+                                               asc_dvc->pci_fix_asyn_xfer &= ~target_id;
+                                               AscSetChipSDTR(iop_base, sdtr_data, tid_no);
+                                               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 (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) != 0)) {
+
+                       sdtr_data = AscReadLramByte(iop_base,
+                                 (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no));
+                       AscMsgOutSDTR(iop_base,
+                                                 _sdtr_period_tbl_[(sdtr_data >> 4) & (uchar) (ASC_SYN_XFER_NO - 1)],
+                                                 (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET));
+                       q_cntl |= QC_MSG_OUT;
+               }
+               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;
+               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 dosfar *) & out_msg,
+                                                          (ushort) (sizeof (SDTR_XMSG) >> 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);
+
+               } else {
+
+               }
+
+               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);
+                               }
+                       }
+               }
+               AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
+               return (0);
+       }
+       return (0);
+}
+
+uchar
+_AscCopyLramScsiDoneQ(
+                                                PortAddr iop_base,
+                                                ushort q_addr,
+                                                ASC_QDONE_INFO dosfar * scsiq,
+                                                ulong max_dma_count
+)
+{
+       ushort              _val;
+       uchar               sg_queue_cnt;
+
+       DvcGetQinfo(iop_base,
+                               (ushort) (q_addr + (ushort) ASC_SCSIQ_DONE_INFO_BEG),
+                               (ushort dosfar *) 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->user_def = (uchar) (_val >> 8);
+
+       scsiq->remain_bytes = AscReadLramDWord(iop_base,
+                                (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT));
+       scsiq->remain_bytes &= max_dma_count;
+
+       return (sg_queue_cnt);
+}
+
+int
+AscIsrQDone(
+                          ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+       uchar               next_qp;
+       uchar               i;
+       uchar               n_q_used;
+       uchar               sg_list_qp;
+       uchar               sg_queue_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;
+       ASC_QDONE_INFO dosfar *scsiq;
+       int                 false_overrun;
+       ASC_ISR_CALLBACK    asc_isr_callback;
+
+       uchar               tag_code;
+
+#if CC_LINK_BUSY_Q
+       ushort              n_busy_q_done;
+
+#endif
+
+       iop_base = asc_dvc->iop_base;
+       asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
+
+       n_q_used = 1;
+       scsiq = (ASC_QDONE_INFO dosfar *) & 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 (i = 0; i < sg_queue_cnt; i++) {
+                               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 (asc_dvc->bug_fix_cntl) {
+                               if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) {
+                                       tag_code = AscReadLramByte(iop_base,
+                                                (ushort) (q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE));
+                                       if (tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) {
+                                               if (scsiq->remain_bytes != 0UL) {
+                                                       scsiq->remain_bytes--;
+                                                       if (scsiq->remain_bytes == 0UL) {
+                                                               false_overrun = TRUE;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       if ((scsiq->d3.done_stat == QD_WITH_ERROR) &&
+                               (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;
+                               }
+                       }
+#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;
+                                       }
+                               }
+                       }
+
+#if CC_LINK_BUSY_Q
+                       n_busy_q_done = AscIsrExeBusyQueue(asc_dvc, tid_no);
+                       if (n_busy_q_done == 0) {
+
+                               i = tid_no + 1;
+                               while (TRUE) {
+                                       if (i > ASC_MAX_TID)
+                                               i = 0;
+                                       if (i == tid_no)
+                                               break;
+                                       n_busy_q_done = AscIsrExeBusyQueue(asc_dvc, i);
+                                       if (n_busy_q_done != 0)
+                                               break;
+                                       i++;
+                               }
+                       }
+                       if (n_busy_q_done == 0xFFFF)
+                               return (0x80);
+#endif
+
+                       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);
+}
+
+int
+AscISR(
+                 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;
+
+       asc_dvc->int_count++;
+
+       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);
+               asc_dvc->busy_count++;
+               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));
+
+       if ((chipstat = AscGetChipStatus(iop_base)) & CSW_INT_PENDING) {
+               int_pending = TRUE;
+               AscAckInterrupt(iop_base);
+
+               host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B);
+               AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
+                                                (uchar) (host_flag | (uchar) ASC_HOST_FLAG_IN_ISR));
+               saved_ram_addr = AscGetChipLramAddr(iop_base);
+
+               if ((chipstat & CSW_HALTED) &&
+                       (ctrl_reg & CC_SINGLE_STEP)) {
+                       if (AscIsrChipHalted(asc_dvc) == ERR) {
+
+                               goto ISR_REPORT_QDONE_FATAL_ERROR;
+
+                       } else {
+                               saved_ctrl_reg &= ~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;
+               }
+               AscSetChipLramAddr(iop_base, saved_ram_addr);
+               if (AscGetChipLramAddr(iop_base) != saved_ram_addr) {
+                       AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SET_LRAM_ADDR);
+               }
+               AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
+       }
+       AscSetChipControl(iop_base, saved_ctrl_reg);
+       asc_dvc->is_in_int = FALSE;
+       return (int_pending);
+}
+
+int
+AscScsiSetupCmdQ(
+                                       ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                       ASC_SCSI_REQ_Q dosfar * scsiq,
+                                       uchar dosfar * 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.user_def = 0;
+       scsiq->cdbptr = (uchar dosfar *) scsiq->cdb;
+       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->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 dosfar *) buf_addr, scsiq->r1.data_cnt)) == 0L) {
+                       return (ERR);
+               }
+               scsiq->r1.data_addr = phy_addr;
+       }
+       return (0);
+}
+
+uchar               _mcode_buf[] =
+{
+       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, 0xDD, 0x0A, 0x01, 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, 0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
+       0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x88, 0x00, 0x00, 0x00, 0x00,
+       0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC8, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
+       0xB6, 0x00, 0x36, 0x00, 0x06, 0xD6, 0x0D, 0xD2, 0x15, 0xDE, 0x12, 0xDA, 0x00, 0xA2, 0xC8, 0x00,
+       0x92, 0x80, 0xE0, 0x97, 0x50, 0x00, 0xF5, 0x00, 0x0A, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00,
+       0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00, 0x0A, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80,
+       0x80, 0x62, 0x92, 0x80, 0x00, 0x62, 0x92, 0x80, 0x00, 0x46, 0x17, 0xEE, 0x13, 0xEA, 0x02, 0x01,
+       0x09, 0xD8, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xDC, 0x00, 0x68, 0x97, 0x7F, 0x23, 0x04, 0x61,
+       0x84, 0x01, 0xB2, 0x84, 0xCF, 0xC1, 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xE8, 0x01,
+       0x68, 0x97, 0xD4, 0x81, 0x00, 0x33, 0x02, 0x00, 0x82, 0x88, 0x80, 0x73, 0x80, 0x77, 0x00, 0x01,
+       0x01, 0xA1, 0x08, 0x01, 0x4F, 0x00, 0x46, 0x97, 0x07, 0xA6, 0x12, 0x01, 0x00, 0x33, 0x03, 0x00,
+       0x82, 0x88, 0x03, 0x03, 0x03, 0xDE, 0x00, 0x33, 0x05, 0x00, 0x82, 0x88, 0xCE, 0x00, 0x69, 0x60,
+       0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x86, 0x01, 0x80, 0x63, 0x07, 0xA6, 0x32, 0x01,
+       0x86, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6, 0x42, 0x01, 0x00, 0x33, 0x04, 0x00,
+       0x82, 0x88, 0x03, 0x07, 0x02, 0x01, 0x04, 0xCA, 0x0D, 0x23, 0x2A, 0x98, 0x4D, 0x04, 0xD0, 0x84,
+       0x05, 0xD8, 0x0D, 0x23, 0x2A, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xB8, 0x88, 0xFB, 0x23, 0x02, 0x61,
+       0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x70, 0x01, 0x00, 0x33, 0x0A, 0x00, 0x82, 0x88,
+       0x4E, 0x00, 0x07, 0xA3, 0x7C, 0x01, 0x00, 0x33, 0x0B, 0x00, 0x82, 0x88, 0xCD, 0x04, 0x36, 0x2D,
+       0x00, 0x33, 0x1A, 0x00, 0x82, 0x88, 0x50, 0x04, 0x96, 0x81, 0x06, 0xAB, 0x90, 0x01, 0x96, 0x81,
+       0x4E, 0x00, 0x07, 0xA3, 0xA0, 0x01, 0x50, 0x00, 0x00, 0xA3, 0x4A, 0x01, 0x00, 0x05, 0x8A, 0x81,
+       0x08, 0x97, 0x02, 0x01, 0x05, 0xC6, 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xCC, 0x81,
+       0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xC2, 0x01,
+       0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00, 0x82, 0x88, 0x06, 0x23, 0x2A, 0x98,
+       0xCD, 0x04, 0xB2, 0x84, 0x06, 0x01, 0x00, 0xA2, 0xE2, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xE8, 0x01,
+       0xB2, 0x84, 0x80, 0x23, 0xA0, 0x01, 0xB2, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61, 0x00, 0xA2,
+       0x10, 0x02, 0x04, 0x01, 0x0D, 0xDE, 0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x46, 0x97, 0x0A, 0x82,
+       0x08, 0x23, 0x02, 0x41, 0x82, 0x01, 0x4F, 0x00, 0x24, 0x97, 0x48, 0x04, 0xFF, 0x23, 0x84, 0x80,
+       0xB2, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
+       0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x66, 0xEB, 0x11, 0x23, 0xB8, 0x88, 0xC6, 0x97, 0xFA, 0x80,
+       0x80, 0x73, 0x80, 0x77, 0x06, 0xA6, 0x3E, 0x02, 0x00, 0x33, 0x31, 0x00, 0x82, 0x88, 0x04, 0x01,
+       0x03, 0xD8, 0x74, 0x98, 0x02, 0x96, 0x50, 0x82, 0xA2, 0x95, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
+       0xB6, 0x2D, 0x02, 0xA6, 0x7A, 0x02, 0x07, 0xA6, 0x68, 0x02, 0x06, 0xA6, 0x6C, 0x02, 0x03, 0xA6,
+       0x70, 0x02, 0x00, 0x33, 0x10, 0x00, 0x82, 0x88, 0x4A, 0x95, 0x52, 0x82, 0xF8, 0x95, 0x52, 0x82,
+       0x04, 0x23, 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x16, 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, 0xAC, 0x02, 0x07, 0xA6,
+       0x68, 0x02, 0x06, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x12, 0x00, 0x82, 0x88, 0x00, 0x0E, 0x80, 0x63,
+       0x00, 0x43, 0x00, 0xA0, 0x9A, 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,
+       0xEC, 0x82, 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE4, 0x02, 0x04, 0x01, 0x8E, 0xC8, 0x00, 0x33,
+       0x1F, 0x00, 0x82, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x40, 0x98, 0xB6, 0x2D,
+       0x01, 0xA6, 0x0E, 0x03, 0x00, 0xA6, 0x1C, 0x03, 0x07, 0xA6, 0x2A, 0x03, 0x06, 0xA6, 0x2E, 0x03,
+       0x03, 0xA6, 0xFA, 0x03, 0x02, 0xA6, 0x7A, 0x02, 0x00, 0x33, 0x33, 0x00, 0x82, 0x88, 0x08, 0x23,
+       0xB3, 0x01, 0x04, 0x01, 0x0E, 0xD0, 0x00, 0x33, 0x14, 0x00, 0x82, 0x88, 0x10, 0x23, 0xB3, 0x01,
+       0x04, 0x01, 0x07, 0xCC, 0x00, 0x33, 0x15, 0x00, 0x82, 0x88, 0x4A, 0x95, 0xF0, 0x82, 0xF8, 0x95,
+       0xF0, 0x82, 0x44, 0x98, 0x80, 0x42, 0x40, 0x98, 0x48, 0xE4, 0x04, 0x01, 0x29, 0xC8, 0x31, 0x05,
+       0x07, 0x01, 0x00, 0xA2, 0x72, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x48, 0x98, 0x40, 0x98,
+       0x00, 0xA6, 0x34, 0x03, 0x07, 0xA6, 0x6A, 0x03, 0x03, 0xA6, 0x16, 0x04, 0x06, 0xA6, 0x6E, 0x03,
+       0x01, 0xA6, 0x34, 0x03, 0x00, 0x33, 0x25, 0x00, 0x82, 0x88, 0x4A, 0x95, 0x50, 0x83, 0xF8, 0x95,
+       0x50, 0x83, 0x04, 0x01, 0x0C, 0xCE, 0x03, 0xC8, 0x00, 0x33, 0x42, 0x00, 0x82, 0x88, 0x00, 0x01,
+       0x05, 0x05, 0xFF, 0xA2, 0x90, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x4C, 0x83, 0x05, 0x05,
+       0x01, 0xA6, 0x9A, 0x03, 0x00, 0xA6, 0xAA, 0x03, 0xF0, 0x83, 0x68, 0x98, 0x80, 0x42, 0x01, 0xA6,
+       0x9A, 0x03, 0xBA, 0x83, 0x00, 0x33, 0x2F, 0x00, 0x82, 0x88, 0x68, 0x98, 0x80, 0x42, 0x00, 0xA6,
+       0xAA, 0x03, 0xBA, 0x83, 0x00, 0x33, 0x26, 0x00, 0x82, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36,
+       0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0xF0, 0x83, 0x04, 0xF0, 0x80, 0x6B, 0x00, 0x33,
+       0x20, 0x00, 0x82, 0x88, 0x03, 0xA6, 0xEE, 0x03, 0x07, 0xA6, 0xE6, 0x03, 0x06, 0xA6, 0xEA, 0x03,
+       0x00, 0x33, 0x17, 0x00, 0x82, 0x88, 0x4A, 0x95, 0xD4, 0x83, 0xF8, 0x95, 0xD4, 0x83, 0xFA, 0x83,
+       0x04, 0xF0, 0x80, 0x6B, 0x00, 0x33, 0x20, 0x00, 0x82, 0x88, 0xB6, 0x2D, 0x03, 0xA6, 0x16, 0x04,
+       0x07, 0xA6, 0x0E, 0x04, 0x06, 0xA6, 0x12, 0x04, 0x00, 0x33, 0x30, 0x00, 0x82, 0x88, 0x4A, 0x95,
+       0xFA, 0x83, 0xF8, 0x95, 0xFA, 0x83, 0xA2, 0x0D, 0x80, 0x63, 0x07, 0xA6, 0x24, 0x04, 0x00, 0x33,
+       0x18, 0x00, 0x82, 0x88, 0x03, 0x03, 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x2E, 0x04, 0x23, 0x01,
+       0x00, 0xA2, 0x50, 0x04, 0x0A, 0xA0, 0x40, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00, 0x82, 0x88,
+       0x0B, 0xA0, 0x4C, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00, 0x82, 0x88, 0x42, 0x23, 0xB8, 0x88,
+       0x00, 0x23, 0x22, 0xA3, 0xB2, 0x04, 0x08, 0x23, 0x22, 0xA3, 0x6C, 0x04, 0x28, 0x23, 0x22, 0xA3,
+       0x78, 0x04, 0x02, 0x23, 0x22, 0xA3, 0x8E, 0x04, 0x42, 0x23, 0xB8, 0x88, 0x4A, 0x00, 0x06, 0x61,
+       0x00, 0xA0, 0x78, 0x04, 0x45, 0x23, 0xB8, 0x88, 0xC6, 0x97, 0x00, 0xA2, 0x8A, 0x04, 0x74, 0x98,
+       0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62, 0xF6, 0x81, 0x47, 0x23, 0xB8, 0x88, 0x04, 0x01,
+       0x0C, 0xDE, 0x14, 0x01, 0x00, 0xA2, 0xA6, 0x04, 0xC6, 0x97, 0x74, 0x98, 0x00, 0x33, 0x00, 0x81,
+       0xC0, 0x20, 0x81, 0x62, 0x10, 0x82, 0x43, 0x23, 0xB8, 0x88, 0x04, 0x23, 0xA0, 0x01, 0x44, 0x23,
+       0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xC0, 0x04, 0x00, 0x33, 0x27, 0x00, 0x82, 0x88,
+       0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xC6, 0x97, 0xF4, 0x94,
+       0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0xEE, 0x04, 0x00, 0x05, 0x76, 0x00,
+       0x06, 0x61, 0x00, 0xA2, 0xE8, 0x04, 0xD6, 0x84, 0x08, 0x97, 0xCD, 0x04, 0xF2, 0x84, 0x48, 0x04,
+       0xFF, 0x23, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x02, 0x85, 0x02, 0x23,
+       0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x0E, 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, 0x2E, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00, 0x5D, 0x00,
+       0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4, 0xA0, 0x05, 0x03, 0x03,
+       0x02, 0xA0, 0x5C, 0x05, 0x9C, 0x85, 0x00, 0x33, 0x2D, 0x00, 0x82, 0x88, 0x04, 0xA0, 0x82, 0x05,
+       0x80, 0x63, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x6E, 0x05, 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23,
+       0x02, 0x41, 0x82, 0x01, 0x50, 0x00, 0x24, 0x97, 0xD0, 0x84, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01,
+       0xD0, 0x84, 0x08, 0xA0, 0x88, 0x05, 0x9C, 0x85, 0x03, 0xA0, 0x8E, 0x05, 0x9C, 0x85, 0x01, 0xA0,
+       0x9A, 0x05, 0x88, 0x00, 0x80, 0x63, 0x78, 0x96, 0x4A, 0x85, 0x88, 0x86, 0x80, 0x63, 0x4A, 0x85,
+       0x00, 0x63, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xDE, 0x05, 0x1D, 0x01, 0x18, 0xD4, 0xC0, 0x23,
+       0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0xC0, 0x05, 0x00, 0x33, 0x37, 0x00, 0x82, 0x88,
+       0x1D, 0x01, 0x02, 0xD6, 0x46, 0x23, 0xB8, 0x88, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
+       0xD8, 0x05, 0x00, 0x33, 0x38, 0x00, 0x82, 0x88, 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00,
+       0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xF2, 0x05, 0xC0, 0x23, 0x07, 0x41,
+       0x00, 0x63, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63, 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63,
+       0x00, 0x63, 0x06, 0xA6, 0x14, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x02, 0xA6, 0xBC, 0x06, 0x00, 0x33,
+       0x39, 0x00, 0x82, 0x88, 0x00, 0x00, 0x01, 0xA0, 0xD6, 0x06, 0xA2, 0x95, 0x83, 0x03, 0x80, 0x63,
+       0x06, 0xA6, 0x28, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x00, 0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63,
+       0x01, 0x00, 0x06, 0xA6, 0x40, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x33, 0x3A, 0x00, 0x82, 0x88,
+       0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x32, 0x06, 0x06, 0xA6, 0x58, 0x06, 0x07, 0xA6,
+       0x64, 0x06, 0x00, 0x33, 0x3B, 0x00, 0x82, 0x88, 0x80, 0x67, 0x40, 0x0E, 0x80, 0x63, 0x07, 0xA6,
+       0x64, 0x06, 0x00, 0x63, 0x03, 0x03, 0x80, 0x63, 0x88, 0x00, 0x01, 0xA2, 0x78, 0x06, 0x07, 0xA2,
+       0xBC, 0x06, 0x00, 0x33, 0x35, 0x00, 0x82, 0x88, 0x07, 0xA6, 0x82, 0x06, 0x00, 0x33, 0x2A, 0x00,
+       0x82, 0x88, 0x03, 0x03, 0x03, 0xA2, 0x8E, 0x06, 0x07, 0x23, 0x80, 0x00, 0xC8, 0x86, 0x80, 0x63,
+       0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0x9E, 0x06, 0x00, 0x33, 0x29, 0x00, 0x82, 0x88, 0x00, 0x43,
+       0x00, 0xA2, 0xAA, 0x06, 0xC0, 0x0E, 0x80, 0x63, 0x94, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80,
+       0xC0, 0x20, 0x81, 0x62, 0x04, 0x01, 0x08, 0xDA, 0x80, 0x63, 0x00, 0x63, 0x80, 0x67, 0x00, 0x33,
+       0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x20, 0x06,
+       0x00, 0x33, 0x2C, 0x00, 0x82, 0x88, 0x0C, 0xA2, 0xF0, 0x06, 0xA2, 0x95, 0x83, 0x03, 0x80, 0x63,
+       0x06, 0xA6, 0xEE, 0x06, 0x07, 0xA6, 0x64, 0x06, 0x00, 0x33, 0x3D, 0x00, 0x82, 0x88, 0x00, 0x00,
+       0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x06, 0x07, 0x07, 0xA6, 0x64, 0x06, 0xBF, 0x23,
+       0x04, 0x61, 0x84, 0x01, 0xB2, 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, 0x86, 0x07,
+       0x00, 0x33, 0x07, 0x00, 0x82, 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,
+       0xA6, 0x07, 0x00, 0x05, 0x9C, 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, 0xD6, 0x07, 0xD8, 0x87, 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,
+       0x06, 0x08, 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0xE6, 0x07,
+       0xC6, 0x97, 0xF4, 0x94, 0xE6, 0x87, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x1C, 0x88,
+       0x02, 0x01, 0x04, 0xD8, 0x08, 0x97, 0xC6, 0x97, 0xF4, 0x94, 0x0C, 0x88, 0x75, 0x00, 0x00, 0xA3,
+       0x26, 0x08, 0x00, 0x05, 0x10, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6,
+       0x38, 0x08, 0x00, 0x33, 0x3E, 0x00, 0x82, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63,
+       0x38, 0x2B, 0x5E, 0x88, 0x38, 0x2B, 0x54, 0x88, 0x32, 0x09, 0x31, 0x05, 0x54, 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, 0x74, 0x08, 0x5D, 0x00, 0xFE, 0xC3,
+       0x00, 0x63, 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
+       0x13, 0x23, 0xB8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01,
+       0x81, 0x62, 0xA2, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2,
+       0xF1, 0xC7, 0x41, 0x23, 0xB8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xB2, 0x84,
+
+};
+
+ushort              _mcode_size = sizeof (_mcode_buf);
+ulong               _mcode_chksum = 0x012258FBUL;
+
+extern uchar        _sdtr_period_tbl_[];
+
+int
+AscExeScsiQueue(
+                                  ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                  ASC_SCSI_Q dosfar * scsiq
+)
+{
+       PortAddr            iop_base;
+       int                 last_int_level;
+       int                 sta;
+       ulong               addr;
+       uchar               sg_entry_cnt;
+       uchar               target_ix;
+       int                 n_q_required;
+       uchar               sg_entry_cnt_minus_one;
+       uchar               tid_no;
+       uchar               sdtr_data;
+       ASC_EXE_CALLBACK    asc_exe_callback;
+
+#if CC_DEBUG_SG_LIST
+       int                 i;
+
+#endif
+#if CC_LINK_BUSY_Q
+       ASC_SCSI_Q dosfar  *scsiq_tail;
+       ASC_SCSI_Q dosfar  *scsiq_next;
+       ASC_SCSI_Q dosfar  *scsiq_prev;
+
+#endif
+
+       iop_base = asc_dvc->iop_base;
+       asc_exe_callback = (ASC_EXE_CALLBACK) asc_dvc->exe_callback;
+       if (asc_dvc->err_code != 0)
+               return (ERR);
+       if (scsiq == (ASC_SCSI_Q dosfar *) 0L) {
+               AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR);
+               return (ERR);
+       }
+       scsiq->q1.q_no = 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) != 0)) {
+                       sdtr_data = AscReadLramByte(iop_base,
+                                 (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no));
+                       AscMsgOutSDTR(iop_base,
+                                                 _sdtr_period_tbl_[(sdtr_data >> 4) & (uchar) (ASC_SYN_XFER_NO - 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 = scsiq->sg_head->entry_cnt) == 0) {
+                       asc_dvc->in_critical_cnt--;
+                       DvcLeaveCritical(last_int_level);
+                       return (ERR);
+               }
+               if (sg_entry_cnt == 1) {
+                       scsiq->q1.data_addr = scsiq->sg_head->sg_list[0].addr;
+                       scsiq->q1.data_cnt = scsiq->sg_head->sg_list[0].bytes;
+                       scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
+                       goto NON_SG_LIST_REQ;
+               }
+               if (sg_entry_cnt > ASC_MAX_SG_LIST) {
+
+                       return (ERR);
+               }
+               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 = scsiq->sg_head->sg_list[i].addr +
+                                 scsiq->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
+
+               if (asc_dvc->bug_fix_cntl) {
+                       if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) {
+
+                               addr = scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].addr +
+                                 scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].bytes;
+                               if (((ushort) addr & 0x0003) != 0) {
+                                       if ((scsiq->cdbptr[0] == SCSICMD_Read6) ||
+                                               (scsiq->cdbptr[0] == SCSICMD_Read10)) {
+                                               if ((scsiq->q2.tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) == 0) {
+
+                                                       scsiq->sg_head->sg_list[sg_entry_cnt_minus_one].bytes++;
+                                                       scsiq->q2.tag_code |= ASC_TAG_FLAG_ADD_ONE_BYTE;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               scsiq->sg_head->entry_to_copy = scsiq->sg_head->entry_cnt;
+               n_q_required = AscSgListToQueue(sg_entry_cnt);
+
+#if CC_LINK_BUSY_Q
+               scsiq_next = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_head[tid_no];
+               if (scsiq_next != (ASC_SCSI_Q dosfar *) 0L) {
+                       goto link_scisq_to_busy_list;
+               }
+#endif
+
+               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 {
+
+         NON_SG_LIST_REQ:
+
+               if (asc_dvc->bug_fix_cntl) {
+                       if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ADD_ONE_BYTE) {
+
+                               addr = scsiq->q1.data_addr + scsiq->q1.data_cnt;
+                               if ((scsiq->cdbptr[0] == SCSICMD_Read6) ||
+                                       (scsiq->cdbptr[0] == SCSICMD_Read10)) {
+                                       if (((ushort) addr & 0x0003) != 0) {
+                                               if (((ushort) scsiq->q1.data_cnt & 0x01FF) == 0) {
+
+                                                       if ((scsiq->q2.tag_code & ASC_TAG_FLAG_ADD_ONE_BYTE) == 0) {
+
+                                                               scsiq->q2.tag_code |= ASC_TAG_FLAG_ADD_ONE_BYTE;
+                                                               scsiq->q1.data_cnt++;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               n_q_required = 1;
+
+#if CC_LINK_BUSY_Q
+               scsiq_next = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_head[tid_no];
+               if (scsiq_next != (ASC_SCSI_Q dosfar *) 0L) {
+                       goto link_scisq_to_busy_list;
+               }
+#endif
+               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);
+                       }
+               }
+       }
+
+#if CC_LINK_BUSY_Q
+       if (sta == 0) {
+
+         link_scisq_to_busy_list:
+               scsiq->ext.q_required = n_q_required;
+               if (scsiq_next == (ASC_SCSI_Q dosfar *) 0L) {
+                       asc_dvc->scsiq_busy_head[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
+                       asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
+                       scsiq->ext.next = (ASC_SCSI_Q dosfar *) 0L;
+                       scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
+                       scsiq->q1.status = QS_BUSY;
+                       sta = 1;
+               } else {
+                       scsiq_tail = (ASC_SCSI_Q dosfar *) asc_dvc->scsiq_busy_tail[tid_no];
+                       if (scsiq_tail->ext.next == (ASC_SCSI_Q dosfar *) 0L) {
+                               if ((scsiq->q1.cntl & QC_URGENT) != 0) {
+
+                                       asc_dvc->scsiq_busy_head[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
+                                       scsiq->ext.next = scsiq_next;
+                                       scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
+                               } else {
+                                       if (scsiq->ext.cntl & QCX_SORT) {
+                                               do {
+                                                       scsiq_prev = scsiq_next;
+                                                       scsiq_next = scsiq_next->ext.next;
+                                                       if (scsiq->ext.lba < scsiq_prev->ext.lba)
+                                                               break;
+                                               } while (scsiq_next != (ASC_SCSI_Q dosfar *) 0L);
+
+                                               scsiq_prev->ext.next = scsiq;
+                                               scsiq->ext.next = scsiq_next;
+                                               if (scsiq_next == (ASC_SCSI_Q dosfar *) 0L) {
+                                                       asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
+                                               }
+                                               scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
+                                       } else {
+
+                                               scsiq_tail->ext.next = (ASC_SCSI_Q dosfar *) scsiq;
+                                               asc_dvc->scsiq_busy_tail[tid_no] = (ASC_SCSI_Q dosfar *) scsiq;
+                                               scsiq->ext.next = (ASC_SCSI_Q dosfar *) 0L;
+                                               scsiq->ext.join = (ASC_SCSI_Q dosfar *) 0L;
+                                       }
+                               }
+                               scsiq->q1.status = QS_BUSY;
+                               sta = 1;
+                       } else {
+
+                               AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_BAD_NEXT_PTR);
+                               sta = ERR;
+                       }
+               }
+       }
+#endif
+       asc_dvc->in_critical_cnt--;
+       DvcLeaveCritical(last_int_level);
+       return (sta);
+}
+
+int
+AscSendScsiQueue(
+                                       ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                       ASC_SCSI_Q dosfar * 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) {
+
+#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);
+               }
+       }
+       return (sta);
+}
+
+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);
+}
+
+uint
+AscGetNumOfFreeQueue(
+                                               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) {
+                       asc_dvc->last_q_shortage = n_qs;
+               }
+       }
+       return (0);
+}
+
+int
+AscPutReadyQueue(
+                                       ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                       ASC_SCSI_Q dosfar * 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 = AscReadLramByte(iop_base,
+                                 (ushort) ((ushort) ASCV_SDTR_DATA_BEG + (ushort) tid_no));
+               syn_period_ix = (sdtr_data >> 4) & (ASC_SYN_XFER_NO - 1);
+               syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
+               AscMsgOutSDTR(iop_base,
+                                         _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 dosfar *) 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 dosfar *) & 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 dosfar *) 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 dosfar *) & scsiq->q1.cntl,
+                (ushort) (((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1))
+                       != 0) {
+                       AscSetLibErrorCode(asc_dvc, ASCQ_ERR_LOCAL_MEM);
+                       return (ERR);
+               }
+       }
+#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);
+}
+
+int
+AscPutReadySgListQueue(
+                                                 ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                                 ASC_SCSI_Q dosfar * scsiq,
+                                                 uchar q_no
+)
+{
+       uchar               sg_list_dwords;
+       uchar               sg_index, i;
+       uchar               sg_entry_cnt;
+       uchar               next_qp;
+       ushort              q_addr;
+       int                 sta;
+       ASC_SG_HEAD dosfar *sg_head;
+       ASC_SG_LIST_Q       scsi_sg_q;
+       ulong               saved_data_addr;
+       ulong               saved_data_cnt;
+       PortAddr            iop_base;
+
+       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 dosfar *) & scsi_sg_q,
+                                                                (ushort) (sizeof (ASC_SG_LIST_Q) >> 1));
+
+                       AscMemDWordCopyToLram(iop_base,
+                                                                 (ushort) (q_addr + ASC_SGQ_LIST_BEG),
+                                                         (ulong dosfar *) & 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);
+}
+
+int
+AscAbortSRB(
+                          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);
+}
+
+int
+AscResetDevice(
+                                 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 dosfar *scsiq;
+       uchar dosfar       *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 dosfar *) & scsiq_buf;
+                       buf = (uchar dosfar *) & 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 dosfar *) 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 dosfar *) scsiq)
+                               == 1) {
+                               asc_dvc->unit_not_ready = target_id;
+                               DvcSleepMilliSecond(1000);
+                               _AscWaitQDone(iop_base, (ASC_SCSI_Q dosfar *) 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);
+}
+
+int
+AscResetSB(
+                         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));
+
+#if CC_SCAM
+       if (!(asc_dvc->dvc_cntl & ASC_CNTL_NO_SCAM)) {
+               AscSCAM(asc_dvc);
+       }
+#endif
+       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 & (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);
+}
+
+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);
+}
+
+int
+AscSetChipSynRegAtID(
+                                               PortAddr iop_base,
+                                               uchar id,
+                                               uchar sdtr_data
+)
+{
+       AscSetBank(iop_base, 1);
+       AscWriteChipScsiID(iop_base, id);
+       if (AscReadChipScsiID(iop_base) != (0x01 << id)) {
+               return (FALSE);
+       }
+       AscSetBank(iop_base, 0);
+       AscWriteChipSyn(iop_base, sdtr_data);
+       if (AscReadChipSyn(iop_base) != sdtr_data) {
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+int
+AscReInitLram(
+                                ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+       AscInitLram(asc_dvc);
+       AscInitQLinkVar(asc_dvc);
+       return (0);
+}
+
+ushort
+AscInitLram(
+                          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);
+}
+
+ushort
+AscInitQLinkVar(
+                                  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);
+
+       AscWriteLramByte(iop_base, (ushort) ASCV_CDBCNT_B, 0);
+
+       lram_addr = ASC_QADR_BEG;
+       for (i = 0; i < 32; i++, lram_addr += 2) {
+               AscWriteLramWord(iop_base, lram_addr, 0);
+       }
+
+       return (0);
+}
+
+int
+AscSetLibErrorCode(
+                                         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);
+}
+
+int
+_AscWaitQDone(
+                                PortAddr iop_base,
+                                ASC_SCSI_Q dosfar * 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);
+}
+
+uchar               _sdtr_period_tbl_[ASC_SYN_XFER_NO] =
+{
+       SYN_XFER_NS_0,
+       SYN_XFER_NS_1,
+       SYN_XFER_NS_2,
+       SYN_XFER_NS_3,
+       SYN_XFER_NS_4,
+       SYN_XFER_NS_5,
+       SYN_XFER_NS_6,
+       SYN_XFER_NS_7};
+
+uchar
+AscMsgOutSDTR(
+                                PortAddr iop_base,
+                                uchar sdtr_period,
+                                uchar sdtr_offset
+)
+{
+       SDTR_XMSG           sdtr_buf;
+       uchar               sdtr_period_index;
+
+       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;
+       AscMemWordCopyToLram(iop_base, ASCV_MSGOUT_BEG,
+                                                (ushort dosfar *) & sdtr_buf, SYN_XMSG_WLEN);
+       if ((sdtr_period_index = AscGetSynPeriodIndex(sdtr_period)) <=
+               ASC_MAX_SDTR_PERIOD_INDEX) {
+               return ((sdtr_period_index << 4) | sdtr_offset);
+       } else {
+
+               return (0);
+       }
+}
+
+uchar
+AscCalSDTRData(
+                                 uchar sdtr_period,
+                                 uchar syn_offset
+)
+{
+       uchar               byte;
+       uchar               sdtr_period_ix;
+
+       sdtr_period_ix = AscGetSynPeriodIndex(sdtr_period);
+       if ((sdtr_period_ix > ASC_MAX_SDTR_PERIOD_INDEX) ||
+               (sdtr_period_ix > ASC_SDTR_PERIOD_IX_MIN)) {
+               return (0xFF);
+       }
+       byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
+       return (byte);
+}
+
+void
+AscSetChipSDTR(
+                                 PortAddr iop_base,
+                                 uchar sdtr_data,
+                                 uchar tid_no
+)
+{
+
+       AscWriteChipSyn(iop_base, sdtr_data);
+       AscWriteLramByte(iop_base,
+                                  (ushort) ((ushort) ASCV_SDTR_DONE_BEG + (ushort) tid_no),
+                                        sdtr_data);
+       return;
+}
+
+uchar
+AscGetSynPeriodIndex(
+                                               uchar syn_time
+)
+{
+       if ((syn_time >= SYN_XFER_NS_0) && (syn_time <= SYN_XFER_NS_7)) {
+               if (syn_time <= SYN_XFER_NS_6) {
+                       if (syn_time <= SYN_XFER_NS_5) {
+                               if (syn_time <= SYN_XFER_NS_4) {
+                                       if (syn_time <= SYN_XFER_NS_3) {
+                                               if (syn_time <= SYN_XFER_NS_2) {
+                                                       if (syn_time <= SYN_XFER_NS_1) {
+                                                               if (syn_time <= SYN_XFER_NS_0) {
+                                                                       return (0);
+                                                               } else
+                                                                       return (1);
+                                                       } else {
+                                                               return (2);
+                                                       }
+                                               } else {
+                                                       return (3);
+                                               }
+                                       } else {
+                                               return (4);
+                                       }
+                               } else {
+                                       return (5);
+                               }
+                       } else {
+                               return (6);
+                       }
+               } else {
+                       return (7);
+               }
+       } else {
+
+               return (8);
+       }
+}
+
+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);
+}
+
+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);
+}
+
+int
+AscRiscHaltedAbortSRB(
+                                                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 dosfar *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 dosfar *) & scsiq_buf;
+
+#if CC_LINK_BUSY_Q
+       _AscAbortSrbBusyQueue(asc_dvc, scsiq, srb_ptr);
+#endif
+
+       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);
+}
+
+int
+AscRiscHaltedAbortTIX(
+                                                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 dosfar *scsiq;
+       ASC_ISR_CALLBACK    asc_isr_callback;
+       int                 last_int_level;
+
+#if CC_LINK_BUSY_Q
+       uchar               tid_no;
+
+#endif
+
+       iop_base = asc_dvc->iop_base;
+       asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
+       last_int_level = DvcEnterCritical();
+       scsiq = (ASC_QDONE_INFO dosfar *) & scsiq_buf;
+
+#if CC_LINK_BUSY_Q
+
+       tid_no = ASC_TIX_TO_TID(target_ix);
+       _AscAbortTidBusyQueue(asc_dvc, scsiq, tid_no);
+
+#endif
+
+       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);
+}
+
+#if CC_LINK_BUSY_Q
+
+#endif
+
+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);
+}
+
+int
+AscStopQueueExe(
+                                  PortAddr iop_base
+)
+{
+       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);
+       }
+       return (0);
+}
+
+int
+AscStartQueueExe(
+                                       PortAddr iop_base
+)
+{
+       if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) {
+               AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
+       }
+       return (1);
+}
+
+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);
+}
+
+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);
+}
+
+int
+AscWaitTixISRDone(
+                                        ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                        uchar target_ix
+)
+{
+       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;
+               }
+       }
+       return (1);
+}
+
+int
+AscWaitISRDone(
+                                 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);
+}
+
+ulong
+AscGetOnePhyAddr(
+                                       ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                       uchar dosfar * buf_addr,
+                                       ulong buf_size
+)
+{
+       ASC_MIN_SG_HEAD     sg_head;
+
+       sg_head.entry_cnt = ASC_MIN_SG_LIST;
+       if (DvcGetSGList(asc_dvc, (uchar dosfar *) buf_addr,
+                                 buf_size, (ASC_SG_HEAD dosfar *) & sg_head) != buf_size) {
+               return (0L);
+       }
+       if (sg_head.entry_cnt > 1) {
+               return (0L);
+       }
+       return (sg_head.sg_list[0].addr);
+}
+
+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);
+}
+
+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);
+}
+
+int
+AscStartChip(
+                               PortAddr iop_base
+)
+{
+       AscSetChipControl(iop_base, 0);
+       if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
+               return (0);
+       }
+       return (1);
+}
+
+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);
+}
+
+int
+AscIsChipHalted(
+                                  PortAddr iop_base
+)
+{
+
+       if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
+               if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
+                       return (1);
+               }
+       }
+       return (0);
+}
+
+void
+AscSetChipIH(
+                               PortAddr iop_base,
+                               ushort ins_code
+)
+{
+       AscSetBank(iop_base, 1);
+       AscWriteChipIH(iop_base, ins_code);
+       AscSetBank(iop_base, 0);
+       return;
+}
+
+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);
+       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;
+}
+
+void
+AscDisableInterrupt(
+                                          PortAddr iop_base
+)
+{
+       ushort              cfg;
+
+       cfg = AscGetChipCfgLsw(iop_base);
+       AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
+       return;
+}
+
+void
+AscEnableInterrupt(
+                                         PortAddr iop_base
+)
+{
+       ushort              cfg;
+
+       cfg = AscGetChipCfgLsw(iop_base);
+       AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
+       return;
+}
+
+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;
+}
+
+int
+AscResetChipAndScsiBus(
+                                                 PortAddr iop_base
+)
+{
+       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);
+       return (AscIsChipHalted(iop_base));
+}
+
+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);
+}
+
+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);
+}
+
+uchar
+AscSetIsaDmaSpeed(
+                                        PortAddr iop_base,
+                                        uchar speed_value
+)
+{
+       speed_value &= 0x07;
+       AscSetBank(iop_base, 1);
+       AscSetChipDmaSpeed(iop_base, speed_value);
+       AscSetBank(iop_base, 0);
+       return (AscGetIsaDmaSpeed(iop_base));
+}
+
+uchar
+AscGetIsaDmaSpeed(
+                                        PortAddr iop_base
+)
+{
+       uchar               speed_value;
+
+       AscSetBank(iop_base, 1);
+       speed_value = AscGetChipDmaSpeed(iop_base);
+       speed_value &= 0x07;
+       AscSetBank(iop_base, 0);
+       return (speed_value);
+}
+
+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);
+}
+
+ushort
+AscInitGetConfig(
+                                       ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+       ushort              warn_code;
+
+       warn_code = 0;
+       asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
+       if (asc_dvc->err_code != 0)
+               return (UW_ERR);
+       if (AscFindSignature(asc_dvc->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 > 10)
+                       asc_dvc->scsi_reset_wait = 10;
+
+       } else {
+               asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
+       }
+       return (warn_code);
+}
+
+ushort
+AscInitSetConfig(
+                                       ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+       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;
+       } else {
+               asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
+       }
+       return (warn_code);
+}
+
+ushort
+AscInitAsc1000Driver(
+                                               ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+       ushort              warn_code;
+       PortAddr            iop_base;
+
+       extern ushort       _mcode_size;
+       extern ulong        _mcode_chksum;
+       extern uchar        _mcode_buf[];
+
+       ASC_DBG(3, "AscInitAsc1000Driver: begin\n");
+       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)) {
+
+               ASC_DBG(3, "AscInitAsc1000Driver: AscResetChipAndScsiBus()\n");
+               AscResetChipAndScsiBus(iop_base);
+               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);
+       ASC_DBG(3, "AscInitAsc1000Driver: AscFindSignature()\n");
+       if (!AscFindSignature(asc_dvc->iop_base)) {
+               asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
+               return (warn_code);
+       }
+       ASC_DBG(3, "AscInitAsc1000Driver: AscDisableInterrupt()\n");
+       AscDisableInterrupt(iop_base);
+
+       ASC_DBG(3, "AscInitAsc1000Driver: AscInitLram()\n");
+       warn_code |= AscInitLram(asc_dvc);
+       if (asc_dvc->err_code != 0)
+               return (UW_ERR);
+       ASC_DBG(3, "AscInitAsc1000Driver: AscLoadMicroCode()\n");
+       if (AscLoadMicroCode(iop_base, 0, (ushort dosfar *) _mcode_buf,
+                                                _mcode_size) != _mcode_chksum) {
+               asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
+               return (warn_code);
+       }
+       ASC_DBG(3, "AscInitAsc1000Driver: AscInitMicroCodeVar()\n");
+       warn_code |= AscInitMicroCodeVar(asc_dvc);
+       asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
+       ASC_DBG(3, "AscInitAsc1000Driver: AscEnableInterrupt()\n");
+       AscEnableInterrupt(iop_base);
+       return (warn_code);
+}
+
+ushort
+AscInitAscDvcVar(
+                                       ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+       int                 i;
+       PortAddr            iop_base;
+       ushort              warn_code;
+
+       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;
+       }
+#if CC_LINK_BUSY_Q
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q dosfar *) 0L;
+               asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q dosfar *) 0L;
+       }
+#endif
+
+       asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
+       asc_dvc->bug_fix_cntl = 0;
+       asc_dvc->pci_fix_asyn_xfer = 0;
+       asc_dvc->init_sdtr = 0;
+       asc_dvc->sdtr_done = 0;
+       asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
+       asc_dvc->cur_total_qng = 0;
+       asc_dvc->is_in_int = 0;
+       asc_dvc->scsi_reset_wait = 3;
+       asc_dvc->in_critical_cnt = 0;
+
+       asc_dvc->last_q_shortage = 0;
+       asc_dvc->use_tagged_qng = 0;
+       asc_dvc->cfg->can_tagged_qng = 0;
+       asc_dvc->no_scam = 0;
+       asc_dvc->irq_no = 10;
+       asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
+       asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
+       asc_dvc->cfg->cmd_qng_enabled = ASC_SCSI_WIDTH_BIT_SET;
+       asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
+       asc_dvc->cfg->chip_version = AscGetChipVersion(iop_base,
+                                                                                                  asc_dvc->bus_type);
+       if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) {
+
+               AscPutChipIFC(iop_base, IFC_INIT_DEFAULT);
+               asc_dvc->bus_type = ASC_IS_ISAPNP;
+       }
+       asc_dvc->unit_not_ready = 0;
+       asc_dvc->queue_full_or_busy = 0;
+
+       if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
+               asc_dvc->cfg->isa_dma_channel = (uchar) AscGetIsaDmaChannel(iop_base);
+               asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
+       }
+       asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
+       asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
+         ASC_LIB_VERSION_MINOR;
+       asc_dvc->int_count = 0L;
+       asc_dvc->req_count = 0L;
+       asc_dvc->busy_count = 0L;
+       asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
+
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               asc_dvc->cfg->sdtr_data[i] =
+                 (uchar) (ASC_DEF_SDTR_OFFSET | (ASC_DEF_SDTR_INDEX << 4));
+               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 dosfar *) 0L;
+               asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q dosfar *) 0L;
+       }
+       return (warn_code);
+}
+
+ushort
+AscInitFromAscDvcVar(
+                                               ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+       PortAddr            iop_base;
+       ushort              cfg_msw;
+       ushort              warn_code;
+
+       iop_base = asc_dvc->iop_base;
+       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 (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
+               warn_code |= ASC_WARN_AUTO_CONFIG;
+
+       }
+       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 ((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 (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) != 0) {
+               AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
+               AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
+       }
+       return (warn_code);
+}
+
+ushort
+AscInitFromEEP(
+                                 ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+       ASCEEP_CONFIG       eep_config_buf;
+       ASCEEP_CONFIG dosfar *eep_config;
+       PortAddr            iop_base;
+       ushort              chksum;
+       ushort              warn_code;
+       ushort              cfg_msw, cfg_lsw;
+       uchar               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 dosfar *) & eep_config_buf;
+
+       cfg_msw = AscGetChipCfgMsw(iop_base);
+       cfg_lsw = AscGetChipCfgLsw(iop_base);
+
+       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->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) {
+                       asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ADD_ONE_BYTE;
+               }
+       }
+       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);
+
+       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);
+                       }
+                       if (eep_config->cfg_msw != cfg_msw) {
+                               warn_code |= ASC_WARN_EEPROM_RECOVER;
+                               eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
+                       }
+               }
+       }
+       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 ((asc_dvc->bus_type & ASC_IS_PCI) &&
+               !(asc_dvc->dvc_cntl & ASC_CNTL_NO_PCI_FIX_ASYN_XFER)) {
+               if ((asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) ||
+                       (asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) {
+                       asc_dvc->pci_fix_asyn_xfer = ASC_ALL_DEVICE_BIT_SET;
+               }
+       } else if (asc_dvc->bus_type & ASC_IS_ISAPNP) {
+
+               if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
+                       == ASC_CHIP_VER_ASYN_BUG) {
+                       asc_dvc->pci_fix_asyn_xfer = ASC_ALL_DEVICE_BIT_SET;
+               }
+       }
+       if (!AscTestExternalLram(asc_dvc)) {
+               if (asc_dvc->bus_type & ASC_IS_PCI) {
+                       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 CC_TEST_RW_LRAM
+               asc_dvc->err_code |= AscTestLramEndian(iop_base);
+#endif
+       }
+       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;
+       }
+       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;
+
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               asc_dvc->cfg->sdtr_data[i] = eep_config->sdtr_data[i];
+               asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
+       }
+
+       eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
+       if (AscSetEEPConfig(iop_base, eep_config, asc_dvc->bus_type) != 0) {
+               asc_dvc->err_code |= ASC_IERR_WRITE_EEPROM;
+       }
+       return (warn_code);
+}
+
+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++) {
+               AscWriteLramByte(iop_base, (ushort) (ASCV_SDTR_DATA_BEG + i),
+                                                asc_dvc->cfg->sdtr_data[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 dosfar *) 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);
+}
+
+void                dosfar
+AscInitPollIsrCallBack(
+                                                 ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                                 ASC_QDONE_INFO dosfar * scsi_done_q
+)
+{
+       ASC_SCSI_REQ_Q dosfar *scsiq_req;
+       ASC_ISR_CALLBACK    asc_isr_callback;
+       uchar               cp_sen_len;
+       uchar               i;
+
+       if ((scsi_done_q->d2.flag & ASC_FLAG_SCSIQ_REQ) != 0) {
+               scsiq_req = (ASC_SCSI_REQ_Q dosfar *) scsi_done_q->d2.srb_ptr;
+               ASC_DBG2(3, "AscInitPollIsrCallBack: done_stat %x, host_stat %x\n",
+                                scsiq_req->r3.done_stat, scsiq_req->r3.host_stat);
+               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;
+               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 {
+               ASC_DBG1(3, "AscInitPollIsrCallBack: isr_callback %x\n",
+                                (unsigned) asc_dvc->isr_callback);
+               if (asc_dvc->isr_callback != 0) {
+                       asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
+                       (*asc_isr_callback) (asc_dvc, scsi_done_q);
+               }
+       }
+       return;
+}
+
+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);
+       if (AscVerWriteLramWord(iop_base, q_addr, 0x55AA) == 0) {
+               sta = 1;
+               AscWriteLramWord(iop_base, q_addr, saved_word);
+       }
+       return (sta);
+}
+
+#if CC_TEST_LRAM_ENDIAN
+
+#endif
+
+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);
+               }
+       }
+}
+
+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);
+               }
+       }
+}
+
+void
+AscWaitEEPRead(
+                                 void
+)
+{
+       DvcSleepMilliSecond(1);
+       return;
+}
+
+void
+AscWaitEEPWrite(
+                                  void
+)
+{
+       DvcSleepMilliSecond(20);
+       return;
+}
+
+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);
+}
+
+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);
+}
+
+ushort
+AscGetEEPConfig(
+                                  PortAddr iop_base,
+                                  ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type
+)
+{
+       ushort              wval;
+       ushort              sum;
+       ushort dosfar      *wbuf;
+       int                 cfg_beg;
+       int                 cfg_end;
+       int                 s_addr;
+       int                 isa_pnp_wsize;
+
+       wbuf = (ushort dosfar *) 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);
+}
+
+int
+AscSetEEPConfigOnce(
+                                          PortAddr iop_base,
+                                          ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type
+)
+{
+       int                 n_error;
+       ushort dosfar      *wbuf;
+       ushort              sum;
+       int                 s_addr;
+       int                 cfg_beg;
+       int                 cfg_end;
+
+       wbuf = (ushort dosfar *) 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 dosfar *) 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);
+}
+
+int
+AscSetEEPConfig(
+                                  PortAddr iop_base,
+                                  ASCEEP_CONFIG dosfar * cfg_buf, ushort bus_type
+)
+{
+       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);
+}
+
+int
+AscInitPollBegin(
+                                       ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+       PortAddr            iop_base;
+
+       iop_base = asc_dvc->iop_base;
+
+#if CC_INIT_INQ_DISPLAY
+       DvcDisplayString((uchar dosfar *) "\r\n");
+#endif
+
+       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);
+}
+
+int
+AscInitPollEnd(
+                                 ASC_DVC_VAR asc_ptr_type * asc_dvc
+)
+{
+       PortAddr            iop_base;
+       int                 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]);
+       }
+
+       AscEnableInterrupt(iop_base);
+
+#if CC_INIT_INQ_DISPLAY
+       DvcDisplayString((uchar dosfar *) "\r\n");
+#endif
+       asc_dvc->init_state |= ASC_INIT_STATE_END_INQUIRY;
+
+       return (0);
+}
+
+int                 _asc_wait_slow_device_ = FALSE;
+
+int
+AscInitPollTarget(
+                                        ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                        ASC_SCSI_REQ_Q dosfar * scsiq,
+                                        ASC_SCSI_INQUIRY dosfar * inq,
+                                        ASC_CAP_INFO dosfar * cap_info
+)
+{
+       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;
+       ulong               phy_addr;
+
+       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 ((phy_addr = AscGetOnePhyAddr(asc_dvc,
+                                                                        (uchar dosfar *) scsiq->sense_ptr,
+                                                                        (ulong) scsiq->r1.sense_len)) == 0L) {
+               return (ERR);
+       }
+       scsiq->r1.sense_addr = phy_addr;
+       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;
+       }
+       ASC_DBG(3, "AscInitPollTarget: PollScsiInquiry()\n");
+       if (PollScsiInquiry(asc_dvc, scsiq, (uchar dosfar *) 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 CC_INIT_INQ_DISPLAY
+                       AscDispInquiry(tid_no, lun, inq);
+#endif
+
+                       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->pci_fix_asyn_xfer & tid_bits) {
+                               if (!(asc_dvc->init_sdtr & tid_bits)) {
+
+                                       AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no,
+                                                                                       ASYN_SDTR_DATA_FIX_PCI_REV_AB);
+                               }
+                       }
+                       ASC_DBG(3, "AscInitPollTarget: InitTestUnitReady()\n");
+                       if (InitTestUnitReady(asc_dvc, scsiq) != 1) {
+
+                       } else {
+                               if ((cap_info != 0L) && support_read_cap) {
+                                       ASC_DBG(3, "AscInitPollTarget: 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 {
+
+       }
+       return (dvc_found);
+}
+
+int
+PollQueueDone(
+                                ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                ASC_SCSI_REQ_Q dosfar * scsiq,
+                                int timeout_sec
+)
+{
+       int                 status;
+       int                 retry;
+
+       retry = 0;
+       do {
+               ASC_DBG(3, "PollQueueDone: AscExeScsiQueue()\n");
+               if ((status = AscExeScsiQueue(asc_dvc,
+                                                                         (ASC_SCSI_Q dosfar *) scsiq)) == 1) {
+                       ASC_DBG(3, "PollQueueDone: AscPollQDone()\n");
+                       if ((status = AscPollQDone(asc_dvc, scsiq,
+                                                                          timeout_sec)) != 1) {
+                               ASC_DBG1(3, "PollQueueDone: AscPollQDone() 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(100);
+                                       continue;
+                               }
+                               scsiq->r3.done_stat = 0;
+                               scsiq->r3.host_stat = 0;
+                               scsiq->r3.scsi_stat = 0;
+                               scsiq->r3.scsi_msg = 0;
+                               ASC_DBG1(3, "PollQueueDone: AscAbortSRB() scsiq %x\n",
+                                                (unsigned) scsiq);
+
+                               AscAbortSRB(asc_dvc, (ulong) scsiq);
+                       }
+                       ASC_DBG1(3, "PollQueueDone: done_stat %x\n", scsiq->r3.done_stat);
+                       return (scsiq->r3.done_stat);
+               }
+       } while ((status == 0) || (status == 0x80));
+       ASC_DBG(3, "PollQueueDone: done_stat QD_WITH_ERROR\n");
+       return (scsiq->r3.done_stat = QD_WITH_ERROR);
+}
+
+int
+PollScsiInquiry(
+                                  ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                  ASC_SCSI_REQ_Q dosfar * scsiq,
+                                  uchar dosfar * buf,
+                                  int buf_len
+)
+{
+       if (AscScsiInquiry(asc_dvc, scsiq, buf, buf_len) == ERR) {
+               return (scsiq->r3.done_stat = QD_WITH_ERROR);
+       }
+       return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 4));
+}
+
+int
+PollScsiReadCapacity(
+                                               ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                               ASC_SCSI_REQ_Q dosfar * scsiq,
+                                               ASC_CAP_INFO dosfar * cap_info
+)
+{
+       ASC_CAP_INFO        scsi_cap_info;
+       int                 status;
+
+       if (AscScsiReadCapacity(asc_dvc, scsiq,
+                                                       (uchar dosfar *) & scsi_cap_info) == ERR) {
+               return (scsiq->r3.done_stat = QD_WITH_ERROR);
+       }
+       status = PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 8);
+       if (status == 1) {
+#if CC_LITTLE_ENDIAN_HOST
+               cap_info->lba = (ulong) * swapfarbuf4((uchar dosfar *) & scsi_cap_info.lba);
+               cap_info->blk_size = (ulong) * swapfarbuf4((uchar dosfar *) & 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);
+       }
+       return (scsiq->r3.done_stat = QD_WITH_ERROR);
+}
+
+ulong dosfar       *
+swapfarbuf4(
+                          uchar dosfar * 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 dosfar *) buf);
+}
+
+int
+PollScsiTestUnitReady(
+                                                ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                                ASC_SCSI_REQ_Q dosfar * scsiq
+)
+{
+       if (AscScsiTestUnitReady(asc_dvc, scsiq) == ERR) {
+               return (scsiq->r3.done_stat = QD_WITH_ERROR);
+       }
+       return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 12));
+}
+
+int
+PollScsiStartUnit(
+                                        ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                        ASC_SCSI_REQ_Q dosfar * scsiq
+)
+{
+       if (AscScsiStartStopUnit(asc_dvc, scsiq, 1) == ERR) {
+               return (scsiq->r3.done_stat = QD_WITH_ERROR);
+       }
+       return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q dosfar *) scsiq, 40));
+}
+
+int
+InitTestUnitReady(
+                                        ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                        ASC_SCSI_REQ_Q dosfar * scsiq
+)
+{
+       ASC_SCSI_BIT_ID_TYPE tid_bits;
+       int                 retry;
+       ASC_REQ_SENSE dosfar *sen;
+
+       retry = 0;
+       tid_bits = scsiq->r1.target_id;
+       while (retry++ < 2) {
+               ASC_DBG(3, "InitTestUnitReady: PollScsiTestUnitReady()\n");
+               PollScsiTestUnitReady(asc_dvc, scsiq);
+               ASC_DBG1(3, "InitTestUnitReady: done_stat %x\n", scsiq->r3.done_stat);
+               if (scsiq->r3.done_stat == 0x01) {
+                       return (1);
+               } else if (scsiq->r3.done_stat == QD_WITH_ERROR) {
+                       DvcSleepMilliSecond(100);
+
+                       sen = (ASC_REQ_SENSE dosfar *) 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(100);
+                                       }
+                               } else if (sen->sense_key == SCSI_SENKEY_ATTENSION) {
+                                       DvcSleepMilliSecond(100);
+                               } else {
+                                       break;
+                               }
+                       } else {
+                               break;
+                       }
+               } else if (scsiq->r3.done_stat == QD_ABORTED_BY_HOST) {
+                       break;
+               } else {
+                       break;
+               }
+       }
+       return (0);
+}
+
+#if CC_INIT_INQ_DISPLAY
+
+#endif
+
+int
+AscPollQDone(
+                               ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                               ASC_SCSI_REQ_Q dosfar * scsiq,
+                               int timeout_sec
+)
+{
+       int                 loop, loop_end;
+       int                 sta;
+       PortAddr            iop_base;
+
+       iop_base = asc_dvc->iop_base;
+       loop = 0;
+       loop_end = timeout_sec * 100;
+       sta = 1;
+
+       while (TRUE) {
+               ASC_DBG4(3,
+                "AscPollQDone: loop %d, err_code %x, done_stat %x, scsi_stat %x\n",
+                loop, asc_dvc->err_code, scsiq->r3.done_stat, scsiq->r3.scsi_stat);
+               if (asc_dvc->err_code != 0) {
+                       scsiq->r3.done_stat = QD_WITH_ERROR;
+                       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;
+                       }
+                       break;
+               }
+               DvcSleepMilliSecond(10);
+               if (loop++ > loop_end) {
+                       sta = 0;
+                       break;
+               }
+               if (AscIsChipHalted(iop_base)) {
+                       AscISR(asc_dvc);
+                       loop = 0;
+               } else {
+                       ASC_DBG(3, "AscPollQDone: AscIsIntPending()\n");
+                       if (AscIsIntPending(iop_base)) {
+                               ASC_DBG(3, "AscPollQDone: AscISR()\n");
+                               AscISR(asc_dvc);
+                       }
+               }
+       }
+       ASC_DBG1(3, "AscPollQDone: sta %x\n", sta);
+       return (sta);
+}
+
+uchar
+AscReadLramByte(
+                                  PortAddr iop_base,
+                                  ushort addr
+)
+{
+       uchar               byte_data;
+       ushort              word_data;
+
+       if (isodd_word(addr)) {
+               AscSetChipLramAddr(iop_base, addr - 1);
+               word_data = AscGetChipLramData(iop_base);
+
+#if CC_LITTLE_ENDIAN_HOST
+               byte_data = (uchar) ((word_data >> 8) & 0xFF);
+#else
+               byte_data = (uchar) (word_data & 0xFF);
+#endif
+
+       } else {
+               AscSetChipLramAddr(iop_base, addr);
+               word_data = AscGetChipLramData(iop_base);
+
+#if CC_LITTLE_ENDIAN_HOST
+               byte_data = (uchar) (word_data & 0xFF);
+#else
+               byte_data = (uchar) ((word_data >> 8) & 0xFF);
+#endif
+
+       }
+       return (byte_data);
+}
+
+ushort
+AscReadLramWord(
+                                  PortAddr iop_base,
+                                  ushort addr
+)
+{
+       ushort              word_data;
+
+       AscSetChipLramAddr(iop_base, addr);
+       word_data = AscGetChipLramData(iop_base);
+       return (word_data);
+}
+
+ulong
+AscReadLramDWord(
+                                       PortAddr iop_base,
+                                       ushort addr
+)
+{
+       ushort              val_low, val_high;
+       ulong               dword_data;
+
+       AscSetChipLramAddr(iop_base, addr);
+
+#if CC_LITTLE_ENDIAN_HOST
+       val_low = AscGetChipLramData(iop_base);
+
+       val_high = AscGetChipLramData(iop_base);
+#else
+       val_high = AscGetChipLramData(iop_base);
+       val_low = AscGetChipLramData(iop_base);
+#endif
+
+       dword_data = ((ulong) val_high << 16) | (ulong) val_low;
+       return (dword_data);
+}
+
+void
+AscWriteLramWord(
+                                       PortAddr iop_base,
+                                       ushort addr,
+                                       ushort word_val
+)
+{
+       AscSetChipLramAddr(iop_base, addr);
+       AscPutChipLramData(iop_base, word_val);
+       return;
+}
+
+void
+AscWriteLramDWord(
+                                        PortAddr iop_base,
+                                        ushort addr,
+                                        ulong dword_val
+)
+{
+       ushort              word_val;
+
+       AscSetChipLramAddr(iop_base, addr);
+
+#if CC_LITTLE_ENDIAN_HOST
+       word_val = (ushort) dword_val;
+       AscPutChipLramData(iop_base, word_val);
+       word_val = (ushort) (dword_val >> 16);
+       AscPutChipLramData(iop_base, word_val);
+#else
+       word_val = (ushort) (dword_val >> 16);
+       AscPutChipLramData(iop_base, word_val);
+       word_val = (ushort) dword_val;
+       AscPutChipLramData(iop_base, word_val);
+#endif
+       return;
+}
+
+void
+AscWriteLramByte(
+                                       PortAddr iop_base,
+                                       ushort addr,
+                                       uchar byte_val
+)
+{
+       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);
+       }
+       AscWriteLramWord(iop_base, addr, word_data);
+       return;
+}
+
+int
+AscVerWriteLramWord(
+                                          PortAddr iop_base,
+                                          ushort addr,
+                                          ushort word_val
+)
+{
+       int                 sta;
+
+       sta = 0;
+       AscSetChipLramAddr(iop_base, addr);
+       AscPutChipLramData(iop_base, word_val);
+       AscSetChipLramAddr(iop_base, addr);
+       if (word_val != AscGetChipLramData(iop_base)) {
+               sta = ERR;
+       }
+       return (sta);
+}
+
+void
+AscMemWordCopyToLram(
+                                               PortAddr iop_base,
+                                               ushort s_addr,
+                                               ushort dosfar * s_buffer,
+                                               int words
+)
+{
+       AscSetChipLramAddr(iop_base, s_addr);
+       DvcOutPortWords(iop_base + IOP_RAM_DATA, s_buffer, words);
+       return;
+}
+
+void
+AscMemDWordCopyToLram(
+                                                PortAddr iop_base,
+                                                ushort s_addr,
+                                                ulong dosfar * s_buffer,
+                                                int dwords
+)
+{
+       AscSetChipLramAddr(iop_base, s_addr);
+       DvcOutPortDWords(iop_base + IOP_RAM_DATA, s_buffer, dwords);
+       return;
+}
+
+void
+AscMemWordCopyFromLram(
+                                                 PortAddr iop_base,
+                                                 ushort s_addr,
+                                                 ushort dosfar * d_buffer,
+                                                 int words
+)
+{
+       AscSetChipLramAddr(iop_base, s_addr);
+       DvcInPortWords(iop_base + IOP_RAM_DATA, d_buffer, words);
+       return;
+}
+
+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);
+       }
+       return (sum);
+}
+
+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++) {
+               AscPutChipLramData(iop_base, set_wval);
+       }
+       return;
+}
+
+int
+AscScsiInquiry(
+                                 ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                 ASC_SCSI_REQ_Q dosfar * scsiq,
+                                 uchar dosfar * buf, int buf_len
+)
+{
+       if (AscScsiSetupCmdQ(asc_dvc, scsiq, buf,
+                                                (ulong) buf_len) == ERR) {
+               return (scsiq->r3.done_stat = QD_WITH_ERROR);
+       }
+       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);
+}
+
+int
+AscScsiReadCapacity(
+                                          ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                          ASC_SCSI_REQ_Q dosfar * scsiq,
+                                          uchar dosfar * info
+)
+{
+       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);
+}
+
+int
+AscScsiTestUnitReady(
+                                               ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                               ASC_SCSI_REQ_Q dosfar * 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);
+}
+
+int
+AscScsiStartStopUnit(
+                                               ASC_DVC_VAR asc_ptr_type * asc_dvc,
+                                               ASC_SCSI_REQ_Q dosfar * scsiq,
+                                               uchar op_mode
+)
+{
+       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_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);
+}
diff --git a/drivers/scsi/advansys.h b/drivers/scsi/advansys.h
new file mode 100644 (file)
index 0000000..9d0a79d
--- /dev/null
@@ -0,0 +1,131 @@
+/* $Id: advansys.h,v 1.10 1996/01/15 04:51:06 bobf Exp bobf $ */
+/*
+ * advansys.h - Linux Host Driver for AdvanSys SCSI Adapters
+ *
+ * Copyright (c) 1995-1996 Advanced System Products, Inc.
+ *
+ * This driver may be modified and freely distributed provided that
+ * the above copyright message and this comment are included in the
+ * distribution. The latest version of this driver is available at
+ * the AdvanSys FTP and BBS sites listed below.
+ *
+ * Please send questions, comments, and bug reports to:
+ * bobf@advansys.com (Bob Frey)
+ */
+
+#ifndef _ADVANSYS_H
+#define _ADVANSYS_H
+
+/* The driver can be used in Linux 1.2.X or 1.3.X. */
+#if !defined(LINUX_1_2) && !defined(LINUX_1_3)
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif /* LINUX_VERSION_CODE */
+#if LINUX_VERSION_CODE > 65536 + 3 * 256
+#define LINUX_1_3
+#else /* LINUX_VERSION_CODE */
+#define LINUX_1_2
+#endif /* LINUX_VERSION_CODE */
+#endif /* !defined(LINUX_1_2) && !defined(LINUX_1_3) */
+
+/*
+ * Scsi_Host_Template function prototypes.
+ */
+int advansys_detect(Scsi_Host_Template *);
+int advansys_release(struct Scsi_Host *);
+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 *);
+int advansys_reset(Scsi_Cmnd *);
+#ifdef LINUX_1_2
+int advansys_biosparam(Disk *, int, int[]);
+#else /* LINUX_1_3 */
+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 /* LINUX_1_3 */
+
+/* init/main.c setup function */
+void advansys_setup(char *, int *);
+
+/*
+ * AdvanSys Host Driver Scsi_Host_Template (struct SHT) from hosts.h.
+ */
+#ifdef LINUX_1_2
+#define ADVANSYS { \
+       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. This apparently obviates any performance
+        * gain provided by setting 'use_clustering'. \
+        */ \
+       DISABLE_CLUSTERING,             /* unsigned use_clustering:1 */ \
+}
+#else /* LINUX_1_3 */
+#define ADVANSYS { \
+       NULL,                                   /* struct SHT *next */ \
+       NULL,                                   /* long *usage_count */ \
+       &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,                 /* int (*reset)(Scsi_Cmnd *) */ \
+       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. This apparently obviates any performance
+        * gain provided by setting 'use_clustering'. \
+        */ \
+       DISABLE_CLUSTERING,             /* unsigned use_clustering:1 */ \
+}
+#endif /* LINUX_1_3 */
+#endif /* _ADVANSYS_H */
index 5e8d826b3a8583f5197a2eda753324aef175b5a6..df08d810163ffc7aa72d183ee24e2cf05b3aa3b4 100644 (file)
  *        Accept parameters from LILO cmd-line. -- 1-Oct-94
  */
 
-#ifdef MODULE
-#include <linux/autoconf.h>
 #include <linux/module.h>
-#endif
 
 #include <linux/kernel.h>
 #include <linux/head.h>
index 4da0c7fefa3995589d96ed07687b8eda7bcdf321..f5ea6aab56c2f6eb81c060a173b34dc6a46514cf 100644 (file)
@@ -136,9 +136,9 @@ CMDCMPLT    = 0x02                          # Command Complete
 SEND_REJECT    = 0x11                          # sending a message reject
 NO_IDENT       = 0x21                          # no IDENTIFY after reconnect
 NO_MATCH       = 0x31                          # no cmd match for reconnect
-MSG_SDTR       = 0x41                          # SDTR message recieved
-MSG_WDTR       = 0x51                          # WDTR message recieved
-MSG_REJECT     = 0x61                          # Reject message recieved
+MSG_SDTR       = 0x41                          # SDTR message received
+MSG_WDTR       = 0x51                          # WDTR message received
+MSG_REJECT     = 0x61                          # Reject message received
 BAD_STATUS     = 0x71                          # Bad status from target
 RESIDUAL       = 0x81                          # Residual byte count != 0
 ABORT_TAG      = 0x91                          # Sent an ABORT_TAG message
index 661d8c41cf8274559b1d8d9310b4f4ccb0e0348d..aa47bad0b589d62e84f0bff856793c3f77266d9e 100644 (file)
 
 #include "hosts.h"
 
+#ifdef CONFIG_SCSI_ADVANSYS
+#include "advansys.h"
+#endif
+
 #ifdef CONFIG_SCSI_AHA152X
 #include "aha152x.h"
 #endif
@@ -158,6 +162,9 @@ Scsi_Host_Template * scsi_hosts = NULL;
 
 static Scsi_Host_Template builtin_scsi_hosts[] =
 {
+#ifdef CONFIG_SCSI_ADVANSYS
+       ADVANSYS,
+#endif
 /* BusLogic must come before aha1542.c */
 #ifdef CONFIG_SCSI_BUSLOGIC
     BUSLOGIC,
index c10bb21c23ce3860c0eed5962ddaa157c76d6997..fb2dd90613044a9e644a70c3168781c706543dad 100644 (file)
@@ -82,6 +82,8 @@ static int scan_scsis_single (int channel,int dev,int lun,int * max_scsi_dev ,
                  struct Scsi_Host *shpnt, char * scsi_result);
 void scsi_build_commandblocks(Scsi_Device * SDpnt);
 
+extern struct symbol_table scsi_symbol_table;
+
 
 static FreeSectorBitmap * dma_malloc_freelist = NULL;
 static int scsi_need_isa_bounce_buffers;
@@ -395,8 +397,8 @@ static void scan_scsis (struct Scsi_Host *shpnt, unchar hardcoded,
 
 
   /* Make sure we have something that is valid for DMA purposes */
-  scsi_result = ((!dma_malloc_freelist || !shpnt->unchecked_isa_dma)
-                 ? &scsi_result0[0] : scsi_malloc (512));
+  scsi_result = ( ( !shpnt->unchecked_isa_dma )
+                 ? &scsi_result0[0] : scsi_init_malloc (512, GFP_DMA));
 
   if (scsi_result == NULL) {
     printk ("Unable to obtain scsi_result buffer\n");
@@ -489,7 +491,7 @@ static void scan_scsis (struct Scsi_Host *shpnt, unchar hardcoded,
 
     /* If we allocated a buffer so we could do DMA, free it now */
     if (scsi_result != &scsi_result0[0] && scsi_result != NULL)
-      scsi_free (scsi_result, 512);
+      scsi_init_free (scsi_result, 512);
 
 }
 
@@ -2329,6 +2331,7 @@ int scsi_dev_init(void)
     timer_table[SCSI_TIMER].fn = scsi_main_timeout;
     timer_table[SCSI_TIMER].expires = 0;
 
+    register_symtab(&scsi_symbol_table);
 
     /* Register the /proc/scsi/scsi entry */
 #if CONFIG_PROC_FS 
@@ -3117,8 +3120,6 @@ scsi_dump_status(void)
 
 #ifdef MODULE
 
-extern struct symbol_table scsi_symbol_table;
-
 int init_module(void) {
     unsigned long size;
 
index 90374a769dba53c7e1957bb7775cbead0bf04fa3..536534672493ed3ef32c54919823178904eddc4b 100644 (file)
@@ -7,10 +7,7 @@
  *  anything out of the ordinary is seen.
  */
 
-#ifdef MODULE
-#include <linux/autoconf.h>
 #include <linux/module.h>
-#endif
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
index 50f5ec1263f11213f7b198b9ab25b253fb0bf5dd..2af6747a9d7f0285e52c3219945c57f7d6ab0b8d 100644 (file)
@@ -1,8 +1,4 @@
 *********************************************************
-* IF YOU HAVE ANY PROBLEMS WITH THE SOUND DRIVER,       *
-* PLEASE READ THE SOUND-HOWTO. IT'S AVAILABLE FROM YOUR *
-* NEAREST LINUX FTP SITE AND CONTAINS ANSWER TO YOUR    *
-* PROBLEM.                                              *
 * Readme.cards (this directory) contains some card     *
 * specific instructions.                               *
 *********************************************************
index a8695f2d4f4666f2402e1a1cc6e619dc1f2698a9..4ba152101b527d0cff64bd65b97abc6ca59b9ede 100644 (file)
@@ -64,14 +64,10 @@ ifdef CONFIG_PSS
        OBJS := $(OBJS)  pss.o
 endif
 
-ifdef CONFIG_SB16
-       OBJS := $(OBJS)  sb16_dsp.o
-endif
-
 ifdef CONFIG_SB
        OBJS := $(OBJS)  sb16_midi.o sb_card.o sb_dsp.o sb_midi.o sb_mixer.o
        OBJS := $(OBJS)  sb_card.o
-       OBJS := $(OBJS)  sb_dsp.o
+       OBJS := $(OBJS)  sb_dsp.o sb16_dsp.o
        OBJS := $(OBJS)  sb_midi.o
        OBJS := $(OBJS)  sb_mixer.o
 endif
@@ -92,14 +88,14 @@ ifdef CONFIG_SSCAPE
        OBJS := $(OBJS)  sscape.o
 endif
 
-ifdef CONFIG_SEQUENCER
-       OBJS := $(OBJS)  sys_timer.o
-endif
-
 ifdef CONFIG_TRIX
        OBJS := $(OBJS)  trix.o
 endif
 
+ifdef CONFIG_SEQUENCER
+       OBJS := $(OBJS)  sys_timer.o
+endif
+
 ifdef CONFIG_UART6850
        OBJS := $(OBJS)  uart6850.o
 endif
index 2a33b48270b3c12c7c9b966b8929cdbed3a41981..dccae463dcfb8e72e3578e40e058f379b8610a8e 100644 (file)
@@ -1,2 +1,2 @@
-3.5-alpha5
+3.5-alpha8
 0x030505
index f9c32a7ac7e69081f9bc5f9bab378432adcffbc1..60fbb41c6d03ff44140ccff30768d979f7425990 100644 (file)
@@ -1,6 +1,38 @@
-Changelog for version 3.5-alpha3
+Changelog for version 3.5-alpha8
 --------------------------------
 
+Since 3.5-alpha7
+- Linux kernel compatible configuration (_EXPERIMENTAL_). Enable
+  using command "cd /linux/drivers/sound;make script" and then
+  just run kernel's make config normally.
+- Minor fixes to the SB support. Hopefully the driver works with
+  all SB models now.
+- Added support for ESS ES1688 "AudioDrive" based cards.
+
+Since 3.5-alpha6
+- SB Pro and SB16 supports are no longer separately selectable options.
+  Enabling SB enables them too.
+- Changed all #ifndef EXCLUDE_xx stuff to #ifdef CONFIG_xx. Modified
+configure to handle this. 
+- Removed initialization messages from the
+modularized version. They can be enabled by using init_trace=1 in
+the insmod command line (insmod sound init_trace=1).
+- More AIX stuff.
+- Added support for syncronizing dsp/audio devices with /dev/sequencer.
+- mmap() support for dsp/audio devices.
+
+Since 3.5-alpha5
+- AIX port.
+- Changed some xxx_PATCH macros in soundcard.h to work with
+  big endian machines.
+
+Since 3.5-alpha4
+- Removed the 'setfx' stuff from the version distributed with kernel
+  sources. Running 'setfx' is required again.
+
+Since 3.5-alpha3
+- Moved stuff from the 'setfx' program to the AudioTriX Pro driver.
+
 Since 3.5-alpha2
 - Modifications to makefile and configure.c. Unnecessary sources
   are no longer compiled. Newly created local.h is also copied to
index 63d68bfd94d30fedfa72c1b8625ed889ad3d1a6c..de49f5025c7e46b1030368162aa662ee158133df 100644 (file)
@@ -1,8 +1,12 @@
 #
 # Sound driver configuration
 #
-# This is really ugly: it should probably be changed
-# to use the normal config script setup
+#--------
+# There is another confic script which is compatible with rest of
+# the kernel. It can be activated by running 'make script' in this
+# directory. Please note that this is an _experimental_ feature which
+# doesn't work with all cards (PSS, SM Wave, AudioTriX Pro).
+#--------
 #
 $MAKE -C drivers/sound config || exit 1
 
index 5e3f96623aaf0c52ca2d944b869e50feac725f06..8bf2ffc9240a362986d50c6e2ca4d5f714f9c473 100644 (file)
@@ -25,14 +25,6 @@ OBJS   = audio.o dmabuf.o sb_dsp.o \
         mad16.o mad16_sb_midi.o cs4232.o maui.o sound_pnp.o
 endif
 
-ifndef HOSTCC
-#
-#      Running outside the kernel build.
-#
-CC     = gcc
-HOSTCC = gcc
-CFLAGS = -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -m486
-
 
 build:
        @echo Compiling modularized sound driver
@@ -44,18 +36,27 @@ install:    sound.o
 
 .c.o:
        $(CC) $(CFLAGS) -c $<
-endif
 
 ifeq ($(CONFIG_SOUND),y)
-OBJS += $(FIXEDOBJS)
 
 all:   local.h sound.a
 
+OBJS += $(FIXEDOBJS)
+
 else
 all:
 endif
 
+ifndef HOSTCC
+#
+#      Running outside the kernel build.
+#
+CC     = gcc
+HOSTCC = gcc
+CFLAGS = -D__KERNEL__ -DMODULE -DMODVERSIONS -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -m486
+else
 include $(TOPDIR)/Rules.make
+endif
 
 sound.a: $(OBJS) 
        -rm -f sound.a
@@ -64,7 +65,7 @@ sound.a: $(OBJS)
 
 clean:
        rm -f core core.* *.o *.a tmp_make *~ x y z *%
-       rm -f configure sound_stub.c
+       rm -f configure sound_stub.c objects/*.o
 
 indent:
        for n in *.c;do echo indent $$n;indent $$n;done
@@ -100,6 +101,24 @@ oldconfig: setup-$(TARGET_OS) configure
 #      @echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h 2>/dev/null
        @echo \#define SOUND_UNAME_A \"`uname -a`\" >> local.h
 
+kernelconfig: setup-$(TARGET_OS)
+       rm -f configure
+       $(HOSTCC) -o configure configure.c
+       ./configure fixedlocal > local.h
+       ./configure fixeddefines > .defines
+       @echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h
+       @echo \#define SOUND_CONFIG_BY \"`whoami`\" >> local.h
+#      @echo \#define SOUND_CONFIG_HOST \"`hostname`\" >> local.h 2>/dev/null
+#      @echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h 2>/dev/null
+       @echo \#define SOUND_UNAME_A \"`uname -a`\" >> local.h
+
+script: setup-$(TARGET_OS)
+       rm -f configure
+       $(HOSTCC) -o configure configure.c
+       ./configure script > Config.in
+       ./configure fixedlocal > local.h
+       ./configure fixeddefines > .defines
+
 clrconf:
        rm -f local.h .depend synth-ld.h trix_boot.h smw-midi0001.h .defines
 
@@ -118,4 +137,12 @@ sound.o: local.h $(FIXEDOBJS) sound.a
        $(LD) -r -o sound.o $(FIXEDOBJS) sound.a
 
 modules: local.h sound.o
-       ln -fs `pwd`/sound.o $(TOPDIR)/modules/sound.o
+       ln -fs `pwd`/sound.o /usr/src/linux/modules/sound.o
+
+
+#
+# include a dependency file if one exists
+#
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
index 259414357c7b428195dbcab4102e3f7f797856c2..c0898697709200e3cae45c86ecb940eb45965cea 100644 (file)
@@ -1,9 +1,9 @@
 
-VoxWare v3.5-alpha5 release notes
+VoxWare v3.5-alpha4 release notes
 ---------------------------------
 
 IMPORTANT! This version of the driver is compatible only with Linux versions
-          1.3.33 and later. It may work with earlier ones as a loadable
+          1.3.58 and later. It may work with earlier ones as a loadable
           module but...
 
           Also this is an ALPHA test version which has not been tested
@@ -33,11 +33,11 @@ them are still on my mailbox and they should be included in versions
 after v3.0 (I will not add aditional features before v3.0 is ready).
 
    ====================================================
--  THIS VERSION ____REQUIRES____ Linux 1.3.33 OR LATER.
+-  THIS VERSION ____REQUIRES____ Linux 1.3.58 OR LATER.
    ====================================================
 
 -  THIS VERSION MAY NOT WORK WITH Linux VERSIONS RELEASED
-   AFTER end of Nov 1995. If this version doesn't compile with
+   AFTER end of Feb 1996. If this version doesn't compile with
    your kernel version, please use the sound driver version
    included in your kernel.
 
@@ -65,7 +65,7 @@ MediaTriX AudioTriX Pro (OPL4 and the optional effect daughtercard
        the snd-util-3.0.tar.gz package which does it).
 Ensoniq SoundScape (works but needs some improvements)
 MV Jazz16 based soundcards (ProSonic, 3D etc).
-SoundMan Wave (recording may not work, mixer support is limited)
+SoundMan Wave
 Mozart (OAK OTI-601 interface chip) based soundcards.
 MAD16 (an interface chip by OPTi) based soundcards (TB Tropez ???).
 (NOTE! The MAD16 looks similar to the Mozart chip. It could be a good
index c91454788562f05b51f9a417fa5619dfb46bce62..3d0da809d2ef77423c10c8b3b896f9568dcccf74 100644 (file)
@@ -40,7 +40,7 @@ Sound Blasters
                cards in the market (July95). It's likely that your card
                is compatible just with SB Pro but there is also a non SB
                compatible 16 bit mode. Usually it's MSS/WSS but could also
-               be a proprietary one like MV Jazz16.
+               be a proprietary one like MV Jazz16 or ESS ES688.
 
 Gravis Ultrasound (GUS)
        GUS
@@ -117,6 +117,8 @@ Ensoniq SoundScape and compatibles
        Several companies (including Ensoniq, Reveal and Spea) are selling
        cards based on this architecture.
 
+       NOTE! The new PnP SoundScape is not supported yet.
+
 MAD16 and Mozart based cards
        The Mozart (OAK OTI-601) and MAD16 Pro (OPTi 82C929) interface
        chips are used in many different soundcards, including some
@@ -337,12 +339,11 @@ select some options automaticly as well.
          have one of them. In addition the MAD16 chip is used in some
          cards made by known manufacturers such as Turtle Beach (Tropez),
          Reveal (some models) and Diamond (latest ones).
-  "SoundBlaster Pro support",
-       - Enable this option if your card is SB Pro or SB16. Enable it
-         also with any SB Pro clones. Answering 'n' saves some amount of
-         memory but 'y' is the safe alterative.
-  "SoundBlaster 16 support",
-       - Enable if you have a SB16 (including the AWE32).
+  "Support for TB Maui"
+       - This is just an experimental extension to the MPU401 driver.
+         Don't enable this option unless you are writing a .MOD
+         player for Maui.
+
   "Audio Excel DSP 16 initialization support",
        - Don't know much about this card. Look at aedsp16.c for more info.
 
@@ -468,6 +469,10 @@ Configuring GUS is simple. Just enable the GUS support and GUS MAX or
 the 16 bit daughtercard if you have them. Note that enabling the daughter
 card disables GUS MAX driver.
 
+NOTE for owners of the 16 bit daughtercard: By default the daughtercard
+uses /dev/dsp (and /dev/audio). Command "ln -sf /dev/dsp1 /dev/dsp"
+selects the daughter card as the default device.
+
 With just the standard GUS enabled the configuration program prompts
 for the I/O, IRQ and DMA numbers for the card. Use the same values than
 with DOS.
@@ -559,23 +564,17 @@ Also the ATP has a microcontroller for the General MIDI emulation (OPL4).
 For this reason the driver asks for the name of a file containing the
 microcode (TRXPRO.HEX). This file is usually located in the directory
 where the DOS drivers were installed. You must have access to this file
-when configuring the driver.
-
-IMPORTANT!!!!!!!!!!!
-
-The OPL4/OPL3 chip and the (optional) effects daughtercard require 
-initialization after boot. Since information about the effect processor
-is not public, the initialization must be done by running a special program
-after boot. The setfx program is distributed in Linux binary form (only)
-in snd-util-3.0.tar.gz package.
-It's calls ioperm() so it must be run as root.
+when configuring the driver. 
 
-Another way to initialize the effects processor (and OPL4) is to boot DOS
-before running Linux.
+If you have the effects daughtercard, it must be initialized by running
+the setfx program of snd-util-3.0.tar.gz package. This step is not required
+when using the (future) binary distribution version of the driver.
 
 Ensoniq SoundScape
 ------------------
 
+NOTE!  The new PnP SoundScape is not supported yet.
+
 The SoundScape driver handles initialization of MSS and MPU supports
 itself so you don't need to enable other drivers than SoundScape
 (enable also the /dev/dsp, /dev/sequencer and MIDI supports).
@@ -695,11 +694,14 @@ MIDI0001.BIN and it's located in the DOS/Windows driver directory. The file
 may also be called as TSUNAMI.BIN or something else (older cards?).
 
 The OPL4 synth will be inaccessible without loading the microcontroller code.
-Also remember to enable MPU401 support if you want to use the OPL4 mode.
+
+Also remember to enable SB MPU401 support if you want to use the OPL4 mode.
+(Don't enable the 'normal' MPU401 device as with some earlier driver
+versions (pre 3.5-alpha8)).
 
 NOTE!  Don't answer 'y' when the driver asks about SM Games support
        (the next question after the MIDI0001.BIN name). However
-       aneswering 'y' is not dangerous
+       aneswering 'y' doesn't cause damage your computer so don't panic
 
 Sound Galaxies
 --------------
@@ -722,6 +724,11 @@ SG NX Pro. Answer 'y' to these questions if you have one of the above 8 or
 There are some new Sound Galaxies in the market. I have no experience with
 them so read the card's manual carefully.
 
+ESS ES1688 'AudioDrive' based cards
+-----------------------------------
+
+Configure these cards just like SB Pro. Enable the 'SB MPU401 MIDI port'
+if you want to use MIDI features of the card.
 
 Reveal cards
 ------------
@@ -779,12 +786,6 @@ SB but that may require a TSR which is not possible with Linux. If
 the card is compatible with MSS, it's a better choise. Some cards
 don't work in the SB and MSS modes at the same time.
 
-There are some cards which will be supported by VoxWare sooner or later
-(currently at least cards based on the ESS chipset). Such cards are
-so common that there is some idea in writing the driver. Check the
-VoxWare home page (http://personal.eunet.fi/pp/voxware) for latest
-information.
-
 Then there are cards which are no longer manufactured and/or which
 are relatively rarely used (such as the 8 bit ProAudioSpectrum
 models). It's extremely unlikely that such cards never get supported.
@@ -837,8 +838,8 @@ for some of the banned cards. Please, don't send me messages asking if
 there is any plans to write a driver for the cards mentioned above. I 
 will put any news to the VoxWare www home page (see below).
 
-There are some common audio chipsets that are supported yet. For example
-the ESS chips and Sierra Aria. It's likely that these architectures
+There are some common audio chipsets that are not supported yet. For example
+Sierra Aria and IBM Mwave. It's possible that these architectures
 get some support in future but I can't make any promises. Just look
 at the home page for latest info.
 
index 66a92c54922c81838b39b0dec84a68bf916dcd83..2dab12552d1bc2ecbbc0622441e24d77d4f97cea 100644 (file)
@@ -86,3 +86,14 @@ Look at Readme.linux for more info.
 NOTE!  This method is not normally required. You should use it only when
        you have to use different configuration than normally. The sound=
        command line parameter is error phrone and not recommended.
+
+Debugging and tracing
+---------------------
+
+Modularized sound driver doesn't display messages during initialization as
+the kernel compiled one does. This feature can be turned on by adding
+init_trace=1 to the insmod command line.
+
+For example:
+
+       insmod sound init_trace=1
index 78c284192d1493bd6fee07e665c314707ef07a1f..9cc24033afb45339887fa73f7e9705b7c3ce4c18 100644 (file)
@@ -44,7 +44,7 @@
 #define DEB1(x)
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AD1848)
+#if defined(CONFIG_AD1848)
 
 #include "ad1848_mixer.h"
 
@@ -72,6 +72,7 @@ typedef struct
 #define MD_4231                2
 #define MD_4231A       3
 #define MD_1845                4
+#define MD_4232                5
 
     /* Mixer parameters */
     int             recmask;
@@ -153,7 +154,8 @@ ad_write (ad1848_info * devc, int reg, int data)
   unsigned long   flags;
   int             timeout = 90000;
 
-  while (timeout > 0 && inb (devc->base) == 0x80)      /*Are we initializing */
+  while (timeout > 0 &&
+        inb (devc->base) == 0x80)      /*Are we initializing */
     timeout--;
 
   save_flags (flags);
@@ -436,11 +438,19 @@ ad1848_mixer_reset (ad1848_info * devc)
 {
   int             i;
 
-  devc->recmask = 0;
-  if (devc->mode != MD_1848)
-    devc->supported_devices = MODE2_MIXER_DEVICES;
-  else
-    devc->supported_devices = MODE1_MIXER_DEVICES;
+  switch (devc->mode)
+    {
+    case MD_4231:
+      devc->supported_devices = MODE2_MIXER_DEVICES;
+      break;
+
+    case MD_4232:
+      devc->supported_devices = MODE3_MIXER_DEVICES;
+      break;
+
+    default:
+      devc->supported_devices = MODE1_MIXER_DEVICES;
+    }
 
   devc->supported_rec_devices = MODE1_REC_DEVICES;
 
@@ -466,7 +476,8 @@ ad1848_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
 
   if (((cmd >> 8) & 0xff) == 'M')
     {
-      if (cmd & IOC_IN)
+
+      if (_IOC_DIR (cmd) & _IOC_WRITE)
        switch (cmd & 0xff)
          {
          case SOUND_MIXER_RECSRC:
@@ -570,6 +581,7 @@ ad1848_open (int dev, int mode)
   devc->intr_active = 0;
   devc->opened = 1;
   devc->irq_mode = 0;
+  ad1848_trigger (dev, 0);
   restore_flags (flags);
 /*
  * Mute output until the playback really starts. This decreases clicking.
@@ -991,7 +1003,7 @@ ad1848_prepare_for_IO (int dev, int bsize, int bcount)
   restore_flags (flags);
   devc->xfer_count = 0;
 
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
   if (dev == timer_installed && devc->timer_running)
     if ((fs & 0x01) != (old_fs & 0x01))
       {
@@ -1012,11 +1024,14 @@ ad1848_halt (int dev)
 {
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
   unsigned long   flags;
+  int             timeout;
 
   save_flags (flags);
   cli ();
 
   ad_mute (devc);
+  ad_enter_MCE (devc);
+  ad_write (devc, 9, ad_read (devc, 9) & ~0x03);       /* Stop DMA */
   ad_write (devc, 9, ad_read (devc, 9) & ~0x03);       /* Stop DMA */
 
   ad_write (devc, 15, 0);      /* Clear DMA counter */
@@ -1028,11 +1043,14 @@ ad1848_halt (int dev)
       ad_write (devc, 31, 0);  /* Clear DMA counter */
     }
 
-  ad_write (devc, 9, ad_read (devc, 9) & ~0x03);       /* Stop DMA */
+  for (timeout = 0; timeout < 1000 && !(inb (io_Status (devc)) & 0x80);
+       timeout++);             /* Wait for interrupt */
 
+  ad_write (devc, 9, ad_read (devc, 9) & ~0x03);       /* Stop DMA */
   outb (0, io_Status (devc));  /* Clear interrupt status */
   outb (0, io_Status (devc));  /* Clear interrupt status */
   devc->irq_mode = 0;
+  ad_leave_MCE (devc);
 
   /* DMAbuf_reset_dma (dev); */
   restore_flags (flags);
@@ -1116,6 +1134,8 @@ ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp)
   ad1848_info    *devc = &dev_info[nr_ad1848_devs];
   unsigned char   tmp1 = 0xff, tmp2 = 0xff;
 
+  DDB (printk ("ad1848_detect(%x)\n", io_base));
+
   if (ad_flags)
     *ad_flags = 0;
 
@@ -1149,6 +1169,8 @@ ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp)
      *
      * If the I/O address is unused, it typically returns 0xff.
    */
+
+  DDB (printk ("ad1848_detect() - step A\n"));
   if ((inb (devc->base) & 0x80) != 0x00)       /* Not a AD1848 */
     {
       DDB (printk ("ad1848 detect error - step A (%02x)\n",
@@ -1162,6 +1184,7 @@ ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp)
      * so try to avoid using it.
    */
 
+  DDB (printk ("ad1848_detect() - step B\n"));
   ad_write (devc, 0, 0xaa);
   ad_write (devc, 1, 0x45);    /* 0x55 with bit 0x10 clear */
 
@@ -1171,6 +1194,7 @@ ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp)
       return 0;
     }
 
+  DDB (printk ("ad1848_detect() - step C\n"));
   ad_write (devc, 0, 0x45);
   ad_write (devc, 1, 0xaa);
 
@@ -1185,6 +1209,7 @@ ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp)
      * try to change them.
    */
 
+  DDB (printk ("ad1848_detect() - step D\n"));
   tmp = ad_read (devc, 12);
   ad_write (devc, 12, (~tmp) & 0x0f);
 
@@ -1206,6 +1231,7 @@ ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp)
      * with CS4231.
    */
 
+  DDB (printk ("ad1848_detect() - step F\n"));
   ad_write (devc, 12, 0);      /* Mode2=disabled */
 
   for (i = 0; i < 16; i++)
@@ -1220,6 +1246,7 @@ ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp)
      * The bit 0x80 is always 1 in CS4248 and CS4231.
    */
 
+  DDB (printk ("ad1848_detect() - step G\n"));
   ad_write (devc, 12, 0x40);   /* Set mode2, clear 0x80 */
 
   tmp1 = ad_read (devc, 12);
@@ -1238,6 +1265,7 @@ ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp)
          *
          *      Verify that setting I0 doesn't change I16.
        */
+      DDB (printk ("ad1848_detect() - step H\n"));
       ad_write (devc, 16, 0);  /* Set I16 to known value */
 
       ad_write (devc, 0, 0x45);
@@ -1255,6 +1283,7 @@ ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp)
             * Verify that some bits of I25 are read only.
           */
 
+         DDB (printk ("ad1848_detect() - step I\n"));
          tmp1 = ad_read (devc, 25);    /* Original bits */
          ad_write (devc, 25, ~tmp1);   /* Invert all bits */
          if ((ad_read (devc, 25) & 0xe7) == (tmp1 & 0xe7))
@@ -1266,10 +1295,7 @@ ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp)
               */
              devc->chip_name = "CS4231";
 
-#ifdef MOZART_PORT
-             if (devc->base != MOZART_PORT + 4)
-#endif
-               devc->mode = MD_4231;
+             devc->mode = MD_4231;
 
              /*
               * It could be an AD1845 or CS4231A as well.
@@ -1277,6 +1303,7 @@ ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp)
               * while the CS4231A reports different.
               */
 
+             DDB (printk ("ad1848_detect() - step I\n"));
              id = ad_read (devc, 25) & 0xe7;
 
              switch (id)
@@ -1289,12 +1316,12 @@ ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp)
 
                case 0xa2:
                  devc->chip_name = "CS4232";
-                 devc->mode = MD_4231A;
+                 devc->mode = MD_4232;
                  break;
 
                case 0xb2:
                  devc->chip_name = "CS4232A";
-                 devc->mode = MD_4231A;
+                 devc->mode = MD_4232;
                  break;
 
                case 0x80:
@@ -1326,15 +1353,18 @@ ad1848_detect (int io_base, int *ad_flags, sound_os_info * osp)
            }
          ad_write (devc, 25, tmp1);    /* Restore bits */
 
+         DDB (printk ("ad1848_detect() - step K\n"));
        }
     }
 
+  DDB (printk ("ad1848_detect() - step L\n"));
   if (ad_flags)
     {
       if (devc->mode != MD_1848)
        *ad_flags |= AD_F_CS4231;
     }
 
+  DDB (printk ("ad1848_detect() - Detected OK\n"));
   return 1;
 }
 
@@ -1360,6 +1390,7 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
   };
   int             i, my_dev;
+
   ad1848_info    *devc = &dev_info[nr_ad1848_devs];
 
   if (!ad1848_detect (io_base, NULL, osp))
@@ -1402,14 +1433,17 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
       for (i = 16; i < 32; i++)
        ad_write (devc, i, init_values[i]);
 
-      if (devc->mode == MD_4231A)
+      if (devc->mode == MD_4231A || devc->mode == MD_4232)
        ad_write (devc, 9, init_values[9] | 0x18);      /* Enable full calibration */
 
       if (devc->mode == MD_1845)
        ad_write (devc, 27, init_values[27] | 0x08);    /* Alternate freq select enabled */
     }
   else
-    ad_write (devc, 9, ad_read (devc, 9) | 0x04);      /* Single DMA mode */
+    {
+      ad1848_pcm_operations[nr_ad1848_devs].flags &= ~DMA_DUPLEX;
+      ad_write (devc, 9, ad_read (devc, 9) | 0x04);    /* Single DMA mode */
+    }
 
   outb (0, io_Status (devc));  /* Clear pending interrupts */
 
@@ -1420,7 +1454,8 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
     sprintf (ad1848_pcm_operations[nr_ad1848_devs].name,
             "Generic audio codec (%s)", devc->chip_name);
 
-  printk (" <%s>", ad1848_pcm_operations[nr_ad1848_devs].name);
+  conf_printf2 (ad1848_pcm_operations[nr_ad1848_devs].name,
+               devc->base, devc->irq, dma_playback, dma_capture);
 
   if (num_audiodevs < MAX_AUDIO_DEV)
     {
@@ -1473,7 +1508,7 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
       audio_devs[my_dev]->format_mask = ad_format_mask[devc->mode];
       nr_ad1848_devs++;
 
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
       if (devc->mode != MD_1848 && devc->irq_ok)
        ad1848_tmr_install (my_dev);
 #endif
@@ -1546,6 +1581,7 @@ ad1848_interrupt (int irq, struct pt_regs *dummy)
   unsigned char   status;
   ad1848_info    *devc;
   int             dev;
+  int             alt_stat = 0xff;
 
   if (irq < 0 || irq > 15)
     {
@@ -1579,54 +1615,78 @@ ad1848_interrupt (int irq, struct pt_regs *dummy)
 
   if (status & 0x01)
     {
-      int             alt_stat;
 
       if (devc->mode != MD_1848)
-       {
-         alt_stat = ad_read (devc, 24);
-         if (alt_stat & 0x40)  /* Timer interrupt */
-           {
-             devc->timer_ticks++;
-#ifndef EXCLUDE_SEQUENCER
-             if (timer_installed == dev && devc->timer_running)
-               sound_timer_interrupt ();
-#endif
-           }
-       }
-      else
-       alt_stat = 0xff;
+       alt_stat = ad_read (devc, 24);
 
       if (devc->opened && devc->irq_mode & PCM_ENABLE_INPUT && alt_stat & 0x20)
        {
          DMAbuf_inputintr (dev);
        }
 
-      if (devc->opened && devc->irq_mode & PCM_ENABLE_OUTPUT && alt_stat & 0x10)
+      if (devc->opened && devc->irq_mode & PCM_ENABLE_OUTPUT &&
+         alt_stat & 0x10)
        {
          DMAbuf_outputintr (dev, 1);
        }
-    }
 
-  outb (0, io_Status (devc));  /* Clear interrupt status */
+      if (devc->mode != MD_1848 && alt_stat & 0x40)    /* Timer interrupt */
+       {
+         devc->timer_ticks++;
+#ifdef CONFIG_SEQUENCER
+         if (timer_installed == dev && devc->timer_running)
+           sound_timer_interrupt ();
+#endif
+       }
+    }
 
+  if (devc->mode != MD_1848)
+    ad_write (devc, 24, ad_read (devc, 24) & ~alt_stat);       /* Selective ack */
+  else
+    outb (0, io_Status (devc));        /* Clear interrupt status */
 }
 
 /*
  * Some extra code for the MS Sound System
  */
 
+void
+check_opl3 (int base, struct address_info *hw_config)
+{
+
+  if (check_region (base, 4))
+    {
+      printk ("\n\nopl3.c: I/O port %x already in use\n\n", base);
+      return;
+    }
+
+  if (!opl3_detect (base, hw_config->osp))
+    return;
+
+  opl3_init (0, base, hw_config->osp);
+  request_region (base, 4, "OPL3/OPL2");
+}
+
 int
 probe_ms_sound (struct address_info *hw_config)
 {
   unsigned char   tmp;
 
+  DDB (printk ("Entered probe_ms_sound(%x, %d)\n", hw_config->io_base, hw_config->card_subtype));
+
   if (check_region (hw_config->io_base, 8))
     {
       printk ("MSS: I/O port conflict\n");
       return 0;
     }
 
-#if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_MSS)
+  if (hw_config->card_subtype == 1)    /* Has no IRQ/DMA registers */
+    {
+      /* check_opl3(0x388, hw_config); */
+      return ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp);
+    }
+
+#if defined(CONFIG_AEDSP16) && defined(AEDSP16_MSS)
   /*
      * Initialize Audio Excel DSP 16 to MSS: before any operation
      * we must enable MSS I/O ports.
@@ -1635,9 +1695,6 @@ probe_ms_sound (struct address_info *hw_config)
   InitAEDSP16_MSS (hw_config);
 #endif
 
-  if (hw_config->card_subtype == 1)    /* Has IRQ/DMA registers */
-    return ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp);
-
   /*
      * Check if the IO port returns valid signature. The original MS Sound
      * system returns 0x04 while some cards (AudioTriX Pro for example)
@@ -1645,7 +1702,10 @@ probe_ms_sound (struct address_info *hw_config)
    */
 
   if ((tmp = inb (hw_config->io_base + 3)) == 0xff)    /* Bus float */
-    return 0;
+    {
+      DDB (printk ("I/O address is inactive (%x)\n", tmp));
+      return 0;
+    }
   if ((tmp & 0x3f) != 0x04 &&
       (tmp & 0x3f) != 0x0f &&
       (tmp & 0x3f) != 0x00)
@@ -1700,11 +1760,22 @@ attach_ms_sound (long mem_start, struct address_info *hw_config)
     1, 2, 0, 3
   };
 
-  int             config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
+  int             config_port = hw_config->io_base + 0;
+  int             version_port = hw_config->io_base + 3;
 
   if (!ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp))
     return mem_start;
 
+  if (hw_config->card_subtype == 1)    /* Has no IRQ/DMA registers */
+    {
+      ad1848_init ("MS Sound System", hw_config->io_base + 4,
+                  hw_config->irq,
+                  hw_config->dma,
+                  hw_config->dma2, 0, hw_config->osp);
+      request_region (hw_config->io_base, 4, "WSS config");
+      return mem_start;
+    }
+
   /*
      * Set the IRQ and DMA addresses.
    */
@@ -1768,7 +1839,7 @@ unload_pnp_ad1848 (struct address_info *hw_config)
   release_region (hw_config->io_base, 4);
 }
 
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
 /*
  * Timer stuff (for /dev/music).
  */
index aabbac738c389a9f5c8eb009997fae6516a620fa..3fcacf75503dd4c734169139d8418a9b3dd4bf34 100644 (file)
  * (Actually this is not a mapping but rather some kind of interleaving
  * solution).
  */
-#ifdef GUSMAX_MIXER
-#define MODE1_REC_DEVICES              (SOUND_MASK_LINE | SOUND_MASK_MIC | \
-                                        SOUND_MASK_CD|SOUND_MASK_IMIX)
-
-#define MODE1_MIXER_DEVICES            (SOUND_MASK_SYNTH | SOUND_MASK_MIC | \
-                                        SOUND_MASK_CD | \
-                                        SOUND_MASK_IGAIN | \
-                                        SOUND_MASK_PCM|SOUND_MASK_IMIX)
-
-#define MODE2_MIXER_DEVICES            (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
-                                        SOUND_MASK_CD | SOUND_MASK_SPEAKER | \
-                                        SOUND_MASK_IGAIN | \
-                                        SOUND_MASK_PCM | SOUND_MASK_IMIX)
-#else  /* Generic mapping */
 #define MODE1_REC_DEVICES              (SOUND_MASK_LINE3 | SOUND_MASK_MIC | \
                                         SOUND_MASK_LINE1|SOUND_MASK_IMIX)
 
@@ -61,7 +47,8 @@
                                         SOUND_MASK_LINE3 | SOUND_MASK_SPEAKER | \
                                         SOUND_MASK_IGAIN | \
                                         SOUND_MASK_PCM | SOUND_MASK_IMIX)
-#endif
+
+#define MODE3_MIXER_DEVICES            (MODE2_MIXER_DEVICES | SOUND_MASK_VOLUME)
 
 struct mixer_def {
        unsigned int regno: 7;
@@ -93,8 +80,8 @@ typedef struct mixer_def mixer_ent;
 #define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r)        \
        {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}}
 
-mixer_ent mix_devices[32][2] = {       /* As used in GUS MAX */
-MIX_ENT(SOUND_MIXER_VOLUME,     0, 0, 0, 0,     0, 0, 0, 0),
+mixer_ent mix_devices[32][2] = {
+MIX_ENT(SOUND_MIXER_VOLUME,    27, 1, 0, 4,    29, 1, 0, 4),
 MIX_ENT(SOUND_MIXER_BASS,       0, 0, 0, 0,     0, 0, 0, 0),
 MIX_ENT(SOUND_MIXER_TREBLE,     0, 0, 0, 0,     0, 0, 0, 0),
 MIX_ENT(SOUND_MIXER_SYNTH,      4, 1, 0, 5,     5, 1, 0, 5),
@@ -115,11 +102,11 @@ MIX_ENT(SOUND_MIXER_LINE3,        18, 1, 0, 5,    19, 1, 0, 5)
 
 static unsigned short default_mixer_levels[SOUND_MIXER_NRDEVICES] =
 {
-  0x5a5a,                      /* Master Volume */
+  0x3232,                      /* Master Volume */
   0x3232,                      /* Bass */
   0x3232,                      /* Treble */
   0x4b4b,                      /* FM */
-  0x4040,                      /* PCM */
+  0x3232,                      /* PCM */
   0x4b4b,                      /* PC Speaker */
   0x2020,                      /* Ext Line */
   0x1010,                      /* Mic */
index 0f469f31fa146cb246e4e27a44125548eb002866..769698560082ea3445da16aed493a636e04c5dcf 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_YM3812)
+#if defined(CONFIG_YM3812)
 
 long
 attach_adlib_card (long mem_start, struct address_info *hw_config)
index 77bfbf3017a9fe51139880c4dc771e7a7d1c3963..9dbdc1ca06d06a5f2104a7c33d0706c88f2ba3be 100644 (file)
 #include "sound_config.h"
 
 #ifndef AEDSP16_BASE
-#define EXCLUDE_AEDSP16
+#undef CONFIG_AEDSP16
 #endif
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AEDSP16)
+#if defined(CONFIG_AEDSP16)
 /*
 
    READ THIS
@@ -865,4 +865,4 @@ ResetAEDSP16 (void)
 
 #endif /* 0 */
 
-#endif /* !EXCLUDE_AEDSP16 */
+#endif /* CONFIG_AEDSP16 */
index fa747b555ff2a8445d7cf6de131af059eac0da7c..12e071efe54ce4085bec0277de10e3347ce4fbc5 100644 (file)
@@ -29,8 +29,7 @@
 
 #include "sound_config.h"
 
-#ifdef CONFIGURE_SOUNDCARD
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
 
 #include "ulaw.h"
 #include "coproc.h"
 #define ON             1
 #define OFF            0
 
-static int      wr_buff_no[MAX_AUDIO_DEV];     /*
-
-                                                * != -1, if there is
-                                                * a incomplete output
-                                                * block in the queue.
-                                                */
-static int      wr_buff_size[MAX_AUDIO_DEV], wr_buff_ptr[MAX_AUDIO_DEV];
-
 static int      audio_mode[MAX_AUDIO_DEV];
 static int      dev_nblock[MAX_AUDIO_DEV];     /* 1 if in noblocking mode */
 
@@ -53,12 +44,11 @@ static int      dev_nblock[MAX_AUDIO_DEV];  /* 1 if in noblocking mode */
 #define                AM_WRITE        1
 #define        AM_READ         2
 
-static char    *wr_dma_buf[MAX_AUDIO_DEV];
 static int      audio_format[MAX_AUDIO_DEV];
 static int      local_conversion[MAX_AUDIO_DEV];
 
 static int
-set_format (int dev, long fmt)
+set_format (int dev, int fmt)
 {
   if (fmt != AFMT_QUERY)
     {
@@ -87,7 +77,7 @@ int
 audio_open (int dev, struct fileinfo *file)
 {
   int             ret;
-  long            bits;
+  int             bits;
   int             dev_type = dev & 0x0f;
   int             mode = file->mode & O_ACCMODE;
 
@@ -126,14 +116,24 @@ audio_open (int dev, struct fileinfo *file)
   else
     set_format (dev, bits);
 
-  wr_buff_no[dev] = -1;
   audio_mode[dev] = AM_NONE;
-  wr_buff_size[dev] = wr_buff_ptr[dev] = 0;
   dev_nblock[dev] = 0;
 
   return ret;
 }
 
+void
+sync_output (int dev)
+{
+  int             buf_no, buf_ptr, buf_size;
+  char           *dma_buf;
+
+  if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
+    {
+      DMAbuf_start_output (dev, buf_no, buf_ptr);
+    }
+}
+
 void
 audio_release (int dev, struct fileinfo *file)
 {
@@ -142,12 +142,7 @@ audio_release (int dev, struct fileinfo *file)
   dev = dev >> 4;
   mode = file->mode & O_ACCMODE;
 
-  if (wr_buff_no[dev] >= 0)
-    {
-      DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
-
-      wr_buff_no[dev] = -1;
-    }
+  sync_output (dev);
 
   if (audio_devs[dev]->coproc)
     audio_devs[dev]->coproc->close (audio_devs[dev]->coproc->devc, COPR_PCM);
@@ -188,8 +183,9 @@ translate_bytes (const void *table, void *buff, int n)
 int
 audio_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
 {
-  int             c, p, l;
+  int             c, p, l, buf_no, buf_ptr, buf_size;
   int             err;
+  char           *dma_buf;
 
   dev = dev >> 4;
 
@@ -198,7 +194,6 @@ audio_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
 
   if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
     {                          /* Direction change */
-      wr_buff_no[dev] = -1;
     }
 
   if (audio_devs[dev]->flags & DMA_DUPLEX)
@@ -206,57 +201,41 @@ audio_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
   else
     audio_mode[dev] = AM_WRITE;
 
-  if (!count)                  /*
-                                * Flush output
-                                */
+  if (!count)                  /* Flush output */
     {
-      if (wr_buff_no[dev] >= 0)
-       {
-         DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
-
-         wr_buff_no[dev] = -1;
-       }
+      sync_output (dev);
       return 0;
     }
 
   while (c)
-    {                          /*
-                                * Perform output blocking
-                                */
-      if (wr_buff_no[dev] < 0) /*
-                                * There is no incomplete buffers
-                                */
+    {
+      if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) < 0)
        {
-         if ((wr_buff_no[dev] = DMAbuf_getwrbuffer (dev, &wr_dma_buf[dev],
-                                                    &wr_buff_size[dev],
-                                                    dev_nblock[dev])) < 0)
+         if ((buf_no = DMAbuf_getwrbuffer (dev, &dma_buf,
+                                           &buf_size,
+                                           dev_nblock[dev])) < 0)
            {
              /* Handle nonblocking mode */
-             if (dev_nblock[dev] && wr_buff_no[dev] == -EAGAIN)
+             if (dev_nblock[dev] && buf_no == -EAGAIN)
                return p;       /* No more space. Return # of accepted bytes */
-             return wr_buff_no[dev];
+             return buf_no;
            }
-         wr_buff_ptr[dev] = 0;
+         buf_ptr = 0;
        }
 
       l = c;
-      if (l > (wr_buff_size[dev] - wr_buff_ptr[dev]))
-       l = (wr_buff_size[dev] - wr_buff_ptr[dev]);
+      if (l > (buf_size - buf_ptr))
+       l = (buf_size - buf_ptr);
 
       if (!audio_devs[dev]->copy_from_user)
        {                       /*
                                 * No device specific copy routine
                                 */
-         memcpy_fromfs (&wr_dma_buf[dev][wr_buff_ptr[dev]], &((buf)[p]), l);
+         memcpy_fromfs (&dma_buf[buf_ptr], &((buf)[p]), l);
        }
       else
        audio_devs[dev]->copy_from_user (dev,
-                             wr_dma_buf[dev], wr_buff_ptr[dev], buf, p, l);
-
-
-      /*
-       * Insert local processing here
-       */
+                                        dma_buf, buf_ptr, buf, p, l);
 
       if (local_conversion[dev] == AFMT_MU_LAW)
        {
@@ -264,22 +243,23 @@ audio_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
           * This just allows interrupts while the conversion is running
           */
          sti ();
-         translate_bytes (ulaw_dsp, (unsigned char *) &wr_dma_buf[dev][wr_buff_ptr[dev]], l);
+         translate_bytes (ulaw_dsp, (unsigned char *) &dma_buf[buf_ptr], l);
        }
 
       c -= l;
       p += l;
-      wr_buff_ptr[dev] += l;
+      buf_ptr += l;
 
-      if (wr_buff_ptr[dev] >= wr_buff_size[dev])
+      if (buf_ptr >= buf_size)
        {
-         if ((err = DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev])) < 0)
+         if ((err = DMAbuf_start_output (dev, buf_no, buf_ptr)) < 0)
            {
              return err;
            }
 
-         wr_buff_no[dev] = -1;
        }
+      else
+       DMAbuf_set_count (dev, buf_no, buf_ptr);
 
     }
 
@@ -291,7 +271,7 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 {
   int             c, p, l;
   char           *dmabuf;
-  int             buff_no;
+  int             buf_no;
 
   dev = dev >> 4;
   p = 0;
@@ -299,13 +279,7 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 
   if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
     {
-      if (wr_buff_no[dev] >= 0)
-       {
-         DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
-
-         if (!(audio_devs[dev]->flags & DMA_DUPLEX))
-           wr_buff_no[dev] = -1;
-       }
+      sync_output (dev);
     }
 
   if (audio_devs[dev]->flags & DMA_DUPLEX)
@@ -315,15 +289,15 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 
   while (c)
     {
-      if ((buff_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l,
-                                        dev_nblock[dev])) < 0)
+      if ((buf_no = DMAbuf_getrdbuffer (dev, &dmabuf, &l,
+                                       dev_nblock[dev])) < 0)
        {
          /* Nonblocking mode handling. Return current # of bytes */
 
-         if (dev_nblock[dev] && buff_no == -EAGAIN)
+         if (dev_nblock[dev] && buf_no == -EAGAIN)
            return p;
 
-         return buff_no;
+         return buf_no;
        }
 
       if (l > c)
@@ -345,7 +319,7 @@ audio_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
 
       memcpy_tofs (&((buf)[p]), dmabuf, l);
 
-      DMAbuf_rmchars (dev, buff_no, l);
+      DMAbuf_rmchars (dev, buf_no, l);
 
       p += l;
       c -= l;
@@ -374,27 +348,16 @@ audio_ioctl (int dev, struct fileinfo *file,
     switch (cmd)
       {
       case SNDCTL_DSP_SYNC:
-       if (wr_buff_no[dev] >= 0)
-         {
-           DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
-
-           wr_buff_no[dev] = -1;
-         }
+       sync_output (dev);
        return DMAbuf_ioctl (dev, cmd, arg, 0);
        break;
 
       case SNDCTL_DSP_POST:
-       if (wr_buff_no[dev] >= 0)
-         {
-           DMAbuf_start_output (dev, wr_buff_no[dev], wr_buff_ptr[dev]);
-
-           wr_buff_no[dev] = -1;
-         }
+       sync_output (dev);
        return 0;
        break;
 
       case SNDCTL_DSP_RESET:
-       wr_buff_no[dev] = -1;
        audio_mode[dev] = AM_NONE;
        return DMAbuf_ioctl (dev, cmd, arg, 0);
        break;
@@ -428,14 +391,16 @@ audio_ioctl (int dev, struct fileinfo *file,
 
        {
          audio_buf_info  info;
+         char           *dma_buf;
+         int             buf_no, buf_ptr, buf_size;
 
          int             err = DMAbuf_ioctl (dev, cmd, (ioctl_arg) & info, 1);
 
          if (err < 0)
            return err;
 
-         if (wr_buff_no[dev] != -1)
-           info.bytes += wr_buff_size[dev] - wr_buff_ptr[dev];
+         if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
+           info.bytes += buf_size - buf_ptr;
 
          memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
          return 0;
@@ -482,8 +447,10 @@ audio_init (long mem_start)
 }
 
 int
-audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
+audio_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
 {
+  char           *dma_buf;
+  int             buf_no, buf_ptr, buf_size;
 
   dev = dev >> 4;
 
@@ -493,7 +460,6 @@ audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
       if (!(audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
        return 0;               /* Not recording */
 
-
       return DMAbuf_select (dev, file, sel_type, wait);
       break;
 
@@ -501,7 +467,7 @@ audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
       if (!(audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
        return 0;               /* Wrong direction */
 
-      if (wr_buff_no[dev] != -1)
+      if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
        {
          return 1;             /* There is space in the current buffer */
        }
@@ -518,4 +484,3 @@ audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 
 
 #endif
-#endif
index 9c1eefede2369370d6929553512c329e24d73d4b..954918226062d2b7e95f33066890d4a91e1fbe8e 100644 (file)
@@ -1,4 +1,4 @@
-#define DISABLED_OPTIONS       (B(OPT_PNP))
+#define DISABLED_OPTIONS       (B(OPT_PNP)|B(OPT_AEDSP16))
 /*
  * sound/configure.c  - Configuration program for the Linux Sound Driver
  *
@@ -67,6 +67,7 @@
 #define OPT_SEQUENCER  24
 #define OPT_LAST       24      /* Last defined OPT number */
 
+#define DUMMY_OPTS (B(OPT_MIDI_AUTO)|B(OPT_YM3812_AUTO))
 
 #define ANY_DEVS (B(OPT_AUDIO)|B(OPT_MIDI)|B(OPT_SEQUENCER)|B(OPT_GUS)| \
                  B(OPT_MPU401)|B(OPT_PSS)|B(OPT_GUS16)|B(OPT_GUSMAX)| \
@@ -204,10 +205,13 @@ extra_options[] =
 char           *oldconf = "/etc/soundconf";
 
 int             old_config_used = 0;
+int             def_size, sb_base = 0;
 
 unsigned long   selected_options = 0;
 int             sb_dma = 0;
 
+int             dump_only = 0;
+
 void            build_defines (void);
 
 #include "hex2hex.h"
@@ -242,8 +246,7 @@ think_positively (int def_answ)
       fprintf (stderr, "\n\nERROR! Cannot read stdin\n");
 
       perror ("stdin");
-      printf ("#undef CONFIGURE_SOUNDCARD\n");
-      printf ("#undef KERNEL_SOUNDCARD\n");
+      printf ("invalid_configuration__run_make_config_again\n");
       exit (-1);
     }
 
@@ -273,8 +276,7 @@ play_it_again_Sam:
       fprintf (stderr, "\n\nERROR! Cannot read stdin\n");
 
       perror ("stdin");
-      printf ("#undef CONFIGURE_SOUNDCARD\n");
-      printf ("#undef KERNEL_SOUNDCARD\n");
+      printf ("invalid_configuration__run_make_config_again\n");
       exit (-1);
     }
 
@@ -294,6 +296,74 @@ play_it_again_Sam:
   return num;
 }
 
+#define FMT_HEX 1
+#define FMT_INT 2
+
+void
+ask_int_choice (int mask, char *macro,
+               char *question,
+               int format,
+               int defa,
+               char *choices)
+{
+  int             num, i;
+
+  if (dump_only)
+    {
+
+      for (i = 0; i < OPT_LAST; i++)
+       if (mask == B (i))
+         {
+           int             j;
+
+           for (j = 0; j < strlen (choices); j++)
+             if (choices[j] == '\'')
+               choices[j] = '_';
+
+           printf ("\nif [ \"$CONFIG_%s\" = \"y\" ]; then\n",
+                   hw_table[i].macro);
+           if (format == FMT_INT)
+             printf ("int '%s %s' %s %d\n", question, choices, macro, defa);
+           else
+             printf ("hex '%s %s' %s %x\n", question, choices, macro, defa);
+           printf ("fi\n");
+         }
+    }
+  else
+    {
+      if (!(mask & selected_options))
+       return;
+
+      fprintf (stderr, "\n%s\n", question);
+      fprintf (stderr, "Possible values are: %s\n", choices);
+
+      if (format == FMT_INT)
+       {
+         if (defa == -1)
+           fprintf (stderr, "\t(-1 disables this feature)\n");
+         fprintf (stderr, "The default value is %d\n", defa);
+         fprintf (stderr, "Enter the value: ");
+         num = ask_value ("%d", defa);
+         if (num == -1)
+           return;
+         fprintf (stderr, "%s set to %d.\n", question, num);
+         printf ("#define %s %d\n", macro, num);
+       }
+      else
+       {
+         if (defa == 0)
+           fprintf (stderr, "\t(0 disables this feature)\n");
+         fprintf (stderr, "The default value is %x\n", defa);
+         fprintf (stderr, "Enter the value: ");
+         num = ask_value ("%x", defa);
+         if (num == 0)
+           return;
+         fprintf (stderr, "%s set to %x.\n", question, num);
+         printf ("#define %s 0x%x\n", macro, num);
+       }
+    }
+}
+
 void
 rebuild_file (char *line)
 {
@@ -398,10 +468,30 @@ use_old_config (char *filename)
          if (strcmp (tmp, "SELECTED_SOUND_OPTIONS") == 0)
            continue;
 
+         if (strcmp (tmp, "KERNEL_SOUNDCARD") == 0)
+           continue;
+
          tmp[8] = 0;           /* Truncate the string */
          if (strcmp (tmp, "EXCLUDE_") == 0)
            continue;           /* Skip excludes */
 
+         strncpy (tmp, id, i);
+         tmp[7] = 0;           /* Truncate the string */
+
+         if (strcmp (tmp, "CONFIG_") == 0)
+           {
+             strncpy (tmp, &id[7], i - 7);
+             tmp[i - 7] = 0;
+
+             for (i = 0; i <= OPT_LAST; i++)
+               if (strcmp (hw_table[i].macro, tmp) == 0)
+                 {
+                   selected_options |= (1 << i);
+                   break;
+                 }
+             continue;
+           }
+
          printf ("%s", buf);
          continue;
        }
@@ -416,7 +506,11 @@ use_old_config (char *filename)
            i++;
 
          strncpy (tmp, id, i);
-         tmp[i] = 0;
+         tmp[7] = 0;           /* Truncate the string */
+         if (strcmp (tmp, "CONFIG_") == 0)
+           continue;
+
+         strncpy (tmp, id, i);
 
          tmp[8] = 0;           /* Truncate the string */
          if (strcmp (tmp, "EXCLUDE_") != 0)
@@ -440,9 +534,9 @@ use_old_config (char *filename)
   for (i = 0; i <= OPT_LAST; i++)
     if (!hw_table[i].alias)
       if (selected_options & B (i))
-       printf ("#undef  EXCLUDE_%s\n", hw_table[i].macro);
+       printf ("#define CONFIG_%s\n", hw_table[i].macro);
       else
-       printf ("#define EXCLUDE_%s\n", hw_table[i].macro);
+       printf ("#undef  CONFIG_%s\n", hw_table[i].macro);
 
 
   printf ("\n");
@@ -452,9 +546,9 @@ use_old_config (char *filename)
   while (extra_options[i].name != NULL)
     {
       if (selected_options & extra_options[i].mask)
-       printf ("#undef  EXCLUDE_%s\n", extra_options[i].name);
+       printf ("#define CONFIG_%s\n", extra_options[i].name);
       else
-       printf ("#define EXCLUDE_%s\n", extra_options[i].name);
+       printf ("#undef  CONFIG_%s\n", extra_options[i].name);
       i++;
     }
 
@@ -502,16 +596,484 @@ build_defines (void)
   fclose (optf);
 }
 
+void
+ask_parameters (void)
+{
+  int             num;
+
+  build_defines ();
+  /*
+   * IRQ and DMA settings
+   */
+
+  ask_int_choice (B (OPT_AEDSP16), "AEDSP16_BASE",
+                 "I/O base for Audio Excel DSP 16",
+                 FMT_HEX,
+                 0x220,
+                 "220 or 240");
+
+  ask_int_choice (B (OPT_SB), "SBC_BASE",
+                 "I/O base for SB",
+                 FMT_HEX,
+                 0x220,
+                 "");
+
+  ask_int_choice (B (OPT_SB), "SBC_IRQ",
+                 "SoundBlaster IRQ",
+                 FMT_INT,
+                 7,
+                 "");
+
+  ask_int_choice (B (OPT_SB), "SBC_DMA",
+                 "SoundBlaster DMA",
+                 FMT_INT,
+                 1,
+                 "");
+
+  ask_int_choice (B (OPT_SB), "SB_DMA2",
+                 "SoundBlaster 16 bit DMA (if required)",
+                 FMT_INT,
+                 -1,
+                 "5, 6 or 7");
+
+  ask_int_choice (B (OPT_SB), "SB_MPU_BASE",
+                 "MPU401 I/O base of SB16, Jazz16 and ES1688",
+                 FMT_HEX,
+                 0,
+                 "");
+
+  ask_int_choice (B (OPT_SB), "SB_MPU_IRQ",
+                 "SB MPU401 IRQ (SB16, Jazz16 and ES1688)",
+                 FMT_INT,
+                 -1,
+                 "");
+
+  ask_int_choice (B (OPT_PAS), "PAS_IRQ",
+                 "PAS16 IRQ",
+                 FMT_INT,
+                 10,
+                 "");
+
+  ask_int_choice (B (OPT_PAS), "PAS_DMA",
+                 "PAS16 DMA",
+                 FMT_INT,
+                 3,
+                 "");
+
+  if (selected_options & B (OPT_PAS))
+    {
+      fprintf (stderr, "\nEnable Joystick port on ProAudioSpectrum (n/y) ? ");
+      if (think_positively (0))
+       printf ("#define PAS_JOYSTICK_ENABLE\n");
+
+
+      fprintf (stderr, "PAS16 could be noisy with some mother boards\n"
+              "There is a command line switch (was it :T?)\n"
+              "in the DOS driver for PAS16 which solves this.\n"
+              "Don't enable this feature unless you have problems!\n"
+              "Do you have to use this switch with DOS (y/n) ?");
+      if (think_positively (0))
+       printf ("#define BROKEN_BUS_CLOCK\n");
+    }
+
+
+  ask_int_choice (B (OPT_GUS), "GUS_BASE",
+                 "I/O base for Gravis UltraSound (GUS)",
+                 FMT_HEX,
+                 0x220,
+                 "210, 220, 230, 240, 250 or 260");
+
+
+  ask_int_choice (B (OPT_GUS), "GUS_IRQ",
+                 "GUS IRQ",
+                 FMT_INT,
+                 15,
+                 "");
+
+  ask_int_choice (B (OPT_GUS), "GUS_DMA",
+                 "GUS DMA",
+                 FMT_INT,
+                 6,
+                 "");
+
+  ask_int_choice (B (OPT_GUS), "GUS_DMA2",
+                 "Second DMA channel for GUS",
+                 FMT_INT,
+                 -1,
+                 "");
+
+  ask_int_choice (B (OPT_GUS16), "GUS16_BASE",
+                 "I/O base for the 16 bit daughtercard of GUS",
+                 FMT_HEX,
+                 0x530,
+                 "530, 604, E80 or F40");
+
+
+  ask_int_choice (B (OPT_GUS16), "GUS16_IRQ",
+                 "GUS 16 bit daughtercard IRQ",
+                 FMT_INT,
+                 7,
+                 "3, 4, 5, 7, or 9");
+
+  ask_int_choice (B (OPT_GUS16), "GUS16_DMA",
+                 "GUS DMA",
+                 FMT_INT,
+                 3,
+                 "0, 1 or 3");
+
+  ask_int_choice (B (OPT_MPU401), "MPU_BASE",
+                 "I/O base for MPU401",
+                 FMT_HEX,
+                 0x330,
+                 "");
+
+  ask_int_choice (B (OPT_MPU401), "MPU_IRQ",
+                 "MPU401 IRQ",
+                 FMT_INT,
+                 9,
+                 "");
+
+  ask_int_choice (B (OPT_MAUI), "MAUI_BASE",
+                 "I/O base for Maui",
+                 FMT_HEX,
+                 0x330,
+                 "210, 230, 260, 290, 300, 320, 338 or 330");
+
+  ask_int_choice (B (OPT_MAUI), "MAUI_IRQ",
+                 "Maui IRQ",
+                 FMT_INT,
+                 9,
+                 "5, 9, 12 or 15");
+
+  ask_int_choice (B (OPT_UART6850), "U6850_BASE",
+                 "I/O base for UART 6850 MIDI port",
+                 FMT_HEX,
+                 0,
+                 "(Unknown)");
+
+  ask_int_choice (B (OPT_UART6850), "U6850_IRQ",
+                 "UART6850 IRQ",
+                 FMT_INT,
+                 -1,
+                 "(Unknown)");
+
+  ask_int_choice (B (OPT_PSS), "PSS_BASE",
+                 "PSS I/O base",
+                 FMT_HEX,
+                 0x220,
+                 "220 or 240");
+
+  ask_int_choice (B (OPT_PSS), "PSS_MSS_BASE",
+                 "PSS audio I/O base",
+                 FMT_HEX,
+                 0x530,
+                 "530, 604, E80 or F40");
+
+  ask_int_choice (B (OPT_PSS), "PSS_MSS_IRQ",
+                 "PSS audio IRQ",
+                 FMT_INT,
+                 11,
+                 "7, 9, 10 or 11");
+
+  ask_int_choice (B (OPT_PSS), "PSS_MSS_DMA",
+                 "PSS audio DMA",
+                 FMT_INT,
+                 3,
+                 "0, 1 or 3");
+
+  ask_int_choice (B (OPT_PSS), "PSS_MPU_BASE",
+                 "PSS MIDI I/O base",
+                 FMT_HEX,
+                 0x330,
+                 "");
+
+  ask_int_choice (B (OPT_PSS), "PSS_MPU_IRQ",
+                 "PSS MIDI IRQ",
+                 FMT_INT,
+                 9,
+                 "3, 4, 5, 7 or 9");
+
+  ask_int_choice (B (OPT_MSS), "MSS_BASE",
+                 "MSS/WSS I/O base",
+                 FMT_HEX,
+                 0x530,
+                 "530, 604, E80 or F40");
+
+  ask_int_choice (B (OPT_MSS), "MSS_IRQ",
+                 "MSS/WSS IRQ",
+                 FMT_INT,
+                 11,
+                 "7, 9, 10 or 11");
+
+  ask_int_choice (B (OPT_MSS), "MSS_DMA",
+                 "MSS/WSS DMA",
+                 FMT_INT,
+                 3,
+                 "0, 1 or 3");
+
+  ask_int_choice (B (OPT_SSCAPE), "SSCAPE_BASE",
+                 "Soundscape MIDI I/O base",
+                 FMT_HEX,
+                 0x330,
+                 "");
+
+  ask_int_choice (B (OPT_SSCAPE), "SSCAPE_IRQ",
+                 "Soundscape MIDI IRQ",
+                 FMT_INT,
+                 9,
+                 "");
+
+  ask_int_choice (B (OPT_SSCAPE), "SSCAPE_DMA",
+                 "Soundscape initialization DMA",
+                 FMT_INT,
+                 3,
+                 "0, 1 or 3");
+
+  ask_int_choice (B (OPT_SSCAPE), "SSCAPE_MSS_BASE",
+                 "Soundscape audio I/O base",
+                 FMT_HEX,
+                 0x534,
+                 "534, 608, E84 or F44");
+
+  ask_int_choice (B (OPT_SSCAPE), "SSCAPE_MSS_IRQ",
+                 "Soundscape audio IRQ",
+                 FMT_INT,
+                 11,
+                 "7, 9, 10 or 11");
+
+  ask_int_choice (B (OPT_SSCAPE), "SSCAPE_MSS_DMA",
+                 "Soundscape audio DMA",
+                 FMT_INT,
+                 0,
+                 "0, 1 or 3");
+
+  if (selected_options & B (OPT_SSCAPE))
+    {
+      int             reveal_spea;
+
+      fprintf (stderr, "Is your SoundScape card made/marketed by Reveal or Spea? ");
+      reveal_spea = think_positively (0);
+      if (reveal_spea)
+       printf ("#define REVEAL_SPEA\n");
+
+    }
+
+  ask_int_choice (B (OPT_TRIX), "TRIX_BASE",
+                 "AudioTriX audio I/O base",
+                 FMT_HEX,
+                 0x530,
+                 "530, 604, E80 or F40");
+
+  ask_int_choice (B (OPT_TRIX), "TRIX_IRQ",
+                 "AudioTriX audio IRQ",
+                 FMT_INT,
+                 11,
+                 "7, 9, 10 or 11");
+
+  ask_int_choice (B (OPT_TRIX), "TRIX_DMA",
+                 "AudioTriX audio DMA",
+                 FMT_INT,
+                 0,
+                 "0, 1 or 3");
+
+  ask_int_choice (B (OPT_TRIX), "TRIX_DMA2",
+                 "AudioTriX second (duplex) DMA",
+                 FMT_INT,
+                 3,
+                 "0, 1 or 3");
+
+  ask_int_choice (B (OPT_TRIX), "TRIX_MPU_BASE",
+                 "AudioTriX MIDI I/O base",
+                 FMT_HEX,
+                 0x330,
+                 "330, 370, 3B0 or 3F0");
+
+  ask_int_choice (B (OPT_TRIX), "TRIX_MPU_IRQ",
+                 "AudioTriX MIDI IRQ",
+                 FMT_INT,
+                 9,
+                 "3, 4, 5, 7 or 9");
+
+  ask_int_choice (B (OPT_TRIX), "TRIX_SB_BASE",
+                 "AudioTriX SB I/O base",
+                 FMT_HEX,
+                 0x220,
+                 "220, 210, 230, 240, 250, 260 or 270");
+
+  ask_int_choice (B (OPT_TRIX), "TRIX_SB_IRQ",
+                 "AudioTriX SB IRQ",
+                 FMT_INT,
+                 7,
+                 "3, 4, 5 or 7");
+
+  ask_int_choice (B (OPT_TRIX), "TRIX_SB_DMA",
+                 "AudioTriX SB DMA",
+                 FMT_INT,
+                 1,
+                 "1 or 3");
+
+  ask_int_choice (B (OPT_CS4232), "CS4232_BASE",
+                 "CS4232 audio I/O base",
+                 FMT_HEX,
+                 0x530,
+                 "530, 604, E80 or F40");
+
+  ask_int_choice (B (OPT_CS4232), "CS4232_IRQ",
+                 "CS4232 audio IRQ",
+                 FMT_INT,
+                 11,
+                 "5, 7, 9, 11, 12 or 15");
+
+  ask_int_choice (B (OPT_CS4232), "CS4232_DMA",
+                 "CS4232 audio DMA",
+                 FMT_INT,
+                 0,
+                 "0, 1 or 3");
+
+  ask_int_choice (B (OPT_CS4232), "CS4232_DMA2",
+                 "CS4232 second (duplex) DMA",
+                 FMT_INT,
+                 3,
+                 "0, 1 or 3");
+
+  ask_int_choice (B (OPT_CS4232), "CS4232_MPU_BASE",
+                 "CS4232 MIDI I/O base",
+                 FMT_HEX,
+                 0x330,
+                 "330, 370, 3B0 or 3F0");
+
+  ask_int_choice (B (OPT_CS4232), "CS4232_MPU_IRQ",
+                 "CS4232 MIDI IRQ",
+                 FMT_INT,
+                 9,
+                 "5, 7, 9, 11, 12 or 15");
+
+  ask_int_choice (B (OPT_MAD16), "MAD16_BASE",
+                 "MAD16 audio I/O base",
+                 FMT_HEX,
+                 0x530,
+                 "530, 604, E80 or F40");
+
+  ask_int_choice (B (OPT_MAD16), "MAD16_IRQ",
+                 "MAD16 audio IRQ",
+                 FMT_INT,
+                 11,
+                 "7, 9, 10 or 11");
+
+  ask_int_choice (B (OPT_MAD16), "MAD16_DMA",
+                 "MAD16 audio DMA",
+                 FMT_INT,
+                 3,
+                 "0, 1 or 3");
+
+  ask_int_choice (B (OPT_MAD16), "MAD16_DMA2",
+                 "MAD16 second (duplex) DMA",
+                 FMT_INT,
+                 0,
+                 "0, 1 or 3");
+
+  ask_int_choice (B (OPT_MAD16), "MAD16_MPU_BASE",
+                 "MAD16 MIDI I/O base",
+                 FMT_HEX,
+                 0x330,
+                 "300, 310, 320 or 330 (0 disables)");
+
+  ask_int_choice (B (OPT_MAD16), "MAD16_MPU_IRQ",
+                 "MAD16 MIDI IRQ",
+                 FMT_INT,
+                 9,
+                 "5, 7, 9 or 10");
+  ask_int_choice (B (OPT_AUDIO), "DSP_BUFFSIZE",
+                 "Audio DMA buffer size",
+                 FMT_INT,
+                 65536,
+                 "4096, 16384, 32768 or 65536");
+}
+
+void
+dump_script (void)
+{
+  int             i;
+
+  for (i = 0; i <= OPT_LAST; i++)
+    if (!(DUMMY_OPTS & B (i)))
+      if (!(DISABLED_OPTIONS & B (i)))
+       {
+         printf ("bool '%s' CONFIG_%s\n", questions[i], hw_table[i].macro);
+       }
+
+  dump_only = 1;
+  selected_options = 0;
+  ask_parameters ();
+
+  printf ("#\n$MAKE -C drivers/sound kernelconfig || exit 1\n");
+}
+
+void
+dump_fixed_local (void)
+{
+  int             i = 0;
+
+  printf ("/* Computer generated file. Please don't edit! */\n\n");
+  printf ("#define KERNEL_COMPATIBLE_CONFIG\n\n");
+  printf ("#define SELECTED_SOUND_OPTIONS\t0x%08x\n\n", selected_options);
+
+  while (extra_options[i].name != NULL)
+    {
+      int             n = 0, j;
+
+      printf ("#if ");
+
+      for (j = 0; j < OPT_LAST; j++)
+       if (!(DISABLED_OPTIONS & B (j)))
+         if (extra_options[i].mask & B (j))
+           {
+             if (n)
+               printf (" || ");
+             if (!(n++ % 2))
+               printf ("\\\n  ");
+
+             printf ("defined(CONFIG_%s)", hw_table[j].macro);
+           }
+
+      printf ("\n");
+      printf ("#\tdefine CONFIG_%s\n", extra_options[i].name);
+      printf ("#endif\n\n");
+      i++;
+    }
+}
+
+void
+dump_fixed_defines (void)
+{
+  int             i = 0;
+
+  printf ("# Computer generated file. Please don't edit\n\n");
+
+  while (extra_options[i].name != NULL)
+    {
+      int             n = 0, j;
+
+      for (j = 0; j < OPT_LAST; j++)
+       if (!(DISABLED_OPTIONS & B (j)))
+         if (extra_options[i].mask & B (j))
+           {
+             printf ("ifdef CONFIG_%s\n", hw_table[j].macro);
+             printf ("CONFIG_%s=y\n", extra_options[i].name);
+             printf ("endif\n\n");
+           }
+
+      i++;
+    }
+}
+
 int
 main (int argc, char *argv[])
 {
-  int             i, num, def_size, full_driver = 1;
+  int             i, num, full_driver = 1;
   char            answ[10];
-  int             sb_base = 0;
   char            old_config_file[200];
 
-  fprintf (stderr, "\nConfiguring the sound support\n\n");
-
   if (getuid () != 0)          /* Not root */
     {
       char           *home;
@@ -528,8 +1090,25 @@ main (int argc, char *argv[])
       if (strcmp (argv[1], "-o") == 0 &&
          use_old_config (oldconf))
        exit (0);
+      else if (strcmp (argv[1], "script") == 0)
+       {
+         dump_script ();
+         exit (0);
+       }
+      else if (strcmp (argv[1], "fixedlocal") == 0)
+       {
+         dump_fixed_local ();
+         exit (0);
+       }
+      else if (strcmp (argv[1], "fixeddefines") == 0)
+       {
+         dump_fixed_defines ();
+         exit (0);
+       }
     }
 
+  fprintf (stderr, "\nConfiguring the sound support\n\n");
+
   if (access (oldconf, R_OK) == 0)
     {
       fprintf (stderr, "Old configuration exists in %s. Use it (y/n) ? ",
@@ -540,7 +1119,10 @@ main (int argc, char *argv[])
 
     }
 
-  printf ("/*\tGenerated by configure. Don't edit!!!!\t*/\n\n");
+  printf ("/*\tGenerated by configure. Don't edit!!!!\t*/\n");
+  printf ("/*\tMaking changes to this file is not as simple as it may look.\t*/\n\n");
+  printf ("/*\tIf you change the CONFIG_ settings in local.h you\t*/\n");
+  printf ("/*\t_have_ to edit .defines too.\t*/\n\n");
 
   {
     /*
@@ -590,18 +1172,6 @@ main (int argc, char *argv[])
       fprintf (stderr, "Do you want support for the MV Jazz16 (ProSonic etc.) ? ");
       if (think_positively (0))
        {
-         printf ("#define JAZZ16\n");
-         do
-           {
-             fprintf (stderr, "\tValid 16 bit DMA channels for ProSonic/Jazz 16 are\n");
-             fprintf (stderr, "\t1, 3, 5 (default), 7\n");
-             fprintf (stderr, "\tEnter 16bit DMA channel for Prosonic : ");
-             num = ask_value ("%d", 5);
-           }
-         while (num != 1 && num != 3 && num != 5 && num != 7);
-         fprintf (stderr, "ProSonic 16 bit DMA set to %d\n", num);
-         printf ("#define JAZZ_DMA16 %d\n", num);
-
          fprintf (stderr, "Do you have SoundMan Wave (n/y) ? ");
 
          if (think_positively (0))
@@ -687,9 +1257,8 @@ main (int argc, char *argv[])
 
       if (sel1 == 0)
        {
-         printf ("#undef CONFIGURE_SOUNDCARD\n");
-         printf ("#undef KERNEL_SOUNDCARD\n");
-         fprintf (stderr, "ERROR!!!!!\nYou loose: you must select at least one mode when using Audio Excel!\n");
+         printf ("invalid_configuration__run_make_config_again\n");
+         fprintf (stderr, "ERROR!!!!!\nYou must select at least one mode when using Audio Excel!\n");
          exit (-1);
        }
       if (selected_options & B (OPT_MPU401))
@@ -769,20 +1338,17 @@ main (int argc, char *argv[])
 
   if (!(selected_options & ANY_DEVS))
     {
-      printf ("#undef CONFIGURE_SOUNDCARD\n");
-      printf ("#undef KERNEL_SOUNDCARD\n");
+      printf ("invalid_configuration__run_make_config_again\n");
       fprintf (stderr, "\n*** This combination is useless. Sound driver disabled!!! ***\n\n");
       exit (0);
     }
-  else
-    printf ("#define KERNEL_SOUNDCARD\n");
 
   for (i = 0; i <= OPT_LAST; i++)
     if (!hw_table[i].alias)
       if (selected_options & B (i))
-       printf ("#undef  EXCLUDE_%s\n", hw_table[i].macro);
+       printf ("#define CONFIG_%s\n", hw_table[i].macro);
       else
-       printf ("#define EXCLUDE_%s\n", hw_table[i].macro);
+       printf ("#undef  CONFIG_%s\n", hw_table[i].macro);
 
 
   printf ("\n");
@@ -792,922 +1358,15 @@ main (int argc, char *argv[])
   while (extra_options[i].name != NULL)
     {
       if (selected_options & extra_options[i].mask)
-       printf ("#undef  EXCLUDE_%s\n", extra_options[i].name);
+       printf ("#define CONFIG_%s\n", extra_options[i].name);
       else
-       printf ("#define EXCLUDE_%s\n", extra_options[i].name);
+       printf ("#undef  CONFIG_%s\n", extra_options[i].name);
       i++;
     }
 
   printf ("\n");
 
-
-
-  build_defines ();
-  /*
-   * IRQ and DMA settings
-   */
-
-  if (selected_options & B (OPT_AEDSP16))
-    {
-      fprintf (stderr, "\nI/O base for Audio Excel DSP 16 ?\n"
-              "Warning:\n"
-              "If you are using Audio Excel SoundBlaster emulation,\n"
-       "you must use the same I/O base for Audio Excel and SoundBlaster.\n"
-              "The factory default is 220 (other possible value is 240)\n"
-              "Enter the Audio Excel DSP 16 I/O base: ");
-
-      num = ask_value ("%x", 0x220);
-      fprintf (stderr, "Audio Excel DSP 16 I/O base set to %03x\n", num);
-      printf ("#define AEDSP16_BASE 0x%03x\n", num);
-    }
-
-  if ((selected_options & B (OPT_SB)) && selected_options & (B (OPT_AUDIO) | B (OPT_MIDI)))
-    {
-      fprintf (stderr, "\nI/O base for SB?\n"
-              "The factory default is 220\n"
-              "Enter the SB I/O base: ");
-
-      sb_base = num = ask_value ("%x", 0x220);
-      fprintf (stderr, "SB I/O base set to %03x\n", num);
-      printf ("#define SBC_BASE 0x%03x\n", num);
-
-      fprintf (stderr, "\nIRQ number for SoundBlaster?\n"
-              "The IRQ address is defined by the jumpers on your card.\n"
-         "The factory default is either 5 or 7 (depending on the model).\n"
-              "Valid values are 9(=2), 5, 7 and 10.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 7);
-      if (num != 9 && num != 5 && num != 7 && num != 10)
-       {
-
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 7;
-       }
-      fprintf (stderr, "SoundBlaster IRQ set to %d\n", num);
-
-      printf ("#define SBC_IRQ %d\n", num);
-
-      if (selected_options & (B (OPT_SBPRO) | B (OPT_PAS)))
-       {
-         fprintf (stderr, "\nDMA channel for SoundBlaster?\n"
-                  "For SB 1.0, 1.5 and 2.0 this MUST be 1\n"
-                  "SB Pro supports DMA channels 0, 1 and 3 (jumper)\n"
-                  "For SB16 give the 8 bit DMA# here\n"
-                  "The default value is 1\n"
-                  "Enter the value: ");
-
-         num = ask_value ("%d", 1);
-         if (num < 0 || num > 3)
-           {
-
-             fprintf (stderr, "*** Illegal input! ***\n");
-             num = 1;
-           }
-         fprintf (stderr, "SoundBlaster DMA set to %d\n", num);
-         printf ("#define SBC_DMA %d\n", num);
-         sb_dma = num;
-       }
-
-      if (selected_options & B (OPT_SB16))
-       {
-
-         fprintf (stderr, "\n16 bit DMA channel for SoundBlaster 16?\n"
-                  "Possible values are 5, 6 or 7\n"
-                  "The default value is 6\n"
-                  "Enter the value: ");
-
-         num = ask_value ("%d", 6);
-         if ((num < 5 || num > 7) && (num != sb_dma))
-           {
-
-             fprintf (stderr, "*** Illegal input! ***\n");
-             num = 6;
-           }
-         fprintf (stderr, "SoundBlaster DMA set to %d\n", num);
-         printf ("#define SB16_DMA %d\n", num);
-
-         fprintf (stderr, "\nI/O base for SB16 Midi?\n"
-                  "Possible values are 300 and 330\n"
-                  "The factory default is 330\n"
-                  "Enter the SB16 Midi I/O base: ");
-
-         num = ask_value ("%x", 0x330);
-         fprintf (stderr, "SB16 Midi I/O base set to %03x\n", num);
-         printf ("#define SB16MIDI_BASE 0x%03x\n", num);
-       }
-    }
-
-  if (selected_options & B (OPT_PAS))
-    {
-
-      if (selected_options & (B (OPT_AUDIO) | B (OPT_MIDI)))
-       {
-         fprintf (stderr, "\nIRQ number for ProAudioSpectrum?\n"
-                  "The recommended value is the IRQ used under DOS.\n"
-                  "Please refer to the ProAudioSpectrum User's Guide.\n"
-                  "The default value is 10.\n"
-                  "Enter the value: ");
-
-         num = ask_value ("%d", 10);
-         if (num == 6 || num < 3 || num > 15 || num == 2)      /*
-                                                                * Illegal
-                                                                */
-           {
-
-             fprintf (stderr, "*** Illegal input! ***\n");
-             num = 10;
-           }
-         fprintf (stderr, "ProAudioSpectrum IRQ set to %d\n", num);
-         printf ("#define PAS_IRQ %d\n", num);
-       }
-
-      if (selected_options & B (OPT_AUDIO))
-       {
-         fprintf (stderr, "\nDMA number for ProAudioSpectrum?\n"
-                  "The recommended value is the DMA channel under DOS.\n"
-                  "Please refer to the ProAudioSpectrum User's Guide.\n"
-                  "The default value is 3\n"
-                  "Enter the value: ");
-
-         num = ask_value ("%d", 3);
-         if (num == 4 || num < 0 || num > 7)
-           {
-
-             fprintf (stderr, "*** Illegal input! ***\n");
-             num = 3;
-           }
-         fprintf (stderr, "\nProAudioSpectrum DMA set to %d\n", num);
-         printf ("#define PAS_DMA %d\n", num);
-       }
-      fprintf (stderr, "\nEnable Joystick port on ProAudioSpectrum (n/y) ? ");
-      if (think_positively (0))
-       printf ("#define PAS_JOYSTICK_ENABLE\n");
-
-      fprintf (stderr, "PAS16 could be noisy with some mother boards\n"
-              "There is a command line switch (was it :T?)\n"
-              "in the DOS driver for PAS16 which solves this.\n"
-              "Don't enable this feature unless you have problems!\n"
-              "Do you have to use this switch with DOS (y/n) ?");
-      if (think_positively (0))
-       printf ("#define BROKEN_BUS_CLOCK\n");
-    }
-
-  if (selected_options & B (OPT_GUS))
-    {
-      fprintf (stderr, "\nI/O base for Gravis Ultrasound?\n"
-              "Valid choices are 210, 220, 230, 240, 250 or 260\n"
-              "The factory default is 220\n"
-              "Enter the GUS I/O base: ");
-
-      num = ask_value ("%x", 0x220);
-      if ((num > 0x260) || ((num & 0xf0f) != 0x200) || ((num & 0x0f0) > 0x060))
-       {
-
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 0x220;
-       }
-
-      if ((selected_options & B (OPT_SB)) && (num == sb_base))
-       {
-         fprintf (stderr, "FATAL ERROR!!!!!!!!!!!!!!\n"
-                  "\t0x220 cannot be used if SoundBlaster is enabled.\n"
-                  "\tRun the config again.\n");
-         printf ("#undef CONFIGURE_SOUNDCARD\n");
-         printf ("#undef KERNEL_SOUNDCARD\n");
-         exit (-1);
-       }
-      fprintf (stderr, "GUS I/O base set to %03x\n", num);
-      printf ("#define GUS_BASE 0x%03x\n", num);
-
-      fprintf (stderr, "\nIRQ number for Gravis UltraSound?\n"
-              "The recommended value is the IRQ used under DOS.\n"
-              "Please refer to the Gravis Ultrasound User's Guide.\n"
-              "The default value is 15.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 15);
-      if (num == 6 || num < 3 || num > 15 || num == 2) /*
-                                                        * Invalid
-                                                        */
-       {
-
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 15;
-       }
-      fprintf (stderr, "Gravis UltraSound IRQ set to %d\n", num);
-      printf ("#define GUS_IRQ %d\n", num);
-
-      fprintf (stderr, "\nDMA number for Gravis UltraSound?\n"
-              "The recommended value is the DMA channel under DOS.\n"
-              "Please refer to the Gravis Ultrasound User's Guide.\n"
-              "The default value is 6\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 6);
-      if (num == 4 || num < 0 || num > 7)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 6;
-       }
-      fprintf (stderr, "\nGravis UltraSound DMA set to %d\n", num);
-      printf ("#define GUS_DMA %d\n", num);
-
-      fprintf (stderr, "\nSecond DMA channel for GUS (optional)?\n"
-              "The default value is 7 (-1 disables)\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 7);
-      if (num > 7)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 7;
-       }
-
-      fprintf (stderr, "\nGUS DMA2 set to %d\n", num);
-      printf ("#define GUS_DMA2 %d\n", num);
-
-      if (selected_options & B (OPT_GUS16))
-       {
-         fprintf (stderr, "\nI/O base for GUS16 (GUS 16 bit sampling option)?\n"
-                  "The factory default is 530\n"
-                  "Other possible values are  604, E80 or F40\n"
-                  "Enter the GUS16 I/O base: ");
-
-         num = ask_value ("%x", 0x530);
-         fprintf (stderr, "GUS16 I/O base set to %03x\n", num);
-         printf ("#define GUS16_BASE 0x%03x\n", num);
-
-         fprintf (stderr, "\nIRQ number for GUS16?\n"
-                  "Valid numbers are: 3, 4, 5, 7, or 9(=2).\n"
-                  "The default value is 7.\n"
-                  "Enter the value: ");
-
-         num = ask_value ("%d", 7);
-         if (num == 6 || num < 3 || num > 15)
-           {
-             fprintf (stderr, "*** Illegal input! ***\n");
-             num = 7;
-           }
-         fprintf (stderr, "GUS16 IRQ set to %d\n", num);
-         printf ("#define GUS16_IRQ %d\n", num);
-
-         fprintf (stderr, "\nDMA number for GUS16?\n"
-                  "The default value is 3\n"
-                  "Enter the value: ");
-
-         num = ask_value ("%d", 3);
-         if (num < 0 || num > 3)
-           {
-             fprintf (stderr, "*** Illegal input! ***\n");
-             num = 3;
-           }
-         fprintf (stderr, "\nGUS16 DMA set to %d\n", num);
-         printf ("#define GUS16_DMA %d\n", num);
-       }
-    }
-
-  if (selected_options & B (OPT_MPU401))
-    {
-      fprintf (stderr, "\nI/O base for MPU-401?\n"
-              "The factory default is 330\n"
-              "Enter the MPU-401 I/O base: ");
-
-      num = ask_value ("%x", 0x330);
-      fprintf (stderr, "MPU-401 I/O base set to %03x\n", num);
-      printf ("#define MPU_BASE 0x%03x\n", num);
-
-      fprintf (stderr, "\nIRQ number for MPU-401?\n"
-              "Valid numbers are: 3, 4, 5, 7 and 9(=2).\n"
-              "The default value is 9.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 9);
-      if (num == 6 || num < 3 || num > 15)
-       {
-
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 5;
-       }
-      fprintf (stderr, "MPU-401 IRQ set to %d\n", num);
-      printf ("#define MPU_IRQ %d\n", num);
-    }
-
-  if (selected_options & B (OPT_MAUI))
-    {
-      fprintf (stderr, "\nI/O base for TB Maui (MIDI I/O of TB Tropez)?\n"
-              "The factory default is 330\n"
-       "Valid alternatives are 210, 230, 260, 290, 300, 320, 338 and 330\n"
-              "Enter the Maui/Tropez MIDI I/O base: ");
-
-      num = ask_value ("%x", 0x330);
-      fprintf (stderr, "Maui I/O base set to %03x\n", num);
-      printf ("#define MAUI_BASE 0x%03x\n", num);
-
-      fprintf (stderr, "\nIRQ number for TB Maui (TB Tropez MIDI)?\n"
-              "Valid numbers are: 5, 9, 12 and 15.\n"
-              "The default value is 9.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 9);
-      if (num == 6 || num < 3 || num > 15)
-       {
-
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 5;
-       }
-      fprintf (stderr, "Maui/Tropez MIDI IRQ set to %d\n", num);
-      printf ("#define MAUI_IRQ %d\n", num);
-    }
-
-  if (selected_options & B (OPT_UART6850))
-    {
-      fprintf (stderr, "\nI/O base for 6850 UART Midi?\n"
-              "Be carefull. No defaults.\n"
-              "Enter the 6850 UART I/O base: ");
-
-      num = ask_value ("%x", 0);
-      if (num == 0)
-       {
-         /*
-            * Invalid value entered
-          */
-         printf ("#define EXCLUDE_UART6850\n");
-       }
-      else
-       {
-         fprintf (stderr, "6850 UART I/O base set to %03x\n", num);
-         printf ("#define U6850_BASE 0x%03x\n", num);
-
-         fprintf (stderr, "\nIRQ number for 6850 UART?\n"
-                  "Valid numbers are: 3, 4, 5, 7 and 9(=2).\n"
-                  "The default value is 5.\n"
-                  "Enter the value: ");
-
-         num = ask_value ("%d", 5);
-         if (num == 6 || num < 3 || num > 15)
-           {
-
-             fprintf (stderr, "*** Illegal input! ***\n");
-             num = 5;
-           }
-         fprintf (stderr, "6850 UART IRQ set to %d\n", num);
-         printf ("#define U6850_IRQ %d\n", num);
-       }
-    }
-
-  if (selected_options & B (OPT_PSS))
-    {
-      fprintf (stderr, "\nI/O base for PSS?\n"
-              "The factory default is 220 (240 also possible)\n"
-              "Enter the PSS I/O base: ");
-
-      num = ask_value ("%x", 0x220);
-      fprintf (stderr, "PSS I/O base set to %03x\n", num);
-      printf ("#define PSS_BASE 0x%03x\n", num);
-
-#if YOU_WANT_TO_WASTE_RESOURCES
-      fprintf (stderr, "\nIRQ number for PSS?\n"
-              "Valid numbers are: 3, 4, 5, 7, 9(=2) or 10.\n"
-              "The default value is 10.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 10);
-      if (num == 6 || num < 3 || num > 15)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 7;
-       }
-      fprintf (stderr, "PSS IRQ set to %d\n", num);
-      printf ("#define PSS_IRQ %d\n", num);
-
-      fprintf (stderr, "\nDMA number for ECHO-PSS?\n"
-              "The default value is 5\n"
-              "Valid values are 5, 6 and 7\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 5);
-      if (num < 5 || num > 7)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 5;
-       }
-      fprintf (stderr, "\nECHO-PSS DMA set to %d\n", num);
-      printf ("#define PSS_DMA %d\n", num);
-#endif
-
-      fprintf (stderr, "\nMSS (MS Sound System) I/O base for the PSS card?\n"
-              "The factory default is 530\n"
-              "Other possible values are  604, E80 or F40\n"
-              "Enter the MSS I/O base: ");
-
-      num = ask_value ("%x", 0x530);
-      fprintf (stderr, "PSS/MSS I/O base set to %03x\n", num);
-      printf ("#define PSS_MSS_BASE 0x%03x\n", num);
-
-      fprintf (stderr, "\nIRQ number for the MSS mode of PSS ?\n"
-              "Valid numbers are: 7, 9(=2), 10 and 11.\n"
-              "The default value is 11.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 11);
-      if (num == 6 || num < 3 || num > 15)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 11;
-       }
-      fprintf (stderr, "PSS/MSS IRQ set to %d\n", num);
-      printf ("#define PSS_MSS_IRQ %d\n", num);
-
-      fprintf (stderr, "\nMSS DMA number for PSS?\n"
-              "Valid values are 0, 1 and 3.\n"
-              "The default value is 3\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 3);
-      if (num == 4 || num < 0 || num > 7)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 3;
-       }
-      fprintf (stderr, "\nPSS/MSS DMA set to %d\n", num);
-      printf ("#define PSS_MSS_DMA %d\n", num);
-
-      fprintf (stderr, "\nMIDI I/O base for PSS?\n"
-              "The factory default is 330\n"
-              "Enter the PSS MIDI I/O base: ");
-
-      num = ask_value ("%x", 0x330);
-      fprintf (stderr, "PSS/MIDI I/O base set to %03x\n", num);
-      printf ("#define PSS_MPU_BASE 0x%03x\n", num);
-
-      fprintf (stderr, "\nIRQ number for PSS MIDI?\n"
-              "Valid numbers are: 3, 4, 5, 7 and 9(=2).\n"
-              "The default value is 9.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 9);
-      if (num == 6 || num < 3 || num > 15)
-       {
-
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 5;
-       }
-      fprintf (stderr, "PSS MIDI IRQ set to %d\n", num);
-      printf ("#define PSS_MPU_IRQ %d\n", num);
-    }
-
-  if (selected_options & B (OPT_MSS))
-    {
-      fprintf (stderr, "\nI/O base for MSS (MS Sound System)?\n"
-              "The factory default is 530\n"
-              "Other possible values are  604, E80 or F40\n"
-              "Enter the MSS I/O base: ");
-
-      num = ask_value ("%x", 0x530);
-      fprintf (stderr, "MSS I/O base set to %03x\n", num);
-      printf ("#define MSS_BASE 0x%03x\n", num);
-
-      fprintf (stderr, "\nIRQ number for MSS?\n"
-              "Valid numbers are: 7, 9(=2), 10 and 11.\n"
-              "The default value is 10.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 10);
-      if (num == 6 || num < 3 || num > 15)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 7;
-       }
-      fprintf (stderr, "MSS IRQ set to %d\n", num);
-      printf ("#define MSS_IRQ %d\n", num);
-
-      fprintf (stderr, "\nDMA number for MSS?\n"
-              "Valid values are 0, 1 and 3.\n"
-              "The default value is 3\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 3);
-      if (num == 4 || num < 0 || num > 7)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 3;
-       }
-      fprintf (stderr, "\nMSS DMA set to %d\n", num);
-      printf ("#define MSS_DMA %d\n", num);
-    }
-
-  if (selected_options & B (OPT_SSCAPE))
-    {
-      int             reveal_spea;
-
-      fprintf (stderr, "\n(MIDI) I/O base for Ensoniq Soundscape?\n"
-              "The factory default is 330\n"
-              "Other possible values are 320, 340 or 350\n"
-              "Enter the Soundscape I/O base: ");
-
-      num = ask_value ("%x", 0x330);
-      fprintf (stderr, "Soundscape I/O base set to %03x\n", num);
-      printf ("#define SSCAPE_BASE 0x%03x\n", num);
-
-      fprintf (stderr, "Is your SoundScape card made/marketed by Reveal or Spea? ");
-      reveal_spea = think_positively (0);
-      if (reveal_spea)
-       printf ("#define REVEAL_SPEA\n");
-
-      fprintf (stderr, "\nIRQ number for Soundscape?\n");
-
-      if (reveal_spea)
-       fprintf (stderr, "Check valid interrupts from the manual of your card.\n");
-      else
-       fprintf (stderr, "Valid numbers are: 5, 7, 9(=2) and 10.\n");
-
-      fprintf (stderr, "The default value is 9.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 9);
-      if (num == 6 || num < 3 || num > 15)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 9;
-       }
-      fprintf (stderr, "Soundscape IRQ set to %d\n", num);
-      printf ("#define SSCAPE_IRQ %d\n", num);
-
-      fprintf (stderr, "\nDMA number for Soundscape?\n"
-              "Valid values are 1 and 3 (sometimes 0)"
-              "The default value is 3\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 3);
-      if (num == 4 || num < 0 || num > 7)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 3;
-       }
-      fprintf (stderr, "\nSoundscape DMA set to %d\n", num);
-      printf ("#define SSCAPE_DMA %d\n", num);
-
-      fprintf (stderr, "\nMSS (MS Sound System) I/O base for the SSCAPE card?\n"
-              "The factory default is 534\n"
-              "Other possible values are  608, E84 or F44\n"
-              "Enter the MSS I/O base: ");
-
-      num = ask_value ("%x", 0x534);
-      fprintf (stderr, "SSCAPE/MSS I/O base set to %03x\n", num);
-      printf ("#define SSCAPE_MSS_BASE 0x%03x\n", num);
-
-      fprintf (stderr, "\nIRQ number for the MSS mode of SSCAPE ?\n");
-      if (reveal_spea)
-       fprintf (stderr, "Valid numbers are: 5, 7, 9(=2) and 15.\n");
-      else
-       fprintf (stderr, "Valid numbers are: 5, 7, 9(=2) and 10.\n");
-      fprintf (stderr, "The default value is 5.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 5);
-      if (num == 6 || num < 3 || num > 15)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 10;
-       }
-      fprintf (stderr, "SSCAPE/MSS IRQ set to %d\n", num);
-      printf ("#define SSCAPE_MSS_IRQ %d\n", num);
-
-      fprintf (stderr, "\nMSS DMA number for SSCAPE?\n"
-              "Valid values are 0, 1 and 3.\n"
-              "The default value is 3\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 3);
-      if (num == 4 || num < 0 || num > 7)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 3;
-       }
-      fprintf (stderr, "\nSSCAPE/MSS DMA set to %d\n", num);
-      printf ("#define SSCAPE_MSS_DMA %d\n", num);
-    }
-  if (selected_options & B (OPT_TRIX))
-    {
-
-      fprintf (stderr, "\nWindows Sound System I/O base for the AudioTriX card?\n"
-              "The factory default is 530\n"
-              "Other possible values are  604, E80 or F40\n"
-              "Enter the MSS I/O base: ");
-
-      num = ask_value ("%x", 0x530);
-      fprintf (stderr, "AudioTriX MSS I/O base set to %03x\n", num);
-      printf ("#define TRIX_BASE 0x%03x\n", num);
-
-      fprintf (stderr, "\nIRQ number for the WSS mode of AudioTriX ?\n"
-              "Valid numbers are: 5, 7, 9(=2), 10 and 11.\n"
-              "The default value is 11.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 11);
-      if (num != 5 && num != 7 && num != 9 && num != 10 && num != 11)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 11;
-       }
-      fprintf (stderr, " AudioTriX WSS IRQ set to %d\n", num);
-      printf ("#define TRIX_IRQ %d\n", num);
-
-      fprintf (stderr, "\nWSS DMA number for AudioTriX?\n"
-              "Valid values are 0, 1 and 3.\n"
-              "The default value is 3\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 3);
-      if (num != 0 && num != 1 && num != 3)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 3;
-       }
-      fprintf (stderr, "\nAudioTriX/WSS DMA set to %d\n", num);
-      printf ("#define TRIX_DMA %d\n", num);
-
-      fprintf (stderr, "\nSecond (capture) DMA number for AudioTriX?\n"
-              "Valid values are 0, 1 and 3.\n"
-              "The default value is 0\n"
-              "(-1 disables the second DMA)\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 0);
-      if (num != 0 && num != 1 && num != 3 || num != -1)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 0;
-       }
-      fprintf (stderr, "\nAudioTriX/WSS DMA2 set to %d\n", num);
-      printf ("#define TRIX_DMA2 %d\n", num);
-
-      fprintf (stderr, "\nSoundBlaster I/O address for the AudioTriX card?\n"
-              "The factory default is 220\n"
-         "Other possible values are 200, 210, 230, 240, 250, 260 and 270\n"
-              "Enter the MSS I/O base: ");
-
-      num = ask_value ("%x", 0x220);
-      fprintf (stderr, "AudioTriX SB I/O base set to %03x\n", num);
-      printf ("#define TRIX_SB_BASE 0x%03x\n", num);
-
-      fprintf (stderr, "\nIRQ number for the SB mode of AudioTriX ?\n"
-              "Valid numbers are: 3, 4, 5 and 7.\n"
-              "The default value is 7.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 7);
-      if (num != 3 && num != 4 && num != 5 && num != 7)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 7;
-       }
-      fprintf (stderr, " AudioTriX SB IRQ set to %d\n", num);
-      printf ("#define TRIX_SB_IRQ %d\n", num);
-
-      fprintf (stderr, "\nSB DMA number for AudioTriX?\n"
-              "Valid values are 1 and 3.\n"
-              "The default value is 1\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 1);
-      if (num != 1 && num != 3)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 1;
-       }
-      fprintf (stderr, "\nAudioTriX/SB DMA set to %d\n", num);
-      printf ("#define TRIX_SB_DMA %d\n", num);
-
-      fprintf (stderr, "\nMIDI (MPU-401) I/O address for the AudioTriX card?\n"
-              "The factory default is 330\n"
-              "Other possible values are 330, 370, 3B0 and 3F0\n"
-              "Enter the MPU I/O base: ");
-
-      num = ask_value ("%x", 0x330);
-      fprintf (stderr, "AudioTriX MIDI I/O base set to %03x\n", num);
-      printf ("#define TRIX_MPU_BASE 0x%03x\n", num);
-
-      fprintf (stderr, "\nMIDI IRQ number for the AudioTriX ?\n"
-              "Valid numbers are: 3, 4, 5, 7 and 9(=2).\n"
-              "The default value is 5.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 5);
-      if (num != 3 && num != 4 && num != 5 && num != 7 && num != 9)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 5;
-       }
-      fprintf (stderr, " AudioTriX MIDI IRQ set to %d\n", num);
-      printf ("#define TRIX_MPU_IRQ %d\n", num);
-    }
-
-  if (selected_options & B (OPT_CS4232))
-    {
-      int             dma1;
-
-      fprintf (stderr, "\nWindows Sound System I/O base for CS4232?\n"
-              "The factory default is 534\n"
-              "Other possible values are  608, E84 or F44\n"
-              "Enter the MSS I/O base: ");
-
-      num = ask_value ("%x", 0x534);
-      fprintf (stderr, "CS4232 MSS I/O base set to %03x\n", num);
-      printf ("#define CS4232_BASE 0x%03x\n", num);
-
-      fprintf (stderr, "\nIRQ number for the WSS mode of CS4232 ?\n"
-              "Valid numbers are: 5, 7, 9(=2), 11, 12 or 15.\n"
-              "The default value is 11.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 11);
-      if (num != 5 && num != 7 && num != 9 && num != 11 && num != 12 || num != 15)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 11;
-       }
-      fprintf (stderr, " CS4232 WSS IRQ set to %d\n", num);
-      printf ("#define CS4232_IRQ %d\n", num);
-
-      fprintf (stderr, "\nWSS DMA number for CS4232?\n"
-              "Valid values are 0, 1 and 3.\n"
-              "The default value is 0\n"
-              "(select the lowes possible one if you want to\n"
-              "use full duplex mode)\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 0);
-      if (num != 0 && num != 1 && num != 3)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 0;
-       }
-      fprintf (stderr, "\nCS4232/WSS DMA set to %d\n", num);
-      printf ("#define CS4232_DMA %d\n", num);
-      dma1 = num;
-
-      fprintf (stderr, "\n Second WSS DMA number for CS4232?\n"
-              "Valid values are 0, 1 and 3.\n"
-              "The default value is 3\n"
-              "Enter the value (-1 disables duplex mode): ");
-
-      num = ask_value ("%d", 3);
-      if (num == dma1 || (num != -1 && num != 0 && num != 1 && num != 3))
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 3;
-       }
-      fprintf (stderr, "\nCS4232/WSS DMA2 set to %d\n", num);
-      printf ("#define CS4232_DMA2 %d\n", num);
-
-      fprintf (stderr, "\nMIDI (MPU-401) I/O address for the CS4232 card?\n"
-              "The factory default is 330\n"
-              "Other possible values are 330, 370, 3B0 and 3F0\n"
-              "Enter the MPU I/O base: ");
-
-      num = ask_value ("%x", 0x330);
-      fprintf (stderr, "CS4232 MIDI I/O base set to %03x\n", num);
-      printf ("#define CS4232_MPU_BASE 0x%03x\n", num);
-
-      fprintf (stderr, "\nMIDI IRQ number for CS4232?\n"
-              "Valid numbers are: 5, 7, 9(=2), 11, 12 or 15.\n"
-              "The default value is 5.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 5);
-      if (num != 5 && num != 7 && num != 9 && num != 11 && num != 12 || num != 15)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 5;
-       }
-      fprintf (stderr, " CS4232 MIDI IRQ set to %d\n", num);
-      printf ("#define CS4232_MPU_IRQ %d\n", num);
-    }
-
-  if (selected_options & B (OPT_MAD16))
-    {
-      fprintf (stderr, "\n*** Options for the MAD16 and Mozart based cards ***\n\n");
-
-      fprintf (stderr, "\nWindows Sound System I/O base for the MAD16/Mozart card?\n"
-              "The factory default is 530\n"
-              "Other possible values are  604, E80 or F40\n"
-              "(Check which ones are supported by your card!!!!!!)\n"
-              "Enter the MSS I/O base: ");
-
-      num = ask_value ("%x", 0x530);
-      fprintf (stderr, "MAD16 MSS I/O base set to %03x\n", num);
-      printf ("#define MAD16_BASE 0x%03x\n", num);
-
-      if ((sb_base == 0x220 && (num == 0x530 || num == 0x480)) ||
-         (sb_base == 0x240 && (num == 0xf40 || num == 0x604)))
-       {
-         fprintf (stderr, "FATAL ERROR!!!!!!!!!!!!!!\n"
-                  "\tThis I/O port selection makes MAD16/Mozart\n"
-                  "\tto use 0x%03x as the SB port.\n"
-                  "\tThis conflicts with the true SB card.\n"
-                  "\tRun the config again and select another I/O base.\n",
-                  sb_base);
-         printf ("#undef CONFIGURE_SOUNDCARD\n");
-         printf ("#undef KERNEL_SOUNDCARD\n");
-         exit (-1);
-       }
-
-      fprintf (stderr, "\nIRQ number for the WSS mode of MAD16/Mozart ?\n"
-              "Valid numbers are: 7, 9(=2), 10 and 11.\n"
-              "The default value is 11.\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 11);
-      if (num != 7 && num != 9 && num != 10 && num != 11)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 11;
-       }
-      fprintf (stderr, " MAD16 WSS IRQ set to %d\n", num);
-      printf ("#define MAD16_IRQ %d\n", num);
-
-      fprintf (stderr, "\nWSS DMA (playback) number for MAD16/Mozart?\n"
-              "Valid values are 0, 1 and 3.\n"
-              "The default value is 3\n"
-              "Enter the value: ");
-
-      num = ask_value ("%d", 3);
-      if (num != 0 && num != 1 && num != 3)
-       {
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = 3;
-       }
-      fprintf (stderr, "\nMAD16/WSS DMA set to %d\n", num);
-      printf ("#define MAD16_DMA %d\n", num);
-
-      num = (num == 0) ? 1 : 0;
-
-      fprintf (stderr, "\nMAD16/Mozart supports full duplex mode if the\n"
-              "card has a suitable codec chip (CS423x or AD1845).\n"
-              "This mode requires another DMA channel (DMA%d)\n"
-              "Do you want to enable this mode? (n/y)", num);
-
-      if (think_positively (0))
-       {
-         fprintf (stderr, "\nMAD16/WSS capture DMA set to %d\n", num);
-         printf ("#define MAD16_DMA2 %d\n", num);
-       }
-      else
-       printf ("#define MAD16_DMA2 -1\n");
-
-
-      fprintf (stderr, "\nMIDI (MPU-401/SB) I/O address for the MAD16 card?\n"
-              "(This is the second MIDI port in TB Tropez)\n"
-              "Other possible values are 330, 320, 310 and 300\n"
-              "For 82C928 and Mozart you may use any nonzero value\n"
-              "since the driver ignores this setting.\n"
-              "The factory default is 330 (use 0 to disable)\n"
-              "Enter the MIDI I/O base: ");
-
-      num = ask_value ("%x", 0x330);
-      if (num == 0)
-       fprintf (stderr, "MAD16/Mozart MIDI port disabled\n");
-      else
-       {
-         fprintf (stderr, "MAD16 MIDI I/O base set to %03x\n", num);
-         printf ("#define MAD16_MPU_BASE 0x%03x\n", num);
-
-         fprintf (stderr, "\nMIDI IRQ number for the MAD16 ?\n"
-                  "Valid numbers are: 5, 7, 9(=2) and 10.\n"
-                  "The default value is 5.\n"
-                  "Enter the value: ");
-
-         num = ask_value ("%d", 5);
-         if (num != 3 && num != 4 && num != 5 && num != 7 && num != 9)
-           {
-             fprintf (stderr, "*** Illegal input! ***\n");
-             num = 5;
-           }
-         fprintf (stderr, " MAD16 MIDI IRQ set to %d\n", num);
-         printf ("#define MAD16_MPU_IRQ %d\n", num);
-       }
-    }
-
-  if (selected_options & B (OPT_AUDIO))
-    {
-      def_size = 65536;
-
-      fprintf (stderr, "\nSelect the DMA buffer size (4096, 16384, 32768 or 65536 bytes)\n"
-              "%d is recommended value for this configuration.\n"
-              "Enter the value: ", def_size);
-
-      num = ask_value ("%d", def_size);
-      if (num != 4096 && num != 16384 && num != 32768 && num != 65536)
-       {
-
-         fprintf (stderr, "*** Illegal input! ***\n");
-         num = def_size;
-       }
-      fprintf (stderr, "The DMA buffer size set to %d\n", num);
-      printf ("#define DSP_BUFFSIZE %d\n", num);
-    }
+  ask_parameters ();
 
   printf ("#define SELECTED_SOUND_OPTIONS\t0x%08x\n", selected_options);
   fprintf (stderr, "The sound driver is now configured.\n");
index e04ca2ca774083730d6a71ce3ef92fcb055c9b82..0fa6dd1201671c4790b31335c6775af8c3ba4e4d 100644 (file)
@@ -34,7 +34,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_CS4232)
+#if defined(CONFIG_CS4232)
 
 #define KEY_PORT       0x279   /* Same as LPT1 status port */
 #define CSN_NUM                0x99    /* Just a random number */
@@ -44,6 +44,7 @@
 #define CS_OUT3(a, b, c)       {CS_OUT(a);CS_OUT(b);CS_OUT(c);}
 
 static int      mpu_base = 0, mpu_irq = 0;
+static int      mpu_detected = 0;
 
 int
 probe_cs4232_mpu (struct address_info *hw_config)
@@ -88,6 +89,9 @@ probe_cs4232 (struct address_info *hw_config)
       return 0;
     }
 
+  if (ad1848_detect (hw_config->io_base, NULL, hw_config->osp))
+    return 1;                  /* The card is already active */
+
 /*
  * This version of the driver doesn't use the PnP method when configuring
  * the card but a simplified method defined by Crystal. This means that
@@ -108,14 +112,6 @@ probe_cs4232 (struct address_info *hw_config)
 
   CS_OUT2 (0x06, CSN_NUM);
 
-/*
- * Ensure that there is no other codec using the same address.
- */
-
-  CS_OUT2 (0x15, 0x00);                /* Select logical device 0 (WSS/SB/FM) */
-  CS_OUT2 (0x33, 0x00);                /* Inactivate logical dev 0 */
-  if (ad1848_detect (hw_config->io_base, NULL, hw_config->osp))
-    return 0;
 
 /*
  * Then set some config bytes. First logical device 0 
@@ -144,7 +140,7 @@ probe_cs4232 (struct address_info *hw_config)
  * Initialize logical device 3 (MPU)
  */
 
-#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
   if (mpu_base != 0 && mpu_irq != 0)
     {
       CS_OUT2 (0x15, 0x03);    /* Select logical device 3 (MPU) */
@@ -182,7 +178,7 @@ attach_cs4232 (long mem_start, struct address_info *hw_config)
               0,
               hw_config->osp);
 
-#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
   if (mpu_base != 0 && mpu_irq != 0)
     {
       static struct address_info hw_config2 =
@@ -201,6 +197,7 @@ attach_cs4232 (long mem_start, struct address_info *hw_config)
 
       if (probe_mpu401 (&hw_config2))
        {
+         mpu_detected = 1;
          mem_start = attach_mpu401 (mem_start, &hw_config2);
        }
       else
@@ -227,8 +224,8 @@ unload_cs4232 (struct address_info *hw_config)
                 dma2,          /* Capture DMA */
                 0);
 
-#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
-  if (mpu_base != 0 && mpu_irq != 0)
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+  if (mpu_base != 0 && mpu_irq != 0 && mpu_detected)
     {
       static struct address_info hw_config2 =
       {0};                     /* Ensure it's initialized */
index 6b4fd45ceff924537e204cb2fd027757ad1d84d2..be3a034d3268370ec5f7a6d0564916a44715eabf 100644 (file)
@@ -30,8 +30,6 @@
 #define _DEV_TABLE_C_
 #include "sound_config.h"
 
-#ifdef CONFIGURE_SOUNDCARD
-
 int             sound_started = 0;
 
 int             sndtable_get_cardcount (void);
@@ -48,6 +46,33 @@ snd_find_driver (int type)
   return -1;
 }
 
+static long
+start_services (long mem_start)
+{
+  int             soundcards_installed;
+
+  if (!(soundcards_installed = sndtable_get_cardcount ()))
+    return mem_start;          /* No cards detected */
+
+#ifdef CONFIG_AUDIO
+  if (num_audiodevs)           /* Audio devices present */
+    {
+      DMAbuf_init (0);
+      audio_init (0);
+    }
+#endif
+
+#ifdef CONFIG_MIDI
+  if (num_midis)
+    MIDIbuf_init (0);
+#endif
+
+#ifdef CONFIG_SEQUENCER
+  if (num_midis + num_synths)
+    sequencer_init (0);
+#endif
+  return mem_start;
+}
 
 static long
 start_cards (long mem_start)
@@ -56,7 +81,8 @@ start_cards (long mem_start)
   int             drv;
 
   sound_started = 1;
-  printk ("Sound initialization started\n");
+  if (trace_init)
+    printk ("Sound initialization started\n");
 
 /*
  * Check the number of cards actually defined in the table
@@ -83,27 +109,9 @@ start_cards (long mem_start)
 
        if (sound_drivers[drv].probe (&snd_installed_cards[i].config))
          {
-           int             tmp;
-
-           printk ("snd%d",
-                   snd_installed_cards[i].card_type);
 
            mem_start = sound_drivers[drv].attach (mem_start, &snd_installed_cards[i].config);
-           printk (" at 0x%x",
-                   snd_installed_cards[i].config.io_base);
-
-           if ((tmp = snd_installed_cards[i].config.irq) != 0)
-             printk (" irq %d",
-                     (tmp > 0) ? tmp : -tmp);
-
-           if (snd_installed_cards[i].config.dma >= 0)
-             printk (" drq %d",
-                     snd_installed_cards[i].config.dma);
-           if (snd_installed_cards[i].config.dma2 != -1)
-             printk (",%d\n",
-                     snd_installed_cards[i].config.dma2);
-           else
-             printk ("\n");
+
          }
        else
          snd_installed_cards[i].enabled = 0;   /*
@@ -111,7 +119,8 @@ start_cards (long mem_start)
                                                 */
       }
 
-  printk ("Sound initialization complete\n");
+  if (trace_init)
+    printk ("Sound initialization complete\n");
   return mem_start;
 }
 
@@ -130,7 +139,8 @@ sound_unload_drivers (void)
   if (!sound_started)
     return;
 
-  printk ("Sound unload started\n");
+  if (trace_init)
+    printk ("Sound unload started\n");
 
   for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
     if (snd_installed_cards[i].enabled)
@@ -141,7 +151,8 @@ sound_unload_drivers (void)
            snd_installed_cards[i].enabled = 0;
          }
 
-  printk ("Sound unload complete\n");
+  if (trace_init)
+    printk ("Sound unload complete\n");
 }
 
 void
@@ -182,6 +193,8 @@ sndtable_probe (int unit, struct address_info *hw_config)
 {
   int             i, sel = -1, n = num_sound_cards;
 
+  DDB (printk ("sndtable_probe(%d)\n", unit));
+
   if (!unit)
     return TRUE;
 
@@ -221,16 +234,22 @@ sndtable_probe (int unit, struct address_info *hw_config)
       if ((drv = snd_find_driver (snd_installed_cards[sel].card_type)) == -1)
        {
          snd_installed_cards[sel].enabled = 0;
+         DDB (printk ("Failed to find driver\n"));
          return FALSE;
        }
+      DDB (printk ("Driver name '%s'\n", sound_drivers[drv].name));
 
-
-      snd_installed_cards[sel].config.card_subtype =
+      hw_config->card_subtype =
+       snd_installed_cards[sel].config.card_subtype =
        sound_drivers[drv].card_subtype;
 
       if (sound_drivers[drv].probe (hw_config))
-       return TRUE;
+       {
+         return TRUE;
+         DDB (printk ("Hardware probed OK\n"));
+       }
 
+      DDB (printk ("Failed to find hardware\n"));
       snd_installed_cards[sel].enabled = 0;    /*
                                                 * Mark as not detected
                                                 */
@@ -278,26 +297,17 @@ sndtable_init_card (int unit, struct address_info *hw_config)
          {
 
            DDB (printk ("Located card - calling attach routine\n"));
-           printk ("snd%d", unit);
            if (sound_drivers[drv].attach (0, hw_config) != 0)
              panic ("sound: Invalid memory allocation\n");
 
            DDB (printk ("attach routine finished\n"));
-           printk (" at 0x%x irq %d drq %d",
-                   snd_installed_cards[i].config.io_base,
-                   snd_installed_cards[i].config.irq,
-                   snd_installed_cards[i].config.dma);
-           if (snd_installed_cards[i].config.dma2 != -1)
-             printk (",%d\n",
-                     snd_installed_cards[i].config.dma2);
-           else
-             printk ("\n");
          }
+       start_services (0);
        return TRUE;
       }
 
-  printk ("sndtable_init_card: No card defined with type=%d, num cards: %d\n",
-         unit, num_sound_cards);
+  DDB (printk ("sndtable_init_card: No card defined with type=%d, num cards: %d\n",
+              unit, num_sound_cards));
   return FALSE;
 }
 
@@ -413,7 +423,3 @@ sound_getconf (int card_type)
 
   return &snd_installed_cards[ptr].config;
 }
-
-
-
-#endif
index 7653b6a408b9c9b94ff007965cc14a1c5c5ba399..74b5e94f30528ae2d1a7f5fd9e71bf8c35771b29 100644 (file)
@@ -26,7 +26,6 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
-
 */
 
 #ifndef _DEV_TABLE_H_
@@ -77,6 +76,7 @@ typedef struct pnp_sounddev
 
 struct dma_buffparms {
        int      dma_mode;      /* DMODE_INPUT, DMODE_OUTPUT or DMODE_NONE */
+       int      closing;
 
        /*
         * Pointers to raw buffers
@@ -104,6 +104,7 @@ struct dma_buffparms {
                int      qlen;
                int      qhead;
                int      qtail;
+       int      cfrag; /* Current incomplete fragment (write) */
 
        int      nbufs;
        int      counts[MAX_SUB_BUFFERS];
@@ -120,6 +121,9 @@ struct dma_buffparms {
        int      mapping_flags;
 #define                        DMA_MAP_MAPPED          0x00000001
        char    neutral_byte;
+#ifdef OS_DMA_PARMS
+       OS_DMA_PARMS
+#endif
 };
 
 /*
@@ -265,7 +269,7 @@ struct sound_timer_operations {
        struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV] = {NULL}; int num_synths = 0;
        struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL}; int num_midis = 0;
 
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
        extern struct sound_timer_operations default_sound_timer;
        struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = 
                {&default_sound_timer, NULL}; 
@@ -281,66 +285,64 @@ struct sound_timer_operations {
  */
 
        struct driver_info sound_drivers[] = {
-#ifndef EXCLUDE_PSS
+#ifdef CONFIG_PSS
          {"PSSECHO", 0, SNDCARD_PSS, "Echo Personal Sound System PSS (ESC614)", attach_pss, probe_pss, unload_pss},
          {"PSSMPU", 0, SNDCARD_PSS_MPU, "PSS-MPU", attach_pss_mpu, probe_pss_mpu, unload_pss_mpu},
          {"PSSMSS", 0, SNDCARD_PSS_MSS, "PSS-MSS", attach_pss_mss, probe_pss_mss, unload_pss_mss},
 #endif
-#ifndef EXCLUDE_MSS
+#ifdef CONFIG_MSS
                {"MSS", 0, SNDCARD_MSS, "MS Sound System",      attach_ms_sound, probe_ms_sound, unload_ms_sound},
        /* MSS without IRQ/DMA config registers (for DEC Alphas) */
-               {"PCXBJ", 1, SNDCARD_PSEUDO_MSS,        "MS Sound System",      attach_ms_sound, probe_ms_sound, unload_ms_sound},
+               {"PCXBJ", 1, SNDCARD_PSEUDO_MSS,        "MS Sound System (AXP)",        attach_ms_sound, probe_ms_sound, unload_ms_sound},
 #endif
-#ifndef EXCLUDE_MAD16
+#ifdef CONFIG_MAD16
                {"MAD16", 0, SNDCARD_MAD16,     "MAD16/Mozart (MSS)",           attach_mad16, probe_mad16, unload_mad16},
                {"MAD16MPU", 0, SNDCARD_MAD16_MPU,      "MAD16/Mozart (MPU)",           attach_mad16_mpu, probe_mad16_mpu, unload_mad16_mpu},
 #endif
-#ifndef EXCLUDE_CS4232
+#ifdef CONFIG_CS4232
                {"CS4232", 0, SNDCARD_CS4232,   "CS4232",               attach_cs4232, probe_cs4232, unload_cs4232},
                {"CS4232MPU", 0, SNDCARD_CS4232_MPU,    "CS4232 MIDI",          attach_cs4232_mpu, probe_cs4232_mpu, unload_cs4232_mpu},
 #endif
-#ifndef EXCLUDE_YM3812
+#ifdef CONFIG_YM3812
                {"OPL3", 0, SNDCARD_ADLIB,      "OPL-2/OPL-3 FM",               attach_adlib_card, probe_adlib, unload_adlib},
 #endif
-#ifndef EXCLUDE_PAS
+#ifdef CONFIG_PAS
                {"PAS16", 0, SNDCARD_PAS,       "ProAudioSpectrum",     attach_pas_card, probe_pas, unload_pas},
 #endif
-#if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI)
+#if defined(CONFIG_MPU401) && defined(CONFIG_MIDI)
                {"MPU401", 0, SNDCARD_MPU401,"Roland MPU-401",  attach_mpu401, probe_mpu401, unload_mpu401},
 #endif
-#if !defined(EXCLUDE_MAUI)
+#if defined(CONFIG_MAUI)
                {"MAUI", 0, SNDCARD_MAUI,"TB Maui",     attach_maui, probe_maui, unload_maui},
 #endif
-#if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI)
+#if defined(CONFIG_UART6850) && defined(CONFIG_MIDI)
                {"MIDI6850", 0, SNDCARD_UART6850,"6860 UART Midi",      attach_uart6850, probe_uart6850, unload_uart6850},
 #endif
-#ifndef EXCLUDE_SB
+#ifdef CONFIG_SB
                {"SBLAST", 0, SNDCARD_SB,       "SoundBlaster",         attach_sb_card, probe_sb, unload_sb},
+#ifdef CONFIG_AUDIO
+               {"SBX", 0, SNDCARD_SB16,        "SoundBlaster 16bit",   sb16_dsp_init, sb16_dsp_detect, unload_sb16},
 #endif
-#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16)
-#ifndef EXCLUDE_AUDIO
-               {"SB16", 0, SNDCARD_SB16,       "SoundBlaster16",       sb16_dsp_init, sb16_dsp_detect, unload_sb16},
+#ifdef CONFIG_MIDI
+               {"SBMPU", 0, SNDCARD_SB16MIDI,"SB MPU", attach_sb16midi, probe_sb16midi, unload_sb16midi},
 #endif
-#ifndef EXCLUDE_MIDI
-               {"SB16MIDI", 0, SNDCARD_SB16MIDI,"SB16 MIDI",   attach_sb16midi, probe_sb16midi, unload_sb16midi},
 #endif
-#endif
-#ifndef EXCLUDE_GUS16
+#ifdef CONFIG_GUS16
                {"GUS16", 0, SNDCARD_GUS16,     "Ultrasound 16-bit opt.",       attach_gus_db16, probe_gus_db16, unload_gus_db16},
 #endif
-#ifndef EXCLUDE_GUS
+#ifdef CONFIG_GUS
                {"GUS", 0, SNDCARD_GUS, "Gravis Ultrasound",    attach_gus_card, probe_gus, unload_gus},
 #endif
-#ifndef EXCLUDE_SSCAPE
+#ifdef CONFIG_SSCAPE
                {"SSCAPE", 0, SNDCARD_SSCAPE, "Ensoniq Soundscape",     attach_sscape, probe_sscape, unload_sscape},
                {"SSCAPEMSS", 0, SNDCARD_SSCAPE_MSS,    "MS Sound System (SoundScape)", attach_ss_ms_sound, probe_ss_ms_sound, unload_ss_ms_sound},
 #endif
-#ifndef EXCLUDE_TRIX
+#ifdef CONFIG_TRIX
                {"TRXPRO", 0, SNDCARD_TRXPRO, "MediaTriX AudioTriX Pro",        attach_trix_wss, probe_trix_wss, unload_trix_wss},
                {"TRXPROSB", 0, SNDCARD_TRXPRO_SB, "AudioTriX (SB mode)",       attach_trix_sb, probe_trix_sb, unload_trix_sb},
                {"TRXPROMPU", 0, SNDCARD_TRXPRO_MPU, "AudioTriX MIDI",  attach_trix_mpu, probe_trix_mpu, unload_trix_mpu},
 #endif
-#ifndef EXCLUDE_PNP
+#ifdef CONFIG_PNP
                {"AD1848", 0, 500, "PnP MSS",   attach_pnp_ad1848, probe_pnp_ad1848, unload_pnp_ad1848},
 #endif
                {NULL, 0, 0,            "*?*",                  NULL, NULL, NULL}
@@ -360,7 +362,7 @@ struct sound_timer_operations {
  */
 
        struct card_info snd_installed_cards[] = {
-#ifndef EXCLUDE_PSS
+#ifdef CONFIG_PSS
             {SNDCARD_PSS, {PSS_BASE, 0, -1, -1}, SND_DEFAULT_ENABLE},
 #      ifdef PSS_MPU_BASE
             {SNDCARD_PSS_MPU, {PSS_MPU_BASE, PSS_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
@@ -369,7 +371,10 @@ struct sound_timer_operations {
             {SNDCARD_PSS_MSS, {PSS_MSS_BASE, PSS_MSS_IRQ, PSS_MSS_DMA, -1}, SND_DEFAULT_ENABLE},
 #      endif
 #endif
-#ifndef EXCLUDE_TRIX
+#ifdef CONFIG_TRIX
+#ifndef TRIX_DMA2
+#define TRIX_DMA2 TRIX_DMA
+#endif
             {SNDCARD_TRXPRO, {TRIX_BASE, TRIX_IRQ, TRIX_DMA, TRIX_DMA2}, SND_DEFAULT_ENABLE},
 #      ifdef TRIX_SB_BASE
             {SNDCARD_TRXPRO_SB, {TRIX_SB_BASE, TRIX_SB_IRQ, TRIX_SB_DMA, -1}, SND_DEFAULT_ENABLE},
@@ -378,26 +383,32 @@ struct sound_timer_operations {
             {SNDCARD_TRXPRO_MPU, {TRIX_MPU_BASE, TRIX_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #      endif
 #endif
-#ifndef EXCLUDE_SSCAPE
+#ifdef CONFIG_SSCAPE
             {SNDCARD_SSCAPE, {SSCAPE_BASE, SSCAPE_IRQ, SSCAPE_DMA, -1}, SND_DEFAULT_ENABLE},
             {SNDCARD_SSCAPE_MSS, {SSCAPE_MSS_BASE, SSCAPE_MSS_IRQ, SSCAPE_MSS_DMA, -1}, SND_DEFAULT_ENABLE},
 #endif
-#ifndef EXCLUDE_MAD16
+#ifdef CONFIG_MAD16
+#ifndef MAD16_DMA2
+#define MAD16_DMA2 MAD16_DMA
+#endif
             {SNDCARD_MAD16, {MAD16_BASE, MAD16_IRQ, MAD16_DMA, MAD16_DMA2}, SND_DEFAULT_ENABLE},
 #      ifdef MAD16_MPU_BASE
             {SNDCARD_MAD16_MPU, {MAD16_MPU_BASE, MAD16_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #      endif
 #endif
 
-#ifndef EXCLUDE_CS4232
+#ifdef CONFIG_CS4232
+#ifndef CS4232_DMA2
+#define CS4232_DMA2 CS4232_DMA
+#endif
 #      ifdef CS4232_MPU_BASE
             {SNDCARD_CS4232_MPU, {CS4232_MPU_BASE, CS4232_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #      endif
             {SNDCARD_CS4232, {CS4232_BASE, CS4232_IRQ, CS4232_DMA, CS4232_DMA2}, SND_DEFAULT_ENABLE},
 #endif
 
-#ifndef EXCLUDE_MSS
-#      ifdef PSEUDO_MSS
+#ifdef CONFIG_MSS
+#      ifndef PSEUDO_MSS
                {SNDCARD_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA, -1}, SND_DEFAULT_ENABLE},
 #      else
                {SNDCARD_PSEUDO_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA, -1}, SND_DEFAULT_ENABLE},
@@ -407,21 +418,21 @@ struct sound_timer_operations {
 #      endif
 #endif
 
-#ifndef EXCLUDE_PAS
+#ifdef CONFIG_PAS
                {SNDCARD_PAS, {PAS_BASE, PAS_IRQ, PAS_DMA, -1}, SND_DEFAULT_ENABLE},
 #endif
 
-#ifndef EXCLUDE_SB
+#ifdef CONFIG_SB
 #      ifndef SBC_DMA
 #              define SBC_DMA          1
 #      endif
                {SNDCARD_SB, {SBC_BASE, SBC_IRQ, SBC_DMA, -1}, SND_DEFAULT_ENABLE},
 #endif
-#if !defined(EXCLUDE_MAUI) 
+#if defined(CONFIG_MAUI) 
                {SNDCARD_MAUI, {MAUI_BASE, MAUI_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #endif
 
-#if !defined(EXCLUDE_MPU401) && !defined(EXCLUDE_MIDI)
+#if defined(CONFIG_MPU401) && defined(CONFIG_MIDI)
                {SNDCARD_MPU401, {MPU_BASE, MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #ifdef MPU2_BASE
                {SNDCARD_MPU401, {MPU2_BASE, MPU2_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
@@ -431,27 +442,30 @@ struct sound_timer_operations {
 #endif
 #endif
 
-#if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI)
+#if defined(CONFIG_UART6850) && defined(CONFIG_MIDI)
                {SNDCARD_UART6850, {U6850_BASE, U6850_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #endif
 
-#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16)
-#ifndef EXCLUDE_AUDIO
-               {SNDCARD_SB16, {SBC_BASE, SBC_IRQ, SB16_DMA, -1}, SND_DEFAULT_ENABLE},
+#if defined(CONFIG_SB) 
+#if defined(CONFIG_AUDIO) && defined(SB_DMA2)
+               {SNDCARD_SB16, {SBC_BASE, SBC_IRQ, SB_DMA2, -1}, SND_DEFAULT_ENABLE},
 #endif
-#ifndef EXCLUDE_MIDI
-               {SNDCARD_SB16MIDI,{SB16MIDI_BASE, SBC_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
+#if defined(CONFIG_MIDI) && defined(SB_MPU_BASE)
+               {SNDCARD_SB16MIDI,{SB_MPU_BASE, SB_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
 #endif
 #endif
 
-#ifndef EXCLUDE_GUS
-#ifndef EXCLUDE_GUS16
+#ifdef CONFIG_GUS
+#ifndef GUS_DMA2
+#define GUS_DMA2 GUS_DMA
+#endif
+#ifdef CONFIG_GUS16
                {SNDCARD_GUS16, {GUS16_BASE, GUS16_IRQ, GUS16_DMA, -1}, SND_DEFAULT_ENABLE},
 #endif
                {SNDCARD_GUS, {GUS_BASE, GUS_IRQ, GUS_DMA, GUS_DMA2}, SND_DEFAULT_ENABLE},
 #endif
 
-#ifndef EXCLUDE_YM3812
+#ifdef CONFIG_YM3812
                {SNDCARD_ADLIB, {FM_MONO, 0, 0, -1}, SND_DEFAULT_ENABLE},
 #endif
 /* Define some expansion space */
@@ -473,8 +487,13 @@ struct sound_timer_operations {
        int max_sound_cards = 20;
 #endif
 
+#   ifdef MODULE
+       int trace_init = 0;
+#   else
+       int trace_init = 1;
+#   endif
 #else
-       extern struct audio_operations * audio_devs[MAX_AUDIO_DEV]; int num_audiodevs;
+       extern struct audio_operations * audio_devs[MAX_AUDIO_DEV]; extern int num_audiodevs;
        extern struct mixer_operations * mixer_devs[MAX_MIXER_DEV]; extern int num_mixers;
        extern struct synth_operations * synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; extern int num_synths;
        extern struct midi_operations * midi_devs[MAX_MIDI_DEV]; extern int num_midis;
@@ -487,6 +506,8 @@ struct sound_timer_operations {
        extern int num_sound_cards;
        extern int max_sound_cards;
 
+       extern int trace_init;
+
 long sndtable_init(long mem_start);
 int sndtable_get_cardcount (void);
 struct address_info *sound_getconf(int card_type);
index a7ce2f31084a370123fefbbb7d985985528e5c95..7cacc7f99314ba2961553f99eb13ca44a3412333 100644 (file)
 
 #include "sound_config.h"
 
-#ifdef CONFIGURE_SOUNDCARD
+#if defined(CONFIG_AUDIO) || defined(CONFIG_GUS)
 
-#if !defined(EXCLUDE_AUDIO) || !defined(EXCLUDE_GUS)
-
-static struct wait_queue *in_sleeper[MAX_AUDIO_DEV] =
+static wait_handle *in_sleeper[MAX_AUDIO_DEV] =
 {NULL};
 static volatile struct snd_wait in_sleep_flag[MAX_AUDIO_DEV] =
 {
   {0}};
-static struct wait_queue *out_sleeper[MAX_AUDIO_DEV] =
+static wait_handle *out_sleeper[MAX_AUDIO_DEV] =
 {NULL};
 static volatile struct snd_wait out_sleep_flag[MAX_AUDIO_DEV] =
 {
@@ -133,6 +131,9 @@ reorganize_buffers (int dev, struct dma_buffparms *dmap)
     }
 
   bsz &= ~0x03;                        /* Force size which is multiple of 4 bytes */
+#ifdef OS_DMA_ALIGN_CHECK
+  OS_DMA_ALIGN_CHECK (bsz);
+#endif
 
   n = dsp_dev->buffsize / bsz;
   if (n > MAX_SUB_BUFFERS)
@@ -158,7 +159,9 @@ dma_init_buffers (int dev, struct dma_buffparms *dmap)
       out_sleep_flag[dev].mode = WK_NONE;
     }
   else
-    in_sleep_flag[dev].mode = WK_NONE;
+    {
+      in_sleep_flag[dev].mode = WK_NONE;
+    }
 
   dmap->flags = DMA_BUSY;      /* Other flags off */
   dmap->qlen = dmap->qhead = dmap->qtail = 0;
@@ -168,6 +171,8 @@ dma_init_buffers (int dev, struct dma_buffparms *dmap)
   dmap->dma_mode = DMODE_NONE;
   dmap->mapping_flags = 0;
   dmap->neutral_byte = 0x00;
+  dmap->cfrag = -1;
+  dmap->closing = 0;
 }
 
 static int
@@ -262,6 +267,8 @@ DMAbuf_open (int dev, int mode)
       }
   audio_devs[dev]->open_mode = mode;
   audio_devs[dev]->go = 1;
+  in_sleep_flag[dev].mode = WK_NONE;
+  out_sleep_flag[dev].mode = WK_NONE;
 
   audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_BITS, (ioctl_arg) 8, 1);
   audio_devs[dev]->ioctl (dev, SOUND_PCM_WRITE_CHANNELS, (ioctl_arg) 1, 1);
@@ -335,19 +342,19 @@ dma_sync (int dev)
       save_flags (flags);
       cli ();
 
-      while (!(current->signal & ~current->blocked)
-            && audio_devs[dev]->dmap_out->qlen)
+      while (!current_got_fatal_signal ()
+            && audio_devs[dev]->dmap_out->qlen > 1)
        {
 
          {
            unsigned long   tl;
 
-           if (10 * HZ)
-             current->timeout = tl = jiffies + (10 * HZ);
+           if (HZ)
+             current_set_timeout (tl = jiffies + (HZ));
            else
              tl = 0xffffffff;
            out_sleep_flag[dev].mode = WK_SLEEP;
-           interruptible_sleep_on (&out_sleeper[dev]);
+           module_interruptible_sleep_on (&out_sleeper[dev]);
            if (!(out_sleep_flag[dev].mode & WK_WAKEUP))
              {
                if (jiffies >= tl)
@@ -372,7 +379,7 @@ dma_sync (int dev)
       cli ();
       if (audio_devs[dev]->local_qlen) /* Device has hidden buffers */
        {
-         while (!((current->signal & ~current->blocked))
+         while (!(current_got_fatal_signal ())
                 && audio_devs[dev]->local_qlen (dev))
            {
 
@@ -380,11 +387,11 @@ dma_sync (int dev)
                unsigned long   tl;
 
                if (HZ)
-                 current->timeout = tl = jiffies + (HZ);
+                 current_set_timeout (tl = jiffies + (HZ));
                else
                  tl = 0xffffffff;
                out_sleep_flag[dev].mode = WK_SLEEP;
-               interruptible_sleep_on (&out_sleeper[dev]);
+               module_interruptible_sleep_on (&out_sleeper[dev]);
                if (!(out_sleep_flag[dev].mode & WK_WAKEUP))
                  {
                    if (jiffies >= tl)
@@ -404,7 +411,10 @@ DMAbuf_release (int dev, int mode)
 {
   unsigned long   flags;
 
-  if (!((current->signal & ~current->blocked))
+  audio_devs[dev]->dmap_out->closing = 1;
+  audio_devs[dev]->dmap_in->closing = 1;
+
+  if (!(current_got_fatal_signal ())
       && (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT))
     {
       dma_sync (dev);
@@ -412,7 +422,6 @@ DMAbuf_release (int dev, int mode)
 
   save_flags (flags);
   cli ();
-  audio_devs[dev]->reset (dev);
 
   audio_devs[dev]->close (dev);
 
@@ -485,6 +494,14 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock)
 
   save_flags (flags);
   cli ();
+#ifdef ALLOW_BUFFER_MAPPING
+  if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
+    {
+      printk ("Sound: Can't read from mmapped device (1)\n");
+      return -EINVAL;
+    }
+  else
+#endif
   if (!dmap->qlen)
     {
       int             timeout;
@@ -520,11 +537,11 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock)
        unsigned long   tl;
 
        if (timeout)
-         current->timeout = tl = jiffies + (timeout);
+         current_set_timeout (tl = jiffies + (timeout));
        else
          tl = 0xffffffff;
        in_sleep_flag[dev].mode = WK_SLEEP;
-       interruptible_sleep_on (&in_sleeper[dev]);
+       module_interruptible_sleep_on (&in_sleeper[dev]);
        if (!(in_sleep_flag[dev].mode & WK_WAKEUP))
          {
            if (jiffies >= tl)
@@ -536,6 +553,7 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock)
        {
          printk ("Sound: DMA (input) timed out - IRQ/DRQ config error?\n");
          err = EIO;
+         audio_devs[dev]->reset (dev);
          ;
        }
       else
@@ -559,6 +577,14 @@ DMAbuf_rmchars (int dev, int buff_no, int c)
 
   int             p = dmap->counts[dmap->qhead] + c;
 
+#ifdef ALLOW_BUFFER_MAPPING
+  if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
+    {
+      printk ("Sound: Can't read from mmapped device (2)\n");
+      return -EINVAL;
+    }
+  else
+#endif
   if (p >= dmap->fragment_size)
     {                          /* This buffer is completely empty */
       dmap->counts[dmap->qhead] = 0;
@@ -623,6 +649,11 @@ dma_set_fragment (int dev, struct dma_buffparms *dmap, ioctl_arg arg, int fact)
   if (count < 2)
     return -EINVAL;
 
+#ifdef OS_DMA_MINBITS
+  if (bytes < OS_DMA_MINBITS)
+    bytes = OS_DMA_MINBITS;
+#endif
+
   dmap->fragment_size = (1 << bytes);
   dmap->max_fragments = count;
 
@@ -739,6 +770,10 @@ DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
          if (cmd == SNDCTL_DSP_GETISPACE && audio_devs[dev]->flags & DMA_DUPLEX)
            dmap = dmap_in;
 
+#ifdef ALLOW_BUFFER_MAPPING
+         if (dmap->mapping_flags & DMA_MAP_MAPPED)
+           return -EINVAL;
+#endif
 
          if (!(dmap->flags & DMA_ALLOC_DONE))
            reorganize_buffers (dev, dmap);
@@ -758,7 +793,7 @@ DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
                    {
                      int             tmp = audio_devs[dev]->local_qlen (dev);
 
-                     if (tmp & info->fragments)
+                     if (tmp && info->fragments)
                        tmp--;  /*
                                   * This buffer has been counted twice
                                 */
@@ -809,6 +844,18 @@ DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
            activate_recording (dev, dmap_in);
          }
 
+#ifdef ALLOW_BUFFER_MAPPING
+       if ((changed & bits) & PCM_ENABLE_OUTPUT &&
+           dmap_out->mapping_flags & DMA_MAP_MAPPED &&
+           audio_devs[dev]->go)
+         {
+           if (!(dmap_out->flags & DMA_ALLOC_DONE))
+             reorganize_buffers (dev, dmap_out);
+
+           dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size;
+           DMAbuf_start_output (dev, 0, dmap_out->fragment_size);
+         }
+#endif
 
        audio_devs[dev]->enable_bits = bits;
        if (changed && audio_devs[dev]->trigger)
@@ -819,6 +866,16 @@ DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
       return snd_ioctl_return ((int *) arg, audio_devs[dev]->enable_bits);
       break;
 
+    case SNDCTL_DSP_SETSYNCRO:
+
+      if (!audio_devs[dev]->trigger)
+       return -EINVAL;
+
+      audio_devs[dev]->trigger (dev, 0);
+      audio_devs[dev]->go = 0;
+      return 0;
+      break;
+
     case SNDCTL_DSP_GETIPTR:
       {
        count_info      info;
@@ -832,6 +889,10 @@ DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
        info.bytes += info.ptr;
        memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
 
+#ifdef ALLOW_BUFFER_MAPPING
+       if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
+         audio_devs[dev]->dmap_in->qlen = 0;   /* Acknowledge interrupts */
+#endif
        restore_flags (flags);
        return 0;
       }
@@ -850,6 +911,10 @@ DMAbuf_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
        info.bytes += info.ptr;
        memcpy_tofs ((&((char *) arg)[0]), (char *) &info, sizeof (info));
 
+#ifdef ALLOW_BUFFER_MAPPING
+       if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
+         audio_devs[dev]->dmap_out->qlen = 0;  /* Acknowledge interrupts */
+#endif
        restore_flags (flags);
        return 0;
       }
@@ -879,6 +944,10 @@ DMAbuf_start_devices (unsigned int devmask)
          {
            /* OK to start the device */
            audio_devs[dev]->go = 1;
+
+           if (audio_devs[dev]->trigger)
+             audio_devs[dev]->trigger (dev,
+                       audio_devs[dev]->enable_bits * audio_devs[dev]->go);
          }
 }
 
@@ -902,7 +971,7 @@ space_in_queue (int dev)
   if (audio_devs[dev]->local_qlen)
     {
       tmp = audio_devs[dev]->local_qlen (dev);
-      if (tmp & len)
+      if (tmp && len)
        tmp--;                  /*
                                   * This buffer has been counted twice
                                 */
@@ -921,6 +990,13 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
   int             abort, err = EIO;
   struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
 
+#ifdef ALLOW_BUFFER_MAPPING
+  if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
+    {
+      printk ("Sound: Can't write to mmapped device (3)\n");
+      return -EINVAL;
+    }
+#endif
 
   if (dmap->dma_mode == DMODE_INPUT)   /* Direction change */
     {
@@ -983,11 +1059,11 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
        unsigned long   tl;
 
        if (timeout)
-         current->timeout = tl = jiffies + (timeout);
+         current_set_timeout (tl = jiffies + (timeout));
        else
          tl = 0xffffffff;
        out_sleep_flag[dev].mode = WK_SLEEP;
-       interruptible_sleep_on (&out_sleeper[dev]);
+       module_interruptible_sleep_on (&out_sleeper[dev]);
        if (!(out_sleep_flag[dev].mode & WK_WAKEUP))
          {
            if (jiffies >= tl)
@@ -1001,8 +1077,9 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
          err = EIO;
          abort = 1;
          ;
+         audio_devs[dev]->reset (dev);
        }
-      else if ((current->signal & ~current->blocked))
+      else if (current_got_fatal_signal ())
        {
          err = EINTR;
          abort = 1;
@@ -1022,20 +1099,59 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
   return dmap->qtail;
 }
 
+int
+DMAbuf_get_curr_buffer (int dev, int *buf_no, char **dma_buf, int *buf_ptr, int *buf_size)
+{
+  struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
+
+  if (dmap->cfrag < 0)
+    return -1;
+
+  *dma_buf = dmap->raw_buf + dmap->qtail * dmap->fragment_size;
+  *buf_ptr = dmap->counts[dmap->qtail];
+  *buf_size = dmap->fragment_size;
+  return *buf_no = dmap->cfrag;
+}
+
+int
+DMAbuf_set_count (int dev, int buff_no, int l)
+{
+  struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
+
+  if (buff_no == dmap->qtail)
+    {
+      dmap->cfrag = buff_no;
+      dmap->counts[buff_no] = l;
+    }
+  else
+    dmap->cfrag = -1;
+  return 0;
+}
+
 int
 DMAbuf_start_output (int dev, int buff_no, int l)
 {
   struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
 
+  dmap->cfrag = -1;
 /*
  * Bypass buffering if using mmaped access
  */
 
+#ifdef ALLOW_BUFFER_MAPPING
+  if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
+    {
+      l = dmap->fragment_size;
+      dmap->counts[dmap->qtail] = l;
+      dmap->flags &= ~DMA_RESTART;
+      dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+    }
+  else
+#else
   if (dmap != NULL)
+#endif
     {
 
-      if (buff_no != dmap->qtail)
-       printk ("Sound warning: DMA buffers out of sync %d != %d\n", buff_no, dmap->qtail);
 
       dmap->qlen++;
       if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
@@ -1165,12 +1281,43 @@ DMAbuf_outputintr (int dev, int event_type)
   unsigned long   flags;
   struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
 
+  int             p;
+
   dmap->byte_counter += dmap->counts[dmap->qhead];
 
 #ifdef OS_DMA_INTR
   sound_dma_intr (dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1);
 #endif
 
+#ifdef ALLOW_BUFFER_MAPPING
+  if (dmap->mapping_flags & DMA_MAP_MAPPED)
+    {
+      /* mmapped access */
+
+      p = dmap->fragment_size * dmap->qhead;
+      memset (dmap->raw_buf + p,
+             dmap->neutral_byte,
+             dmap->fragment_size);
+
+      dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
+      dmap->qlen++;            /* Yes increment it (don't decrement) */
+      dmap->flags &= ~DMA_ACTIVE;
+      dmap->counts[dmap->qhead] = dmap->fragment_size;
+
+      if (!(audio_devs[dev]->flags & DMA_AUTOMODE))
+       {
+         audio_devs[dev]->output_block (dev, dmap->raw_buf_phys +
+                                        dmap->qhead * dmap->fragment_size,
+                                        dmap->counts[dmap->qhead], 1,
+                                 !(audio_devs[dev]->flags & DMA_AUTOMODE));
+         if (audio_devs[dev]->trigger)
+           audio_devs[dev]->trigger (dev,
+                       audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+       }
+      dmap->flags |= DMA_ACTIVE;
+    }
+  else
+#endif
   if (event_type != 2)
     {
       if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
@@ -1184,6 +1331,27 @@ DMAbuf_outputintr (int dev, int event_type)
       dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
       dmap->flags &= ~DMA_ACTIVE;
 
+      if (event_type == 1 && dmap->qlen < 1)
+       {
+         dmap->underrun_count++;
+         /* Ignore underrun. Just move the tail pointer forward and go */
+         if (dmap->closing)
+           {
+             audio_devs[dev]->halt_xfer (dev);
+           }
+         else
+           {
+             dmap->qlen++;
+             dmap->cfrag = -1;
+             dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+
+             p = dmap->fragment_size * dmap->qhead;
+             memset (dmap->raw_buf + p,
+                     dmap->neutral_byte,
+                     dmap->fragment_size);
+           }
+       }
+
       if (dmap->qlen)
        {
          if (!(audio_devs[dev]->flags & DMA_AUTOMODE))
@@ -1198,21 +1366,6 @@ DMAbuf_outputintr (int dev, int event_type)
            }
          dmap->flags |= DMA_ACTIVE;
        }
-      else if (event_type == 1)
-       {
-         dmap->underrun_count++;
-         if ((audio_devs[dev]->flags & DMA_DUPLEX) &&
-             audio_devs[dev]->halt_output)
-           audio_devs[dev]->halt_output (dev);
-         else
-           audio_devs[dev]->halt_xfer (dev);
-
-         if ((audio_devs[dev]->flags & DMA_AUTOMODE) &&
-             audio_devs[dev]->flags & NEEDS_RESTART)
-           dmap->flags |= DMA_RESTART;
-         else
-           dmap->flags &= ~DMA_RESTART;
-       }
     }                          /* event_type != 2 */
 
   save_flags (flags);
@@ -1221,7 +1374,7 @@ DMAbuf_outputintr (int dev, int event_type)
     {
       {
        out_sleep_flag[dev].mode = WK_WAKEUP;
-       wake_up (&out_sleeper[dev]);
+       module_wake_up (&out_sleeper[dev]);
       };
     }
   restore_flags (flags);
@@ -1239,21 +1392,47 @@ DMAbuf_inputintr (int dev)
   sound_dma_intr (dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2);
 #endif
 
+#ifdef ALLOW_BUFFER_MAPPING
+  if (dmap->mapping_flags & DMA_MAP_MAPPED)
+    {
+      dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+      dmap->qlen++;
+
+      if (!(audio_devs[dev]->flags & DMA_AUTOMODE))
+       {
+         audio_devs[dev]->start_input (dev, dmap->raw_buf_phys +
+                                       dmap->qtail * dmap->fragment_size,
+                                       dmap->fragment_size, 1,
+                                 !(audio_devs[dev]->flags & DMA_AUTOMODE));
+         if (audio_devs[dev]->trigger)
+           audio_devs[dev]->trigger (dev,
+                       audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+       }
+
+      dmap->flags |= DMA_ACTIVE;
+    }
+  else
+#endif
   if (dmap->qlen == (dmap->nbufs - 1))
     {
       printk ("Sound: Recording overrun\n");
       dmap->underrun_count++;
-      if ((audio_devs[dev]->flags & DMA_DUPLEX) &&
-         audio_devs[dev]->halt_input)
-       audio_devs[dev]->halt_input (dev);
-      else
-       audio_devs[dev]->halt_xfer (dev);
 
-      dmap->flags &= ~DMA_ACTIVE;
       if (audio_devs[dev]->flags & DMA_AUTOMODE)
-       dmap->flags |= DMA_RESTART;
-      else
-       dmap->flags &= ~DMA_RESTART;
+       {
+         /* Force restart on next write */
+         if ((audio_devs[dev]->flags & DMA_DUPLEX) &&
+             audio_devs[dev]->halt_input)
+           audio_devs[dev]->halt_input (dev);
+         else
+           audio_devs[dev]->halt_xfer (dev);
+
+         dmap->flags &= ~DMA_ACTIVE;
+         if (audio_devs[dev]->flags & DMA_AUTOMODE)
+           dmap->flags |= DMA_RESTART;
+         else
+           dmap->flags &= ~DMA_RESTART;
+       }
     }
   else
     {
@@ -1262,28 +1441,28 @@ DMAbuf_inputintr (int dev)
        printk ("\nSound: Audio queue4 corrupted for dev%d (%d/%d)\n",
                dev, dmap->qlen, dmap->nbufs);
       dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+    }
 
-      if (!(audio_devs[dev]->flags & DMA_AUTOMODE))
-       {
-         audio_devs[dev]->start_input (dev, dmap->raw_buf_phys +
-                                       dmap->qtail * dmap->fragment_size,
-                                       dmap->fragment_size, 1,
+  if (!(audio_devs[dev]->flags & DMA_AUTOMODE))
+    {
+      audio_devs[dev]->start_input (dev, dmap->raw_buf_phys +
+                                   dmap->qtail * dmap->fragment_size,
+                                   dmap->fragment_size, 1,
                                  !(audio_devs[dev]->flags & DMA_AUTOMODE));
-         if (audio_devs[dev]->trigger)
-           audio_devs[dev]->trigger (dev,
+      if (audio_devs[dev]->trigger)
+       audio_devs[dev]->trigger (dev,
                        audio_devs[dev]->enable_bits * audio_devs[dev]->go);
-       }
-
-      dmap->flags |= DMA_ACTIVE;
     }
 
+  dmap->flags |= DMA_ACTIVE;
+
   save_flags (flags);
   cli ();
   if ((in_sleep_flag[dev].mode & WK_SLEEP))
     {
       {
        in_sleep_flag[dev].mode = WK_WAKEUP;
-       wake_up (&in_sleeper[dev]);
+       module_wake_up (&in_sleeper[dev]);
       };
     }
   restore_flags (flags);
@@ -1352,7 +1531,7 @@ DMAbuf_reset_dma (int dev)
 }
 
 int
-DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
+DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
 {
   struct dma_buffparms *dmap;
   unsigned long   flags;
@@ -1362,6 +1541,20 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait
     case SEL_IN:
       dmap = audio_devs[dev]->dmap_in;
 
+#ifdef ALLOW_BUFFER_MAPPING
+      if (dmap->mapping_flags & DMA_MAP_MAPPED)
+       {
+         if (dmap->qlen)
+           return 1;
+
+         save_flags (flags);
+         cli ();
+         in_sleep_flag[dev].mode = WK_SLEEP;
+         module_select_wait (&in_sleeper[dev], wait);
+         restore_flags (flags);
+         return 0;
+       }
+#endif
 
       if (dmap->dma_mode != DMODE_INPUT)
        {
@@ -1384,7 +1577,7 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait
          save_flags (flags);
          cli ();
          in_sleep_flag[dev].mode = WK_SLEEP;
-         select_wait (&in_sleeper[dev], wait);
+         module_select_wait (&in_sleeper[dev], wait);
          restore_flags (flags);
          return 0;
        }
@@ -1394,6 +1587,20 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait
     case SEL_OUT:
       dmap = audio_devs[dev]->dmap_out;
 
+#ifdef ALLOW_BUFFER_MAPPING
+      if (dmap->mapping_flags & DMA_MAP_MAPPED)
+       {
+         if (dmap->qlen)
+           return 1;
+
+         save_flags (flags);
+         cli ();
+         out_sleep_flag[dev].mode = WK_SLEEP;
+         module_select_wait (&out_sleeper[dev], wait);
+         restore_flags (flags);
+         return 0;
+       }
+#endif
 
       if (dmap->dma_mode == DMODE_INPUT)
        {
@@ -1410,7 +1617,7 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait
          save_flags (flags);
          cli ();
          out_sleep_flag[dev].mode = WK_SLEEP;
-         select_wait (&out_sleeper[dev], wait);
+         module_select_wait (&out_sleeper[dev], wait);
          restore_flags (flags);
          return 0;
        }
@@ -1425,7 +1632,7 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait
 }
 
 
-#else /* EXCLUDE_AUDIO */
+#else /* CONFIG_AUDIO */
 /*
  * Stub versions if audio services not included
  */
@@ -1514,5 +1721,3 @@ DMAbuf_outputintr (int dev, int underrun_flag)
   return;
 }
 #endif
-
-#endif
diff --git a/drivers/sound/experimental.txt b/drivers/sound/experimental.txt
deleted file mode 100644 (file)
index 456de53..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-This version contains some features which is may NOT be enabled by default. 
-I'm trying to release an official/reliable version soon so that the
-Linux version of Doom (and other games) becomes possible. For that reason
-I have disabled some features which are not reliable enough to be
-released for wide public. If you are interested to try them, please
-read this file carefully.
-
-1) ECHO PSS (Personal Sound System support)
-
-This version contains support for soundcards based on the AD20msp614
-chipset made by Analog Devices. This chipset consist of the
-AD1848 codec, ADSP-21xx DSP chip and a ESC614 ASIC and is used in some
-soundcards made by Orchid, Cardinal, Echo Speech Corporation, Western
-Digital and Wearnes Technology. The PSS support is by Marc M. Hoffman
-(marc.hoffman@analog.com). I received this stuff about a week ago and
-have not been able to test it yet.
-If you are interested, remove the B(OPT_PSS) from the DISABLED_OPTIONS
-(see above).
-You have also to enable the MSS support since I have not integrated
-the AD1848 driver with the PSS one yet.
-
-2) /dev/music (/dev/sequencer2)
-
-This version has a new device file called /dev/music. I have not
-implemented all parts of it but it's there. It's only interesting if
-you are writing a sequencer program yourself. Enable by creating
-the device file /dev/music. Use the script at the end of linux/Readme
-
-3) /dev/midi##
-
-These are tty like raw devices for MIDI ports. Since there is a minor
-incompatibility between different versions of Linux, I have disabled
-this feature by default. You just need to create the device files yourself.
-
-4) Support for hardware based u-Law/A-Law and ADPCM formats.
-
-The AD1848 (and compatibles) are able to do compression and
-decompression by hardware. This version has experimental support
-for some of them. Currently they are implemented just in the
-AD1848 driver. The GUS MAX (and the 16 bit daughtercard) support
-also 16->4 bit ADPCM (the IMA one) but it don't work yet.
-The argument ioctl(SNDCTL_DSP_SAMPLESIZE) can have some new values
-in addition to the 8 and 16 supported earlier. Look at soundcard.h
-for more info.
-(In case somebody dares to ask: The ASP chip of SB16 is not supported
-so the hardware compression/decompression doesn't work with it. Also
-the ADPCM format is different than the standard (IMA) one (I guess).
-This feature is enabled by default.
-
-5) Real time fix to /dev/dsp and /dev/audio drivers
-
-The following feature should help game writers. This stuff is enabled
-by default.
----------------- cut here ---------------------
-There is a new ioctl called SNDCTL_DSP_SETFRAGMENT. It accepts a
-int parameter which has format 0x00nn00ss where the nn is max number of 
-buffer fragments (between 0x02 and 0xff) and the ss gives indirectly the 
-size of a buffer fragment (fragment_size = (1 << ss)). Valid sizes are 
-between (ss=0x07 -> 128 bytes and ss=0x11 (17 dec) -> 128k).
-
-This ioctl must be used ONCE between open() and first call to 
-read()/write() or ioctl(SNDCTL_DSP_GETBLKSIZE). 
-
-You need just to force the fragment size to a value which is sufficiently 
-short (gives the 1/20th of sec with the speed/#channels/#bits you are using).
-
-Using a small number of fragments offers (I guess) a significant advantage.
-For example with 2 fragments the driver works as the following (at least 
-I hope so). Assuming that the process writes exactly 'fragment_size' of 
-bytes each time (this is really important).
-
-       1) When the process writes the first fragment, it will be copied to
-       the DMA buffer area and the playback begins. The write() returns
-       immediately and the process is free to continue.
-
-
-       2a) If the fragment gets played before the application writes a new
-       one, the device will be stoppen and restarted which causes a click.
-       When the process calls write next time, it will be processes as 
-       in step 1.
-
-       2b) If the process calls write before the buffer underflows, the
-       data will be queued and the process is free to continue. (There
-       is now one full and one partially played fragment in the kernel
-       buffers. This gives average delay of 1.5*fragment_time (for 
-       example 1/20th sec) before the last byte in the buffer gets played.
-
-
-       3a) If the device gets both fragments played before the next write
-       (underflow), there will be a click. The write will be processed as
-       in step 1.
-
-       3b) If the 1st fragment gets played before next write (the process
-       calls write during playback of the second fragment), it will be
-       processed as step 2b.
-
-       3c) If the process writes 3rd fragment when there is already 2
-       fragments in the queue (1 playing and 1 waiting), the process
-       will block until the 1st fragment gets played. It will then be
-       woken up and it continues as in step 2b. This means that
-       the process blocks for at most the time required to play a
-       buffer fragment.
-
-This method syncronizes the process and the audio device together 
-automaticly. The process will block at most the 'fragment_time'. Usually 
-less, depending on how much it needs time to do other things. The maximum
-delay between writing a byte and the time when it finally plays is
-at most 3 times the 'fragment_time'. 
-
-The delay depends on how much time the program needs to do it's 
-computations for the next sample (updating screen etc). If it's about
-80% of the 'fragment_time' the game will run almost without delays. If it 
-uses more time, there is a risk that the audio buffer gets empty.
-       
-The application code should be something like the following:
-
-int frag = 0x00020008; /* 2 fragments of 2^8=256 bytes */
-int frag_size;
-
-int fd=open("/dev/dsp");
-ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag);
-ioctl(NDCTL_DSP_SPEED); /* And #channels & #bits if required */
-
-/*
- * Query the actual fragment sice since the driver may refuse
- * the requested one (unlikely but possible?)
- */
-
-ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &frag_size);
-
-while(True)
-{
-       do_computations();
-       write(fd, buf, frag_size);      /* Always the same size!!!!!!! */
-}
-
-I have tested this with a modified version of str.c. The algorithm works 
-as long as the playing program gets enough time to run. Hitting ENTER on 
-another virtual console causes a pause/click (with 2 frags of 64 bytes).
-
-NOTE! It's important to know that this call may be called just once and
-it must be done immediately after open(). The fragment size will remain
-in effect until the device is closed.
-------------------- cut here ---------------------
-
-6)     Detection and initialization code for Ensoniq Soundscape
-
-This version is able to initialize SoundScape (almost). However
-PCM recording and playback don't work. Also MIDI playback sounds wierd
-since the driver is not able to set volume controls properly.
-The soundscape support is disabled. You need to enable it by editing
-beginning of configure.c. Also read comments in sndscape/README.
-
-7)     select() support for /dev/audio and /dev/dsp. (/dev/midi## and
-       /dev/sequencer had it already in v2.90).
-
-There is now select() support in the audio/dsp driver (for Linux only).
-However I have not tried this feature yet. 
-There are also some new ioctl() calls (please look at soundcard.h).
-
-8)     MIDI recording in /dev/music (/dev/sequencer2)
-
-MIDI recording was earlier implemented only with full MPU-401 devices.
-This version has it also for dumb MIDI ports. However I have not tested it
-yet.
index 41dd9e46683854a3b4a74127c886703373fee687..85ffdd18075f329f48e0f103c13487642e06b109 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS)
+#if defined(CONFIG_GUS)
 
 #include "gus_hw.h"
 
@@ -64,7 +64,7 @@ attach_gus_card (long mem_start, struct address_info *hw_config)
       if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
        if (sound_alloc_dma (hw_config->dma2, "GUS(2)"))
          printk ("gus_card.c: Can't allocate DMA channel2\n");
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
       mem_start = gus_midi_init (mem_start);
 #endif
       return mem_start;
@@ -93,7 +93,7 @@ attach_gus_card (long mem_start, struct address_info *hw_config)
          if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
            if (sound_alloc_dma (hw_config->dma2, "GUS"))
              printk ("gus_card.c: Can't allocate DMA channel2\n");
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
          mem_start = gus_midi_init (mem_start);
 #endif
          return mem_start;
@@ -166,7 +166,7 @@ gusintr (int irq, struct pt_regs *dummy)
 
   sti ();
 
-#ifndef EXCLUDE_GUSMAX
+#ifdef CONFIG_GUSMAX
   if (have_gus_max)
     ad1848_interrupt (irq, NULL);
 #endif
@@ -183,16 +183,19 @@ gusintr (int irq, struct pt_regs *dummy)
 
       if (src & (MIDI_TX_IRQ | MIDI_RX_IRQ))
        {
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
          gus_midi_interrupt (0);
 #endif
        }
 
       if (src & (GF1_TIMER1_IRQ | GF1_TIMER2_IRQ))
        {
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
          if (gus_timer_enabled)
-           sound_timer_interrupt ();
+           {
+             sound_timer_interrupt ();
+           }
+
          gus_write8 (0x45, 0); /* Ack IRQ */
          gus_timer_command (4, 0x80);  /* Reset IRQ flags */
 
@@ -213,7 +216,7 @@ gusintr (int irq, struct pt_regs *dummy)
 /*
  * Some extra code for the 16 bit sampling option
  */
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS16)
+#if defined(CONFIG_GUS16)
 
 int
 probe_gus_db16 (struct address_info *hw_config)
@@ -224,8 +227,10 @@ probe_gus_db16 (struct address_info *hw_config)
 long
 attach_gus_db16 (long mem_start, struct address_info *hw_config)
 {
+#ifdef CONFIG_GUS
   gus_pcm_volume = 100;
   gus_wave_volume = 90;
+#endif
 
   ad1848_init ("GUS 16 bit sampling", hw_config->io_base,
               hw_config->irq,
index 10c8cc2c45825ab96c3f24c996b4d39fd7a393cc..b5879a90d5dcc19aad6d2b118e3afeef6ca3b585 100644 (file)
 
 #include "sound_config.h"
 
-#ifdef CONFIGURE_SOUNDCARD
-
 #include "gus_hw.h"
 
-#if !defined(EXCLUDE_GUS) && !defined(EXCLUDE_MIDI)
+#if defined(CONFIG_GUS) && defined(CONFIG_MIDI)
 
 static int      midi_busy = 0, input_opened = 0;
 static int      my_dev;
@@ -75,14 +73,8 @@ gus_midi_open (int dev, int mode,
       input_opened = 1;
     }
 
-  if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
-    {
-      gus_midi_control |= MIDI_ENABLE_XMIT;
-    }
 
-  outb (gus_midi_control, u_MidiControl);      /*
-                                                  * Enable
-                                                */
+  outb (gus_midi_control, u_MidiControl);      /* Enable */
 
   midi_busy = 1;
   qlen = qhead = qtail = output_used = 0;
@@ -276,37 +268,37 @@ gus_midi_interrupt (int dummy)
   save_flags (flags);
   cli ();
 
-  stat = GUS_MIDI_STATUS ();
-
-  if (stat & MIDI_RCV_FULL)
-    {
-      data = inb (u_MidiData);
-      if (input_opened)
-       midi_input_intr (my_dev, data);
-    }
-
-  if (stat & MIDI_XMIT_EMPTY)
+  while ((stat = GUS_MIDI_STATUS ()) & (MIDI_RCV_FULL | MIDI_XMIT_EMPTY))
     {
-      while (qlen && dump_to_midi (tmp_queue[qhead]))
+      if (stat & MIDI_RCV_FULL)
        {
-         qlen--;
-         qhead++;
+         data = inb (u_MidiData);
+         if (input_opened)
+           midi_input_intr (my_dev, data);
        }
 
-      if (!qlen)
+      if (stat & MIDI_XMIT_EMPTY)
        {
-         /*
-          * Disable Midi output interrupts, since no data in the buffer
-          */
-         gus_midi_control &= ~MIDI_ENABLE_XMIT;
-         outb (gus_midi_control, u_MidiControl);
+         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);
 }
 
 #endif
-
-#endif
index bddaad75bc038423b220d6e3562bd9d6273ebb25..f817da59fa7c39205d35fe0ac8096e4114499e61 100644 (file)
@@ -4,7 +4,7 @@
  * Greg Lee 1993.
  */
 #include "sound_config.h"
-#ifndef EXCLUDE_GUS
+#ifdef CONFIG_GUS
 #include "gus_linearvol.h"
 
 #define GUS_VOLUME     gus_wave_volume
index 944bc9124c53db55cfbad6b058e9158eb6d17f60..7ba2698efcb083f9d628a271c56a38701426b006 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/ultrasound.h>
 #include "gus_hw.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS)
+#if defined(CONFIG_GUS)
 
 #define MAX_SAMPLE     150
 #define MAX_PATCH      256
@@ -112,7 +112,7 @@ static int      gus_sampling_speed;
 static int      gus_sampling_channels;
 static int      gus_sampling_bits;
 
-static struct wait_queue *dram_sleeper = NULL;
+static wait_handle *dram_sleeper = NULL;
 static volatile struct snd_wait dram_sleep_flag =
 {0};
 
@@ -1734,11 +1734,11 @@ guswave_load_patch (int dev, int format, const snd_rw_buf * addr,
            unsigned long   tl;
 
            if (HZ)
-             current->timeout = tl = jiffies + (HZ);
+             current_set_timeout (tl = jiffies + (HZ));
            else
              tl = 0xffffffff;
            dram_sleep_flag.mode = WK_SLEEP;
-           interruptible_sleep_on (&dram_sleeper);
+           module_interruptible_sleep_on (&dram_sleeper);
            if (!(dram_sleep_flag.mode & WK_WAKEUP))
              {
                if (jiffies >= tl)
@@ -2829,7 +2829,7 @@ gus_default_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
                         SOUND_MASK_SYNTH|SOUND_MASK_PCM)
   if (((cmd >> 8) & 0xff) == 'M')
     {
-      if (cmd & IOC_IN)
+      if (_IOC_DIR (cmd) & _IOC_WRITE)
        switch (cmd & 0xff)
          {
          case SOUND_MIXER_RECSRC:
@@ -3052,7 +3052,7 @@ gus_wave_init (long mem_start, struct address_info *hw_config)
          model_num = "MAX";
          gus_type = 0x40;
          mixer_type = CS4231;
-#ifndef EXCLUDE_GUSMAX
+#ifdef CONFIG_GUSMAX
          {
            unsigned char   max_config = 0x40;  /* Codec enable */
 
@@ -3098,10 +3098,8 @@ gus_wave_init (long mem_start, struct address_info *hw_config)
        */
     }
 
-
-  printk (" <Gravis UltraSound %s (%dk)>", model_num, (int) gus_mem_size / 1024);
-
   sprintf (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
+  conf_printf (gus_info.name, hw_config);
 
   if (num_synths >= MAX_SYNTH_DEV)
     printk ("GUS Error: Too many synthesizers\n");
@@ -3109,7 +3107,7 @@ gus_wave_init (long mem_start, struct address_info *hw_config)
     {
       voice_alloc = &guswave_operations.alloc;
       synth_devs[num_synths++] = &guswave_operations;
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
       gus_tmr_install (gus_base + 8);
 #endif
     }
@@ -3157,7 +3155,7 @@ gus_wave_init (long mem_start, struct address_info *hw_config)
 void
 gus_wave_unload (void)
 {
-#ifndef EXCLUDE_GUSMAX
+#ifdef CONFIG_GUSMAX
   if (have_gus_max)
     {
       ad1848_unload (gus_base + 0x10c,
@@ -3389,7 +3387,7 @@ guswave_dma_irq (void)
        if ((dram_sleep_flag.mode & WK_SLEEP))
          {
            dram_sleep_flag.mode = WK_WAKEUP;
-           wake_up (&dram_sleeper);
+           module_wake_up (&dram_sleeper);
          };
        break;
 
@@ -3426,7 +3424,7 @@ guswave_dma_irq (void)
 
 }
 
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
 /*
  * Timer stuff
  */
@@ -3469,7 +3467,7 @@ arm_timer (int timer, unsigned int interval)
       gus_timer_command (0x04, 0x02);  /* Start timer 2 */
     }
 
-  gus_timer_enabled = 0;
+  gus_timer_enabled = 1;
 }
 
 static unsigned int
@@ -3510,6 +3508,7 @@ gus_tmr_restart (int dev)
     gus_write8 (0x45, 0x04);   /* Start timer 1 again */
   else
     gus_write8 (0x45, 0x08);   /* Start timer 2 again */
+  gus_timer_enabled = 1;
 }
 
 static struct sound_lowlev_timer gus_tmr =
index 1c11a43d8e8c8c6296004eeaf49b20463cbd8c63..6b0992c95ef4aee8e81bc2a6fe0a31e0fdaa574f 100644 (file)
@@ -28,7 +28,7 @@
  */
 
 #include "sound_config.h"
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS)
+#if defined(CONFIG_GUS)
 
 #include <linux/ultrasound.h>
 #include "gus_hw.h"
@@ -134,7 +134,7 @@ ics2101_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
 {
   if (((cmd >> 8) & 0xff) == 'M')
     {
-      if (cmd & IOC_IN)
+      if (_IOC_DIR (cmd) & _IOC_WRITE)
        switch (cmd & 0xff)
          {
          case SOUND_MIXER_RECSRC:
index ed89d909d17d261a4b12c3226569f946d43de137..80bfb2e4bebe74aaf539a8e7bfff2f2a290bbfbe 100644 (file)
@@ -72,7 +72,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MAD16)
+#if defined(CONFIG_MAD16)
 
 static int      already_initialized = 0;
 
@@ -451,7 +451,7 @@ attach_mad16_mpu (long mem_start, struct address_info *hw_config)
 {
   if (board_type < C929)       /* Early chip. No MPU support. Just SB MIDI */
     {
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
 
       if (mad_read (MC1_PORT) & 0x20)
        hw_config->io_base = 0x240;
@@ -464,7 +464,7 @@ attach_mad16_mpu (long mem_start, struct address_info *hw_config)
 #endif
     }
 
-#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
   if (!already_initialized)
     return mem_start;
 
@@ -477,7 +477,7 @@ attach_mad16_mpu (long mem_start, struct address_info *hw_config)
 int
 probe_mad16_mpu (struct address_info *hw_config)
 {
-#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
   static int      mpu_attached = 0;
   static int      valid_ports[] =
   {0x330, 0x320, 0x310, 0x300};
@@ -497,7 +497,7 @@ probe_mad16_mpu (struct address_info *hw_config)
   if (board_type < C929)       /* Early chip. No MPU support. Just SB MIDI */
     {
 
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
       unsigned char   tmp;
 
       tmp = mad_read (MC3_PORT);
@@ -597,7 +597,15 @@ unload_mad16 (struct address_info *hw_config)
 void
 unload_mad16_mpu (struct address_info *hw_config)
 {
-#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+#ifdef CONFIG_MIDI
+  if (board_type < C929)       /* Early chip. No MPU support. Just SB MIDI */
+    {
+      mad16_sb_dsp_unload (hw_config);
+      return;
+    }
+#endif
+
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
   unload_mpu401 (hw_config);
 #endif
 }
index d6b66f8db7bb2f6391508d30dfcea75bc0ecedc2..565b8ed8047ad14a47f8a8e3ac24fd192546f389 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MAD16) && !defined(EXCLUDE_MIDI)
+#if defined(CONFIG_MAD16) && defined(CONFIG_MIDI)
 
 #define sbc_base mad16_sb_base
 #include "sb.h"
@@ -39,6 +39,7 @@ static int      my_dev;
 static int      mad16_sb_base = 0x220;
 static int      mad16_sb_irq = 0;
 static int      mad16_sb_dsp_ok = 0;
+static int      mad16_sb_dsp_attached = 0;
 static sound_os_info *midi_osp;
 
 int             mad16_sb_midi_mode = NORMAL_MIDI;
@@ -111,11 +112,11 @@ mad16_sb_reset_dsp (void)
   int             loopc;
 
   outb (1, DSP_RESET);
-  tenmicrosec ();
+  tenmicrosec (midi_osp);
   outb (0, DSP_RESET);
-  tenmicrosec ();
-  tenmicrosec ();
-  tenmicrosec ();
+  tenmicrosec (midi_osp);
+  tenmicrosec (midi_osp);
+  tenmicrosec (midi_osp);
 
   for (loopc = 0; loopc < 1000 && !(inb (DSP_DATA_AVAIL) & 0x80); loopc++);    /*
                                                                                   * Wait
@@ -165,6 +166,7 @@ mad16_sb_dsp_init (long mem_start, struct address_info *hw_config)
  * mad16_sb_midi_init -- everything else is done elsewhere */
 {
 
+  mad16_sb_dsp_attached = 1;
   midi_osp = hw_config->osp;
   if (snd_set_irq_handler (mad16_sb_irq, mad16_sbintr, "MAD16 SB MIDI", midi_osp) < 0)
     {
@@ -174,13 +176,23 @@ mad16_sb_dsp_init (long mem_start, struct address_info *hw_config)
 
   request_region (hw_config->io_base, 16, "mad16/Mozart MIDI");
 
-  printk (" <MAD16 MIDI (SB mode)>");
+  conf_printf ("MAD16 MIDI (SB mode)", hw_config);
   mad16_sb_midi_init (2);
 
   mad16_sb_dsp_ok = 1;
   return mem_start;
 }
 
+void
+mad16_sb_dsp_unload (struct address_info *hw_config)
+{
+  if (!mad16_sb_dsp_attached)
+    return;
+
+  release_region (hw_config->io_base, 16);
+  snd_release_irq (hw_config->irq);
+}
+
 static int
 mad16_sb_midi_open (int dev, int mode,
                    void            (*input) (int dev, unsigned char data),
index 45ec04283ec8d19472fa2ba2394b4c53d112157d..4b1096ee51db1f090f75c9a268a2c966f8b55077 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MAUI)
+#if defined(CONFIG_MAUI)
 
 static int      maui_base = 0x330;
 
@@ -191,13 +191,16 @@ probe_maui (struct address_info *hw_config)
       return 0;
     }
 
-  printk ("WaveFront hardware version %d.%d\n", tmp1, tmp2);
+  if (trace_init)
+    printk ("WaveFront hardware version %d.%d\n", tmp1, tmp2);
 
   if (!maui_write (0x9F))      /* Report firmware version */
     return 0;
   if ((tmp1 = maui_read ()) == -1 || (tmp2 = maui_read ()) == -1)
     return 0;
-  printk ("WaveFront firmware version %d.%d\n", tmp1, tmp2);
+
+  if (trace_init)
+    printk ("WaveFront firmware version %d.%d\n", tmp1, tmp2);
 
   if (!maui_write (0x85))      /* Report free DRAM */
     return 0;
@@ -206,7 +209,8 @@ probe_maui (struct address_info *hw_config)
     {
       tmp1 |= maui_read () << (7 * i);
     }
-  printk ("Available DRAM %dk\n", tmp1 / 1024);
+  if (trace_init)
+    printk ("Available DRAM %dk\n", tmp1 / 1024);
 
   request_region (hw_config->io_base + 2, 6, "Maui");
 
@@ -222,7 +226,7 @@ attach_maui (long mem_start, struct address_info *hw_config)
 {
   int             this_dev = num_midis;
 
-  printk (" <Maui>");
+  conf_printf ("Maui", hw_config);
 
   hw_config->irq *= -1;
   mem_start = attach_mpu401 (mem_start, hw_config);
index 39680e28c46ef7d59b5374f83bad9f1fe6b01dac..b396af8860b7c22592ecddb39f503250bc6d175a 100644 (file)
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MIDI)
+#if defined(CONFIG_MIDI)
 
 #define _MIDI_SYNTH_C_
 
-static struct wait_queue *sysex_sleeper = NULL;
+static wait_handle *sysex_sleeper = NULL;
 static volatile struct snd_wait sysex_sleep_flag =
 {0};
 
@@ -47,7 +47,7 @@ static int      sysex_state[MAX_MIDI_DEV] =
 {0};
 static unsigned char prev_out_status[MAX_MIDI_DEV];
 
-#ifdef EXCLUDE_SEQUENCER
+#ifndef CONFIG_SEQUENCER
 #define STORE(cmd)
 #else
 #define STORE(cmd) \
@@ -472,6 +472,8 @@ midi_synth_open (int dev, int mode)
   inc->m_prev_status = 0x00;
   restore_flags (flags);
 
+  sysex_sleep_flag.mode = WK_NONE;
+
   return 1;
 }
 
@@ -545,7 +547,7 @@ midi_synth_load_patch (int dev, int format, const snd_rw_buf * addr,
 
   sysex_sleep_flag.mode = WK_NONE;
 
-  for (i = 0; i < left && !(current->signal & ~current->blocked); i++)
+  for (i = 0; i < left && !current_got_fatal_signal (); i++)
     {
       unsigned char   data;
 
@@ -566,17 +568,17 @@ midi_synth_load_patch (int dev, int format, const snd_rw_buf * addr,
        }
 
       while (!midi_devs[orig_dev]->putc (orig_dev, (unsigned char) (data & 0xff)) &&
-            !(current->signal & ~current->blocked))
+            !current_got_fatal_signal ())
 
        {
          unsigned long   tl;
 
          if (1)
-           current->timeout = tl = jiffies + (1);
+           current_set_timeout (tl = jiffies + (1));
          else
            tl = 0xffffffff;
          sysex_sleep_flag.mode = WK_SLEEP;
-         interruptible_sleep_on (&sysex_sleeper);
+         module_interruptible_sleep_on (&sysex_sleeper);
          if (!(sysex_sleep_flag.mode & WK_WAKEUP))
            {
              if (jiffies >= tl)
@@ -638,8 +640,8 @@ midi_synth_controller (int dev, int channel, int ctrl_num, int value)
   int             orig_dev = synth_devs[dev]->midi_dev;
   int             chn, msg;
 
-  if (ctrl_num < 1 || ctrl_num > 127)
-    return;                    /* NOTE! Controller # 0 ignored */
+  if (ctrl_num < 0 || ctrl_num > 127)
+    return;
   if (channel < 0 || channel > 15)
     return;
 
index 6256ea41ee6faeed107cbe495046f56ea0309050..55386c45567727a646c6935cb2247110316f483c 100644 (file)
@@ -15,7 +15,6 @@ void midi_synth_controller (int dev, int channel, int ctrl_num, int value);
 int midi_synth_patchmgr (int dev, struct patmgr_info *rec);
 void midi_synth_bender (int dev, int chn, int value);
 void midi_synth_setup_voice (int dev, int voice, int chn);
-void do_midi_msg (int synthno, unsigned char *msg, int mlen);
 int midi_synth_send_sysex(int dev, unsigned char *bytes,int len);
 
 #ifndef _MIDI_SYNTH_C_
index c1618a12c1d2991bf30106978bf5ffb587dded0f..9270cafff93069f2f23045fdbd8c2ce4a0d0da57 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MIDI)
+#if defined(CONFIG_MIDI)
 
 /*
  * Don't make MAX_QUEUE_SIZE larger than 4000
 
 #define MAX_QUEUE_SIZE 4000
 
-static struct wait_queue *midi_sleeper[MAX_MIDI_DEV] =
+static wait_handle *midi_sleeper[MAX_MIDI_DEV] =
 {NULL};
 static volatile struct snd_wait midi_sleep_flag[MAX_MIDI_DEV] =
 {
   {0}};
-static struct wait_queue *input_sleeper[MAX_MIDI_DEV] =
+static wait_handle *input_sleeper[MAX_MIDI_DEV] =
 {NULL};
 static volatile struct snd_wait input_sleep_flag[MAX_MIDI_DEV] =
 {
@@ -106,18 +106,18 @@ drain_midi_queue (int dev)
    */
 
   if (midi_devs[dev]->buffer_status != NULL)
-    while (!(current->signal & ~current->blocked) &&
+    while (!current_got_fatal_signal () &&
           midi_devs[dev]->buffer_status (dev))
 
       {
        unsigned long   tl;
 
        if (HZ / 10)
-         current->timeout = tl = jiffies + (HZ / 10);
+         current_set_timeout (tl = jiffies + (HZ / 10));
        else
          tl = 0xffffffff;
        midi_sleep_flag[dev].mode = WK_SLEEP;
-       interruptible_sleep_on (&midi_sleeper[dev]);
+       module_interruptible_sleep_on (&midi_sleeper[dev]);
        if (!(midi_sleep_flag[dev].mode & WK_WAKEUP))
          {
            if (jiffies >= tl)
@@ -146,7 +146,7 @@ midi_input_intr (int dev, unsigned char data)
       if ((input_sleep_flag[dev].mode & WK_SLEEP))
        {
          input_sleep_flag[dev].mode = WK_WAKEUP;
-         wake_up (&input_sleeper[dev]);
+         module_wake_up (&input_sleeper[dev]);
        };
     }
 
@@ -185,7 +185,7 @@ midi_poll (unsigned long dummy)
                (midi_sleep_flag[dev].mode & WK_SLEEP))
              {
                midi_sleep_flag[dev].mode = WK_WAKEUP;
-               wake_up (&midi_sleeper[dev]);
+               module_wake_up (&midi_sleeper[dev]);
              };
          }
 
@@ -203,7 +203,6 @@ int
 MIDIbuf_open (int dev, struct fileinfo *file)
 {
   int             mode, err;
-  unsigned long   flags;
 
   dev = dev >> 4;
   mode = file->mode & O_ACCMODE;
@@ -224,27 +223,20 @@ MIDIbuf_open (int dev, struct fileinfo *file)
      *    Interrupts disabled. Be careful
    */
 
-  save_flags (flags);
-  cli ();
   if ((err = midi_devs[dev]->open (dev, mode,
                                   midi_input_intr, midi_output_intr)) < 0)
     {
-      restore_flags (flags);
       return err;
     }
 
   parms[dev].prech_timeout = 0;
 
-  midi_sleep_flag[dev].mode = WK_NONE;
-  input_sleep_flag[dev].mode = WK_NONE;
-
   midi_in_buf[dev] = (struct midi_buf *) kmalloc (sizeof (struct midi_buf), GFP_KERNEL);
 
   if (midi_in_buf[dev] == NULL)
     {
       printk ("midi: Can't allocate buffer\n");
       midi_devs[dev]->close (dev);
-      restore_flags (flags);
       return -EIO;
     }
   midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
@@ -257,20 +249,23 @@ MIDIbuf_open (int dev, struct fileinfo *file)
       midi_devs[dev]->close (dev);
       kfree (midi_in_buf[dev]);
       midi_in_buf[dev] = NULL;
-      restore_flags (flags);
       return -EIO;
     }
   midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
-  if (!open_devs)
+  open_devs++;
 
+  midi_sleep_flag[dev].mode = WK_NONE;
+  input_sleep_flag[dev].mode = WK_NONE;
+
+  if (open_devs < 2)           /* This was first open */
     {
-      poll_timer.expires = (1) + jiffies;
-      add_timer (&poll_timer);
-    };                         /*
-                                  * Come back later
-                                */
-  open_devs++;
-  restore_flags (flags);
+      ;
+
+      {
+       poll_timer.expires = (1) + jiffies;
+       add_timer (&poll_timer);
+      };                       /* Start polling */
+    }
 
   return err;
 }
@@ -284,6 +279,9 @@ MIDIbuf_release (int dev, struct fileinfo *file)
   dev = dev >> 4;
   mode = file->mode & O_ACCMODE;
 
+  if (dev < 0 || dev >= num_midis)
+    return;
+
   save_flags (flags);
   cli ();
 
@@ -298,18 +296,18 @@ MIDIbuf_release (int dev, struct fileinfo *file)
                                                   * devices
                                                 */
 
-      while (!(current->signal & ~current->blocked) &&
+      while (!current_got_fatal_signal () &&
             DATA_AVAIL (midi_out_buf[dev]))
 
        {
          unsigned long   tl;
 
          if (0)
-           current->timeout = tl = jiffies + (0);
+           current_set_timeout (tl = jiffies + (0));
          else
            tl = 0xffffffff;
          midi_sleep_flag[dev].mode = WK_SLEEP;
-         interruptible_sleep_on (&midi_sleeper[dev]);
+         module_interruptible_sleep_on (&midi_sleeper[dev]);
          if (!(midi_sleep_flag[dev].mode & WK_WAKEUP))
            {
              if (jiffies >= tl)
@@ -325,14 +323,17 @@ MIDIbuf_release (int dev, struct fileinfo *file)
                                 */
     }
 
+  restore_flags (flags);
+
   midi_devs[dev]->close (dev);
+
   kfree (midi_in_buf[dev]);
   kfree (midi_out_buf[dev]);
   midi_in_buf[dev] = NULL;
   midi_out_buf[dev] = NULL;
+  if (open_devs < 2)
+    del_timer (&poll_timer);;
   open_devs--;
-  del_timer (&poll_timer);;
-  restore_flags (flags);
 }
 
 int
@@ -365,11 +366,11 @@ MIDIbuf_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count
            unsigned long   tl;
 
            if (0)
-             current->timeout = tl = jiffies + (0);
+             current_set_timeout (tl = jiffies + (0));
            else
              tl = 0xffffffff;
            midi_sleep_flag[dev].mode = WK_SLEEP;
-           interruptible_sleep_on (&midi_sleeper[dev]);
+           module_interruptible_sleep_on (&midi_sleeper[dev]);
            if (!(midi_sleep_flag[dev].mode & WK_WAKEUP))
              {
                if (jiffies >= tl)
@@ -377,7 +378,7 @@ MIDIbuf_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count
              }
            midi_sleep_flag[dev].mode &= ~WK_SLEEP;
          };
-         if ((current->signal & ~current->blocked))
+         if (current_got_fatal_signal ())
            {
              restore_flags (flags);
              return -EINTR;
@@ -424,11 +425,11 @@ MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
        unsigned long   tl;
 
        if (parms[dev].prech_timeout)
-         current->timeout = tl = jiffies + (parms[dev].prech_timeout);
+         current_set_timeout (tl = jiffies + (parms[dev].prech_timeout));
        else
          tl = 0xffffffff;
        input_sleep_flag[dev].mode = WK_SLEEP;
-       interruptible_sleep_on (&input_sleeper[dev]);
+       module_interruptible_sleep_on (&input_sleeper[dev]);
        if (!(input_sleep_flag[dev].mode & WK_WAKEUP))
          {
            if (jiffies >= tl)
@@ -436,7 +437,7 @@ MIDIbuf_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
          }
        input_sleep_flag[dev].mode &= ~WK_SLEEP;
       };
-      if ((current->signal & ~current->blocked))
+      if (current_got_fatal_signal ())
        c = -EINTR;             /*
                                   * The user is getting restless
                                 */
@@ -501,7 +502,7 @@ MIDIbuf_ioctl (int dev, struct fileinfo *file,
 }
 
 int
-MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
+MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
 {
   dev = dev >> 4;
 
@@ -511,7 +512,7 @@ MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wai
       if (!DATA_AVAIL (midi_in_buf[dev]))
        {
          input_sleep_flag[dev].mode = WK_SLEEP;
-         select_wait (&input_sleeper[dev], wait);
+         module_select_wait (&input_sleeper[dev], wait);
          return 0;
        }
       return 1;
@@ -521,7 +522,7 @@ MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wai
       if (SPACE_AVAIL (midi_out_buf[dev]))
        {
          midi_sleep_flag[dev].mode = WK_SLEEP;
-         select_wait (&midi_sleeper[dev], wait);
+         module_select_wait (&midi_sleeper[dev], wait);
          return 0;
        }
       return 1;
index df9fa738df80060563c3878b244d0dc512e8b06e..d4507ee266d1cab84ccbf183a6e0056397105190 100644 (file)
 
 #include "sound_config.h"
 
-#ifdef CONFIGURE_SOUNDCARD
-
-#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
 #include "coproc.h"
 
 static int      init_sequence[20];     /* NOTE! pos 0 = len, start pos 1. */
 
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
 static int      timer_mode = TMR_INTERNAL, timer_caps = TMR_INTERNAL;
 
 #endif
@@ -122,7 +120,7 @@ static void     mpu_timer_interrupt (void);
 static void     timer_ext_event (struct mpu_config *devc, int event, int parm);
 
 static struct synth_info mpu_synth_info_proto =
-{"MPU-401 MIDI interface", 0, SYNTH_TYPE_MIDI, 0, 0, 128, 0, 128, SYNTH_CAP_INPUT};
+{"MPU-401 MIDI interface", 0, SYNTH_TYPE_MIDI, MIDI_TYPE_MPU401, 0, 128, 0, 128, SYNTH_CAP_INPUT};
 
 static struct synth_info mpu_synth_info[MAX_MIDI_DEV];
 
@@ -153,7 +151,7 @@ static unsigned char len_tab[] =    /* # of data bytes following a status
   0                            /* Fx */
 };
 
-#ifdef EXCLUDE_SEQUENCER
+#ifndef CONFIG_SEQUENCER
 #define STORE(cmd)
 #else
 #define STORE(cmd) \
@@ -576,11 +574,11 @@ mpu401_out (int dev, unsigned char midi_byte)
   devc = &dev_conf[dev];
 
   /*
-   * Sometimes it takes about 13000 loops before the output becomes ready
+   * Sometimes it takes about 30000 loops before the output becomes ready
    * (After reset). Normally it takes just about 10 loops.
    */
 
-  for (timeout = 3000; timeout > 0 && !output_ready (devc); timeout--);
+  for (timeout = 30000; timeout > 0 && !output_ready (devc); timeout--);
 
   save_flags (flags);
   cli ();
@@ -919,6 +917,7 @@ mpu_synth_open (int dev, int mode)
     {
       mpu_cmd (midi_dev, 0x8B, 0);     /* Enable data in stop mode */
       mpu_cmd (midi_dev, 0x34, 0);     /* Return timing bytes in stop mode */
+      mpu_cmd (midi_dev, 0x87, 0);     /* Enable pitch & controller */
     }
 
   return 0;
@@ -1129,9 +1128,6 @@ attach_mpu401 (long mem_start, struct address_info *hw_config)
        MPU_CAP_CLS | MPU_CAP_2PORT;
 
       revision_char = (devc->revision == 0x7f) ? 'M' : ' ';
-      printk (" <MQX-%d%c MIDI Interface>",
-             ports,
-             revision_char);
       sprintf (mpu_synth_info[num_midis].name,
               "MQX-%d%c MIDI Interface #%d",
               ports,
@@ -1147,10 +1143,6 @@ attach_mpu401 (long mem_start, struct address_info *hw_config)
 
       devc->capabilities |= MPU_CAP_SYNC | MPU_CAP_FSK;
 
-      printk (" <MPU-401 MIDI Interface %d.%d%c>",
-             (int) (devc->version & 0xf0) >> 4,
-             devc->version & 0x0f,
-             revision_char);
       sprintf (mpu_synth_info[num_midis].name,
               "MPU-401 %d.%d%c Midi interface #%d",
               (int) (devc->version & 0xf0) >> 4,
@@ -1162,6 +1154,8 @@ attach_mpu401 (long mem_start, struct address_info *hw_config)
   strcpy (mpu401_midi_operations[num_midis].info.name,
          mpu_synth_info[num_midis].name);
 
+  conf_printf (mpu_synth_info[num_midis].name, hw_config);
+
   mpu401_synth_operations[num_midis]->midi_dev = devc->devno = num_midis;
   mpu401_synth_operations[devc->devno]->info =
     &mpu_synth_info[devc->devno];
@@ -1273,7 +1267,7 @@ probe_mpu401 (struct address_info *hw_config)
   tmp_devc.opened = 0;
   tmp_devc.osp = hw_config->osp;
 
-#if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_MPU401)
+#if defined(CONFIG_AEDSP16) && defined(AEDSP16_MPU401)
   /*
      * Initialize Audio Excel DSP 16 to MPU-401, before any operation.
    */
@@ -1311,7 +1305,7 @@ unload_mpu401 (struct address_info *hw_config)
  *      Timer stuff
  ****************************************************/
 
-#if !defined(EXCLUDE_SEQUENCER)
+#if defined(CONFIG_SEQUENCER)
 
 static volatile int timer_initialized = 0, timer_open = 0, tmr_running = 0;
 static volatile int curr_tempo, curr_timebase, hw_timebase;
@@ -1828,6 +1822,4 @@ mpu_timer_init (int midi_dev)
 
 
 
-#endif
-
 #endif
index ec47ef6597c353f3ed15d17c43fa2fe47d80ad69..0a1de665db0e2f09e70611134366bd7214ee47e0 100644 (file)
@@ -36,7 +36,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_YM3812)
+#if defined(CONFIG_YM3812)
 
 #include "opl3.h"
 
@@ -226,7 +226,7 @@ opl3_detect (int ioaddr, sound_os_info * osp)
    */
 
   for (i = 0; i < 50; i++)
-    tenmicrosec ();
+    tenmicrosec (devc->osp);
 
   stat2 = inb (ioaddr);                /*
                                   * Read status after timers have expired
@@ -281,18 +281,18 @@ opl3_detect (int ioaddr, sound_os_info * osp)
          int             tmp;
 
          outb (0x02, ioaddr - 8);      /* Select OPL4 ID register */
-         tenmicrosec ();
+         tenmicrosec (devc->osp);
          tmp = inb (ioaddr - 7);       /* Read it */
-         tenmicrosec ();
+         tenmicrosec (devc->osp);
 
          if (tmp == 0x20)      /* OPL4 should return 0x20 here */
            {
              detected_model = 4;
 
              outb (0xF8, ioaddr - 8);  /* Select OPL4 FM mixer control */
-             tenmicrosec ();
+             tenmicrosec (devc->osp);
              outb (0x1B, ioaddr - 7);  /* Write value */
-             tenmicrosec ();
+             tenmicrosec (devc->osp);
            }
          else
            detected_model = 3;
@@ -775,7 +775,7 @@ opl3_command (int io_addr, unsigned int addr, unsigned int val)
   outb ((unsigned char) (addr & 0xff), io_addr);
 
   if (!devc->model != 2)
-    tenmicrosec ();
+    tenmicrosec (devc->osp);
   else
     for (i = 0; i < 2; i++)
       inb (io_addr);
@@ -784,9 +784,9 @@ opl3_command (int io_addr, unsigned int addr, unsigned int val)
 
   if (devc->model != 2)
     {
-      tenmicrosec ();
-      tenmicrosec ();
-      tenmicrosec ();
+      tenmicrosec (devc->osp);
+      tenmicrosec (devc->osp);
+      tenmicrosec (devc->osp);
     }
   else
     for (i = 0; i < 2; i++)
@@ -1222,9 +1222,9 @@ opl3_init (long mem_start, int ioaddr, sound_os_info * osp)
   if (devc->model == 2)
     {
       if (devc->is_opl4)
-       printk (" <Yamaha OPL4/OPL3 FM>");
+       conf_printf2 ("Yamaha OPL4/OPL3 FM", ioaddr, 0, -1, -1);
       else
-       printk (" <Yamaha OPL-3 FM>");
+       conf_printf2 ("Yamaha OPL3 FM", ioaddr, 0, -1, -1);
 
       devc->v_alloc->max_voice = devc->nr_voice = 18;
       devc->fm_info.nr_drums = 0;
@@ -1242,7 +1242,7 @@ opl3_init (long mem_start, int ioaddr, sound_os_info * osp)
     }
   else
     {
-      printk (" <Yamaha 2-OP FM>");
+      conf_printf2 ("Yamaha OPL2 FM", ioaddr, 0, -1, -1);
       devc->v_alloc->max_voice = devc->nr_voice = 9;
       devc->fm_info.nr_drums = 0;
 
index b8de01c29b45c6cc3d352cecce28c96585ef1ed8..07e39c66e1eb2764a979df6aebe8739b7baa507f 100644 (file)
@@ -1,7 +1,18 @@
+
 #define ALLOW_SELECT
-#undef ALLOW_BUFFER_MAPPING
 #undef NO_INLINE_ASM
-#undef SHORT_BANNERS
+#define SHORT_BANNERS
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/version.h>
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#endif
 
 #include <linux/param.h>
 #include <linux/types.h>
@@ -22,6 +33,7 @@
 #include <linux/string.h>
 #include <linux/ioport.h>
 
+#include <linux/wrapper.h>
 
 #include <linux/soundcard.h>
 
@@ -46,3 +58,5 @@ extern caddr_t sound_mem_blocks[1024];
 extern int sound_num_blocks;
 
 typedef int sound_os_info;
+
+#undef PSEUDO_DMA_AUTOINIT
index 2d05dd422924ffc1701d92c4c078ae37238887dc..c9917052cf65c6c7c39c0086e390ba5438f20f02 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PAS)
+#if defined(CONFIG_PAS)
 
 #define DEFINE_TRANSLATIONS
 #include "pas.h"
@@ -93,14 +93,14 @@ pasintr (int irq, struct pt_regs *dummy)
 
   if (status & I_S_PCM_SAMPLE_BUFFER_IRQ)
     {
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
       pas_pcm_interrupt (status, 1);
 #endif
       status &= ~I_S_PCM_SAMPLE_BUFFER_IRQ;
     }
   if (status & I_S_MIDI_IRQ)
     {
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
       pas_midi_interrupt ();
 #endif
       status &= ~I_S_MIDI_IRQ;
@@ -259,7 +259,7 @@ config_pas_hw (struct address_info *hw_config)
   mix_write (P_M_MV508_ADDRESS | 5, PARALLEL_MIXER);
   mix_write (5, PARALLEL_MIXER);
 
-#if !defined(EXCLUDE_SB_EMULATION) && !defined(EXCLUDE_SB)
+#if defined(CONFIG_SB_EMULATION) && defined(CONFIG_SB)
 
   {
     struct address_info *sb_config;
@@ -369,17 +369,22 @@ attach_pas_card (long mem_start, struct address_info *hw_config)
 
       if ((pas_model = pas_read (CHIP_REV)))
        {
-         printk (" <%s rev %d>", pas_model_names[(int) pas_model], pas_read (BOARD_REV_ID));
+         char            temp[100];
+
+         sprintf (temp,
+                  "%s rev %d", pas_model_names[(int) pas_model],
+                  pas_read (BOARD_REV_ID));
+         conf_printf (temp, hw_config);
        }
 
       if (config_pas_hw (hw_config))
        {
 
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
          mem_start = pas_pcm_init (mem_start, hw_config);
 #endif
 
-#if !defined(EXCLUDE_SB_EMULATION) && !defined(EXCLUDE_SB)
+#if defined(CONFIG_SB_EMULATION) && defined(CONFIG_SB)
 
          sb_dsp_disable_midi ();       /*
                                         * The SB emulation don't support *
@@ -388,7 +393,7 @@ attach_pas_card (long mem_start, struct address_info *hw_config)
 #endif
 
 
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
          mem_start = pas_midi_init (mem_start);
 #endif
 
index 6ed91a83cad7de0102df681644b35a2169f2bee4..690773d395a70ca8e6df4de32baee26389cb2411 100644 (file)
 
 #include "sound_config.h"
 
-#ifdef CONFIGURE_SOUNDCARD
-
 #include "pas.h"
 
-#if !defined(EXCLUDE_PAS) && !defined(EXCLUDE_MIDI)
+#if defined(CONFIG_PAS) && defined(CONFIG_MIDI)
 
 static int      midi_busy = 0, input_opened = 0;
 static int      my_dev;
@@ -337,5 +335,3 @@ pas_midi_interrupt (void)
 }
 
 #endif
-
-#endif
index d186f69d3f184f70eade52cc3e2600e104ef90d0..851091da3844cc472ecd65b47f5ceddfba23302e 100644 (file)
@@ -31,7 +31,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PAS)
+#if defined(CONFIG_PAS)
 
 #include "pas.h"
 
@@ -264,7 +264,7 @@ pas_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
 
   if (((cmd >> 8) & 0xff) == 'M')
     {
-      if (cmd & IOC_IN)
+      if (_IOC_DIR (cmd) & _IOC_WRITE)
        return snd_ioctl_return ((int *) arg, pas_mixer_set (cmd & 0xff, get_fs_long ((long *) arg)));
       else
        {                       /*
index cfe3eb6e9363feaa209ff985c3b59e661e7f8cf1..b4a185843680f2109d626012c1efa0bf45a3eea6 100644 (file)
 
 #include "sound_config.h"
 
-#ifdef CONFIGURE_SOUNDCARD
-
 #include "pas.h"
 
-#if !defined(EXCLUDE_PAS) && !defined(EXCLUDE_AUDIO)
+#if defined(CONFIG_PAS) && defined(CONFIG_AUDIO)
 
 #define TRACE(WHAT)            /*
                                   * * * (WHAT)   */
@@ -446,5 +444,3 @@ pas_pcm_interrupt (unsigned char status, int cause)
 }
 
 #endif
-
-#endif
index fd0568a2934d6ce55dd90fd49c5fe4e525418fe3..7456d31d07e04db5317438a4a5faaaced3ad0076 100644 (file)
@@ -30,9 +30,9 @@
 #define PATMGR_C
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SEQUENCER)
+#if defined(CONFIG_SEQUENCER)
 
-static struct wait_queue *server_procs[MAX_SYNTH_DEV] =
+static wait_handle *server_procs[MAX_SYNTH_DEV] =
 {NULL};
 static volatile struct snd_wait server_wait_flag[MAX_SYNTH_DEV] =
 {
@@ -49,7 +49,7 @@ static int      pmgr_opened[MAX_SYNTH_DEV] =
 #define A_TO_S 1
 #define S_TO_A         2
 
-static struct wait_queue *appl_proc = NULL;
+static wait_handle *appl_proc = NULL;
 static volatile struct snd_wait appl_wait_flag =
 {0};
 
@@ -83,7 +83,7 @@ pmgr_release (int dev)
       if ((appl_wait_flag.mode & WK_SLEEP))
        {
          appl_wait_flag.mode = WK_WAKEUP;
-         wake_up (&appl_proc);
+         module_wake_up (&appl_proc);
        };
     }
 
@@ -102,31 +102,18 @@ pmgr_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
       return -EIO;
     }
 
-  while (!ok && !(current->signal & ~current->blocked))
+  while (!ok && !current_got_fatal_signal ())
     {
       save_flags (flags);
       cli ();
 
       while (!(mbox[dev] && msg_direction[dev] == A_TO_S) &&
-            !(current->signal & ~current->blocked))
+            !current_got_fatal_signal ())
        {
 
-         {
-           unsigned long   tl;
-
-           if (0)
-             current->timeout = tl = jiffies + (0);
-           else
-             tl = 0xffffffff;
-           server_wait_flag[dev].mode = WK_SLEEP;
-           interruptible_sleep_on (&server_procs[dev]);
-           if (!(server_wait_flag[dev].mode & WK_WAKEUP))
-             {
-               if (jiffies >= tl)
-                 server_wait_flag[dev].mode |= WK_TIMEOUT;
-             }
-           server_wait_flag[dev].mode &= ~WK_SLEEP;
-         };
+         server_wait_flag[dev].mode = WK_SLEEP;
+         module_interruptible_sleep_on (&server_procs[dev]);
+         server_wait_flag[dev].mode &= ~WK_SLEEP;;
        }
 
       if (mbox[dev] && msg_direction[dev] == A_TO_S)
@@ -193,7 +180,7 @@ pmgr_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int count)
        {
          {
            appl_wait_flag.mode = WK_WAKEUP;
-           wake_up (&appl_proc);
+           module_wake_up (&appl_proc);
          };
        }
     }
@@ -224,27 +211,14 @@ pmgr_access (int dev, struct patmgr_info *rec)
        {
          {
            server_wait_flag[dev].mode = WK_WAKEUP;
-           wake_up (&server_procs[dev]);
+           module_wake_up (&server_procs[dev]);
          };
        }
 
 
-      {
-       unsigned long   tl;
-
-       if (0)
-         current->timeout = tl = jiffies + (0);
-       else
-         tl = 0xffffffff;
-       appl_wait_flag.mode = WK_SLEEP;
-       interruptible_sleep_on (&appl_proc);
-       if (!(appl_wait_flag.mode & WK_WAKEUP))
-         {
-           if (jiffies >= tl)
-             appl_wait_flag.mode |= WK_TIMEOUT;
-         }
-       appl_wait_flag.mode &= ~WK_SLEEP;
-      };
+      appl_wait_flag.mode = WK_SLEEP;
+      module_interruptible_sleep_on (&appl_proc);
+      appl_wait_flag.mode &= ~WK_SLEEP;;
 
       if (msg_direction[dev] != S_TO_A)
        {
@@ -274,9 +248,19 @@ pmgr_inform (int dev, int event, unsigned long p1, unsigned long p2,
   unsigned long   flags;
   int             err = 0;
 
+  struct patmgr_info *tmp_mbox;
+
   if (!pmgr_opened[dev])
     return 0;
 
+  tmp_mbox = (struct patmgr_info *) kmalloc (sizeof (struct patmgr_info), GFP_KERNEL);
+
+  if (tmp_mbox == NULL)
+    {
+      printk ("pmgr: Couldn't allocate memory for a message\n");
+      return 0;
+    }
+
   save_flags (flags);
   cli ();
 
@@ -284,13 +268,8 @@ pmgr_inform (int dev, int event, unsigned long p1, unsigned long p2,
     printk ("  PATMGR: Server %d mbox full. Why?\n", dev);
   else
     {
-      if ((mbox[dev] =
-          (struct patmgr_info *) kmalloc (sizeof (struct patmgr_info), GFP_KERNEL)) == NULL)
-       {
-         printk ("pmgr: Couldn't allocate memory for a message\n");
-         return 0;
-       }
 
+      mbox[dev] = tmp_mbox;
       mbox[dev]->key = PM_K_EVENT;
       mbox[dev]->command = event;
       mbox[dev]->parm1 = p1;
@@ -302,34 +281,20 @@ pmgr_inform (int dev, int event, unsigned long p1, unsigned long p2,
        {
          {
            server_wait_flag[dev].mode = WK_WAKEUP;
-           wake_up (&server_procs[dev]);
+           module_wake_up (&server_procs[dev]);
          };
        }
 
 
-      {
-       unsigned long   tl;
-
-       if (0)
-         current->timeout = tl = jiffies + (0);
-       else
-         tl = 0xffffffff;
-       appl_wait_flag.mode = WK_SLEEP;
-       interruptible_sleep_on (&appl_proc);
-       if (!(appl_wait_flag.mode & WK_WAKEUP))
-         {
-           if (jiffies >= tl)
-             appl_wait_flag.mode |= WK_TIMEOUT;
-         }
-       appl_wait_flag.mode &= ~WK_SLEEP;
-      };
-      if (mbox[dev])
-       kfree (mbox[dev]);
+      appl_wait_flag.mode = WK_SLEEP;
+      module_interruptible_sleep_on (&appl_proc);
+      appl_wait_flag.mode &= ~WK_SLEEP;;
       mbox[dev] = NULL;
       msg_direction[dev] = 0;
     }
 
   restore_flags (flags);
+  kfree (tmp_mbox);
 
   return err;
 }
index 384bc4b07943d9f0762785f6515c3856d9d0edad..4f365fb4a8a87ea2ecb2bca77a52b61adbb4fb7b 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "sound_config.h"
 
-#if defined (CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PSS) && !defined(EXCLUDE_AUDIO)
+#if defined(CONFIG_PSS) && defined(CONFIG_AUDIO)
 
 /*
  * PSS registers.
@@ -109,13 +109,6 @@ probe_pss (struct address_info *hw_config)
       return 0;
     }
 
-  if (irq != 3 && irq != 5 && irq != 7 && irq != 9 &&
-      irq != 10 && irq != 11 && irq != 12)
-    return 0;
-
-  if (dma != 5 && dma != 6 && dma != 7)
-    return 0;
-
   id = inw (REG (PSS_ID));
   if ((id >> 8) != 'E')
     {
@@ -329,6 +322,7 @@ long
 attach_pss (long mem_start, struct address_info *hw_config)
 {
   unsigned short  id;
+  char            tmp[100];
 
   devc->base = hw_config->io_base;
   devc->irq = hw_config->irq;
@@ -370,7 +364,8 @@ attach_pss (long mem_start, struct address_info *hw_config)
 #endif
 
   pss_initialized = 1;
-  printk (" <ECHO-PSS  Rev. %d>", id);
+  sprintf (tmp, "ECHO-PSS  Rev. %d", id);
+  conf_printf (tmp, hw_config);
 
   return mem_start;
 }
@@ -426,7 +421,7 @@ probe_pss_mpu (struct address_info *hw_config)
        break;                  /* No more input */
     }
 
-#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
   return probe_mpu401 (hw_config);
 #else
   return 0
@@ -700,7 +695,7 @@ attach_pss_mpu (long mem_start, struct address_info *hw_config)
   int             prev_devs;
   long            ret;
 
-#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
   prev_devs = num_midis;
   ret = attach_mpu401 (mem_start, hw_config);
 
index 85e582469d4451190bbd2eae79e8b1914e13dbbd..34d8edc3657a0bba0fb9e9e6057cfa6d13d94bc6 100644 (file)
@@ -38,7 +38,7 @@
 #include "sb.h"
 #include "sb_mixer.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_AUDIO) && !defined(EXCLUDE_SBPRO)
+#if defined(CONFIG_SB) && defined(CONFIG_AUDIO)
 
 extern int      sbc_base;
 extern sound_os_info *sb_osp;
@@ -157,7 +157,7 @@ sb16_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
     {
     case SOUND_PCM_WRITE_RATE:
       if (local)
-       return dsp_set_speed ((long) arg);
+       return dsp_set_speed ((int) arg);
       return snd_ioctl_return ((int *) arg, dsp_set_speed (get_fs_long ((long *) arg)));
 
     case SOUND_PCM_READ_RATE:
@@ -167,12 +167,12 @@ sb16_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
 
     case SNDCTL_DSP_STEREO:
       if (local)
-       return dsp_set_stereo ((long) arg);
+       return dsp_set_stereo ((int) arg);
       return snd_ioctl_return ((int *) arg, dsp_set_stereo (get_fs_long ((long *) arg)));
 
     case SOUND_PCM_WRITE_CHANNELS:
       if (local)
-       return dsp_set_stereo ((long) arg - 1) + 1;
+       return dsp_set_stereo ((int) arg - 1) + 1;
       return snd_ioctl_return ((int *) arg, dsp_set_stereo (get_fs_long ((long *) arg) - 1) + 1);
 
     case SOUND_PCM_READ_CHANNELS:
@@ -182,7 +182,7 @@ sb16_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
 
     case SNDCTL_DSP_SETFMT:
       if (local)
-       return dsp_set_bits ((long) arg);
+       return dsp_set_bits ((int) arg);
       return snd_ioctl_return ((int *) arg, dsp_set_bits (get_fs_long ((long *) arg)));
 
     case SOUND_PCM_READ_BITS:
@@ -260,8 +260,23 @@ sb16_dsp_close (int dev)
   restore_flags (flags);
 }
 
+static unsigned long trg_buf;
+static int      trg_bytes;
+static int      trg_intrflag;
+static int      trg_restart;
+
 static void
 sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
+{
+  trg_buf = buf;
+  trg_bytes = count;
+  trg_intrflag = intrflag;
+  trg_restart = dma_restart;
+  irq_mode = IMODE_OUTPUT;
+}
+
+static void
+actually_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
 {
   unsigned long   flags, cnt;
 
@@ -321,6 +336,16 @@ sb16_dsp_output_block (int dev, unsigned long buf, int count, int intrflag, int
 
 static void
 sb16_dsp_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
+{
+  trg_buf = buf;
+  trg_bytes = count;
+  trg_intrflag = intrflag;
+  trg_restart = dma_restart;
+  irq_mode = IMODE_INPUT;
+}
+
+static void
+actually_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
 {
   unsigned long   flags, cnt;
 
@@ -415,7 +440,18 @@ sb16_dsp_trigger (int dev, int bits)
   if (!bits)
     sb_dsp_command (0xd0);     /* Halt DMA */
   else if (bits & irq_mode)
-    sb_dsp_command (0xd4);     /* Continue DMA */
+    switch (irq_mode)
+      {
+      case IMODE_INPUT:
+       actually_start_input (my_dev, trg_buf, trg_bytes,
+                             trg_intrflag, trg_restart);
+       break;
+
+      case IMODE_OUTPUT:
+       actually_output_block (my_dev, trg_buf, trg_bytes,
+                              trg_intrflag, trg_restart);
+       break;
+      }
 }
 
 static void
@@ -491,7 +527,7 @@ sb16_dsp_init (long mem_start, struct address_info *hw_config)
 
   sprintf (sb16_dsp_operations.name, "SoundBlaster 16 %d.%d", sbc_major, sbc_minor);
 
-  printk (" <%s>", sb16_dsp_operations.name);
+  conf_printf (sb16_dsp_operations.name, hw_config);
 
   if (num_audiodevs < MAX_AUDIO_DEV)
     {
@@ -520,11 +556,19 @@ int
 sb16_dsp_detect (struct address_info *hw_config)
 {
   struct address_info *sb_config;
-  extern int      sbc_major;
+  extern int      sbc_major, Jazz16_detected;
+
+  extern void     Jazz16_set_dma16 (int dma);
 
   if (sb16_dsp_ok)
     return 1;                  /* Can't drive two cards */
 
+  if (Jazz16_detected)
+    {
+      Jazz16_set_dma16 (hw_config->dma);
+      return 0;
+    }
+
   if (!(sb_config = sound_getconf (SNDCARD_SB)))
     {
       printk ("SB16 Error: Plain SB not configured\n");
index 79de8d056c505f7cefaedb8d59837e21ac1cd458..cc553e7d951ae655739180e97a57c0e12ca451a6 100644 (file)
@@ -29,9 +29,7 @@
 
 #include "sound_config.h"
 
-#ifdef CONFIGURE_SOUNDCARD
-
-#if !defined(EXCLUDE_SB) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_MIDI)
+#if defined(CONFIG_SB) && defined(CONFIG_MIDI)
 
 #include "sb.h"
 
@@ -60,8 +58,12 @@ static int      sb16midi_detected = 0;
 static int      my_dev;
 extern int      sbc_base;
 
+extern int      Jazz16_detected;
+extern int      AudioDrive;
+
 static int      reset_sb16midi (void);
 static void     (*midi_input_intr) (int dev, unsigned char data);
+static volatile unsigned char input_byte;
 
 static void
 sb16midi_input_loop (void)
@@ -70,7 +72,9 @@ sb16midi_input_loop (void)
     {
       unsigned char   c = sb16midi_read ();
 
-      if (sb16midi_opened & OPEN_READ)
+      if (c == MPU_ACK)
+       input_byte = c;
+      else if (sb16midi_opened & OPEN_READ && midi_input_intr)
        midi_input_intr (my_dev, c);
     }
 }
@@ -82,6 +86,13 @@ sb16midiintr (int unit)
     sb16midi_input_loop ();
 }
 
+void
+sbmidiintr (int irq, struct pt_regs *dummy)
+{
+  if (input_avail ())
+    sb16midi_input_loop ();
+}
+
 static int
 sb16midi_open (int dev, int mode,
               void            (*input) (int dev, unsigned char data),
@@ -175,13 +186,13 @@ sb16midi_buffer_status (int dev)
                                 */
 }
 
-#define MIDI_SYNTH_NAME        "SoundBlaster 16 Midi"
+#define MIDI_SYNTH_NAME        "SoundBlaster MPU"
 #define MIDI_SYNTH_CAPS        SYNTH_CAP_INPUT
 #include "midi_synth.h"
 
 static struct midi_operations sb16midi_operations =
 {
-  {"SoundBlaster 16 Midi", 0, 0, SNDCARD_SB16MIDI},
+  {"SoundBlaster MPU", 0, 0, SNDCARD_SB16MIDI},
   &std_midi_synth,
   {0},
   sb16midi_open,
@@ -196,7 +207,6 @@ static struct midi_operations sb16midi_operations =
   NULL
 };
 
-
 long
 attach_sb16midi (long mem_start, struct address_info *hw_config)
 {
@@ -206,18 +216,23 @@ attach_sb16midi (long mem_start, struct address_info *hw_config)
   sb16midi_base = hw_config->io_base;
 
   if (!sb16midi_detected)
-    return -EIO;
+    return mem_start;
+
+  request_region (hw_config->io_base, 4, "SB MIDI");
 
   save_flags (flags);
   cli ();
   for (timeout = 30000; timeout < 0 && !output_ready (); timeout--);   /*
                                                                         * Wait
                                                                         */
+  input_byte = 0;
   sb16midi_cmd (UART_MODE_ON);
 
   ok = 0;
   for (timeout = 50000; timeout > 0 && !ok; timeout--)
-    if (input_avail ())
+    if (input_byte == MPU_ACK)
+      ok = 1;
+    else if (input_avail ())
       if (sb16midi_read () == MPU_ACK)
        ok = 1;
 
@@ -229,7 +244,7 @@ attach_sb16midi (long mem_start, struct address_info *hw_config)
       return mem_start;
     }
 
-  printk (" <SoundBlaster MPU-401>");
+  conf_printf ("SoundBlaster MPU-401", hw_config);
 
   std_midi_synth.midi_dev = my_dev = num_midis;
   midi_devs[num_midis++] = &sb16midi_operations;
@@ -239,23 +254,25 @@ attach_sb16midi (long mem_start, struct address_info *hw_config)
 static int
 reset_sb16midi (void)
 {
-  unsigned long   flags;
   int             ok, timeout, n;
 
   /*
    * Send the RESET command. Try again if no success at the first time.
    */
 
+  if (inb (STATPORT) == 0xff)
+    return 0;
+
   ok = 0;
 
-  save_flags (flags);
-  cli ();
+  /*save_flags(flags);cli(); */
 
   for (n = 0; n < 2 && !ok; n++)
     {
       for (timeout = 30000; timeout < 0 && !output_ready (); timeout--);       /*
                                                                                 * Wait
                                                                                 */
+      input_byte = 0;
       sb16midi_cmd (MPU_RESET);        /*
                                 * Send MPU-401 RESET Command
                                 */
@@ -266,7 +283,9 @@ reset_sb16midi (void)
        */
 
       for (timeout = 50000; timeout > 0 && !ok; timeout--)
-       if (input_avail ())
+       if (input_byte == MPU_ACK)      /* Interrupt */
+         ok = 1;
+       else if (input_avail ())
          if (sb16midi_read () == MPU_ACK)
            ok = 1;
 
@@ -278,19 +297,28 @@ reset_sb16midi (void)
                                 * Flush input before enabling interrupts
                                 */
 
-  restore_flags (flags);
+  /* restore_flags(flags); */
 
   return ok;
 }
 
-
 int
 probe_sb16midi (struct address_info *hw_config)
 {
   int             ok = 0;
   extern int      sbc_major;
 
-  if (sbc_major < 4)
+  extern void     ess_midi_init (struct address_info *hw_config);
+  extern void     Jazz16_midi_init (struct address_info *hw_config);
+
+  if (check_region (hw_config->io_base, 4))
+    return 0;
+
+  if (AudioDrive)
+    ess_midi_init (hw_config);
+  else if (Jazz16_detected)
+    Jazz16_midi_init (hw_config);
+  else if (sbc_major < 4)
     return 0;                  /* Not a SB16 */
 
   sb16midi_base = hw_config->io_base;
@@ -307,8 +335,7 @@ probe_sb16midi (struct address_info *hw_config)
 void
 unload_sb16midi (struct address_info *hw_config)
 {
+  release_region (hw_config->io_base, 4);
 }
 
 #endif
-
-#endif
index d9e4d1e08cddb2f83704650b35d5ef56faaaa201..08171e45fba303870ecc354af7165b394cdd8e4c 100644 (file)
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB)
+#if defined(CONFIG_SB)
 
 #include "sb.h"
 
 long
 attach_sb_card (long mem_start, struct address_info *hw_config)
 {
-#if !defined(EXCLUDE_AUDIO) || !defined(EXCLUDE_MIDI)
+#if defined(CONFIG_AUDIO) || defined(CONFIG_MIDI)
   if (!sb_dsp_detect (hw_config))
     return mem_start;
   mem_start = sb_dsp_init (mem_start, hw_config);
-  request_region (hw_config->io_base, 16, "SB");
+  request_region (hw_config->io_base, 16, "SoundBlaster");
 #endif
 
   return mem_start;
@@ -59,7 +59,7 @@ probe_sb (struct address_info *hw_config)
       return 0;
     }
 
-#if !defined(EXCLUDE_AEDSP16) && defined(AEDSP16_SBPRO)
+#if defined(CONFIG_AEDSP16) && defined(AEDSP16_SBPRO)
   /*
      * Initialize Audio Excel DSP 16 to SBPRO.
    */
index 465e1bcf79ad30e0ed6f900f74a7cd299e74635b..26286e1ce4032c35dcb92fdcb0a27df56cbb19a4 100644 (file)
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB)
-
-#ifdef SM_WAVE
-#define JAZZ16
-#endif
+#if defined(CONFIG_SB)
 
 #include "sb.h"
 #include "sb_mixer.h"
 #undef SB_TEST_IRQ
 
 int             sbc_base = 0;
-static int      sbc_irq = 0;
+static int      sbc_irq = 0, sbc_dma;
 static int      open_mode = 0; /* Read, write or both */
 int             Jazz16_detected = 0;
+int             AudioDrive = 0;        /* 1=ES1688 detected */
+static int      ess_mpu_irq = 0;
 int             sb_no_recording = 0;
 static int      dsp_count = 0;
 static int      trigger_bits;
+static int      mpu_base = 0, mpu_irq = 0;
 
 /*
  * The DSP channel can be used either for input or output. Variable
@@ -68,46 +67,32 @@ int             sb_dsp_ok = 0;      /*
                                 * initialization  *  */
 static int      midi_disabled = 0;
 int             sb_dsp_highspeed = 0;
-int             sbc_major = 1, sbc_minor = 0;  /*
-
-
-                                                  * *  * * DSP version   */
+int             sbc_major = 1, sbc_minor = 0;
 static int      dsp_stereo = 0;
 static int      dsp_current_speed = DSP_DEFAULT_SPEED;
 static int      sb16 = 0;
 static int      irq_verified = 0;
 
 int             sb_midi_mode = NORMAL_MIDI;
-int             sb_midi_busy = 0;      /*
-
-
-                                        * *  * * 1 if the process has output
-                                        * to *  * MIDI   */
+int             sb_midi_busy = 0;
 int             sb_dsp_busy = 0;
 
-volatile int    sb_irq_mode = IMODE_NONE;      /*
-
-
-                                                * *  * * IMODE_INPUT, *
-                                                * IMODE_OUTPUT * * or *
-                                                * IMODE_NONE   */
+volatile int    sb_irq_mode = IMODE_NONE;
 static volatile int irq_ok = 0;
 
 static int      dma8 = 1;
+static int      dsp_16bit = 0;
 
-#ifdef JAZZ16
 /* 16 bit support
  */
 
-static int      dsp_16bit = 0;
-static int      dma16 = 5;
+static int      dma16 = 1;
 
 static int      dsp_set_bits (int arg);
 static int      initialize_ProSonic16 (void);
 
 /* end of 16 bit support
  */
-#endif
 
 int             sb_duplex_midi = 0;
 static int      my_dev = 0;
@@ -116,11 +101,12 @@ volatile int    sb_intr_active = 0;
 
 static int      dsp_speed (int);
 static int      dsp_set_stereo (int mode);
-int             sb_dsp_command (unsigned char val);
 static void     sb_dsp_reset (int dev);
 sound_os_info  *sb_osp = NULL;
 
-#if !defined(EXCLUDE_MIDI) || !defined(EXCLUDE_AUDIO)
+static void     ess_init (void);
+
+#if defined(CONFIG_MIDI) || defined(CONFIG_AUDIO)
 
 /*
  * Common code for the midi and pcm functions
@@ -154,31 +140,59 @@ sb_dsp_command (unsigned char val)
     }
 
   printk ("SoundBlaster: DSP Command(%x) Timeout.\n", val);
-  printk ("IRQ conflict???\n");
   return 0;
 }
 
+static int
+ess_write (unsigned char reg, unsigned char data)
+{
+  /* Write a byte to an extended mode register of ES1688 */
+
+  if (!sb_dsp_command (reg))
+    return 0;
+
+  return sb_dsp_command (data);
+}
+
+static int
+ess_read (unsigned char reg)
+{
+/* Read a byte from an extended mode register of ES1688 */
+
+  int             i;
+
+  if (!sb_dsp_command (0xc0))  /* Read register command */
+    return -1;
+
+  if (!sb_dsp_command (reg))
+    return -1;
+
+  for (i = 1000; i; i--)
+    {
+      if (inb (DSP_DATA_AVAIL) & 0x80)
+       return inb (DSP_READ);
+    }
+
+  return -1;
+}
+
 void
 sbintr (int irq, struct pt_regs *dummy)
 {
   int             status;
 
-#ifndef EXCLUDE_SBPRO
-  if (sb16)
+  if (sb16 && !AudioDrive)
     {
       unsigned char   src = sb_getmixer (IRQ_STAT);    /* Interrupt source register */
 
-#ifndef EXCLUDE_SB16
       if (src & 3)
        sb16_dsp_interrupt (irq);
 
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
       if (src & 4)
        sb16midiintr (irq);     /*
                                 * SB MPU401 interrupt
                                 */
-#endif
-
 #endif
 
       if (!(src & 1))
@@ -186,26 +200,23 @@ sbintr (int irq, struct pt_regs *dummy)
                                 * Not a DSP interupt
                                 */
     }
-#endif
 
   status = inb (DSP_DATA_AVAIL);       /*
                                           * Clear interrupt
                                         */
-
   if (sb_intr_active)
     switch (sb_irq_mode)
       {
       case IMODE_OUTPUT:
-       sb_intr_active = 0;
+       if (!AudioDrive)
+         sb_intr_active = 0;
        DMAbuf_outputintr (my_dev, 1);
        break;
 
       case IMODE_INPUT:
-       sb_intr_active = 0;
+       if (!AudioDrive)
+         sb_intr_active = 0;
        DMAbuf_inputintr (my_dev);
-       /*
-        * A complete buffer has been input. Let's start new one
-        */
        break;
 
       case IMODE_INIT:
@@ -214,7 +225,7 @@ sbintr (int irq, struct pt_regs *dummy)
        break;
 
       case IMODE_MIDI:
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
        sb_midi_interrupt (irq);
 #endif
        break;
@@ -240,24 +251,31 @@ sb_reset_dsp (void)
 {
   int             loopc;
 
-  outb (1, DSP_RESET);
-  tenmicrosec ();
+  if (AudioDrive)
+    outb (3, DSP_RESET);       /* Reset FIFO too */
+  else
+    outb (1, DSP_RESET);
+
+  tenmicrosec (sb_osp);
   outb (0, DSP_RESET);
-  tenmicrosec ();
-  tenmicrosec ();
-  tenmicrosec ();
+  tenmicrosec (sb_osp);
+  tenmicrosec (sb_osp);
+  tenmicrosec (sb_osp);
 
   for (loopc = 0; loopc < 1000 && !(inb (DSP_DATA_AVAIL) & 0x80); loopc++);
 
   if (inb (DSP_READ) != 0xAA)
     return 0;                  /* Sorry */
 
+  if (AudioDrive)
+    sb_dsp_command (0xc6);     /* Enable extended mode */
+
   return 1;
 }
 
 #endif
 
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
 
 static void
 dsp_speaker (char state)
@@ -268,6 +286,36 @@ dsp_speaker (char state)
     sb_dsp_command (DSP_CMD_SPKOFF);
 }
 
+static int
+ess_speed (int speed)
+{
+  int             rate;
+  unsigned char   bits = 0;
+
+  if (speed < 4000)
+    speed = 4000;
+  else if (speed > 48000)
+    speed = 48000;
+
+  if (speed > 22000)
+    {
+      bits = 0x80;
+      rate = 256 - (795500 + speed / 2) / speed;
+      speed = 795500 / (256 - rate);
+    }
+  else
+    {
+      rate = 128 - (397700 + speed / 2) / speed;
+      speed = 397700 / (128 - rate);
+    }
+
+  bits |= (unsigned char) rate;
+  ess_write (0xa1, bits);
+
+  dsp_current_speed = speed;
+  return speed;
+}
+
 static int
 dsp_speed (int speed)
 {
@@ -275,6 +323,9 @@ dsp_speed (int speed)
   unsigned long   flags;
   int             max_speed = 44100;
 
+  if (AudioDrive)
+    return ess_speed (speed);
+
   if (speed < 4000)
     speed = 4000;
 
@@ -306,7 +357,7 @@ dsp_speed (int speed)
   /*
    * Max. stereo speed is 22050
    */
-  if (dsp_stereo && speed > 22050 && Jazz16_detected == 0)
+  if (dsp_stereo && speed > 22050 && Jazz16_detected == 0 && AudioDrive == 0)
     speed = 22050;
 #endif
 
@@ -373,9 +424,6 @@ dsp_set_stereo (int mode)
 {
   dsp_stereo = 0;
 
-#ifdef EXCLUDE_SBPRO
-  return 0;
-#else
   if (sbc_major < 3 || sb16)
     return 0;                  /*
                                 * Sorry no stereo
@@ -389,14 +437,30 @@ dsp_set_stereo (int mode)
 
   dsp_stereo = !!mode;
   return dsp_stereo;
-#endif
 }
 
+static unsigned long trg_buf;
+static int      trg_bytes;
+static int      trg_intrflag;
+static int      trg_restart;
+
 static void
-sb_dsp_output_block (int dev, unsigned long buf, int count,
+sb_dsp_output_block (int dev, unsigned long buf, int nr_bytes,
                     int intrflag, int restart_dma)
+{
+  trg_buf = buf;
+  trg_bytes = nr_bytes;
+  trg_intrflag = intrflag;
+  trg_restart = restart_dma;
+  sb_irq_mode = IMODE_OUTPUT;
+}
+
+static void
+actually_output_block (int dev, unsigned long buf, int nr_bytes,
+                      int intrflag, int restart_dma)
 {
   unsigned long   flags;
+  int             count = nr_bytes;
 
   if (!sb_irq_mode)
     dsp_speaker (ON);
@@ -411,7 +475,17 @@ sb_dsp_output_block (int dev, unsigned long buf, int count,
   dsp_count = count;
 
   sb_irq_mode = IMODE_OUTPUT;
-  if (sb_dsp_highspeed)
+
+  if (AudioDrive)
+    {
+      int             c = 0x10000 - count;     /* ES1688 increments the count */
+
+      ess_write (0xa4, (unsigned char) (c & 0xff));
+      ess_write (0xa5, (unsigned char) ((c >> 8) & 0xff));
+
+      ess_write (0xb8, ess_read (0xb8) | 0x01);                /* Go */
+    }
+  else if (sb_dsp_highspeed)
     {
       save_flags (flags);
       cli ();
@@ -450,6 +524,17 @@ sb_dsp_output_block (int dev, unsigned long buf, int count,
 static void
 sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag,
                    int restart_dma)
+{
+  trg_buf = buf;
+  trg_bytes = count;
+  trg_intrflag = intrflag;
+  trg_restart = restart_dma;
+  sb_irq_mode = IMODE_INPUT;
+}
+
+static void
+actually_start_input (int dev, unsigned long buf, int count, int intrflag,
+                     int restart_dma)
 {
   unsigned long   flags;
 
@@ -475,7 +560,17 @@ sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag,
   dsp_count = count;
 
   sb_irq_mode = IMODE_INPUT;
-  if (sb_dsp_highspeed)
+
+  if (AudioDrive)
+    {
+      int             c = 0x10000 - count;     /* ES1688 increments the count */
+
+      ess_write (0xa4, (unsigned char) (c & 0xff));
+      ess_write (0xa5, (unsigned char) ((c >> 8) & 0xff));
+
+      ess_write (0xb8, ess_read (0xb8) | 0x01);                /* Go */
+    }
+  else if (sb_dsp_highspeed)
     {
       save_flags (flags);
       cli ();
@@ -515,13 +610,24 @@ sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag,
 static void
 sb_dsp_trigger (int dev, int bits)
 {
-  if (bits == trigger_bits)
-    return;
 
   if (!bits)
     sb_dsp_command (0xd0);     /* Halt DMA */
   else if (bits & sb_irq_mode)
-    sb_dsp_command (0xd4);     /* Continue DMA */
+    {
+      switch (sb_irq_mode)
+       {
+       case IMODE_INPUT:
+         actually_start_input (my_dev, trg_buf, trg_bytes,
+                               trg_intrflag, trg_restart);
+         break;
+
+       case IMODE_OUTPUT:
+         actually_output_block (my_dev, trg_buf, trg_bytes,
+                                trg_intrflag, trg_restart);
+         break;
+       }
+    }
 
   trigger_bits = bits;
 }
@@ -542,30 +648,61 @@ sb_dsp_prepare_for_input (int dev, int bsize, int bcount)
                                 * SB Pro
                                 */
     {
-#ifdef JAZZ16
-      /* Select correct dma channel
-         * for 16/8 bit acccess
-       */
-      audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8;
-      if (dsp_stereo)
-       sb_dsp_command (dsp_16bit ? 0xac : 0xa8);
-      else
-       sb_dsp_command (dsp_16bit ? 0xa4 : 0xa0);
-#else
-      /* 8 bit only cards use this
-       */
-      if (dsp_stereo)
-       sb_dsp_command (0xa8);
+      if (AudioDrive)
+       {
+
+         /* ess_init(); */
+         ess_write (0xb8, 0x0e);       /* Auto init DMA mode */
+         ess_write (0xa8, (ess_read (0xa8) & ~0x04) |
+                    (2 - dsp_stereo));         /* Mono/stereo */
+         ess_write (0xb9, 2);  /* Demand mode (2 bytes/xfer) */
+
+         if (!dsp_stereo)
+           {
+             if (dsp_16bit == 0)
+               {               /* 8 bit mono */
+                 ess_write (0xb7, 0x51);
+                 ess_write (0xb7, 0xd0);
+               }
+             else
+               {               /* 16 bit mono */
+                 ess_write (0xb7, 0x71);
+                 ess_write (0xb7, 0xf4);
+               }
+           }
+         else
+           {                   /* Stereo */
+             if (!dsp_16bit)
+               {               /* 8 bit stereo */
+                 ess_write (0xb7, 0x51);
+                 ess_write (0xb7, 0x98);
+               }
+             else
+               {               /* 16 bit stereo */
+                 ess_write (0xb7, 0x71);
+                 ess_write (0xb7, 0xbc);
+               }
+           }
+
+         ess_write (0xb1, (ess_read (0xb1) & 0x0f) | 0x50);
+         ess_write (0xb2, (ess_read (0xb2) & 0x0f) | 0x50);
+       }
       else
-       sb_dsp_command (0xa0);
-#endif
-      dsp_speed (dsp_current_speed);   /*
-                                        * Speed must be recalculated if
-                                        * #channels * changes
-                                        */
+       {                       /* !AudioDrive */
+
+         /* Select correct dma channel
+            * for 16/8 bit acccess
+          */
+         audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8;
+         if (dsp_stereo)
+           sb_dsp_command (dsp_16bit ? 0xac : 0xa8);
+         else
+           sb_dsp_command (dsp_16bit ? 0xa4 : 0xa0);
+
+         dsp_speed (dsp_current_speed);
+       }                       /* !AudioDrive */
     }
   trigger_bits = 0;
-  sb_dsp_command (0xd0);       /* Halt DMA */
   return 0;
 }
 
@@ -573,34 +710,72 @@ static int
 sb_dsp_prepare_for_output (int dev, int bsize, int bcount)
 {
   dsp_cleanup ();
-  dsp_speaker (ON);
+  dsp_speaker (OFF);
 
-#ifndef EXCLUDE_SBPRO
-  if (sbc_major == 3)          /*
-                                * SB Pro
-                                */
+  if (sbc_major == 3)          /* SB Pro (at least ) */
     {
-#ifdef JAZZ16
-      /* 16 bit specific instructions
-       */
-      audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8;
-      if (Jazz16_detected != 2)        /* SM Wave */
-       sb_mixer_set_stereo (dsp_stereo);
-      if (dsp_stereo)
-       sb_dsp_command (dsp_16bit ? 0xac : 0xa8);
+
+      if (AudioDrive)
+       {
+
+         /* ess_init(); */
+         ess_write (0xb8, 4);  /* Auto init DMA mode */
+         ess_write (0xa8, ess_read (0xa8) |
+                    (2 - dsp_stereo));         /* Mono/stereo */
+         ess_write (0xb9, 2);  /* Demand mode (2 bytes/xfer) */
+
+         if (!dsp_stereo)
+           {
+             if (dsp_16bit == 0)
+               {               /* 8 bit mono */
+                 ess_write (0xb6, 0x80);
+                 ess_write (0xb7, 0x51);
+                 ess_write (0xb7, 0xd0);
+               }
+             else
+               {               /* 16 bit mono */
+                 ess_write (0xb6, 0x00);
+                 ess_write (0xb7, 0x71);
+                 ess_write (0xb7, 0xf4);
+               }
+           }
+         else
+           {                   /* Stereo */
+             if (!dsp_16bit)
+               {               /* 8 bit stereo */
+                 ess_write (0xb6, 0x80);
+                 ess_write (0xb7, 0x51);
+                 ess_write (0xb7, 0x98);
+               }
+             else
+               {               /* 16 bit stereo */
+                 ess_write (0xb6, 0x00);
+                 ess_write (0xb7, 0x71);
+                 ess_write (0xb7, 0xbc);
+               }
+           }
+
+         ess_write (0xb1, (ess_read (0xb1) & 0x0f) | 0x50);
+         ess_write (0xb2, (ess_read (0xb2) & 0x0f) | 0x50);
+       }
       else
-       sb_dsp_command (dsp_16bit ? 0xa4 : 0xa0);
-#else
-      sb_mixer_set_stereo (dsp_stereo);
-#endif
-      dsp_speed (dsp_current_speed);   /*
-                                        * Speed must be recalculated if
-                                        * #channels * changes
-                                        */
+       {                       /* !AudioDrive */
+
+         /* 16 bit specific instructions (Jazz16)
+          */
+         audio_devs[my_dev]->dmachan1 = dsp_16bit ? dma16 : dma8;
+         if (Jazz16_detected != 2)     /* SM Wave */
+           sb_mixer_set_stereo (dsp_stereo);
+         if (dsp_stereo)
+           sb_dsp_command (dsp_16bit ? 0xac : 0xa8);
+         else
+           sb_dsp_command (dsp_16bit ? 0xa4 : 0xa0);
+       }                       /* !AudioDrive */
+
     }
-#endif
+
   trigger_bits = 0;
-  sb_dsp_command (0xd0);       /* Halt DMA */
+  dsp_speaker (ON);
   return 0;
 }
 
@@ -653,11 +828,9 @@ sb_dsp_open (int dev, int mode)
 
   /* Allocate 8 bit dma
    */
-#ifdef JAZZ16
   audio_devs[my_dev]->dmachan1 = dma8;
-#endif
-#ifdef JAZZ16
-  /* Allocate 16 bit dma
+
+  /* Allocate 16 bit dma (jazz16)
    */
   if (Jazz16_detected != 0)
     if (dma16 != dma8)
@@ -669,7 +842,6 @@ sb_dsp_open (int dev, int mode)
            return -EBUSY;
          }
       }
-#endif
 
   sb_irq_mode = IMODE_NONE;
 
@@ -682,7 +854,6 @@ sb_dsp_open (int dev, int mode)
 static void
 sb_dsp_close (int dev)
 {
-#ifdef JAZZ16
   /* Release 16 bit dma channel
    */
   if (Jazz16_detected)
@@ -692,7 +863,6 @@ sb_dsp_close (int dev)
       if (dma16 != dma8)
        sound_close_dma (dma16);
     }
-#endif
 
   /* DMAbuf_close_dma (dev); */
   sb_free_irq ();
@@ -704,14 +874,11 @@ sb_dsp_close (int dev)
   open_mode = 0;
 }
 
-#ifdef JAZZ16
-/* Function dsp_set_bits() only required for 16 bit cards
- */
 static int
 dsp_set_bits (int arg)
 {
   if (arg)
-    if (Jazz16_detected == 0)
+    if (Jazz16_detected == 0 && AudioDrive == 0)
       dsp_16bit = 0;
     else
       switch (arg)
@@ -725,11 +892,10 @@ dsp_set_bits (int arg)
        default:
          dsp_16bit = 0;
        }
+
   return dsp_16bit ? 16 : 8;
 }
 
-#endif /* ifdef JAZZ16 */
-
 static int
 sb_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
 {
@@ -737,7 +903,7 @@ sb_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
     {
     case SOUND_PCM_WRITE_RATE:
       if (local)
-       return dsp_speed ((long) arg);
+       return dsp_speed ((int) arg);
       return snd_ioctl_return ((int *) arg, dsp_speed (get_fs_long ((long *) arg)));
       break;
 
@@ -749,7 +915,7 @@ sb_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
 
     case SOUND_PCM_WRITE_CHANNELS:
       if (local)
-       return dsp_set_stereo ((long) arg - 1) + 1;
+       return dsp_set_stereo ((int) arg - 1) + 1;
       return snd_ioctl_return ((int *) arg, dsp_set_stereo (get_fs_long ((long *) arg) - 1) + 1);
       break;
 
@@ -761,11 +927,10 @@ sb_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
 
     case SNDCTL_DSP_STEREO:
       if (local)
-       return dsp_set_stereo ((long) arg);
+       return dsp_set_stereo ((int) arg);
       return snd_ioctl_return ((int *) arg, dsp_set_stereo (get_fs_long ((long *) arg)));
       break;
 
-#ifdef JAZZ16
       /* Word size specific cases here.
          * SNDCTL_DSP_SETFMT=SOUND_PCM_WRITE_BITS
        */
@@ -780,14 +945,6 @@ sb_dsp_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
        return dsp_16bit ? 16 : 8;
       return snd_ioctl_return ((int *) arg, dsp_16bit ? 16 : 8);
       break;
-#else
-    case SOUND_PCM_WRITE_BITS:
-    case SOUND_PCM_READ_BITS:
-      if (local)
-       return 8;
-      return snd_ioctl_return ((int *) arg, 8);        /* Only 8 bits/sample supported */
-      break;
-#endif /* ifdef JAZZ16  */
 
     case SOUND_PCM_WRITE_FILTER:
     case SOUND_PCM_READ_FILTER:
@@ -818,8 +975,6 @@ sb_dsp_reset (int dev)
 #endif
 
 
-#ifdef JAZZ16
-
 /*
  * Initialization of a Media Vision ProSonic 16 Soundcard.
  * The function initializes a ProSonic 16 like PROS.EXE does for DOS. It sets
@@ -845,7 +1000,6 @@ get_sb_byte (void)
   return 0xffff;
 }
 
-#ifdef SM_WAVE
 /*
  * Logitech Soundman Wave detection and initialization by Hannu Savolainen.
  *
@@ -914,7 +1068,7 @@ initialize_smw (int mpu_base)
   outb ((control & 0xfe) | 2, mpu_base + 7);   /* xxxxxxx0 resets the mc */
 
   for (i = 0; i < 300; i++)    /* Wait at least 1ms */
-    tenmicrosec ();
+    tenmicrosec (sb_osp);
 
   outb (control & 0xfc, mpu_base + 7); /* xxxxxx00 enables RAM */
 
@@ -923,7 +1077,7 @@ initialize_smw (int mpu_base)
    */
   smw_putmem (mp_base, 0, 0x00);
   smw_putmem (mp_base, 1, 0xff);
-  tenmicrosec ();
+  tenmicrosec (sb_osp);
 
   if (smw_getmem (mp_base, 0) != 0x00 || smw_getmem (mp_base, 1) != 0xff)
     {
@@ -995,8 +1149,6 @@ initialize_smw (int mpu_base)
   return 1;
 }
 
-#endif
-
 static int
 initialize_ProSonic16 (void)
 {
@@ -1005,23 +1157,9 @@ initialize_ProSonic16 (void)
   {0, 0, 2, 3, 0, 1, 0, 4, 0, 2, 5, 0, 0, 0, 0, 6}, dma_translat[8] =
   {0, 1, 0, 2, 0, 3, 0, 4};
 
-  struct address_info *mpu_config;
-
-  int             mpu_base, mpu_irq;
-
-  if ((mpu_config = sound_getconf (SNDCARD_MPU401)))
-    {
-      mpu_base = mpu_config->io_base;
-      mpu_irq = mpu_config->irq;
-    }
-  else
-    {
-      mpu_base = mpu_irq = 0;
-    }
-
   outb (0xAF, 0x201);          /* ProSonic/Jazz16 wakeup */
   for (x = 0; x < 1000; ++x)   /* wait 10 milliseconds */
-    tenmicrosec ();
+    tenmicrosec (sb_osp);
   outb (0x50, 0x201);
   outb ((sbc_base & 0x70) | ((mpu_base & 0x30) >> 4), 0x201);
 
@@ -1036,18 +1174,15 @@ initialize_ProSonic16 (void)
        return 1;
 
       if (sb_dsp_command (0xFB) &&     /* set DMA-channels and Interrupts */
-         sb_dsp_command ((dma_translat[JAZZ_DMA16] << 4) | dma_translat[dma8]) &&
+         sb_dsp_command ((dma_translat[dma16] << 4) | dma_translat[dma8]) &&
       sb_dsp_command ((int_translat[mpu_irq] << 4) | int_translat[sbc_irq]))
        {
          Jazz16_detected = 1;
-         if (mpu_base == 0)
-           printk ("Jazz16: No MPU401 devices configured - MIDI port not initialized\n");
 
-#ifdef SM_WAVE
          if (mpu_base != 0)
            if (initialize_smw (mpu_base))
              Jazz16_detected = 2;
-#endif
+
          sb_dsp_disable_midi ();
        }
 
@@ -1056,37 +1191,29 @@ initialize_ProSonic16 (void)
   return 0;                    /* No SB or ProSonic16 detected */
 }
 
-#endif /* ifdef JAZZ16  */
-
 int
 sb_dsp_detect (struct address_info *hw_config)
 {
   sbc_base = hw_config->io_base;
   sbc_irq = hw_config->irq;
+  sbc_dma = hw_config->dma;
   sb_osp = hw_config->osp;
 
   if (sb_dsp_ok)
     return 0;                  /*
                                 * Already initialized
                                 */
-  dma8 = hw_config->dma;
-
-#ifdef JAZZ16
-  dma16 = JAZZ_DMA16;
+  dma8 = dma16 = hw_config->dma;
 
   if (!initialize_ProSonic16 ())
     return 0;
-#else
-  if (!sb_reset_dsp ())
-    return 0;
-#endif
 
   return 1;                    /*
                                 * Detected
                                 */
 }
 
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
 static struct audio_operations sb_dsp_operations =
 {
   "SoundBlaster",
@@ -1111,16 +1238,154 @@ static struct audio_operations sb_dsp_operations =
 
 #endif
 
+static void
+ess_init (void)                        /* ESS1688 Initialization */
+{
+  unsigned char   cfg, irq_bits = 0, dma_bits = 0;
+
+  AudioDrive = 1;
+  midi_disabled = 1;
+
+  sb_reset_dsp ();             /* Turn on extended mode */
+
+/*
+ *    Set IRQ configuration register
+ */
+
+  cfg = 0x50;                  /* Enable only DMA counter interrupt */
+
+  switch (sbc_irq)
+    {
+    case 2:
+    case 9:
+      irq_bits = 0;
+      break;
+
+    case 5:
+      irq_bits = 1;
+      break;
+
+    case 7:
+      irq_bits = 2;
+      break;
+
+    case 10:
+      irq_bits = 3;
+      break;
+
+    default:
+      irq_bits = 0;
+      cfg = 0x10;              /* Disable all interrupts */
+      printk ("\nESS1688: Invalid IRQ %d\n", sbc_irq);
+    }
+
+  if (!ess_write (0xb1, cfg | (irq_bits << 2)))
+    printk ("\nESS1688: Failed to write to IRQ config register\n");
+
+/*
+ *    Set DMA configuration register
+ */
+
+  cfg = 0x50;                  /* Extended mode DMA ebable */
+
+  if (sbc_dma > 3 || sbc_dma < 0 || sbc_dma == 2)
+    {
+      dma_bits = 0;
+      cfg = 0x00;              /* Disable all DMA */
+      printk ("\nESS1688: Invalid DMA %d\n", sbc_dma);
+    }
+  else
+    {
+      if (sbc_dma == 3)
+       dma_bits = 3;
+      else
+       dma_bits = sbc_dma + 1;
+    }
+
+  if (!ess_write (0xb2, cfg | (dma_bits << 2)))
+    printk ("\nESS1688: Failed to write to DMA config register\n");
+
+/*
+ * Enable joystick and OPL3
+ */
+
+  cfg = sb_getmixer (0x40);
+  sb_setmixer (0x40, cfg | 0x03);
+}
+
+void
+ess_midi_init (struct address_info *hw_config) /* called from sb16_midi.c */
+{
+  unsigned char   cfg, tmp;
+
+  cfg = sb_getmixer (0x40) & 0x03;
+
+  tmp = (hw_config->io_base & 0x0f0) >> 4;
+
+  if (tmp > 3)
+    {
+      sb_setmixer (0x40, cfg);
+      return;
+    }
+
+  cfg |= tmp << 3;
+
+  tmp = 1;                     /* MPU enabled without interrupts */
+
+  switch (hw_config->irq)
+    {
+    case 9:
+      tmp = 0x4;
+      break;
+    case 5:
+      tmp = 0x5;
+      break;
+    case 7:
+      tmp = 0x6;
+      break;
+    case 10:
+      tmp = 0x7;
+      break;
+    }
+
+  cfg |= tmp << 5;
+
+  if (tmp != 1)
+    {
+      ess_mpu_irq = hw_config->irq;
+
+      if (snd_set_irq_handler (ess_mpu_irq, sbmidiintr, "ES1688 MIDI", sb_osp) < 0)
+       printk ("ES1688: Can't allocate IRQ%d\n", ess_mpu_irq);
+    }
+
+  sb_setmixer (0x40, cfg);
+}
+
+void
+Jazz16_midi_init (struct address_info *hw_config)
+{
+  mpu_base = hw_config->io_base;
+  mpu_irq = hw_config->irq;
+
+  initialize_ProSonic16 ();
+}
+
+void
+Jazz16_set_dma16 (int dma)
+{
+  dma16 = dma;
+
+  initialize_ProSonic16 ();
+}
+
 long
 sb_dsp_init (long mem_start, struct address_info *hw_config)
 {
   int             i;
+  int             ess_major = 0, ess_minor = 0;
 
-#ifndef EXCLUDE_SBPRO
   int             mixer_type = 0;
 
-#endif
-
   sb_osp = hw_config->osp;
   sbc_major = sbc_minor = 0;
   sb_dsp_command (0xe1);       /*
@@ -1158,7 +1423,6 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
 
   if (sbc_major == 3 && sbc_minor == 1)
     {
-      int             ess_major = 0, ess_minor = 0;
 
 /*
  * Try to detect ESS chips.
@@ -1183,28 +1447,12 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
                }
            }
        }
-
-      if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80)
-       printk ("Hmm... Could this be an ESS488 based card (rev %d)\n",
-               ess_minor & 0x0f);
-      else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80)
-       printk ("Hmm... Could this be an ESS688 based card (rev %d)\n",
-               ess_minor & 0x0f);
     }
 
   if (snd_set_irq_handler (sbc_irq, sbintr, "SoundBlaster", sb_osp) < 0)
     printk ("sb_dsp: Can't allocate IRQ\n");;
 
-#ifndef EXCLUDE_SBPRO
-  if (sbc_major >= 3)
-    mixer_type = sb_mixer_init (sbc_major);
-#else
-  if (sbc_major >= 3)
-    printk ("\n\n\n\nNOTE! SB Pro support is required with your soundcard!\n\n\n");
-#endif
-
-
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
   if (sbc_major >= 3)
     {
       if (Jazz16_detected)
@@ -1228,6 +1476,20 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
        {
          sprintf (sb_dsp_operations.name, "SoundBlaster 16 %d.%d", sbc_major, sbc_minor);
        }
+      else if (ess_major != 0)
+       {
+         if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80)
+           sprintf (sb_dsp_operations.name, "ESS ES488 AudioDrive (rev %d)",
+                    ess_minor & 0x0f);
+         else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80)
+           {
+             sprintf (sb_dsp_operations.name,
+                      "ESS ES1688 AudioDrive (rev %d)",
+                      ess_minor & 0x0f);
+             sb_dsp_operations.format_mask |= AFMT_S16_LE;
+             ess_init ();
+           }
+       }
       else
        {
          sprintf (sb_dsp_operations.name, "SoundBlaster Pro %d.%d", sbc_major, sbc_minor);
@@ -1238,23 +1500,26 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
       sprintf (sb_dsp_operations.name, "SoundBlaster %d.%d", sbc_major, sbc_minor);
     }
 
-  printk (" <%s>", sb_dsp_operations.name);
+  conf_printf (sb_dsp_operations.name, hw_config);
 
-#if !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SBPRO)
-  if (!sb16)                   /*
-                                * There is a better driver for SB16
-                                */
-#endif
+  if (sbc_major >= 3)
+    mixer_type = sb_mixer_init (sbc_major);
+
+  if (!sb16)
     if (num_audiodevs < MAX_AUDIO_DEV)
       {
        audio_devs[my_dev = num_audiodevs++] = &sb_dsp_operations;
+
+       if (AudioDrive)
+         audio_devs[my_dev]->flags |= DMA_AUTOMODE;
+
        audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
        dma8 = audio_devs[my_dev]->dmachan1 = hw_config->dma;
        audio_devs[my_dev]->dmachan2 = -1;
-       if (sound_alloc_dma (hw_config->dma, "soundblaster"))
+       if (sound_alloc_dma (hw_config->dma, "SoundBlaster"))
          printk ("sb_dsp.c: Can't allocate DMA channel\n");
-#ifdef JAZZ16
-       /* Allocate 16 bit dma
+
+       /* Allocate 16 bit dma (Jazz16)
         */
        if (Jazz16_detected != 0)
          if (dma16 != dma8)
@@ -1264,15 +1529,14 @@ sb_dsp_init (long mem_start, struct address_info *hw_config)
                  printk ("Jazz16: Can't allocate 16 bit DMA channel\n");
                }
            }
-#endif
       }
     else
       printk ("SB: Too many DSP devices available\n");
 #else
-  printk (" <SoundBlaster (configured without audio support)>");
+  conf_printf ("SoundBlaster (configured without audio support)", hw_config);
 #endif
 
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
   if (!midi_disabled && !sb16) /*
                                 * Midi don't work in the SB emulation mode *
                                 * of PAS, SB16 has better midi interface
@@ -1288,16 +1552,20 @@ void
 sb_dsp_unload (void)
 {
   sound_free_dma (dma8);
-#ifdef JAZZ16
-  /* Allocate 16 bit dma
+
+  /* Free 16 bit dma (Jazz16)
    */
   if (Jazz16_detected != 0)
     if (dma16 != dma8)
       {
        sound_free_dma (dma16);
       }
-#endif
   snd_release_irq (sbc_irq);
+
+  if (AudioDrive && ess_mpu_irq)
+    {
+      snd_release_irq (ess_mpu_irq);
+    }
 }
 
 void
index 32fa376060bb8c525016e2561a978d2a61655079..9e92383daf25028e43f4e570168d8f0910ddb48c 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_MIDI)
+#if defined(CONFIG_SB) && defined(CONFIG_MIDI)
 
 #include "sb.h"
 #undef SB_TEST_IRQ
index bd5603d9eb73c89aa12f456a74992d1f2272a4a0..0b951e627f69cabdfa32e303b07caa8caa6ea88c 100644 (file)
@@ -34,7 +34,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_SBPRO)
+#if defined(CONFIG_SB)
 #define __SB_MIXER_C__
 
 #include "sb.h"
@@ -44,6 +44,7 @@
 extern int      sbc_base;
 extern int      Jazz16_detected;
 extern sound_os_info *sb_osp;
+extern int      AudioDrive;
 
 static int      mixer_initialized = 0;
 
@@ -64,9 +65,9 @@ sb_setmixer (unsigned int port, unsigned int value)
   outb ((unsigned char) (port & 0xff), MIXER_ADDR);    /*
                                                           * Select register
                                                         */
-  tenmicrosec ();
+  tenmicrosec (sb_osp);
   outb ((unsigned char) (value & 0xff), MIXER_DATA);
-  tenmicrosec ();
+  tenmicrosec (sb_osp);
   restore_flags (flags);
 }
 
@@ -81,9 +82,9 @@ sb_getmixer (unsigned int port)
   outb ((unsigned char) (port & 0xff), MIXER_ADDR);    /*
                                                           * Select register
                                                         */
-  tenmicrosec ();
+  tenmicrosec (sb_osp);
   val = inb (MIXER_DATA);
-  tenmicrosec ();
+  tenmicrosec (sb_osp);
   restore_flags (flags);
 
   return val;
@@ -201,7 +202,6 @@ sb_mixer_get (int dev)
   return levels[dev];
 }
 
-#ifdef JAZZ16
 static char     smw_mix_regs[] =       /* Left mixer registers */
 {
   0x0b,                                /* SOUND_MIXER_VOLUME */
@@ -293,8 +293,6 @@ smw_mixer_set (int dev, int value)
   return left | (right << 8);
 }
 
-#endif
-
 static int
 sb_mixer_set (int dev, int value)
 {
@@ -304,10 +302,8 @@ sb_mixer_set (int dev, int value)
   int             regoffs;
   unsigned char   val;
 
-#ifdef JAZZ16
   if (Jazz16_detected == 2)
     return smw_mixer_set (dev, value);
-#endif
 
   if (left > 100)
     left = 100;
@@ -449,7 +445,7 @@ sb_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
 {
   if (((cmd >> 8) & 0xff) == 'M')
     {
-      if (cmd & IOC_IN)
+      if (_IOC_DIR (cmd) & _IOC_WRITE)
        switch (cmd & 0xff)
          {
          case SOUND_MIXER_RECSRC:
@@ -539,8 +535,13 @@ sb_mixer_init (int major_model)
     case 3:
       mixer_caps = SOUND_CAP_EXCL_INPUT;
 
-#ifdef JAZZ16
-      if (Jazz16_detected == 2)        /* SM Wave */
+      if (AudioDrive)
+       {
+         supported_devices = ES688_MIXER_DEVICES;
+         supported_rec_devices = ES688_RECORDING_DEVICES;
+         iomap = &es688_mix;
+       }
+      else if (Jazz16_detected == 2)   /* SM Wave */
        {
          supported_devices = 0;
          supported_rec_devices = 0;
@@ -549,7 +550,6 @@ sb_mixer_init (int major_model)
          mixer_type = 1;
        }
       else
-#endif
 #ifdef __SGNXPRO__
       if (mixer_type == 2)     /* A SGNXPRO was detected */
        {
index cd103a7248de9c0f36103a5bd7ee5615e3230a18..0a92e5e33d67b80beec5e4ce25e73e688a8f7fe8 100644 (file)
@@ -50,6 +50,9 @@
 #define SB16_RECORDING_DEVICES         (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
                                         SOUND_MASK_CD)
 
+#define ES688_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
+#define ES688_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_LINE2|SOUND_MASK_SPEAKER)
+
 #define SB16_MIXER_DEVICES             (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
                                         SOUND_MASK_CD | \
                                         SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
@@ -131,6 +134,25 @@ MIX_ENT(SOUND_MIXER_IMIX,  0x00, 0, 0, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_ALTPCM,    0x00, 0, 0, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_RECLEV,    0x00, 0, 0, 0x00, 0, 0)
 };
+mixer_tab es688_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME,    0x32, 7, 4, 0x32, 3, 4),
+MIX_ENT(SOUND_MIXER_BASS,      0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE,    0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH,     0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM,       0x14, 7, 4, 0x14, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER,   0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE,      0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC,       0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD,                0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX,      0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM,    0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV,    0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_IGAIN,     0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN,     0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1,     0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2,     0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3,     0x00, 0, 0, 0x00, 0, 0)
+};
 
 #ifdef __SGNXPRO__
 mixer_tab sgnxpro_mix = {
@@ -187,7 +209,10 @@ static unsigned short levels[SOUND_MIXER_NRDEVICES] =
   0x4b4b,                      /* SB PCM */
   0x4b4b,                      /* Recording level */
   0x4b4b,                      /* Input gain */
-  0x4b4b};                     /* Output gain */
+  0x4b4b,                      /* Output gain */
+  0x4040,                      /* Line1 */
+  0x4040,                      /* Line2 */
+  0x1515                       /* Line3 */
 
 #else  /* If the user selected just plain SB Pro */
 
@@ -206,7 +231,11 @@ static unsigned short levels[SOUND_MIXER_NRDEVICES] =
   0x4b4b,                      /* SB PCM */
   0x4b4b,                      /* Recording level */
   0x4b4b,                      /* Input gain */
-  0x4b4b};                     /* Output gain */
+  0x4b4b,                      /* Output gain */
+  0x4040,                      /* Line1 */
+  0x4040,                      /* Line2 */
+  0x1515                       /* Line3 */
+};
 #endif /* SM_GAMES */
 
 static unsigned char sb16_recmasks_L[SOUND_MIXER_NRDEVICES] =
index c838c277a972f10ed8be20e3c9e18e73831196ba..be651ae1bbf21aa5c54f20fc2caadff408750baa 100644 (file)
@@ -30,9 +30,7 @@
 #define SEQUENCER_C
 #include "sound_config.h"
 
-#ifdef CONFIGURE_SOUNDCARD
-
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
 
 #include "midi_ctrl.h"
 
@@ -58,10 +56,10 @@ static int      max_synthdev = 0;
 #define SEQ_2  2
 static int      seq_mode = SEQ_1;
 
-static struct wait_queue *seq_sleeper = NULL;
+static wait_handle *seq_sleeper = NULL;
 static volatile struct snd_wait seq_sleep_flag =
 {0};
-static struct wait_queue *midi_sleeper = NULL;
+static wait_handle *midi_sleeper = NULL;
 static volatile struct snd_wait midi_sleep_flag =
 {0};
 
@@ -84,7 +82,7 @@ static unsigned char *iqueue = NULL;
 static volatile int qhead = 0, qtail = 0, qlen = 0;
 static volatile int iqhead = 0, iqtail = 0, iqlen = 0;
 static volatile int seq_playing = 0;
-static int      sequencer_busy = 0;
+static volatile int sequencer_busy = 0;
 static int      output_treshold;
 static int      pre_event_timeout;
 static unsigned synth_open_mask;
@@ -132,11 +130,11 @@ sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
        unsigned long   tl;
 
        if (pre_event_timeout)
-         current->timeout = tl = jiffies + (pre_event_timeout);
+         current_set_timeout (tl = jiffies + (pre_event_timeout));
        else
          tl = 0xffffffff;
        midi_sleep_flag.mode = WK_SLEEP;
-       interruptible_sleep_on (&midi_sleeper);
+       module_interruptible_sleep_on (&midi_sleeper);
        if (!(midi_sleep_flag.mode & WK_WAKEUP))
          {
            if (jiffies >= tl)
@@ -202,7 +200,7 @@ seq_copy_to_input (unsigned char *event, int len)
     {
       {
        midi_sleep_flag.mode = WK_WAKEUP;
-       wake_up (&midi_sleeper);
+       module_wake_up (&midi_sleeper);
       };
     }
   restore_flags (flags);
@@ -276,9 +274,7 @@ sequencer_write (int dev, struct fileinfo *file, const snd_rw_buf * buf, int cou
   if (mode == OPEN_READ)
     return -EIO;
 
-  if (dev)                     /*
-                                * Patch manager device
-                                */
+  if (dev)
     return pmgr_write (dev - 1, file, buf, count);
 
   c = count;
@@ -412,22 +408,9 @@ seq_queue (unsigned char *note, char nonblock)
        * Sleep until there is enough space on the queue
        */
 
-      {
-       unsigned long   tl;
-
-       if (0)
-         current->timeout = tl = jiffies + (0);
-       else
-         tl = 0xffffffff;
-       seq_sleep_flag.mode = WK_SLEEP;
-       interruptible_sleep_on (&seq_sleeper);
-       if (!(seq_sleep_flag.mode & WK_WAKEUP))
-         {
-           if (jiffies >= tl)
-             seq_sleep_flag.mode |= WK_TIMEOUT;
-         }
-       seq_sleep_flag.mode &= ~WK_SLEEP;
-      };
+      seq_sleep_flag.mode = WK_SLEEP;
+      module_interruptible_sleep_on (&seq_sleeper);
+      seq_sleep_flag.mode &= ~WK_SLEEP;;
     }
 
   if (qlen >= SEQ_MAX_QUEUE)
@@ -729,7 +712,7 @@ seq_timing_event (unsigned char *event)
                {
                  {
                    seq_sleep_flag.mode = WK_WAKEUP;
-                   wake_up (&seq_sleeper);
+                   module_wake_up (&seq_sleeper);
                  };
                }
              restore_flags (flags);
@@ -769,7 +752,7 @@ seq_timing_event (unsigned char *event)
                {
                  {
                    seq_sleep_flag.mode = WK_WAKEUP;
-                   wake_up (&seq_sleeper);
+                   module_wake_up (&seq_sleeper);
                  };
                }
              restore_flags (flags);
@@ -819,7 +802,7 @@ seq_local_event (unsigned char *event)
   switch (cmd)
     {
     case LOCL_STARTAUDIO:
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
       DMAbuf_start_devices (parm);
 #endif
       break;
@@ -905,7 +888,7 @@ play_event (unsigned char *q)
                {
                  {
                    seq_sleep_flag.mode = WK_WAKEUP;
-                   wake_up (&seq_sleeper);
+                   module_wake_up (&seq_sleeper);
                  };
                }
              restore_flags (flags);
@@ -1041,7 +1024,7 @@ seq_startplay (void)
        {
          {
            seq_sleep_flag.mode = WK_WAKEUP;
-           wake_up (&seq_sleeper);
+           module_wake_up (&seq_sleeper);
          };
        }
       restore_flags (flags);
@@ -1095,6 +1078,7 @@ sequencer_open (int dev, struct fileinfo *file)
 {
   int             retval, mode, i;
   int             level, tmp;
+  unsigned long   flags;
 
   level = ((dev & 0x0f) == SND_DEV_SEQ2) ? 2 : 1;
 
@@ -1109,9 +1093,7 @@ sequencer_open (int dev, struct fileinfo *file)
       return -ENXIO;
     }
 
-  if (dev)                     /*
-                                * Patch manager device
-                                */
+  if (dev)                     /* Patch manager device */
     {
       int             err;
 
@@ -1125,19 +1107,22 @@ sequencer_open (int dev, struct fileinfo *file)
       if (pmgr_present[dev])
        return -EBUSY;
       if ((err = pmgr_open (dev)) < 0)
-       return err;             /*
-                                * Failed
-                                */
+       return err;
 
       pmgr_present[dev] = 1;
       return err;
     }
 
+  save_flags (flags);
+  cli ();
   if (sequencer_busy)
     {
       printk ("Sequencer busy\n");
+      restore_flags (flags);
       return -EBUSY;
     }
+  sequencer_busy = 1;
+  restore_flags (flags);
 
   max_mididev = num_midis;
   max_synthdev = num_synths;
@@ -1173,6 +1158,7 @@ sequencer_open (int dev, struct fileinfo *file)
       if (tmr == NULL)
        {
          printk ("sequencer: No timer for level 2\n");
+         sequencer_busy = 0;
          return -ENXIO;
        }
       setup_mode2 ();
@@ -1182,6 +1168,7 @@ sequencer_open (int dev, struct fileinfo *file)
     if (!max_mididev)
       {
        printk ("Sequencer: No Midi devices. Input not possible\n");
+       sequencer_busy = 0;
        return -ENXIO;
       }
 
@@ -1239,7 +1226,6 @@ sequencer_open (int dev, struct fileinfo *file)
       tmr->open (tmr_no, seq_mode);
     }
 
-  sequencer_busy = 1;
   seq_sleep_flag.mode = WK_NONE;
   midi_sleep_flag.mode = WK_NONE;
   output_treshold = SEQ_MAX_QUEUE / 2;
@@ -1262,7 +1248,7 @@ seq_drain_midi_queues (void)
 
   n = 1;
 
-  while (!(current->signal & ~current->blocked) && n)
+  while (!current_got_fatal_signal () && n)
     {
       n = 0;
 
@@ -1282,11 +1268,11 @@ seq_drain_midi_queues (void)
            unsigned long   tl;
 
            if (HZ / 10)
-             current->timeout = tl = jiffies + (HZ / 10);
+             current_set_timeout (tl = jiffies + (HZ / 10));
            else
              tl = 0xffffffff;
            seq_sleep_flag.mode = WK_SLEEP;
-           interruptible_sleep_on (&seq_sleeper);
+           module_interruptible_sleep_on (&seq_sleeper);
            if (!(seq_sleep_flag.mode & WK_WAKEUP))
              {
                if (jiffies >= tl)
@@ -1324,7 +1310,7 @@ sequencer_release (int dev, struct fileinfo *file)
 
   if (mode != OPEN_READ && !(file->flags & (O_NONBLOCK) ?
                             1 : 0))
-    while (!(current->signal & ~current->blocked) && qlen)
+    while (!current_got_fatal_signal () && qlen)
       {
        seq_sync ();
       }
@@ -1370,7 +1356,7 @@ seq_sync (void)
 {
   unsigned long   flags;
 
-  if (qlen && !seq_playing && !(current->signal & ~current->blocked))
+  if (qlen && !seq_playing && !current_got_fatal_signal ())
     seq_startplay ();
 
   save_flags (flags);
@@ -1381,12 +1367,12 @@ seq_sync (void)
       {
        unsigned long   tl;
 
-       if (0)
-         current->timeout = tl = jiffies + (0);
+       if (HZ)
+         current_set_timeout (tl = jiffies + (HZ));
        else
          tl = 0xffffffff;
        seq_sleep_flag.mode = WK_SLEEP;
-       interruptible_sleep_on (&seq_sleeper);
+       module_interruptible_sleep_on (&seq_sleeper);
        if (!(seq_sleep_flag.mode & WK_WAKEUP))
          {
            if (jiffies >= tl)
@@ -1427,11 +1413,11 @@ midi_outc (int dev, unsigned char data)
        unsigned long   tl;
 
        if (4)
-         current->timeout = tl = jiffies + (4);
+         current_set_timeout (tl = jiffies + (4));
        else
          tl = 0xffffffff;
        seq_sleep_flag.mode = WK_SLEEP;
-       interruptible_sleep_on (&seq_sleeper);
+       module_interruptible_sleep_on (&seq_sleeper);
        if (!(seq_sleep_flag.mode & WK_WAKEUP))
          {
            if (jiffies >= tl)
@@ -1521,7 +1507,7 @@ seq_reset (void)
       /*      printk ("Sequencer Warning: Unexpected sleeping process - Waking up\n"); */
       {
        seq_sleep_flag.mode = WK_WAKEUP;
-       wake_up (&seq_sleeper);
+       module_wake_up (&seq_sleeper);
       };
     }
   restore_flags (flags);
@@ -1605,7 +1591,7 @@ sequencer_ioctl (int dev, struct fileinfo *file,
 
       if (mode == OPEN_READ)
        return 0;
-      while (qlen && !(current->signal & ~current->blocked))
+      while (qlen && !current_got_fatal_signal ())
        seq_sync ();
       if (qlen)
        return -EINTR;
@@ -1921,7 +1907,7 @@ sequencer_ioctl (int dev, struct fileinfo *file,
 }
 
 int
-sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
+sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
 {
   unsigned long   flags;
 
@@ -1935,7 +1921,7 @@ sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * w
       if (!iqlen)
        {
          midi_sleep_flag.mode = WK_SLEEP;
-         select_wait (&midi_sleeper, wait);
+         module_select_wait (&midi_sleeper, wait);
          restore_flags (flags);
          return 0;
        }
@@ -1947,10 +1933,10 @@ sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * w
     case SEL_OUT:
       save_flags (flags);
       cli ();
-      if (qlen >= SEQ_MAX_QUEUE)
+      if ((SEQ_MAX_QUEUE - qlen) < output_treshold)
        {
          seq_sleep_flag.mode = WK_SLEEP;
-         select_wait (&seq_sleeper, wait);
+         module_select_wait (&seq_sleeper, wait);
          restore_flags (flags);
          return 0;
        }
@@ -2076,5 +2062,3 @@ sequencer_init (long mem_start)
 }
 
 #endif
-
-#endif
index b92692c70a8964add4ae91be5ba563781fae6a84..381cf2aac035b51bb7a1bc8c1a183c1664713bbc 100644 (file)
@@ -5,9 +5,11 @@
 int DMAbuf_open(int dev, int mode);
 int DMAbuf_release(int dev, int mode);
 int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock);
+int DMAbuf_get_curr_buffer(int dev, int *buff_no, char **dma_buf, int *buff_ptr, int *buff_size);
 int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock);
 int DMAbuf_rmchars(int dev, int buff_no, int c);
 int DMAbuf_start_output(int dev, int buff_no, int l);
+int DMAbuf_set_count(int dev, int buff_no, int l);
 int DMAbuf_ioctl(int dev, unsigned int cmd, ioctl_arg arg, int local);
 long DMAbuf_init(long mem_start);
 int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode);
@@ -16,7 +18,7 @@ void DMAbuf_close_dma (int dev);
 void DMAbuf_reset_dma (int dev);
 void DMAbuf_inputintr(int dev);
 void DMAbuf_outputintr(int dev, int underflow_flag);
-int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
+int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait);
 void DMAbuf_start_devices(unsigned int devmask);
 
 /*
@@ -32,7 +34,7 @@ int audio_ioctl (int dev, struct fileinfo *file,
 int audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
 long audio_init (long mem_start);
 
-int audio_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
+int audio_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait);
 
 /*
  *     System calls for the /dev/sequencer
@@ -52,7 +54,7 @@ unsigned long compute_finetune(unsigned long base_freq, int bend, int range);
 void seq_input_event(unsigned char *event, int len);
 void seq_copy_to_input (unsigned char *event, int len);
 
-int sequencer_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
+int sequencer_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait);
 
 /*
  *     System calls for the /dev/midi
@@ -68,7 +70,7 @@ int MIDIbuf_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
 void MIDIbuf_bytes_received(int dev, unsigned char *buf, int count);
 long MIDIbuf_init(long mem_start);
 
-int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
+int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait);
 
 /*
  *
@@ -77,7 +79,7 @@ int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, select_table *
 
 /*     From soundcard.c        */
 void soundcard_init(void);
-void tenmicrosec(void);
+void tenmicrosec(sound_os_info *osp);
 void request_sound_timer (int count);
 void sound_stop_timer(void);
 int snd_ioctl_return(int *addr, int value);
@@ -85,6 +87,8 @@ int snd_set_irq_handler (int interrupt_level, void(*hndlr)(int, struct pt_regs *
 void snd_release_irq(int vect);
 void sound_dma_malloc(int dev);
 void sound_dma_free(int dev);
+void conf_printf(char *name, struct address_info *hw_config);
+void conf_printf2(char *name, int base, int irq, int dma, int dma2);
 
 /*     From sound_switch.c     */
 int sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf *buf, int count);
@@ -114,6 +118,7 @@ void sb16midiintr (int unit);
 long attach_sb16midi(long mem_start, struct address_info * hw_config);
 int probe_sb16midi(struct address_info *hw_config);
 void sb_midi_interrupt(int dummy);
+void sbmidiintr(int irq, struct pt_regs * dummy);
 
 /*     From sb_midi.c  */
 void sb_midi_init(int model);
@@ -268,6 +273,7 @@ long attach_mad16_mpu (long mem_start, struct address_info *hw_config);
 int probe_mad16_mpu (struct address_info *hw_config);
 int mad16_sb_dsp_detect (struct address_info *hw_config);
 long mad16_sb_dsp_init (long mem_start, struct address_info *hw_config);
+void mad16_sb_dsp_unload(struct address_info *hw_config);
 
 /*     Unload routines from various source files*/
 void unload_pss(struct address_info *hw_info);
index a23a45664e334d24d58c6e502dddf51f18420617..2dd122ec6d3d97d38eb05f7066790f70db536055 100644 (file)
  *
  */
 
-#undef CONFIGURE_SOUNDCARD
-#undef DYNAMIC_BUFFER
-
-#include "local.h"
-
-#ifdef KERNEL_SOUNDCARD
-#define CONFIGURE_SOUNDCARD
-#define DYNAMIC_BUFFER
-#undef LOADABLE_SOUNDCARD
-#endif
-
 #include "os.h"
+#include "local.h"
 #include "soundvers.h"
 
 #if defined(ISC) || defined(SCO) || defined(SVR42)
 
 
 
-
 #ifndef SND_DEFAULT_ENABLE
 #define SND_DEFAULT_ENABLE     1
 #endif
 
-#ifdef CONFIGURE_SOUNDCARD
-
 #ifndef MAX_REALTIME_FACTOR
 #define MAX_REALTIME_FACTOR    4
 #endif
 #define PAS_BASE       0x388
 #endif
 
-#ifdef JAZZ16
-#ifndef JAZZ_DMA16
-#define JAZZ_DMA16     5
+#if defined(SB16_DMA) && !defined(SB_DMA2)
+#  define SB_DMA2 SB16_DMA
+#endif
+
+#if defined(SB16MIDI_BASE) && !defined(SB_MPU_BASE)
+#   define SB_MPU_BASE SB16MIDI_BASE
 #endif
+
+#ifndef SB_MPU_IRQ
+#  define SB_MPU_IRQ SBC_IRQ
 #endif
 
 /* SEQ_MAX_QUEUE is the maximum number of sequencer events buffered by the
@@ -198,5 +191,3 @@ struct channel_info {
 
 #define TIMER_ARMED    121234
 #define TIMER_NOT_ARMED        1
-
-#endif
index 86ea26aec68f63e17d723e5bb2ebad52445a0635..0732235ac608998c2a799a8ff032c4657c6ecbbd 100644 (file)
@@ -28,7 +28,7 @@
  */
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_PNP)
+#if defined(CONFIG_PNP)
 
 #include <linux/pnp.h>
 
index 4adb689b603955aab7149136bfe7521953c4d236..5405a3cbabd2d6a603e3884f9cf4c5487170d70e 100644 (file)
 
 #include "sound_config.h"
 
-#ifdef CONFIGURE_SOUNDCARD
-
 struct sbc_device
   {
     int             usecount;
   };
 
-static struct sbc_device sbc_devices[SND_NDEVS] =
-{
-  {0}};
-
 static int      in_use = 0;    /*
 
 
@@ -210,7 +204,7 @@ init_status (void)
       return;
     }
 
-#ifdef EXCLUDE_AUDIO
+#ifndef CONFIG_AUDIO
   if (!put_status ("\nAudio devices: NOT ENABLED IN CONFIG\n"))
     return;
 #else
@@ -235,7 +229,7 @@ init_status (void)
     }
 #endif
 
-#ifdef EXCLUDE_SEQUENCER
+#ifndef CONFIG_SEQUENCER
   if (!put_status ("\nSynth devices: NOT ENABLED IN CONFIG\n"))
     return;
 #else
@@ -255,7 +249,7 @@ init_status (void)
     }
 #endif
 
-#ifdef EXCLUDE_MIDI
+#ifndef CONFIG_MIDI
   if (!put_status ("\nMidi devices: NOT ENABLED IN CONFIG\n"))
     return;
 #else
@@ -339,7 +333,7 @@ sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
       return read_status (buf, count);
       break;
 
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
     case SND_DEV_DSP:
     case SND_DEV_DSP16:
     case SND_DEV_AUDIO:
@@ -347,14 +341,14 @@ sound_read_sw (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
       break;
 #endif
 
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
     case SND_DEV_SEQ:
     case SND_DEV_SEQ2:
       return sequencer_read (dev, file, buf, count);
       break;
 #endif
 
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
     case SND_DEV_MIDIN:
       return MIDIbuf_read (dev, file, buf, count);
 #endif
@@ -375,14 +369,14 @@ sound_write_sw (int dev, struct fileinfo *file, const snd_rw_buf * buf, int coun
   switch (dev & 0x0f)
     {
 
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
     case SND_DEV_SEQ:
     case SND_DEV_SEQ2:
       return sequencer_write (dev, file, buf, count);
       break;
 #endif
 
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
     case SND_DEV_DSP:
     case SND_DEV_DSP16:
     case SND_DEV_AUDIO:
@@ -390,7 +384,7 @@ sound_write_sw (int dev, struct fileinfo *file, const snd_rw_buf * buf, int coun
       break;
 #endif
 
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
     case SND_DEV_MIDIN:
       return MIDIbuf_write (dev, file, buf, count);
 #endif
@@ -407,7 +401,7 @@ sound_open_sw (int dev, struct fileinfo *file)
 {
   int             retval;
 
-  DEB (printk ("sound_open_sw(dev=%d) : usecount=%d\n", dev, sbc_devices[dev].usecount));
+  DEB (printk ("sound_open_sw(dev=%d)\n", dev));
 
   if ((dev >= SND_NDEVS) || (dev < 0))
     {
@@ -431,7 +425,7 @@ sound_open_sw (int dev, struct fileinfo *file)
       return 0;
       break;
 
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
     case SND_DEV_SEQ:
     case SND_DEV_SEQ2:
       if ((retval = sequencer_open (dev, file)) < 0)
@@ -439,14 +433,14 @@ sound_open_sw (int dev, struct fileinfo *file)
       break;
 #endif
 
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
     case SND_DEV_MIDIN:
       if ((retval = MIDIbuf_open (dev, file)) < 0)
        return retval;
       break;
 #endif
 
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
     case SND_DEV_DSP:
     case SND_DEV_DSP16:
     case SND_DEV_AUDIO:
@@ -460,7 +454,6 @@ sound_open_sw (int dev, struct fileinfo *file)
       return -ENXIO;
     }
 
-  sbc_devices[dev].usecount++;
   in_use++;
 
   return 0;
@@ -484,20 +477,20 @@ sound_release_sw (int dev, struct fileinfo *file)
     case SND_DEV_CTL:
       break;
 
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
     case SND_DEV_SEQ:
     case SND_DEV_SEQ2:
       sequencer_release (dev, file);
       break;
 #endif
 
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
     case SND_DEV_MIDIN:
       MIDIbuf_release (dev, file);
       break;
 #endif
 
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
     case SND_DEV_DSP:
     case SND_DEV_DSP16:
     case SND_DEV_AUDIO:
@@ -508,8 +501,6 @@ sound_release_sw (int dev, struct fileinfo *file)
     default:
       printk ("Sound error: Releasing unknown device 0x%02x\n", dev);
     }
-
-  sbc_devices[dev].usecount--;
   in_use--;
 }
 
@@ -527,7 +518,7 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
 
        switch (dtype)
          {
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
          case SND_DEV_DSP:
          case SND_DEV_DSP16:
          case SND_DEV_AUDIO:
@@ -559,14 +550,14 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
       return mixer_devs[dev]->ioctl (dev, cmd, arg);
       break;
 
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
     case SND_DEV_SEQ:
     case SND_DEV_SEQ2:
       return sequencer_ioctl (dev, file, cmd, arg);
       break;
 #endif
 
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
     case SND_DEV_DSP:
     case SND_DEV_DSP16:
     case SND_DEV_AUDIO:
@@ -574,7 +565,7 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
       break;
 #endif
 
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
     case SND_DEV_MIDIN:
       return MIDIbuf_ioctl (dev, file, cmd, arg);
       break;
@@ -587,5 +578,3 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
 
   return -EPERM;
 }
-
-#endif
index fc387a9a3c5213a597f2baa6f0deed8a878bd659..b19e0e2e94b14fd9698190e235a333c5dde9368c 100644 (file)
@@ -28,9 +28,7 @@
 #define SEQUENCER_C
 #include "sound_config.h"
 
-#ifdef CONFIGURE_SOUNDCARD
-
-#if !defined(EXCLUDE_SEQUENCER)
+#if defined(CONFIG_SEQUENCER)
 
 static volatile int initialized = 0, opened = 0, tmr_running = 0;
 static volatile time_t tmr_offs, tmr_ctr;
@@ -352,4 +350,3 @@ sound_timer_init (struct sound_lowlev_timer *t, char *name)
 }
 
 #endif
-#endif
index 55cdebbd38922bd8bfabe79a2680b7c0608a20d1..e4e0667802862d5bb34275b2badca46be58326f9 100644 (file)
 /*
  * Created modular version by Peter Trattler (peter@sbox.tu-graz.ac.at)
  */
-#include <linux/module.h>
 
 #include "sound_config.h"
 
-#ifdef CONFIGURE_SOUNDCARD
-
 #include <linux/major.h>
 
-#ifndef EXCLUDE_PNP
+#ifdef CONFIG_PNP
 #include <linux/pnp.h>
 #endif
 
@@ -73,37 +70,37 @@ snd_ioctl_return (int *addr, int value)
 }
 
 static int
-sound_read (struct inode *inode, struct file *file, char *buf, int count)
+sound_read (inode_handle * inode, file_handle * file, char *buf, int count)
 {
   int             dev;
 
-  dev = inode->i_rdev;
+  dev = inode_get_rdev (inode);
   dev = MINOR (dev);
-  files[dev].flags = file->f_flags;
+  files[dev].flags = file_get_flags (file);
 
   return sound_read_sw (dev, &files[dev], buf, count);
 }
 
 static int
-sound_write (struct inode *inode, struct file *file, const char *buf, int count)
+sound_write (inode_handle * inode, file_handle * file, const char *buf, int count)
 {
   int             dev;
 
-  dev = inode->i_rdev;
+  dev = inode_get_rdev (inode);
   dev = MINOR (dev);
-  files[dev].flags = file->f_flags;
+  files[dev].flags = file_get_flags (file);
 
   return sound_write_sw (dev, &files[dev], buf, count);
 }
 
 static int
-sound_lseek (struct inode *inode, struct file *file, off_t offset, int orig)
+sound_lseek (inode_handle * inode, file_handle * file, off_t offset, int orig)
 {
   return -EPERM;
 }
 
 static int
-sound_open (struct inode *inode, struct file *file)
+sound_open (inode_handle * inode, file_handle * file)
 {
   int             dev, retval;
   struct fileinfo tmp_file;
@@ -114,7 +111,7 @@ sound_open (struct inode *inode, struct file *file)
       return -EBUSY;
     }
 
-  dev = inode->i_rdev;
+  dev = inode_get_rdev (inode);
   dev = MINOR (dev);
 
   if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS)
@@ -124,7 +121,7 @@ sound_open (struct inode *inode, struct file *file)
     }
 
   tmp_file.mode = 0;
-  tmp_file.flags = file->f_flags;
+  tmp_file.flags = file_get_flags (file);
 
   if ((tmp_file.flags & O_ACCMODE) == O_RDWR)
     tmp_file.mode = OPEN_READWRITE;
@@ -145,13 +142,13 @@ sound_open (struct inode *inode, struct file *file)
 }
 
 static void
-sound_release (struct inode *inode, struct file *file)
+sound_release (inode_handle * inode, file_handle * file)
 {
   int             dev;
 
-  dev = inode->i_rdev;
+  dev = inode_get_rdev (inode);
   dev = MINOR (dev);
-  files[dev].flags = file->f_flags;
+  files[dev].flags = file_get_flags (file);
 
   sound_release_sw (dev, &files[dev]);
 #ifdef MODULE
@@ -160,31 +157,31 @@ sound_release (struct inode *inode, struct file *file)
 }
 
 static int
-sound_ioctl (struct inode *inode, struct file *file,
+sound_ioctl (inode_handle * inode, file_handle * file,
             unsigned int cmd, unsigned long arg)
 {
   int             dev, err;
 
-  dev = inode->i_rdev;
+  dev = inode_get_rdev (inode);
   dev = MINOR (dev);
-  files[dev].flags = file->f_flags;
+  files[dev].flags = file_get_flags (file);
 
-  if (cmd & IOC_INOUT)
+  if (_IOC_DIR (cmd) != _IOC_NONE)
     {
       /*
          * Have to validate the address given by the process.
        */
       int             len;
 
-      len = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
+      len = _IOC_SIZE (cmd);
 
-      if (cmd & IOC_IN)
+      if (_IOC_DIR (cmd) == _IOC_WRITE)
        {
          if ((err = verify_area (VERIFY_READ, (void *) arg, len)) < 0)
            return err;
        }
 
-      if (cmd & IOC_OUT)
+      if (_IOC_DIR (cmd) == _IOC_READ)
        {
          if ((err = verify_area (VERIFY_WRITE, (void *) arg, len)) < 0)
            return err;
@@ -198,32 +195,32 @@ sound_ioctl (struct inode *inode, struct file *file,
 }
 
 static int
-sound_select (struct inode *inode, struct file *file, int sel_type, select_table * wait)
+sound_select (inode_handle * inode, file_handle * file, int sel_type, select_table_handle * wait)
 {
   int             dev;
 
-  dev = inode->i_rdev;
+  dev = inode_get_rdev (inode);
   dev = MINOR (dev);
-  files[dev].flags = file->f_flags;
+  files[dev].flags = file_get_flags (file);
 
   DEB (printk ("sound_select(dev=%d, type=0x%x)\n", dev, sel_type));
 
   switch (dev & 0x0f)
     {
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
     case SND_DEV_SEQ:
     case SND_DEV_SEQ2:
       return sequencer_select (dev, &files[dev], sel_type, wait);
       break;
 #endif
 
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
     case SND_DEV_MIDIN:
       return MIDIbuf_select (dev, &files[dev], sel_type, wait);
       break;
 #endif
 
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
     case SND_DEV_DSP:
     case SND_DEV_DSP16:
     case SND_DEV_AUDIO:
@@ -238,8 +235,98 @@ sound_select (struct inode *inode, struct file *file, int sel_type, select_table
   return 0;
 }
 
+#ifdef ALLOW_BUFFER_MAPPING
+static int
+sound_mmap (inode_handle * inode, file_handle * file, vm_area_handle * vma)
+{
+  int             dev, dev_class;
+  unsigned long   size, i;
+  struct dma_buffparms *dmap = NULL;
+
+  dev = inode_get_rdev (inode);
+  dev = MINOR (dev);
+  files[dev].flags = file_get_flags (file);
+
+  dev_class = dev & 0x0f;
+  dev >>= 4;
+
+  if (dev_class != SND_DEV_DSP && dev_class != SND_DEV_DSP16 && dev_class != SND_DEV_AUDIO)
+    {
+      printk ("Sound: mmap() not supported for other than audio devices\n");
+      return -EINVAL;
+    }
+
+  if ((vma_get_flags (vma) & (VM_READ | VM_WRITE)) == (VM_READ | VM_WRITE))
+    {
+      printk ("Sound: Cannot do read/write mmap()\n");
+      return -EINVAL;
+    }
+
+  if (vma_get_flags (vma) & VM_READ)
+    {
+      dmap = audio_devs[dev]->dmap_in;
+    }
+  else if (vma_get_flags (vma) & VM_WRITE)
+    {
+      dmap = audio_devs[dev]->dmap_out;
+    }
+  else
+    {
+      printk ("Sound: Undefined mmap() access\n");
+      return -EINVAL;
+    }
+
+  if (dmap == NULL)
+    {
+      printk ("Sound: mmap() error. dmap == NULL\n");
+      return -EIO;
+    }
+
+  if (dmap->raw_buf == NULL)
+    {
+      printk ("Sound: mmap() called when raw_buf == NULL\n");
+      return -EIO;
+    }
+
+  if (dmap->mapping_flags)
+    {
+      printk ("Sound: mmap() called twice for the same DMA buffer\n");
+      return -EIO;
+    }
+
+  if (vma_get_offset (vma) != 0)
+    {
+      printk ("Sound: mmap() offset must be 0.\n");
+      return -EINVAL;
+    }
+
+  size = vma_get_end (vma) - vma_get_start (vma);
 
-static struct file_operations sound_fops =
+  if (size != dmap->bytes_in_use)
+    {
+      printk ("Sound: mmap() size = %ld. Should be %d\n",
+             size, dmap->bytes_in_use);
+    }
+
+
+  if (remap_page_range (vma_get_start (vma), dmap->raw_buf_phys,
+                       vma_get_end (vma) - vma_get_start (vma),
+                       vma_get_page_prot (vma)))
+    return -EAGAIN;
+
+  vma_set_inode (vma, inode);
+  inode_inc_count (inode);
+
+  dmap->mapping_flags |= DMA_MAP_MAPPED;
+
+  memset (dmap->raw_buf,
+         dmap->neutral_byte,
+         dmap->bytes_in_use);
+  return 0;
+}
+#endif
+
+static struct file_operation_handle sound_fops =
 {
   sound_lseek,
   sound_read,
@@ -247,7 +334,11 @@ static struct file_operations sound_fops =
   NULL,                                /* sound_readdir */
   sound_select,
   sound_ioctl,
+#ifdef ALLOW_BUFFER_MAPPING
+  sound_mmap,
+#else
   NULL,
+#endif
   sound_open,
   sound_release
 };
@@ -256,7 +347,7 @@ void
 soundcard_init (void)
 {
 #ifndef MODULE
-  register_chrdev (SOUND_MAJOR, "sound", &sound_fops);
+  module_register_chrdev (SOUND_MAJOR, "sound", &sound_fops);
   chrdev_registered = 1;
 #endif
 
@@ -265,14 +356,14 @@ soundcard_init (void)
   sndtable_init (0);           /* Initialize call tables and
                                   * detect cards */
 
-#ifndef EXCLUDE_PNP
+#ifdef CONFIG_PNP
   sound_pnp_init ();
 #endif
 
   if (sndtable_get_cardcount () == 0)
     return;                    /* No cards detected */
 
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
   if (num_audiodevs)           /* Audio devices present */
     {
       DMAbuf_init (0);
@@ -280,12 +371,12 @@ soundcard_init (void)
     }
 #endif
 
-#ifndef EXCLUDE_MIDI
+#ifdef CONFIG_MIDI
   if (num_midis)
     MIDIbuf_init (0);
 #endif
 
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
   if (num_midis + num_synths)
     sequencer_init (0);
 #endif
@@ -309,6 +400,8 @@ free_all_irqs (void)
   irqs = 0;
 }
 
+char            kernel_version[] = UTS_RELEASE;
+
 #endif
 
 static int      debugmem = 0;  /* switched off by default */
@@ -323,7 +416,7 @@ init_module (void)
   int             ints[21];
   int             i;
 
-  if (0 < 0)
+  if (connect_wrapper (WRAPPER_VERSION) < 0)
     {
       printk ("Sound: Incompatible kernel (wrapper) version\n");
       return -EINVAL;
@@ -340,7 +433,7 @@ init_module (void)
   if (i)
     sound_setup ("sound=", ints);
 
-  err = register_chrdev (SOUND_MAJOR, "sound", &sound_fops);
+  err = module_register_chrdev (SOUND_MAJOR, "sound", &sound_fops);
   if (err)
     {
       printk ("sound: driver already loaded/included in kernel\n");
@@ -369,9 +462,9 @@ cleanup_module (void)
       int             i;
 
       if (chrdev_registered)
-       unregister_chrdev (SOUND_MAJOR, "sound");
+       module_unregister_chrdev (SOUND_MAJOR, "sound");
 
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
       sound_stop_timer ();
 #endif
       sound_unload_drivers ();
@@ -388,7 +481,7 @@ cleanup_module (void)
            sound_free_dma (i);
          }
 
-#ifndef EXCLUDE_PNP
+#ifdef CONFIG_PNP
       sound_pnp_disconnect ();
 #endif
 
@@ -397,7 +490,7 @@ cleanup_module (void)
 #endif
 
 void
-tenmicrosec (void)
+tenmicrosec (sound_os_info * osp)
 {
   int             i;
 
@@ -466,7 +559,7 @@ sound_free_dma (int chn)
 {
   if (dma_alloc_map[chn] != DMA_MAP_FREE)
     {
-      printk ("sound_free_dma: Bad access to DMA channel %d\n", chn);
+      /* printk ("sound_free_dma: Bad access to DMA channel %d\n", chn); */
       return;
     }
   free_dma (chn);
@@ -491,7 +584,7 @@ sound_close_dma (int chn)
   restore_flags (flags);
 }
 
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
 
 
 static struct timer_list seq_timer =
@@ -507,6 +600,7 @@ request_sound_timer (int count)
   else
     count += seq_time;
 
+  ;
 
   {
     seq_timer.expires = ((count - jiffies)) + jiffies;
@@ -521,7 +615,7 @@ sound_stop_timer (void)
 }
 #endif
 
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
 
 #ifdef KMALLOC_DMA_BROKEN
 fatal_error__This_version_is_not_compatible_with_this_kernel;
@@ -535,6 +629,10 @@ sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan)
   char           *start_addr, *end_addr;
   int             i, dma_pagesize;
 
+#ifdef ALLOW_BUFFER_MAPPING
+  dmap->mapping_flags &= ~DMA_MAP_MAPPED;
+#endif
+
   if (dmap->raw_buf != NULL)
     return 0;                  /* Already done */
 
@@ -611,7 +709,7 @@ sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan)
 
   for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
     {
-      mem_map[i].reserved = 1;
+      mem_map_reserve (i);
     }
 
   return 0;
@@ -622,6 +720,12 @@ sound_free_dmap (int dev, struct dma_buffparms *dmap)
 {
   if (dmap->raw_buf == NULL)
     return;
+
+#ifdef ALLOW_BUFFER_MAPPING
+  if (dmap->mapping_flags & DMA_MAP_MAPPED)
+    return;                    /* Don't free mmapped buffer. Will use it next time */
+#endif
+
   {
     int             sz, size, i;
     unsigned long   start_addr, end_addr;
@@ -635,7 +739,7 @@ sound_free_dmap (int dev, struct dma_buffparms *dmap)
 
     for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
       {
-       mem_map[i].reserved = 0;
+       mem_map_unreserve (i);
       }
 
     free_pages ((unsigned long) dmap->raw_buf, sz);
@@ -651,13 +755,45 @@ soud_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc * info)
   return -EINVAL;
 }
 
-#else
-
 void
-soundcard_init (void)          /* Dummy version */
+conf_printf (char *name, struct address_info *hw_config)
 {
+  if (!trace_init)
+    return;
+
+  printk ("<%s> at 0x%03x", name, hw_config->io_base);
+
+  if (hw_config->irq)
+    printk (" irq %d", hw_config->irq);
+
+  if (hw_config->dma != -1 || hw_config->dma2 != -1)
+    {
+      printk (" dma %d", hw_config->dma);
+      if (hw_config->dma2 != -1)
+       printk (",%d", hw_config->dma2);
+    }
+
+  printk ("\n");
 }
 
-#endif
+void
+conf_printf2 (char *name, int base, int irq, int dma, int dma2)
+{
+  if (!trace_init)
+    return;
+
+  printk ("<%s> at 0x%03x", name, base);
+
+  if (irq)
+    printk (" irq %d", irq);
 
+  if (dma != -1 || dma2 != -1)
+    {
+      printk (" dma %d", dma);
+      if (dma2 != -1)
+       printk (",%d", dma2);
+    }
+
+  printk ("\n");
+}
 #endif
index 241bef047466593636b6e47ecbc5c019a28fa38d..95fca0fee8dddd7a282cdd340dbe53272e96a35c 100644 (file)
@@ -1,2 +1,2 @@
-#define SOUND_VERSION_STRING "3.5-alpha5-951002"
+#define SOUND_VERSION_STRING "3.5-alpha8-960109"
 #define SOUND_INTERNAL_VERSION 0x030505
index 37dadb931acacc8c1d036e0933e91d931708b3d2..6f9fe07ccd86446aa8e64355c6796ee566defa2a 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SSCAPE)
+#if defined(CONFIG_SSCAPE)
 
 #include "coproc.h"
 
@@ -102,7 +102,7 @@ static struct sscape_info dev_info =
 {0};
 static struct sscape_info *devc = &dev_info;
 
-static struct wait_queue *sscape_sleeper = NULL;
+static wait_handle *sscape_sleeper = NULL;
 static volatile struct snd_wait sscape_sleep_flag =
 {0};
 
@@ -309,7 +309,7 @@ sscapeintr (int irq, struct pt_regs *dummy)
     {
       {
        sscape_sleep_flag.mode = WK_WAKEUP;
-       wake_up (&sscape_sleeper);
+       module_wake_up (&sscape_sleeper);
       };
     }
 
@@ -318,7 +318,7 @@ sscapeintr (int irq, struct pt_regs *dummy)
       printk ("SSCAPE: Host interrupt, data=%02x\n", host_read (devc));
     }
 
-#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
   if (bits & 0x01)
     {
       mpuintr (irq, NULL);
@@ -338,35 +338,6 @@ sscapeintr (int irq, struct pt_regs *dummy)
 
 }
 
-static void
-sscape_enable_intr (struct sscape_info *devc, unsigned intr_bits)
-{
-  unsigned char   temp, orig;
-
-  temp = orig = sscape_read (devc, GA_INTENA_REG);
-  temp |= intr_bits;
-  temp |= 0x80;                        /* Master IRQ enable */
-
-  if (temp == orig)
-    return;                    /* No change */
-
-  sscape_write (devc, GA_INTENA_REG, temp);
-}
-
-static void
-sscape_disable_intr (struct sscape_info *devc, unsigned intr_bits)
-{
-  unsigned char   temp, orig;
-
-  temp = orig = sscape_read (devc, GA_INTENA_REG);
-  temp &= ~intr_bits;
-  if ((temp & ~0x80) == 0x00)
-    temp = 0x00;               /* Master IRQ disable */
-  if (temp == orig)
-    return;                    /* No change */
-
-  sscape_write (devc, GA_INTENA_REG, temp);
-}
 
 static void
 do_dma (struct sscape_info *devc, int dma_chan, unsigned long buf, int blk_size, int mode)
@@ -431,6 +402,7 @@ sscape_coproc_open (void *dev_info, int sub_device)
        return -EIO;
     }
 
+  sscape_sleep_flag.mode = WK_NONE;
   return 0;
 }
 
@@ -445,7 +417,7 @@ sscape_coproc_close (void *dev_info, int sub_device)
   if (devc->dma_allocated)
     {
       sscape_write (devc, GA_DMAA_REG, 0x20);  /* DMA channel disabled */
-#ifndef EXCLUDE_NATIVE_PCM
+#ifdef CONFIG_NATIVE_PCM
 #endif
       devc->dma_allocated = 0;
     }
@@ -478,7 +450,7 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
       cli ();
       if (devc->dma_allocated == 0)
        {
-#ifndef EXCLUDE_NATIVE_PCM
+#ifdef CONFIG_NATIVE_PCM
 #endif
 
          devc->dma_allocated = 1;
@@ -523,11 +495,11 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
        unsigned long   tl;
 
        if (1)
-         current->timeout = tl = jiffies + (1);
+         current_set_timeout (tl = jiffies + (1));
        else
          tl = 0xffffffff;
        sscape_sleep_flag.mode = WK_SLEEP;
-       interruptible_sleep_on (&sscape_sleeper);
+       module_interruptible_sleep_on (&sscape_sleeper);
        if (!(sscape_sleep_flag.mode & WK_WAKEUP))
          {
            if (jiffies >= tl)
@@ -571,11 +543,11 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
            unsigned long   tl;
 
            if (1)
-             current->timeout = tl = jiffies + (1);
+             current_set_timeout (tl = jiffies + (1));
            else
              tl = 0xffffffff;
            sscape_sleep_flag.mode = WK_SLEEP;
-           interruptible_sleep_on (&sscape_sleeper);
+           module_interruptible_sleep_on (&sscape_sleeper);
            if (!(sscape_sleep_flag.mode & WK_WAKEUP))
              {
                if (jiffies >= tl)
@@ -604,11 +576,11 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
            unsigned long   tl;
 
            if (1)
-             current->timeout = tl = jiffies + (1);
+             current_set_timeout (tl = jiffies + (1));
            else
              tl = 0xffffffff;
            sscape_sleep_flag.mode = WK_SLEEP;
-           interruptible_sleep_on (&sscape_sleeper);
+           module_interruptible_sleep_on (&sscape_sleeper);
            if (!(sscape_sleep_flag.mode & WK_WAKEUP))
              {
                if (jiffies >= tl)
@@ -917,10 +889,10 @@ attach_sscape (long mem_start, struct address_info *hw_config)
   if (old_hardware)
     {
       valid_interrupts = valid_interrupts_old;
-      printk (" <Ensoniq Soundscape (old)>");
+      conf_printf ("Ensoniq Soundscape (old)", hw_config);
     }
   else
-    printk (" <Ensoniq Soundscape>");
+    conf_printf ("Ensoniq Soundscape", hw_config);
 
   for (i = 0; i < sizeof (valid_interrupts); i++)
     if (hw_config->irq == valid_interrupts[i])
@@ -964,7 +936,7 @@ attach_sscape (long mem_start, struct address_info *hw_config)
 
       case 9:                  /* Master control reg. Don't modify CR-ROM bits. Disable SB emul */
        sscape_write (devc, i,
-                     (sscape_read (devc, i) & 0xf0) | 0x00);
+                     (sscape_read (devc, i) & 0xf0) | 0x08);
        break;
 
       default:
@@ -986,7 +958,7 @@ attach_sscape (long mem_start, struct address_info *hw_config)
   }
 #endif
 
-#if !defined(EXCLUDE_MIDI) && !defined(EXCLUDE_MPU_EMU)
+#if defined(CONFIG_MIDI) && defined(CONFIG_MPU_EMU)
   if (probe_mpu401 (hw_config))
     hw_config->always_detect = 1;
   {
@@ -1003,7 +975,7 @@ attach_sscape (long mem_start, struct address_info *hw_config)
 #ifndef EXCLUDE_NATIVE_PCM
   /* Not supported yet */
 
-#ifndef EXCLUDE_AUDIO
+#ifdef CONFIG_AUDIO
   if (num_audiodevs < MAX_AUDIO_DEV)
     {
       audio_devs[my_dev = num_audiodevs++] = &sscape_audio_operations;
@@ -1088,7 +1060,6 @@ probe_sscape (struct address_info *hw_config)
 
   if (old_hardware)            /* Check that it's really an old Spea/Reveal card. */
     {
-      int             status = 0;
       unsigned char   tmp;
       int             cc;
 
@@ -1153,7 +1124,7 @@ attach_ss_ms_sound (long mem_start, struct address_info *hw_config)
 
   int             i, irq_bits = 0xff;
 
-#ifdef EXCLUDE_NATIVE_PCM
+#ifndef CONFIG_NATIVE_PCM
   int             prev_devs = num_audiodevs;
 
 #endif
@@ -1192,7 +1163,7 @@ attach_ss_ms_sound (long mem_start, struct address_info *hw_config)
               0,
               devc->osp);
 
-#ifdef EXCLUDE_NATIVE_PCM
+#ifndef CONFIG_NATIVE_PCM
   if (num_audiodevs == (prev_devs + 1))                /* The AD1848 driver installed itself */
     audio_devs[prev_devs]->coproc = &sscape_coproc_operations;
 #endif
index e251ee25cf8213d362d130c91afd1b56ef06254f..15e0232e3db2e1f394cf536906dc5dc07c088c02 100644 (file)
@@ -31,9 +31,7 @@
 #define SEQUENCER_C
 #include "sound_config.h"
 
-#ifdef CONFIGURE_SOUNDCARD
-
-#ifndef EXCLUDE_SEQUENCER
+#ifdef CONFIG_SEQUENCER
 
 static volatile int opened = 0, tmr_running = 0;
 static volatile time_t tmr_offs, tmr_ctr;
@@ -113,6 +111,7 @@ def_tmr_open (int dev, int mode)
   curr_timebase = HZ;
   opened = 1;
 
+  ;
 
   {
     def_tmr.expires = (1) + jiffies;
@@ -307,4 +306,3 @@ struct sound_timer_operations default_sound_timer =
 };
 
 #endif
-#endif
index 3c12d0e1df0de09c4d81f7b8a6a1df85243a120e..53a5aae06e8cf47032494e31a2e4732da46f521c 100644 (file)
 
 #include "sound_config.h"
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_TRIX)
+#if defined(CONFIG_TRIX)
 
 #ifdef INCLUDE_TRIX_BOOT
 #include "trix_boot.h"
 #endif
 
+
 static int      kilroy_was_here = 0;   /* Don't detect twice */
 static int      sb_initialized = 0;
 static int      mpu_initialized = 0;
@@ -80,6 +81,7 @@ download_boot (int base)
   outb (0x00, base + 6);       /* Reset */
   outb (0x50, 0x390);          /* ?????? */
 #endif
+
 }
 
 static int
@@ -324,20 +326,20 @@ probe_trix_sb (struct address_info *hw_config)
 long
 attach_trix_sb (long mem_start, struct address_info *hw_config)
 {
-#ifndef EXCLUDE_SB
+#ifdef CONFIG_SB
   extern int      sb_no_recording;
 
   sb_dsp_disable_midi ();
   sb_no_recording = 1;
 #endif
-  printk (" <AudioTriX (SB)>");
+  conf_printf ("AudioTriX (SB)", hw_config);
   return mem_start;
 }
 
 long
 attach_trix_mpu (long mem_start, struct address_info *hw_config)
 {
-#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
   return attach_mpu401 (mem_start, hw_config);
 #else
   return mem_start;
@@ -347,7 +349,7 @@ attach_trix_mpu (long mem_start, struct address_info *hw_config)
 int
 probe_trix_mpu (struct address_info *hw_config)
 {
-#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
   unsigned char   conf;
   static char     irq_bits[] =
   {-1, -1, -1, 1, 2, 3, -1, 4, -1, 5};
@@ -439,7 +441,7 @@ unload_trix_wss (struct address_info *hw_config)
 void
 unload_trix_mpu (struct address_info *hw_config)
 {
-#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
   unload_mpu401 (hw_config);
 #endif
 }
index f4687ac4b29326b62692636fca1a6a71d155e520..5b148115eaa1e1673746e7699283863a74399402 100644 (file)
@@ -30,9 +30,7 @@
 
 #include "sound_config.h"
 
-#ifdef CONFIGURE_SOUNDCARD
-
-#if !defined(EXCLUDE_UART6850) && !defined(EXCLUDE_MIDI)
+#if defined(CONFIG_UART6850) && defined(CONFIG_MIDI)
 
 #define        DATAPORT   (uart6850_base)      /*
                                           * * * Midi6850 Data I/O Port on IBM
@@ -117,9 +115,7 @@ poll_uart6850 (unsigned long dummy)
   unsigned long   flags;
 
   if (!(uart6850_opened & OPEN_READ))
-    return;                    /*
-                                * No longer required
-                                */
+    return;                    /* Device has been closed */
 
   save_flags (flags);
   cli ();
@@ -150,6 +146,7 @@ uart6850_open (int dev, int mode,
       return -EBUSY;
     }
 
+  ;
   uart6850_cmd (UART_RESET);
 
   uart6850_input_loop ();
@@ -298,7 +295,7 @@ attach_uart6850 (long mem_start, struct address_info *hw_config)
 
   restore_flags (flags);
 
-  printk (" <6850 Midi Interface>");
+  conf_printf ("6850 Midi Interface", hw_config);
 
   std_midi_synth.midi_dev = my_dev = num_midis;
   midi_devs[num_midis++] = &uart6850_operations;
@@ -340,5 +337,3 @@ unload_uart6850 (struct address_info *hw_config)
 }
 
 #endif
-
-#endif
index 2c783ba675958dce51c9669e6aac345e7e7bc8bb..be9f92d9984a61d92d6ae1debddbfeff3204813c 100644 (file)
@@ -1,74 +1,69 @@
-
-/*
- * This is a new ulaw.h made by Andy Fingerhut <jaf@dworkin.wustl.edu>
- */
-
 static unsigned char ulaw_dsp[] = {
-    2,    6,   10,   14,   18,   22,   26,   30,
-   34,   38,   42,   46,   50,   54,   58,   62,
-   65,   67,   69,   71,   73,   75,   77,   79,
-   81,   83,   85,   87,   89,   91,   93,   95,
-   97,   98,   99,  100,  101,  102,  103,  104,
-  105,  106,  107,  108,  109,  110,  111,  112,
-  112,  113,  113,  114,  114,  115,  115,  116,
-  116,  117,  117,  118,  118,  119,  119,  120,
-  120,  120,  121,  121,  121,  121,  122,  122,
-  122,  122,  123,  123,  123,  123,  124,  124,
-  124,  124,  124,  124,  125,  125,  125,  125,
-  125,  125,  125,  125,  126,  126,  126,  126,
-  126,  126,  126,  126,  126,  126,  126,  126,
-  127,  127,  127,  127,  127,  127,  127,  127,
-  127,  127,  127,  127,  127,  127,  127,  127,
-  127,  127,  127,  127,  127,  127,  127,  128,
-  253,  249,  245,  241,  237,  233,  229,  225,
-  221,  217,  213,  209,  205,  201,  197,  193,
-  190,  188,  186,  184,  182,  180,  178,  176,
-  174,  172,  170,  168,  166,  164,  162,  160,
-  158,  157,  156,  155,  154,  153,  152,  151,
-  150,  149,  148,  147,  146,  145,  144,  143,
-  143,  142,  142,  141,  141,  140,  140,  139,
-  139,  138,  138,  137,  137,  136,  136,  135,
-  135,  135,  134,  134,  134,  134,  133,  133,
-  133,  133,  132,  132,  132,  132,  131,  131,
-  131,  131,  131,  131,  130,  130,  130,  130,
-  130,  130,  130,  130,  129,  129,  129,  129,
-  129,  129,  129,  129,  129,  129,  129,  129,
-  128,  128,  128,  128,  128,  128,  128,  128,
-  128,  128,  128,  128,  128,  128,  128,  128,
-  128,  128,  128,  128,  128,  128,  128,  128
+     0,    0,    0,    0,    0,    0,    0,    0, 
+     0,    0,    0,    0,    0,    0,    0,    0, 
+     0,    0,    0,    0,    0,    0,    0,    0, 
+     0,    0,    0,    0,    0,    0,    0,    2, 
+     5,    9,   13,   17,   21,   25,   29,   33, 
+    37,   41,   45,   49,   53,   57,   61,   65, 
+    68,   70,   72,   74,   76,   78,   80,   82, 
+    84,   86,   88,   90,   92,   94,   96,   98, 
+   100,  101,  102,  103,  104,  105,  106,  107, 
+   108,  109,  110,  111,  112,  113,  114,  115, 
+   115,  116,  116,  117,  117,  118,  118,  119, 
+   119,  120,  120,  121,  121,  122,  122,  123, 
+   123,  123,  124,  124,  124,  124,  125,  125, 
+   125,  125,  126,  126,  126,  126,  127,  127, 
+   127,  127,  127,  127,  128,  128,  128,  128, 
+   128,  128,  128,  128,  128,  128,  128,  128, 
+   255,  255,  255,  255,  255,  255,  255,  255, 
+   255,  255,  255,  255,  255,  255,  255,  255, 
+   255,  255,  255,  255,  255,  255,  255,  255, 
+   255,  255,  255,  255,  255,  255,  255,  255, 
+   252,  248,  244,  240,  236,  232,  228,  224, 
+   220,  216,  212,  208,  204,  200,  196,  192, 
+   189,  187,  185,  183,  181,  179,  177,  175, 
+   173,  171,  169,  167,  165,  163,  161,  159, 
+   157,  156,  155,  154,  153,  152,  151,  150, 
+   149,  148,  147,  146,  145,  144,  143,  142, 
+   142,  141,  141,  140,  140,  139,  139,  138, 
+   138,  137,  137,  136,  136,  135,  135,  134, 
+   134,  134,  133,  133,  133,  133,  132,  132, 
+   132,  132,  131,  131,  131,  131,  130,  130, 
+   130,  130,  130,  130,  129,  129,  129,  129, 
+   129,  129,  129,  129,  128,  128,  128,  128, 
 };
 
 static unsigned char dsp_ulaw[] = {
-    0,    0,    0,    0,    0,    1,    1,    1,
-    1,    2,    2,    2,    2,    3,    3,    3,
-    3,    4,    4,    4,    4,    5,    5,    5,
-    5,    6,    6,    6,    6,    7,    7,    7,
-    7,    8,    8,    8,    8,    9,    9,    9,
-    9,   10,   10,   10,   10,   11,   11,   11,
-   11,   12,   12,   12,   12,   13,   13,   13,
-   13,   14,   14,   14,   14,   15,   15,   15,
-   15,   16,   16,   17,   17,   18,   18,   19,
-   19,   20,   20,   21,   21,   22,   22,   23,
-   23,   24,   24,   25,   25,   26,   26,   27,
-   27,   28,   28,   29,   29,   30,   30,   31,
-   31,   32,   33,   34,   35,   36,   37,   38,
-   39,   40,   41,   42,   43,   44,   45,   46,
-   47,   48,   50,   52,   54,   56,   58,   60,
-   62,   65,   69,   73,   77,   83,   91,  103,
-  255,  231,  219,  211,  205,  201,  197,  193,
-  190,  188,  186,  184,  182,  180,  178,  176,
-  175,  174,  173,  172,  171,  170,  169,  168,
-  167,  166,  165,  164,  163,  162,  161,  160,
-  159,  159,  158,  158,  157,  157,  156,  156,
-  155,  155,  154,  154,  153,  153,  152,  152,
-  151,  151,  150,  150,  149,  149,  148,  148,
-  147,  147,  146,  146,  145,  145,  144,  144,
-  143,  143,  143,  143,  142,  142,  142,  142,
-  141,  141,  141,  141,  140,  140,  140,  140,
-  139,  139,  139,  139,  138,  138,  138,  138,
-  137,  137,  137,  137,  136,  136,  136,  136,
-  135,  135,  135,  135,  134,  134,  134,  134,
-  133,  133,  133,  133,  132,  132,  132,  132,
-  131,  131,  131,  131,  130,  130,  130,  130,
-  129,  129,  129,  129,  128,  128,  128,  128
+    31,   31,   31,   32,   32,   32,   32,   33, 
+    33,   33,   33,   34,   34,   34,   34,   35, 
+    35,   35,   35,   36,   36,   36,   36,   37, 
+    37,   37,   37,   38,   38,   38,   38,   39, 
+    39,   39,   39,   40,   40,   40,   40,   41, 
+    41,   41,   41,   42,   42,   42,   42,   43, 
+    43,   43,   43,   44,   44,   44,   44,   45, 
+    45,   45,   45,   46,   46,   46,   46,   47, 
+    47,   47,   47,   48,   48,   49,   49,   50, 
+    50,   51,   51,   52,   52,   53,   53,   54, 
+    54,   55,   55,   56,   56,   57,   57,   58, 
+    58,   59,   59,   60,   60,   61,   61,   62, 
+    62,   63,   63,   64,   65,   66,   67,   68, 
+    69,   70,   71,   72,   73,   74,   75,   76, 
+    77,   78,   79,   81,   83,   85,   87,   89, 
+    91,   93,   95,   99,  103,  107,  111,  119, 
+   255,  247,  239,  235,  231,  227,  223,  221, 
+   219,  217,  215,  213,  211,  209,  207,  206, 
+   205,  204,  203,  202,  201,  200,  199,  198, 
+   197,  196,  195,  194,  193,  192,  191,  191, 
+   190,  190,  189,  189,  188,  188,  187,  187, 
+   186,  186,  185,  185,  184,  184,  183,  183, 
+   182,  182,  181,  181,  180,  180,  179,  179, 
+   178,  178,  177,  177,  176,  176,  175,  175, 
+   175,  175,  174,  174,  174,  174,  173,  173, 
+   173,  173,  172,  172,  172,  172,  171,  171, 
+   171,  171,  170,  170,  170,  170,  169,  169, 
+   169,  169,  168,  168,  168,  168,  167,  167, 
+   167,  167,  166,  166,  166,  166,  165,  165, 
+   165,  165,  164,  164,  164,  164,  163,  163, 
+   163,  163,  162,  162,  162,  162,  161,  161, 
+   161,  161,  160,  160,  160,  160,  159,  159, 
 };
index 6b9e063fbbdb8c0966b1d4a0ec0c913e272b2938..80a253c775bd1367224aacb18299eef72bcda7b0 100644 (file)
@@ -27,3 +27,4 @@ fi
 tristate 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS
 tristate 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS
 tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS
+endmenu
index c3f4faf545f5d2ff077f8836cdaa67fb84953546..8f3261ac62a4408232d84c46017013deb37034bf 100644 (file)
@@ -56,6 +56,7 @@ static struct buffer_head * lru_list[NR_LIST] = {NULL, };
 static struct buffer_head * next_to_age[NR_LIST] = {NULL, };
 static struct buffer_head * free_list[NR_SIZES] = {NULL, };
 static struct buffer_head * unused_list = NULL;
+struct buffer_head * reuse_list = NULL;
 static struct wait_queue * buffer_wait = NULL;
 
 int nr_buffers = 0;
@@ -459,7 +460,7 @@ static inline struct buffer_head * find_buffer(kdev_t dev, int block, int size)
        struct buffer_head * tmp;
 
        for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)
-               if (tmp->b_dev == dev && tmp->b_blocknr == block)
+               if (tmp->b_blocknr == block && tmp->b_dev == dev)
                        if (tmp->b_size == size)
                                return tmp;
                        else {
@@ -980,10 +981,38 @@ static void get_more_buffer_heads(void)
        }
 }
 
+/* 
+ * We can't put completed temporary IO buffer_heads directly onto the
+ * unused_list when they become unlocked, since the device driver
+ * end_request routines still expect access to the buffer_head's
+ * fields after the final unlock.  So, the device driver puts them on
+ * the reuse_list instead once IO completes, and we recover these to
+ * the unused_list here.
+ *
+ * The reuse_list receives buffers from interrupt routines, so we need
+ * to be IRQ-safe here.
+ */
+static inline void recover_reusable_buffer_heads(void)
+{
+       struct buffer_head *bh;
+       unsigned long flags;
+       
+       save_flags(flags);
+       cli();
+       while (reuse_list) {
+               bh = reuse_list;
+               reuse_list = bh->b_next_free;
+               restore_flags(flags);
+               put_unused_buffer_head(bh);
+               cli();
+       }
+}
+
 static struct buffer_head * get_unused_buffer_head(void)
 {
        struct buffer_head * bh;
 
+       recover_reusable_buffer_heads();
        get_more_buffer_heads();
        if (!unused_list)
                return NULL;
@@ -1033,22 +1062,14 @@ no_grow:
        return NULL;
 }
 
-static void read_buffers(struct buffer_head * bh[], int nrbuf)
-{
-       ll_rw_block(READ, nrbuf, bh);
-       bh += nrbuf;
-       do {
-               nrbuf--;
-               bh--;
-               wait_on_buffer(*bh);
-       } while (nrbuf > 0);
-}
-
 static int bread_page(unsigned long address, kdev_t dev, int b[], int size)
 {
-       struct buffer_head *bh, *next, *arr[MAX_BUF_PER_PAGE];
+       struct buffer_head *bh, *prev, *next, *arr[MAX_BUF_PER_PAGE];
        int block, nr;
+       struct page *page;
 
+       page = mem_map + MAP_NR(address);
+       page->uptodate = 0;
        bh = create_buffers(address, size);
        if (!bh)
                return -ENOMEM;
@@ -1057,6 +1078,17 @@ static int bread_page(unsigned long address, kdev_t dev, int b[], int size)
        do {
                struct buffer_head * tmp;
                block = *(b++);
+
+               set_bit(BH_FreeOnIO, &next->b_state);
+               next->b_list = BUF_CLEAN;
+               next->b_dev = dev;
+               next->b_blocknr = block;
+               next->b_count = 1;
+               next->b_flushtime = 0;
+               clear_bit(BH_Dirty, &next->b_state);
+               clear_bit(BH_Req, &next->b_state);
+               set_bit(BH_Uptodate, &next->b_state);
+               
                if (!block) {
                        memset(next->b_data, 0, size);
                        continue;
@@ -1071,32 +1103,47 @@ static int bread_page(unsigned long address, kdev_t dev, int b[], int size)
                        brelse(tmp);
                        continue;
                }
-               arr[nr++] = next;
-               next->b_dev = dev;
-               next->b_blocknr = block;
-               next->b_count = 1;
-               next->b_flushtime = 0;
-               clear_bit(BH_Dirty, &next->b_state);
                clear_bit(BH_Uptodate, &next->b_state);
-               clear_bit(BH_Req, &next->b_state);
-               next->b_list = BUF_CLEAN;
-       } while ((next = next->b_this_page) != NULL);
-
+               arr[nr++] = next;
+       } while (prev = next, (next = next->b_this_page) != NULL);
+       prev->b_this_page = bh;
+       
        if (nr)
-               read_buffers(arr,nr);
-       ++current->maj_flt;
-
-       while ((next = bh) != NULL) {
-               bh = bh->b_this_page;
-               put_unused_buffer_head(next);
+               ll_rw_block(READ, nr, arr);
+       else {
+               page->locked = 0;
+               page->uptodate = 1;
+               wake_up(&page->wait);
        }
+       ++current->maj_flt;
        return 0;
 }
 
+void mark_buffer_uptodate(struct buffer_head * bh, int on)
+{
+       if (on) {
+               struct buffer_head *tmp = bh;
+               int page_uptodate = 1;
+               set_bit(BH_Uptodate, &bh->b_state);
+               do {
+                       if (!test_bit(BH_Uptodate, &tmp->b_state)) {
+                               page_uptodate = 0;
+                               break;
+                       }
+                       tmp=tmp->b_this_page;
+               } while (tmp && tmp != bh);
+               if (page_uptodate)
+                       mem_map[MAP_NR(bh->b_data)].uptodate = 1;
+       } else
+               clear_bit(BH_Uptodate, &bh->b_state);
+}
+
 /*
- * Generic "readpage" function for block devices that have the
- * normal bmap functionality. This is most of the block device
- * filesystems.
+ * Generic "readpage" function for block devices that have the normal
+ * bmap functionality. This is most of the block device filesystems.
+ * Reads the page asynchronously --- the unlock_buffer() and
+ * mark_buffer_uptodate() functions propogate buffer state into the
+ * page struct once IO has completed.
  */
 int generic_readpage(struct inode * inode, struct page * page)
 {
@@ -1104,6 +1151,9 @@ int generic_readpage(struct inode * inode, struct page * page)
        int *p, nr[PAGE_SIZE/512];
        int i;
 
+       wait_on_page(page);
+       page->locked = 1;
+       
        i = PAGE_SIZE >> inode->i_sb->s_blocksize_bits;
        block = page->offset >> inode->i_sb->s_blocksize_bits;
        p = nr;
@@ -1114,20 +1164,11 @@ int generic_readpage(struct inode * inode, struct page * page)
                p++;
        } while (i > 0);
 
-       /*
-        * We should make this asynchronous, but this is good enough for now..
-        */
-
        /* IO start */
        page->count++;
        address = page_address(page);
        bread_page(address, inode->i_dev, nr, inode->i_sb->s_blocksize);
-
-       /* IO ready (this part should be in the "page ready callback" function) */
-       page->uptodate = 1;
-       wake_up(&page->wait);
        free_page(address);
-
        return 0;
 }
 
index 52ba655a27b3a0483264829267e078809afa6abf..f25293449b2a161946e366caf2bbf038b3a928b3 100644 (file)
@@ -451,17 +451,26 @@ int ext_sync_inode (struct inode *inode)
        return err;
 }
 
-#ifdef MODULE
 
 static struct file_system_type ext_fs_type = {
         ext_read_super, "ext", 1, NULL
 };
 
-int init_module(void)
+int init_ext_fs(void)
 {
         return register_filesystem(&ext_fs_type);
 }
 
+#ifdef MODULE
+int init_module(void)
+{
+       int status;
+
+       if ((status = init_ext_fs()) == 0)
+               register_symtab(0);
+       return status;
+}
+
 void cleanup_module(void)
 {
         unregister_filesystem(&ext_fs_type);
index 5cdd72f816a8d3f809343545bac8ce4486673392..aa5aaf0e5911c46071db680a89f2bfbaca80a7a8 100644 (file)
@@ -1,5 +1,7 @@
 Changes from version 0.5a to version 0.5b
 =========================================
+       - Now that we have sysctl(), the immutable flag cannot be changed when
+         the system is running at security level > 0.
        - Some cleanups in the code.
        - More consistency checks on directories.
        - The ext2.diff patch from Tom May <ftom@netcom.com> has been
index e0de8de117ec5ce93cfef72f94b45db69c38fb6a..4e3f56362bc2cf56dd8722dc70ce00e7e3c28b85 100644 (file)
@@ -33,12 +33,13 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
        case EXT2_IOC_SETFLAGS:
                flags = get_fs_long ((long *) arg);
                /*
-                * Only the super-user can change the IMMUTABLE flag
+                * The IMMUTABLE flag can only be changed by the super user
+                * when the security level is zero.
                 */
                if ((flags & EXT2_IMMUTABLE_FL) ^
                    (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL)) {
                        /* This test looks nicer. Thanks to Pauline Middelink */
-                       if (!fsuser())
+                       if (!fsuser() || securelevel > 0)
                                return -EPERM;
                } else
                        if ((current->fsuid != inode->i_uid) && !fsuser())
index c069e49bff197169a1e44c7a5aa5fdd4f9b18953..f05a03baab74537595cd58b868a7e67294df46c9 100644 (file)
@@ -685,17 +685,25 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
        return 0;
 }
 
-#ifdef MODULE
-
 static struct file_system_type ext2_fs_type = {
         ext2_read_super, "ext2", 1, NULL
 };
 
-int init_module(void)
+int init_ext2_fs(void)
 {
         return register_filesystem(&ext2_fs_type);
 }
 
+#ifdef MODULE
+int init_module(void)
+{
+       int status;
+
+       if ((status = init_ext2_fs()) == 0)
+               register_symtab(0);
+       return status;
+}
+
 void cleanup_module(void)
 {
         unregister_filesystem(&ext2_fs_type);
index 7606af007767b05f20f240fe12511ce4ba043cd4..660eef8edffd11a9aa45a7fb5ca70e39588994f4 100644 (file)
@@ -44,74 +44,55 @@ asmlinkage int sys_setup(void)
        device_setup();
 
 #ifdef CONFIG_EXT_FS
-       register_filesystem(&(struct file_system_type)
-               {ext_read_super, "ext", 1, NULL});
+       init_ext_fs();
 #endif
 
 #ifdef CONFIG_EXT2_FS
-       register_filesystem(&(struct file_system_type)
-               {ext2_read_super, "ext2", 1, NULL});
+       init_ext2_fs();
 #endif
 
 #ifdef CONFIG_XIA_FS
-       register_filesystem(&(struct file_system_type)
-               {xiafs_read_super, "xiafs", 1, NULL});
+       init_xiafs_fs();
 #endif
 
 #ifdef CONFIG_MINIX_FS
-       register_filesystem(&(struct file_system_type)
-               {minix_read_super, "minix", 1, NULL});
+       init_minix_fs();
 #endif
 
 #ifdef CONFIG_UMSDOS_FS
-       register_filesystem(&(struct file_system_type)
-       {UMSDOS_read_super,     "umsdos",       1, NULL});
+       init_umsdos_fs();
 #endif
 
 #ifdef CONFIG_MSDOS_FS
-       register_filesystem(&(struct file_system_type)
-               {msdos_read_super, "msdos", 1, NULL});
+       init_msdos_fs();
 #endif
 
 #ifdef CONFIG_PROC_FS
-       register_filesystem(&(struct file_system_type)
-               {proc_read_super, "proc", 0, NULL});
+       init_proc_fs();
 #endif
 
 #ifdef CONFIG_NFS_FS
-       register_filesystem(&(struct file_system_type)
-               {nfs_read_super, "nfs", 0, NULL});
+       init_nfs_fs();
 #endif
 
 #ifdef CONFIG_SMB_FS
-       register_filesystem(&(struct file_system_type)
-               {smb_read_super, "smbfs", 0, NULL});
+       init_smb_fs();
 #endif
 
 #ifdef CONFIG_NCP_FS
-       register_filesystem(&(struct file_system_type)
-               {ncp_read_super, "ncpfs", 0, NULL});
+       init_ncp_fs();
 #endif
 
 #ifdef CONFIG_ISO9660_FS
-       register_filesystem(&(struct file_system_type)
-               {isofs_read_super, "iso9660", 1, NULL});
+       init_iso9660_fs();
 #endif
 
 #ifdef CONFIG_SYSV_FS
-       register_filesystem(&(struct file_system_type)
-               {sysv_read_super, "xenix", 1, NULL});
-
-       register_filesystem(&(struct file_system_type)
-               {sysv_read_super, "sysv", 1, NULL});
-
-       register_filesystem(&(struct file_system_type)
-               {sysv_read_super, "coherent", 1, NULL});
+       init_sysv_fs();
 #endif
 
 #ifdef CONFIG_HPFS_FS
-       register_filesystem(&(struct file_system_type)
-               {hpfs_read_super, "hpfs", 1, NULL});
+       init_hpfs_fs();
 #endif
 
 #ifdef CONFIG_ROOT_NFS
index 1b28756633841627c77b4883d95e242219e22a83..bb8eedeb3540741922f1e620eb64eed88889d381 100644 (file)
@@ -1744,17 +1744,25 @@ static void brelse4(struct quad_buffer_head *qbh)
        kfree_s(qbh->data, 2048);
 }
 
-#ifdef MODULE
-
 static struct file_system_type hpfs_fs_type = {
         hpfs_read_super, "hpfs", 1, NULL
 };
 
-int init_module(void)
+int init_hpfs_fs(void)
 {
         return register_filesystem(&hpfs_fs_type);
 }
 
+#ifdef MODULE
+int init_module(void)
+{
+       int status;
+
+       if ((status = init_hpfs_fs()) == 0)
+               register_symtab(0);
+       return status;
+}
+
 void cleanup_module(void)
 {
         unregister_filesystem(&hpfs_fs_type);
index 3c03869e499bad79d044a150dc2b47fda1f2ddfa..2dc331b04c1910a27fb4abd5bef42854bed659e8 100644 (file)
@@ -801,15 +801,23 @@ void leak_check_brelse(struct buffer_head * bh){
 
 #endif
 
-#ifdef MODULE
-
 static struct file_system_type iso9660_fs_type = {
        isofs_read_super, "iso9660", 1, NULL
 };
 
+int init_iso9660_fs(void)
+{
+        return register_filesystem(&iso9660_fs_type);
+}
+
+#ifdef MODULE
 int init_module(void)
 {
-       return register_filesystem(&iso9660_fs_type);
+       int status;
+
+       if ((status = init_iso9660_fs()) == 0)
+               register_symtab(0);
+       return status;
 }
 
 void cleanup_module(void)
index 0e61f01dcc863cb83814ff94a252217dfe437d35..7b52fbfb4db5ca3068f26366be45d23e663302f1 100644 (file)
@@ -873,15 +873,23 @@ int minix_sync_inode(struct inode * inode)
        return err;
 }
 
-#ifdef MODULE
-
 static struct file_system_type minix_fs_type = {
        minix_read_super, "minix", 1, NULL
 };
 
+int init_minix_fs(void)
+{
+        return register_filesystem(&minix_fs_type);
+}
+
+#ifdef MODULE
 int init_module(void)
 {
-       return register_filesystem(&minix_fs_type);
+       int status;
+
+       if ((status = init_minix_fs()) == 0)
+               register_symtab(0);
+       return status;
 }
 
 void cleanup_module(void)
index 45e31b66d83bfb97b5506427e8318285022bd5a2..b0b1bc35bedf30d502041456319b210f54df347e 100644 (file)
@@ -8,7 +8,8 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 O_TARGET := msdos.o
-O_OBJS   := buffer.o namei.o inode.o file.o dir.o misc.o fat.o mmap.o
+O_OBJS   := buffer.o namei.o file.o dir.o misc.o fat.o mmap.o
+OX_OBJS  := inode.o
 M_OBJS   := $(O_TARGET)
 
 include $(TOPDIR)/Rules.make
index afa784f2b88fc6dbc3611b17e5709c94abe11eda..7648f9ea2dbb7ed7fff3c01ff3265ff7a76dfc39 100644 (file)
@@ -515,15 +515,55 @@ int msdos_notify_change(struct inode * inode,struct iattr * attr)
        return 0;
 }
 
-#ifdef MODULE
+static struct symbol_table msdos_syms = {
+/* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */
+#include <linux/symtab_begin.h>
+       /*
+        * Support for umsdos fs
+        *
+        * These symbols are _always_ exported, in case someone
+        * wants to install the umsdos module later.
+        */
+       X(msdos_bmap),
+       X(msdos_create),
+       X(msdos_file_read),
+       X(msdos_file_write),
+       X(msdos_lookup),
+       X(msdos_mkdir),
+       X(msdos_mmap),
+       X(msdos_put_inode),
+       X(msdos_put_super),
+       X(msdos_read_inode),
+       X(msdos_read_super),
+       X(msdos_readdir),
+       X(msdos_rename),
+       X(msdos_rmdir),
+       X(msdos_smap),
+       X(msdos_statfs),
+       X(msdos_truncate),
+       X(msdos_unlink),
+       X(msdos_unlink_umsdos),
+       X(msdos_write_inode),
+#include <linux/symtab_end.h>
+};
 
 static struct file_system_type msdos_fs_type = {
        msdos_read_super, "msdos", 1, NULL
 };
 
+int init_msdos_fs(void)
+{
+       int status;
+
+       if ((status = register_filesystem(&msdos_fs_type)) == 0)
+               status = register_symtab(&msdos_syms);
+       return status;
+}
+
+#ifdef MODULE
 int init_module(void)
 {
-       return register_filesystem(&msdos_fs_type);
+       return init_msdos_fs();
 }
 
 void cleanup_module(void)
index eadd026b44fb65a461887ff67ba7058d5649ef4c..3aa31ca08543e68a8751e3df80d0536468c2886f 100644 (file)
@@ -551,6 +551,7 @@ ncp_init_root(struct ncp_server *server)
         root->finfo.opened = 0;
        i->attributes  = aDIR;
        i->dataStreamSize = 1024;
+       i->volNumber = NCP_NUMBER_OF_VOLUMES+1; /* illegal volnum */
        ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
        ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate));
        ncp_date_unix2dos(0, &dummy, &(i->lastAccessDate));
@@ -608,6 +609,7 @@ ncp_find_inode(struct inode *dir, const char *name)
         do
        {
                if (   (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum)
+                   && (result->dir->finfo.i.volNumber == dir_info->volNumber)
                    && (strcmp(result->finfo.i.entryName, name) == 0))
                {
                         return result;
@@ -626,8 +628,9 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
 {
        struct nw_file_info finfo;
        struct ncp_server *server;
-        struct ncp_inode_info *result_info;
-        int found_in_cache;
+       struct ncp_inode_info *result_info;
+       int found_in_cache;
+       char name[len+1];
 
        *result = NULL;
 
@@ -671,7 +674,9 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
                }
        }
 
-        result_info = ncp_find_inode(dir, __name);
+       memcpy(name, __name, len);
+       name[len] = 0;
+       result_info = ncp_find_inode(dir, name);
 
         if (result_info != 0)
        {
@@ -710,7 +715,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
                         DDPRINTK("ncp_lookup: trying index: %d, name: %s\n",
                                 i, c_entry[i].i.entryName);
 
-                        if (strcmp(c_entry[i].i.entryName, __name) == 0)
+                        if (strcmp(c_entry[i].i.entryName, name) == 0)
                        {
                                 DPRINTK("ncp_lookup: found in cache!\n");
                                finfo.i = c_entry[i].i;
@@ -724,20 +729,15 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
 
         if (found_in_cache == 0)
        {
-               char this_name[len+1];
-
-               memcpy(this_name, __name, len);
-               this_name[len] = 0;
-               str_upper(this_name);
+               str_upper(name);
 
                DDPRINTK("ncp_lookup: do_lookup on %s/%s\n",
-                        NCP_ISTRUCT(dir)->entryName, this_name);
+                        NCP_ISTRUCT(dir)->entryName, name);
 
                if (ncp_do_lookup(server,
                                  dir->i_ino == (int)&(NCP_SERVER(dir)->root)
                                  ? NULL : NCP_ISTRUCT(dir),
-                                 this_name,
-                                 &(finfo.i)) != 0)
+                                 name, &(finfo.i)) != 0)
                {
                         iput(dir);
                         return -ENOENT;
index 487efcdfa8dae3149fb59dfb5e4afac44b843079..e86c78ca05e2905633fb3d17185b45599bcb0c11 100644 (file)
@@ -483,25 +483,31 @@ int ncp_malloced;
 int ncp_current_malloced;
 #endif
 
-#ifdef MODULE
-
 static struct file_system_type ncp_fs_type = {
         ncp_read_super, "ncpfs", 0, NULL
         };
 
-int
+int init_ncp_fs(void)
+{
+        return register_filesystem(&ncp_fs_type);
+}
+
+#ifdef MODULE
 init_module( void)
 {
+       int status;
+
         DPRINTK("ncpfs: init_module called\n");
 
 #ifdef DEBUG_NCP_MALLOC
         ncp_malloced = 0;
         ncp_current_malloced = 0;
 #endif
-
         ncp_init_dir_cache();
-        register_filesystem(&ncp_fs_type);
-        return 0;
+
+       if ((status = init_ncp_fs()) == 0)
+               register_symtab(0);
+       return status;
 }
 
 void
index e2e0eb54dd31f62a399cff5b2ca529891c2f3aae..9af318dc0bb2ccb039337112874afe0956b245a2 100644 (file)
@@ -288,17 +288,25 @@ int nfs_notify_change(struct inode *inode, struct iattr *attr)
        return error;
 }
 
-#ifdef MODULE
-
 /* Every kernel module contains stuff like this. */
 
 static struct file_system_type nfs_fs_type = {
        nfs_read_super, "nfs", 0, NULL
 };
 
+int init_nfs_fs(void)
+{
+        return register_filesystem(&nfs_fs_type);
+}
+
+#ifdef MODULE
 int init_module(void)
 {
-       return register_filesystem(&nfs_fs_type);
+       int status;
+
+       if ((status = init_nfs_fs()) == 0)
+               register_symtab(0);
+       return status;
 }
 
 void cleanup_module(void)
index e5d5d6f60246799ebafefedbcd4538d093ae4a2b..d975c8504f95afaf52604c1fbca54c8e337a81bd 100644 (file)
@@ -15,6 +15,7 @@
  *
  *     Alan Cox        :       Removed get_address name clash with FPU.
  *     Alan Cox        :       Reformatted a bit.
+ *     Michael Rausch  :       Fixed recognition of an incoming RARP answer.
  *
  */
 
@@ -317,6 +318,7 @@ static int do_rarp(void)
 {
        int retries = 0;
        unsigned long timeout = 0;
+       volatile struct device **root_dev_ptr = (volatile struct device **) &root_dev;
 
        /* Setup RARP protocol */
        root_rarp_open();
@@ -329,16 +331,16 @@ static int do_rarp(void)
         * [Actually we could now, but the nothing else running note still 
         *  applies.. - AC]
         */
-       for (retries = 0; retries < RARP_RETRIES && root_dev == NULL; retries++) {
+       for (retries = 0; retries < RARP_RETRIES && *root_dev_ptr == NULL; retries++) {
                if (root_rarp_send() < 0)
                        break;
                timeout = jiffies + (RARP_TIMEOUT * HZ);
-               while (jiffies < timeout && root_dev == NULL)
-                       ;;
+               while (jiffies < timeout && *root_dev_ptr == NULL)
+                       ;
        }
 
        root_rarp_close();
-       if (root_dev == NULL && timeout > 0) {
+       if (*root_dev_ptr == NULL && timeout > 0) {
                printk(KERN_ERR "NFS: Timed out while waiting for RARP answer\n");
                return -1;
        }
index ba18ed0e94aacdaf1dc2df1ad2d048bb818cea00..eb3c806616ae6259f4689a02f3ceaa1accc3bd3c 100644 (file)
@@ -8,12 +8,8 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 O_TARGET := proc.o
-O_OBJS   := inode.o root.o base.o mem.o link.o fd.o array.o kmsg.o net.o
+O_OBJS   := inode.o root.o base.o mem.o link.o fd.o array.o kmsg.o net.o scsi.o
+OX_OBJS  := procfs_syms.o
 M_OBJS   := $(O_TARGET)
 
-# For either CONFIG_SCSI=y or CONFIG_SCSI=m
-ifdef CONFIG_SCSI
-O_OBJS += scsi.o
-endif
-
 include $(TOPDIR)/Rules.make
index 4125d513ed04bd14daa9b2712b83fbe51eff50d1..f10768a8829c278e6cd2120617afd13aec4469e8 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/stat.h>
 #include <linux/locks.h>
 #include <linux/limits.h>
-#include <linux/config.h>
 
 #include <asm/system.h>
 #include <asm/segment.h>
@@ -171,13 +170,11 @@ void proc_read_inode(struct inode * inode)
                        case PROC_NET:
                                inode->i_nlink = 2;
                                break;
-#ifdef CONFIG_SCSI
                        case PROC_SCSI:
                                 inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
                                 inode->i_nlink = 2;
                                 inode->i_op = &proc_scsi_inode_operations;
                                 break;
-#endif
                        case PROC_KCORE:
                                inode->i_mode = S_IFREG | S_IRUSR;
                                inode->i_op = &proc_kcore_inode_operations;
index b9b70e1984b228d56f25a520fec804ff7daad417..e3cc7973c8884df7c286193a080806135f49ac20 100644 (file)
  *
  *  proc net directory handling functions
  */
-#include <linux/autoconf.h>
-
-#include <asm/segment.h>
-
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
@@ -35,6 +31,8 @@
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 
+#include <asm/segment.h>
+
 #define PROC_BLOCK_SIZE        (3*1024)                /* 4K page size but our output routines use some slack for overruns */
 
 static int proc_readnet(struct inode * inode, struct file * file,
diff --git a/fs/proc/procfs_syms.c b/fs/proc/procfs_syms.c
new file mode 100644 (file)
index 0000000..53639d2
--- /dev/null
@@ -0,0 +1,35 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+
+static struct symbol_table procfs_syms = {
+/* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */
+#include <linux/symtab_begin.h>
+       X(proc_register),
+       X(proc_unregister),
+       X(in_group_p),
+       X(generate_cluster),
+       X(proc_net_inode_operations),
+       X(proc_net),
+#ifdef CONFIG_SCSI /* Ugh... */
+       X(proc_scsi),
+       X(proc_scsi_inode_operations),
+       X(dispatch_scsi_info_ptr),
+#endif
+#include <linux/symtab_end.h>
+};
+
+static struct file_system_type proc_fs_type = {
+       proc_read_super, "proc", 0, NULL
+};
+
+int init_proc_fs(void)
+{
+       int status;
+
+        if ((status = register_filesystem(&proc_fs_type)) == 0)
+               status = register_symtab(&procfs_syms);
+       return status;
+}
+
index d53c9d53b7d418b5b7f9b426d2e296e27c1c89f6..5091e4052949dba094c4b58586ca2dac7d23b3ac 100644 (file)
  *  TODO: Improve support to write to the driver files
  *       Add some more comments
  */
-#include <linux/autoconf.h>
-#include <asm/segment.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/mm.h>
 
+#include <asm/segment.h>
+
 /* forward references */
 static int proc_readscsi(struct inode * inode, struct file * file,
                         char * buf, int count);
index 2bf99fb4c9d40a240b08a0454e0d9f757418cf49..4782aaf54c0c87d5a4405128e0d3125d28b390a7 100644 (file)
@@ -403,15 +403,20 @@ int smb_malloced;
 int smb_current_malloced;
 #endif
 
-#ifdef MODULE
-
 static struct file_system_type smb_fs_type = {
         smb_read_super, "smbfs", 0, NULL
         };
 
-int
-init_module( void)
+int init_smb_fs(void)
 {
+        return register_filesystem(&smb_fs_type);
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+       int status;
+
         DPRINTK("smbfs: init_module called\n");
 
 #ifdef DEBUG_SMB_MALLOC
@@ -420,7 +425,10 @@ init_module( void)
 #endif
 
         smb_init_dir_cache();
-        return register_filesystem(&smb_fs_type);
+
+       if ((status = init_smb_fs()) == 0)
+               register_symtab(0);
+       return status;
 }
 
 void
index dff51047fca58715cb9a0a4148acc4e92a19fbf5..a3627d1083ddf51373e9df7fc3ccb1156781f806 100644 (file)
@@ -1664,7 +1664,7 @@ smb_proc_reconnect(struct smb_server *server)
        }
        
        if (server->packet[0] != 0x82) {
-               printk("smb_proc_connect: Did not recieve positive response "
+               printk("smb_proc_connect: Did not receive positive response "
                        "(err = %x)\n", 
                       server->packet[0]);
                 smb_dont_catch_keepalive(server);
index 645170af1483ffc5fea5447940843960ed7674f8..e0425c9566fa2da42de46a1316071a0d4613d095 100644 (file)
@@ -969,8 +969,6 @@ int sysv_sync_inode(struct inode * inode)
         return err;
 }
 
-#ifdef MODULE
-
 /* Every kernel module contains stuff like this. */
 
 static struct file_system_type sysv_fs_type[3] = {
@@ -979,7 +977,7 @@ static struct file_system_type sysv_fs_type[3] = {
        {sysv_read_super, "coherent", 1, NULL}
 };
 
-int init_module(void)
+int init_sysv_fs(void)
 {
        int i;
        int ouch;
@@ -988,7 +986,17 @@ int init_module(void)
                if ((ouch = register_filesystem(&sysv_fs_type[i])) != 0)
                        return ouch;
        }
-       return 0;
+        return ouch;
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+       int status;
+
+       if ((status = init_sysv_fs()) == 0)
+               register_symtab(0);
+       return status;
 }
 
 void cleanup_module(void)
index 206929ac2242463ad810845a1fcb095e9fff73e5..205879b648f50e962ddb43e021362ac6b3e09b4c 100644 (file)
@@ -494,15 +494,23 @@ struct super_block *UMSDOS_read_super(
 }
 
 
-#ifdef MODULE
-
 static struct file_system_type umsdos_fs_type = {
        UMSDOS_read_super, "umsdos", 1, NULL
 };
 
+int init_umsdos_fs(void)
+{
+        return register_filesystem(&umsdos_fs_type);
+}
+
+#ifdef MODULE
 int init_module(void)
 {
-       return register_filesystem(&umsdos_fs_type);
+       int status;
+
+       if ((status = init_umsdos_fs()) == 0)
+               register_symtab(0);
+       return status;
 }
 
 void cleanup_module(void)
index a31dee748a706b32792ce916a3865a97d194593c..0081a793a87cfcc8b9389c00af2e1d4529eaf859 100644 (file)
@@ -511,17 +511,25 @@ int xiafs_sync_inode (struct inode *inode)
     return err;
 }
 
-#ifdef MODULE
-
 /* Every kernel module contains stuff like this. */
 
 static struct file_system_type xiafs_fs_type = {
        xiafs_read_super, "xiafs", 1, NULL
 };
 
+int init_xiafs_fs(void)
+{
+        return register_filesystem(&xiafs_fs_type);
+}
+
+#ifdef MODULE
 int init_module(void)
 {
-       return register_filesystem(&xiafs_fs_type);
+       int status;
+
+       if ((status = init_xiafs_fs()) == 0)
+               register_symtab(0);
+       return status;
 }
 
 void cleanup_module(void)
index 845ea9f30be1cec5b6431aa737c82551c3180153..3498d77c135de64f869fd979ed5ee9a812867a11 100644 (file)
@@ -4,8 +4,7 @@
 #include <linux/config.h>
 
 #ifndef HZ
-# if defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB66P) || \
-     defined(CONFIG_ALPHA_EB64P)
+# if defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB66P)
 #  define HZ    977    /* Evaluation Boards seem to be a little odd */
 # else
 #  define HZ   1024    /* normal value for Alpha systems */
index 79976f9b036e177c56c61149a3bc4cb9483baf58..e22e8d6b20e4d9cc92b588a962ec5ef16255cdbb 100644 (file)
 
 extern __inline__ void __delay(int loops)
 {
-       __asm__(".align 2,0x90\n1:\tdecl %0\n\tjns 1b": :"a" (loops):"ax");
+       __asm__ __volatile__(
+               ".align 2,0x90\n1:\tdecl %0\n\tjns 1b"
+               :/* no outputs */
+               :"a" (loops)
+               :"ax");
 }
 
 /*
index b3b56f5bedd239bbf2ee581ae1f2677ed59103f3..399b5901b68736541b28b0b539b380edefa4f0f9 100644 (file)
@@ -340,7 +340,7 @@ static void (DEVICE_REQUEST)(void);
 
 #if ! SCSI_MAJOR(MAJOR_NR)
 
-#if defined(_IDE_CD_C) || defined(_TRITON_C) || defined(_IDE_TAPE_C) /* shares copy with ide.c */
+#if defined(IDE_DRIVER) && !defined(_IDE_C) /* shared copy for IDE modules */
 void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup);
 #else
 
@@ -393,7 +393,7 @@ static void end_request(int uptodate) {
        req->rq_status = RQ_INACTIVE;
        wake_up(&wait_for_request);
 }
-#endif /* ndef _IDE_CD_C */
+#endif /* defined(IDE_DRIVER) && !defined(_IDE_C) */
 #endif /* ! SCSI_MAJOR(MAJOR_NR) */
 
 #endif /* defined(MAJOR_NR) || defined(IDE_DRIVER) */
index fcb5e5f62762d61b16625450e4fdf128175fd362..208cf46af363c40fead29e6d1441badb4a6bad77 100644 (file)
@@ -475,6 +475,7 @@ extern void ext2_put_super (struct super_block *);
 extern void ext2_write_super (struct super_block *);
 extern int ext2_remount (struct super_block *, int *, char *);
 extern struct super_block * ext2_read_super (struct super_block *,void *,int);
+extern int init_ext2_fs(void);
 extern void ext2_statfs (struct super_block *, struct statfs *, int);
 
 /* truncate.c */
index d1a44978d65ca55b2adb9e0e12d62400be9b4147..5a33f3c1c18978b066d9e4eb2cb73c1b58b28a6a 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef _LINUX_EXT2_FS_SB
 #define _LINUX_EXT2_FS_SB
 
+#include <linux/ext2_fs.h>
+
 /*
  * The following is not needed anymore since the descriptors buffer
  * heads are now dynamically allocated
index 07f689286eb0c6a746ad1e1f4a4e413eb0ca88d3..55332092e45b74299b954d48352bd5e4aa9e3ca0 100644 (file)
@@ -91,6 +91,7 @@ extern void ext_truncate(struct inode *);
 extern void ext_put_super(struct super_block *);
 extern void ext_write_super(struct super_block *);
 extern struct super_block *ext_read_super(struct super_block *,void *,int);
+extern int init_ext_fs(void);
 extern void ext_read_inode(struct inode *);
 extern void ext_write_inode(struct inode *);
 extern void ext_put_inode(struct inode *);
index 5a7a04442b0873d7895469f83f4744e3a1c71546..dcc4c6870e254834f008ebf650f2a908c3ee6458 100644 (file)
@@ -136,14 +136,35 @@ typedef char buffer_block[BLOCK_SIZE];
 #define BH_Touched     4       /* 1 if the buffer has been touched (aging) */
 #define BH_Has_aged    5       /* 1 if the buffer has been aged (aging) */
 #define BH_Protected   6       /* 1 if the buffer is protected */
+#define BH_FreeOnIO    7       /* 1 to discard the buffer_head after IO */
 
+/*
+ * Try to keep the most commonly used fields in single cache lines (16
+ * bytes) to improve performance.  This ordering should be
+ * particularly beneficial on 32-bit processors.
+ * 
+ * We use the first 16 bytes for the data which is used in searches
+ * over the block hash lists (ie. getblk(), find_buffer() and
+ * friends).
+ * 
+ * The second 16 bytes we use for lru buffer scans, as used by
+ * sync_buffers() and refill_freelist().  -- sct
+ */
 struct buffer_head {
-       char * b_data;                  /* pointer to data block (1024 bytes) */
-       unsigned long b_size;           /* block size */
+       /* First cache line: */
        unsigned long b_blocknr;        /* block number */
        kdev_t b_dev;                   /* device (B_FREE = free) */
+       struct buffer_head * b_next;    /* Hash queue list */
+       struct buffer_head * b_this_page;       /* circular list of buffers in one page */
+
+       /* Second cache line: */
        unsigned long b_state;          /* buffer state bitmap (see above) */
+       struct buffer_head * b_next_free;
        unsigned int b_count;           /* users using this block */
+       unsigned long b_size;           /* block size */
+
+       /* Non-performance-critical data follows. */
+       char * b_data;                  /* pointer to data block (1024 bytes) */
        unsigned int b_list;            /* List that this buffer appears */
        unsigned long b_flushtime;      /* Time when this (dirty) buffer
                                         * should be written */
@@ -151,10 +172,7 @@ struct buffer_head {
                                         * last used. */
        struct wait_queue * b_wait;
        struct buffer_head * b_prev;            /* doubly linked list of hash-queue */
-       struct buffer_head * b_next;
        struct buffer_head * b_prev_free;       /* doubly linked list of buffers */
-       struct buffer_head * b_next_free;
-       struct buffer_head * b_this_page;       /* circular list of buffers in one page */
        struct buffer_head * b_reqnext;         /* request queue */
 };
 
@@ -507,13 +525,7 @@ extern int nr_buffer_heads;
 #define BUF_SHARED 5   /* Buffers shared */
 #define NR_LIST 6
 
-extern inline void mark_buffer_uptodate(struct buffer_head * bh, int on)
-{
-       if (on)
-               set_bit(BH_Uptodate, &bh->b_state);
-       else
-               clear_bit(BH_Uptodate, &bh->b_state);
-}
+void mark_buffer_uptodate(struct buffer_head * bh, int on);
 
 extern inline void mark_buffer_clean(struct buffer_head * bh)
 {
index 0094c359c7f0c835a87e0b9c13697e5d1fe5499e..2b7926aba4dce137d3b6338b69accda829478cc6 100644 (file)
@@ -8,5 +8,6 @@
 /* The entry point for a VFS */
 
 extern struct super_block *hpfs_read_super (struct super_block *, void *, int);
+extern int init_hpfs_fs(void);
 
 #endif
index a89ddca93f7a085fc59e77e0ca803b28ab7665e1..3fdd41f6c164bfdfe26e7216ff54888fd276d432 100644 (file)
@@ -175,6 +175,7 @@ extern int isofs_bmap(struct inode *,int);
 
 extern void isofs_put_super(struct super_block *);
 extern struct super_block *isofs_read_super(struct super_block *,void *,int);
+extern int init_iso9660_fs(void);
 extern void isofs_read_inode(struct inode *);
 extern void isofs_put_inode(struct inode *);
 extern void isofs_statfs(struct super_block *, struct statfs *, int);
index 640eb4bcc2b98fe97686b92699bc8ce8db0c4e4e..14fd7113c8c1baee7bd53f30dbba5b05542c7702 100644 (file)
@@ -1,6 +1,16 @@
 #ifndef _LINUX_LOCKS_H
 #define _LINUX_LOCKS_H
 
+#ifndef _LINUX_MM_H
+#include <linux/mm.h>
+#endif
+
+/*
+ * Unlocked, temporary IO buffer_heads gets moved to the reuse_list
+ * once their page becomes unlocked.  
+ */
+extern struct buffer_head *reuse_list;
+
 /*
  * Buffer cache locking - note that interrupts may only unlock, not
  * lock buffers.
@@ -21,8 +31,36 @@ extern inline void lock_buffer(struct buffer_head * bh)
 
 extern inline void unlock_buffer(struct buffer_head * bh)
 {
+       struct buffer_head *tmp = bh;
+       int page_locked = 0;
+       unsigned long flags;
+       
        clear_bit(BH_Lock, &bh->b_state);
        wake_up(&bh->b_wait);
+       do {
+               if (test_bit(BH_Lock, &tmp->b_state)) {
+                       page_locked = 1;
+                       break;
+               }
+               tmp=tmp->b_this_page;
+       } while (tmp && tmp != bh);
+       save_flags(flags);
+       if (!page_locked) {
+               struct page *page = mem_map + MAP_NR(bh->b_data);
+               page->locked = 0;
+               wake_up(&page->wait);
+               tmp = bh;
+               cli();
+               do {
+                       if (test_bit(BH_FreeOnIO, &tmp->b_state)) {
+                               tmp->b_next_free = reuse_list;
+                               reuse_list = tmp;
+                               clear_bit(BH_FreeOnIO, &tmp->b_state);
+                       }
+                       tmp = tmp->b_this_page;
+               } while (tmp && tmp != bh);
+               restore_flags(flags);
+       }
 }
 
 /*
index 907ae1b3f91909e4dc71ab1bdab709d94ee9cc4a..b5e848482d2ad969f71200b570d14cd4318b3719 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Definitions for the Mitsumi CDROM interface
  * Copyright (C) 1995 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: 1.5
+ * VERSION: 1.5a
  * 
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
index 137521f59fb6553d75db52903cabbef946afcad4..f0ecdea022cb0fb5fd871aefb809eb988fe288a8 100644 (file)
@@ -116,6 +116,7 @@ extern struct buffer_head * minix_bread(struct inode *, int, int);
 extern void minix_truncate(struct inode *);
 extern void minix_put_super(struct super_block *);
 extern struct super_block *minix_read_super(struct super_block *,void *,int);
+extern int init_minix_fs(void);
 extern void minix_write_super(struct super_block *);
 extern int minix_remount (struct super_block * sb, int * flags, char * data);
 extern void minix_read_inode(struct inode *);
index 919dc83db4da9652275856bbfd172eb611bcb76a..7fa8a077b18ef4e062ba8ecf23791c285d0ce4af 100644 (file)
@@ -105,6 +105,15 @@ struct vm_operations_struct {
        pte_t (*swapin)(struct vm_area_struct *, unsigned long, unsigned long);
 };
 
+/*
+ * Try to keep the most commonly accessed fields in single cache lines
+ * here (16 bytes or greater).  This ordering should be particularly
+ * beneficial on 32-bit processors.
+ *
+ * The first line is data used in linear searches (eg. clock algorithm
+ * scans).  The second line is data used in page searches through the
+ * page-cache.  -- sct 
+ */
 typedef struct page {
        unsigned int count;
        unsigned dirty:16,
@@ -112,14 +121,19 @@ typedef struct page {
                 uptodate:1,
                 error:1,
                 referenced:1,
-                unused:4,
+                locked:1,
+                unused:3,
                 reserved:1;
+       struct wait_queue *wait;
+       struct page *next;
+
+       struct page *next_hash;
        unsigned long offset;
        struct inode *inode;
-       struct wait_queue *wait;
        struct page *write_list;
-       struct page *next, *prev;
-       struct page *next_hash, *prev_hash;
+
+       struct page *prev;
+       struct page *prev_hash;
 } mem_map_t;
 
 extern mem_map_t * mem_map;
index 62677673d71136400e8a964f4c05e580d406a61f..2c022fd532a5c945d4987bda34b6e7e282735728 100644 (file)
@@ -164,6 +164,7 @@ extern void msdos_put_inode(struct inode *inode);
 extern void msdos_put_super(struct super_block *sb);
 extern struct super_block *msdos_read_super(struct super_block *s,
                                            void *data,int);
+extern int init_msdos_fs(void);
 extern void msdos_statfs(struct super_block *sb,struct statfs *buf, int);
 extern int msdos_bmap(struct inode *inode,int block);
 extern void msdos_read_inode(struct inode *inode);
index fb2cd44fc2665209cfa2c175ea306ef61dd3a687..1d8235b17117f38697927c75515ca522d7ce8345 100644 (file)
@@ -142,6 +142,7 @@ int ncp_ioctl (struct inode * inode, struct file * filp,
 /* linux/fs/ncpfs/inode.c */
 struct super_block *ncp_read_super(struct super_block *sb,
                                    void *raw_data, int silent);
+extern int init_ncp_fs(void);
 void ncp_invalidate_connection(struct ncp_server *server);
 int ncp_conn_is_valid(struct ncp_server *server);
 
index b30246c2ac1db4738aecedeb3c93b448ce788c12..3ba9a174d702c34ecc4f3397992d1250dc1df73b 100644 (file)
@@ -98,6 +98,7 @@ extern int nfs_rpc_call(struct nfs_server *server, int *start, int *end, int siz
 
 extern struct super_block *nfs_read_super(struct super_block *sb, 
                                          void *data,int);
+extern int init_nfs_fs(void);
 extern struct inode *nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle,
                               struct nfs_fattr *fattr);
 extern void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr);
index 036d4a3da921f6e7868c067450812f90cc650e3d..fb96ea20f87112ce44f25e5b4b3eae0e962745cd 100644 (file)
+/*     linux/include/linux/optcd.h - Optics Storage 8000 AT CDROM driver
+       $Id: optcd.h,v 1.2 1996/01/15 18:43:44 root Exp root $
 
-/* Defines for the Optics Storage 8000AT CDROM drive. */
-
-#ifndef _LINUX_OPTCD_H
-
-#define _LINUX_OPTCD_H
-
-/* Drive registers */
-#define OPTCD_PORTBASE 0x340
-/* Read */
-#define DATA_PORT      optcd_port      /* Read data/status */
-#define STATUS_PORT    optcd_port+1    /* Indicate data/status availability */
-/* Write */
-#define COMIN_PORT     optcd_port      /* For passing command/parameter */
-#define RESET_PORT     optcd_port+1    /* Write anything and wait 0.5 sec */
-#define HCON_PORT      optcd_port+2    /* Host Xfer Configuration */
+       Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
 
 
-/* Command completion/status read from DATA register */
-#define ST_DRVERR              0x80
-#define ST_DOOR_OPEN           0x40
-#define ST_MIXEDMODE_DISK      0x20
-#define ST_MODE_BITS           0x1c
-#define ST_M_STOP              0x00
-#define ST_M_READ              0x04
-#define ST_M_AUDIO             0x04
-#define ST_M_PAUSE             0x08
-#define ST_M_INITIAL           0x0c
-#define ST_M_ERROR             0x10
-#define ST_M_OTHERS            0x14
-#define        ST_MODE2TRACK           0x02
-#define        ST_DSK_CHG              0x01
-#define ST_L_LOCK              0x01
-#define ST_CMD_OK              0x00
-#define ST_OP_OK               0x01
-#define ST_PA_OK               0x02
-#define ST_OP_ERROR            0x05
-#define ST_PA_ERROR            0x06
+       Configuration file for linux/drivers/cdrom/optcd.c
+*/
 
-/* Error codes (appear as command completion code from DATA register) */
-/* Player related errors */
-#define ERR_ILLCMD     0x11    /* Illegal command to player module */
-#define ERR_ILLPARM    0x12    /* Illegal parameter to player module */
-#define ERR_SLEDGE     0x13
-#define ERR_FOCUS      0x14
-#define ERR_MOTOR      0x15
-#define ERR_RADIAL     0x16
-#define ERR_PLL                0x17    /* PLL lock error */
-#define ERR_SUB_TIM    0x18    /* Subcode timeout error */
-#define ERR_SUB_NF     0x19    /* Subcode not found error */
-#define ERR_TRAY       0x1a
-#define ERR_TOC                0x1b    /* Table of Contents read error */
-#define ERR_JUMP       0x1c
-/* Data errors */
-#define ERR_MODE       0x21
-#define ERR_FORM       0x22
-#define ERR_HEADADDR   0x23    /* Header Address not found */
-#define ERR_CRC                0x24
-#define ERR_ECC                0x25    /* Uncorrectable ECC error */
-#define ERR_CRC_UNC    0x26    /* CRC error and uncorrectable error */
-#define ERR_ILLBSYNC   0x27    /* Illegal block sync error */
-#define ERR_VDST       0x28    /* VDST not found */
-/* Timeout errors */
-#define ERR_READ_TIM   0x31    /* Read timeout error */
-#define ERR_DEC_STP    0x32    /* Decoder stopped */
-#define ERR_DEC_TIM    0x33    /* Decoder interrupt timeout error */
-/* Function abort codes */
-#define ERR_KEY                0x41    /* Key -Detected abort */
-#define ERR_READ_FINISH        0x42    /* Read Finish */
-/* Second Byte diagnostic codes */
-#define ERR_NOBSYNC    0x01    /* No block sync */
-#define ERR_SHORTB     0x02    /* Short block */
-#define ERR_LONGB      0x03    /* Long block */
-#define ERR_SHORTDSP   0x04    /* Short DSP word */
-#define ERR_LONGDSP    0x05    /* Long DSP word */
+#ifndef _LINUX_OPTCD_H
+#define _LINUX_OPTCD_H
 
 
-/* Status availability flags read from STATUS register */
-#define FL_EJECT       0x20
-#define FL_WAIT                0x10    /* active low */
-#define FL_EOP         0x08    /* active low */
-#define FL_STEN                0x04    /* Status available when low */
-#define FL_DTEN                0x02    /* Data available when low */
-#define FL_DRQ         0x01    /* active low */
-#define FL_RESET       0xde    /* These bits are high after a reset */
-#define FL_STDT                (FL_STEN|FL_DTEN)
+/* I/O base of drive. Drive uses base to base+2.
+   This setting can be overridden with the kernel or insmod command
+   line option 'optcd=<portbase>'. Use address of 0 to disable driver. */
+#define OPTCD_PORTBASE 0x340
 
 
-/* Transfer mode, written to HCON register */
-#define HCON_DTS       0x08
-#define HCON_SDRQB     0x04
-#define HCON_LOHI      0x02
-#define HCON_DMA16     0x01
+/* enable / disable parts of driver by define / undef */
+#define        MULTISESSION            /* multisession support (ALPHA) */
+#define        PROBE_ISP16             /* ISP16 interface card probing */
+/* ISP16 probing can also be suppressed with kernel command line option
+   'noisp16', or with insmod parameter 'noisp16=1'. */
 
 
-/* Drive command set, written to COMIN register */
-/* Quick response commands */
-#define COMDRVST       0x20    /* Drive Status Read */
-#define COMERRST       0x21    /* Error Status Read */
-#define COMIOCTLISTAT  0x22    /* Status Read; reset disk changed bit */
-#define COMINITSINGLE  0x28    /* Initialize Single Speed */
-#define COMINITDOUBLE  0x29    /* Initialize Double Speed */
-#define COMUNLOCK      0x30    /* Unlock */
-#define COMLOCK                0x31    /* Lock */
-#define COMLOCKST      0x32    /* Lock/Unlock Status */
-#define COMVERSION     0x40    /* Get Firmware Revision */
-#define COMVOIDREADMODE        0x50    /* Void Data Read Mode */
-/* Read commands */
-#define COMFETCH       0x60    /* Prefetch Data */
-#define COMREAD                0x61    /* Read */
-#define COMREADRAW     0x62    /* Read Raw Data */
-#define COMREADALL     0x63    /* Read All 2646 Bytes */
-/* Player control commands */
-#define COMLEADIN      0x70    /* Seek To Lead-in */
-#define COMSEEK                0x71    /* Seek */
-#define COMPAUSEON     0x80    /* Pause On */
-#define COMPAUSEOFF    0x81    /* Pause Off */
-#define COMSTOP                0x82    /* Stop */
-#define COMOPEN                0x90    /* Open Tray Door */
-#define COMCLOSE       0x91    /* Close Tray Door */
-#define COMPLAY                0xa0    /* Audio Play */
-#define COMPLAY_TNO    0xa2    /* Audio Play By Track Number */
-#define COMSUBQ                0xb0    /* Read Sub-q Code */
-#define COMLOCATION    0xb1    /* Read Head Position */
-/* Audio control commands */
-#define COMCHCTRL      0xc0    /* Audio Channel Control */
-/* Miscellaneous (test) commands */
-#define COMDRVTEST     0xd0    /* Write Test Bytes */
-#define COMTEST                0xd1    /* Diagnostic Test */
+/* Change 0 to 1 to debug various parts of the driver */
+#define        DEBUG_DRIVE_IF  0       /* Low level drive interface */
+#define        DEBUG_CONV      0       /* Address conversions */
+#define        DEBUG_BUFFERS   0       /* Buffering and block size conversion */
+#define        DEBUG_REQUEST   0       /* Request mechanism */
+#define        DEBUG_STATE     0       /* State machine */
+#define        DEBUG_TOC       0       /* Q-channel and Table of Contents */
+#define        DEBUG_MULTIS    0       /* Multisession code */
+#define        DEBUG_VFS       0       /* VFS interface */
 
 
+/* Various timeout loop repetition counts. Don't touch unless you know
+   what you're doing. */
 #define BUSY_TIMEOUT           10000000        /* for busy wait */
-#define SLEEP_TIMEOUT          400             /* for timer wait */
+#define FAST_TIMEOUT           100000          /* ibid. for probing */
+#define SLEEP_TIMEOUT          3000            /* for timer wait */
+#define MULTI_SEEK_TIMEOUT     500             /* for timer wait */
 #define READ_TIMEOUT           3000            /* for poll wait */
-#define RESET_WAIT             1000
-
-#define SET_TIMER(func, jifs) \
-       delay_timer.expires = jiffies+(jifs); \
-       delay_timer.function = (void *) (func); \
-       add_timer(&delay_timer);
-#define CLEAR_TIMER            del_timer(&delay_timer)
-
-#define MAX_TRACKS             104
-
-struct msf {
-       unsigned char   min;
-       unsigned char   sec;
-       unsigned char   frame;
-};
-
-struct opt_Play_msf {
-       struct msf      start;
-       struct msf      end;
-};
-
-struct opt_DiskInfo {
-       unsigned char   first;
-       unsigned char   last;
-       struct msf      diskLength;
-       struct msf      firstTrack;
-};
-
-struct opt_Toc {
-       unsigned char   ctrl_addr;
-       unsigned char   track;
-       unsigned char   pointIndex;
-       struct msf      trackTime;
-       struct msf      diskTime;
-};
-
-
-#define CURRENT_VALID \
-       (CURRENT && MAJOR(CURRENT -> rq_dev) == MAJOR_NR \
-        && CURRENT -> cmd == READ && CURRENT -> sector != -1)
-
-
-#undef DEBUG_DRIVE_IF          /* Low level drive interface */
-#undef DEBUG_COMMANDS          /* Commands sent to drive */
-#undef DEBUG_VFS               /* VFS interface */
-#undef DEBUG_CONV              /* Address conversions */
-#undef DEBUG_TOC               /* Q-channel and Table of Contents */
-#undef DEBUG_BUFFERS           /* Buffering and block size conversion */
-#undef DEBUG_REQUEST           /* Request mechanism */
-#undef DEBUG_STATE             /* State machine */
-
-
-/* Low level drive interface */
-
-/* Errors that can occur in the low level interface */
-#define ERR_IF_CMD_TIMEOUT     0x100
-#define ERR_IF_ERR_TIMEOUT     0x101
-#define ERR_IF_RESP_TIMEOUT    0x102
-#define ERR_IF_DATA_TIMEOUT    0x103
-#define ERR_IF_NOSTAT          0x104
-/* Errors in table of contents */
-#define ERR_TOC_MISSINGINFO    0x120
-#define ERR_TOC_MISSINGENTRY   0x121
+#define STOP_TIMEOUT           1000            /* for poll wait */
+#define RESET_WAIT             1000            /* busy wait at drive reset */
 
-/* End .h defines */
 #endif _LINUX_OPTCD_H
index e70875f23540fd3e4a8f04e0ee1d069bd99573f3..086fe4eeefc0ccf974c362e31d8e107d42bbd051 100644 (file)
@@ -110,6 +110,13 @@ static inline void add_page_to_inode_queue(struct inode * inode, struct page * p
        *p = page;
 }
 
+extern void __wait_on_page(struct page *);
+static inline void wait_on_page(struct page * page)
+{
+       if (page->locked)
+               __wait_on_page(page);
+}
+
 extern void update_vm_cache(struct inode *, unsigned long, const char *, int);
 
 #endif
index b64001aee940784f162f6eb44df5c9102a28602f..f23ea0c5522e241c818ac0d4c58b70b70e2bcf10 100644 (file)
 #define PCI_DEVICE_ID_FD_36C70         0x0000
 
 #define PCI_VENDOR_ID_SI               0x1039
+#define PCI_DEVICE_ID_SI_6201          0x0001
 #define PCI_DEVICE_ID_SI_6202          0x0002
 #define PCI_DEVICE_ID_SI_503           0x0008
 #define PCI_DEVICE_ID_SI_501           0x0406
index 58cf6ea5a6b254ffa9ae81a3d34f18d337fe7c84..05524b69fbc8d56cf9740ff800cc153bbde04727 100644 (file)
@@ -98,6 +98,7 @@ enum net_directory_inos {
 
 enum scsi_directory_inos {
        PROC_SCSI_SCSI = 256,
+       PROC_SCSI_ADVANSYS,
        PROC_SCSI_EATA,
        PROC_SCSI_EATA_PIO,
        PROC_SCSI_AHA152X,
@@ -223,6 +224,7 @@ static inline int proc_scsi_unregister(struct proc_dir_entry *driver, int x)
 }
 
 extern struct super_block *proc_read_super(struct super_block *,void *,int);
+extern int init_proc_fs(void);
 extern struct inode * proc_get_inode(struct super_block *, int, struct proc_dir_entry *);
 extern void proc_statfs(struct super_block *, struct statfs *, int);
 extern void proc_read_inode(struct inode *);
index 7c3979763dfe9840396ba5f17681297ea0194097..e7b2588b05b5c4aa7f8f5c98c656ef1b40cfad48 100644 (file)
@@ -192,8 +192,6 @@ struct dquot {
 /*
  * declaration of quota_function calls in kernel.
  */
-int quota_off (kdev_t dev, short type);
-int sync_dquots (kdev_t dev, short type);
 
 extern void dquot_initialize(struct inode *inode, short type);
 extern void dquot_drop(struct inode *inode);
index 8504c455e20ba57a39be8e674f0df1d25ab1e1bf..1ff5b69c914e3546a53ef570417f30e83aad0bf3 100644 (file)
@@ -316,6 +316,8 @@ extern unsigned long * prof_buffer;
 extern unsigned long prof_len;
 extern unsigned long prof_shift;
 
+extern int securelevel;        /* system security level */
+
 #define CURRENT_TIME (xtime.tv_sec)
 
 extern void sleep_on(struct wait_queue ** p);
index 1eda0af96b760e3c41c76b2acd7c6f87744bf56b..f3294d18ebb11535dc53094b6ec60a546370db7e 100644 (file)
@@ -114,6 +114,7 @@ int smb_ioctl (struct inode * inode, struct file * filp,
 /* linux/fs/smbfs/inode.c */
 struct super_block *smb_read_super(struct super_block *sb,
                                    void *raw_data, int silent);
+extern int init_smb_fs(void);
 int smb_notify_change(struct inode *inode, struct iattr *attr);
 void smb_invalidate_connection(struct smb_server *server);
 int smb_conn_is_valid(struct smb_server *server);
index ce2de61d6220bdf9f5e1fc3dbc9cf35c911d27d4..c4035bc903901c60b28b6972e37ad39675515f8c 100644 (file)
 #define SNDCTL_TMR_METRONOME           _IOW ('T', 7, int)
 #define SNDCTL_TMR_SELECT              _IOW ('T', 8, int)
 
+/*
+ *     Endian aware patch key generation algorithm.
+ */
+
+#if defined(_AIX) || defined(AIX)
+#  define _PATCHKEY(id) (0xfd00|id)
+#else
+#  define _PATCHKEY(id) ((id<<8)|0xfd)
+#endif
+
 /*
  *     Sample loading mechanism for internal synthesizers (/dev/sequencer)
  *     The following patch_info structure has been designed to support
  */
 
 struct patch_info {
-               short key;              /* Use GUS_PATCH here */
-#define GUS_PATCH      0x04fd
-#define OBSOLETE_GUS_PATCH     0x02fd
+               unsigned short key;             /* Use GUS_PATCH here */
+#define GUS_PATCH      _PATCHKEY(0x04)
+#define OBSOLETE_GUS_PATCH     _PATCHKEY(0x02)
+
                short device_no;        /* Synthesizer number */
                short instr_no;         /* Midi pgm# */
 
@@ -236,8 +247,8 @@ struct patch_info {
 
 struct sysex_info {
                short key;              /* Use GUS_PATCH here */
-#define SYSEX_PATCH    0x05fd
-#define MAUI_PATCH     0x06fd          /* For future use */
+#define SYSEX_PATCH    _PATCHKEY(0x05)
+#define MAUI_PATCH     _PATCHKEY(0x06)
                short device_no;        /* Synthesizer number */
                long len;       /* Size of the sysex data in bytes */
                unsigned char data[1];  /* Sysex data starts here */
@@ -488,9 +499,9 @@ struct patmgr_info {        /* Note! size must be < 4k since kmalloc() is used */
 typedef unsigned char sbi_instr_data[32];
 
 struct sbi_instrument {
-               unsigned short  key;            /*      Initialize to FM_PATCH or OPL3_PATCH */
-#define FM_PATCH       0x01fd
-#define OPL3_PATCH     0x03fd
+               unsigned short  key;    /* FM_PATCH or OPL3_PATCH */
+#define FM_PATCH       _PATCHKEY(0x01)
+#define OPL3_PATCH     _PATCHKEY(0x03)
                short           device;         /*      Synth# (0-4)    */
                int             channel;        /*      Program# to be initialized      */
                sbi_instr_data  operators;      /*      Register settings for operator cells (.SBI format)      */
@@ -507,6 +518,7 @@ struct synth_info { /* Read only */
                int     synth_subtype;
 #define FM_TYPE_ADLIB                  0x00
 #define FM_TYPE_OPL3                   0x01
+#define MIDI_TYPE_MPU401               0x401
 
 #define SAMPLE_TYPE_GUS                        0x10
 
@@ -628,6 +640,7 @@ typedef struct buffmem_desc {
        } buffmem_desc;
 #define SNDCTL_DSP_MAPINBUF            _IOR ('P', 19, buffmem_desc)
 #define SNDCTL_DSP_MAPOUTBUF           _IOR ('P', 20, buffmem_desc)
+#define SNDCTL_DSP_SETSYNCRO           _IO  ('P', 21)
 
 #define SOUND_PCM_READ_RATE            _IOR ('P', 2, int)
 #define SOUND_PCM_READ_CHANNELS                _IOR ('P', 6, int)
@@ -650,6 +663,7 @@ typedef struct buffmem_desc {
 #define SOUND_PCM_GETCAPS              SNDCTL_DSP_GETCAPS
 #define SOUND_PCM_GETTRIGGER           SNDCTL_DSP_GETTRIGGER
 #define SOUND_PCM_SETTRIGGER           SNDCTL_DSP_SETTRIGGER
+#define SOUND_PCM_SETSYNCRO            SNDCTL_DSP_SETSYNCRO
 #define SOUND_PCM_GETIPTR              SNDCTL_DSP_GETIPTR
 #define SOUND_PCM_GETOPTR              SNDCTL_DSP_GETOPTR
 #define SOUND_PCM_MAPINBUF             SNDCTL_DSP_MAPINBUF
@@ -739,11 +753,19 @@ typedef struct copr_msg {
 #define SOUND_ONOFF_MIN                28
 #define SOUND_ONOFF_MAX                30
 #define SOUND_MIXER_MUTE       28      /* 0 or 1 */
-#define SOUND_MIXER_ENHANCE    29      /* Enhanced stereo (0, 40, 60 or 80) */
 #define SOUND_MIXER_LOUD       30      /* 0 or 1 */
 
 /* Note!       Number 31 cannot be used since the sign bit is reserved */
 
+
+/*
+ * SOUND_MIXER_ENHANCE is an unsupported and undocumented call which
+ * will be removed from the API in future.
+ */
+#define SOUND_MIXER_ENHANCE    29      /* Enhanced stereo (0, 40, 60 or 80) */
+
+
+
 #define SOUND_DEVICE_LABELS    {"Vol  ", "Bass ", "Trebl", "Synth", "Pcm  ", "Spkr ", "Line ", \
                                 "Mic  ", "CD   ", "Mix  ", "Pcm2 ", "Rec  ", "IGain", "OGain", \
                                 "Line1", "Line2", "Line3"}
index 9dd64cec9e851928fa0d8bb42dae23bb8e61a3ea..a8a29fefdc194618eccbc071603d68006bff0898 100644 (file)
@@ -42,6 +42,17 @@ typedef struct kswapd_control_v1
 typedef kswapd_control_v1 kswapd_control_t;
 extern kswapd_control_t kswapd_ctl;
 
+typedef struct swapstat_v1
+{
+       int     wakeups;
+       int     pages_reclaimed;
+       int     pages_shm;
+       int     pages_mmap;
+       int     pages_swap;
+} swapstat_v1;
+typedef swapstat_v1 swapstat_t;
+extern swapstat_t swapstats;
+
 #define SC_VERSION     1
 #define SC_MAX_VERSION 1
 
index b4c23df794c5e844ff476d41c2191a069cca4aaf..e6c3654eba23be6002b236f0e23a5e3b8f9ea4e4 100644 (file)
@@ -54,6 +54,7 @@ struct __sysctl_args {
 #define KERN_NRFILE    11
 #define KERN_MAXFILE   12
 #define KERN_MAXID     13
+#define KERN_SECURELVL 14      /* int: system security level */
 
 /* CTL_VM names: */
 #define VM_SWAPCTL     1       /* struct: Set vm swapping control */
index daa2bba2241cbb6fef102a6e740789242ea29e2d..cfe6b106eb74883c6f083c264d720e99c7b73151 100644 (file)
@@ -390,6 +390,7 @@ extern int sysv_file_read(struct inode *, struct file *, char *, int);
 extern void sysv_truncate(struct inode *);
 extern void sysv_put_super(struct super_block *);
 extern struct super_block *sysv_read_super(struct super_block *,void *,int);
+extern int init_sysv_fs(void);
 extern void sysv_write_super(struct super_block *);
 extern void sysv_read_inode(struct inode *);
 extern int sysv_notify_change(struct inode *, struct iattr *);
index 3702d6294826a6a46ead05e991d90b75772fa9b1..b25f0c31e0b2ceaf21a043f034f5ce3174465734 100644 (file)
@@ -136,6 +136,7 @@ extern struct file_operations  umsdos_file_operations;
 extern struct inode_operations umsdos_file_inode_operations;
 extern struct inode_operations umsdos_file_inode_operations_no_bmap;
 extern struct inode_operations umsdos_symlink_inode_operations;
+extern int init_umsdos_fs(void);
 
 #include <linux/umsdos_fs.p>
 
diff --git a/include/linux/wrapper.h b/include/linux/wrapper.h
new file mode 100644 (file)
index 0000000..64ec739
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _WRAPPER_H_
+#define _WRAPPER_H_
+#define wait_handle struct wait_queue
+#define file_handle struct file
+#define inode_handle struct inode
+#define select_table_handle select_table
+#define vm_area_handle struct vm_area_struct
+#define file_operation_handle file_operations
+
+#define connect_wrapper(x) 0
+#define current_got_fatal_signal() (current->signal & ~current->blocked)
+#define current_set_timeout(val) current->timeout = val
+
+#define module_interruptible_sleep_on interruptible_sleep_on
+#define module_wake_up wake_up
+#define module_select_wait select_wait
+#define module_register_chrdev register_chrdev
+#define module_unregister_chrdev unregister_chrdev
+#define module_register_blkdev register_blkdev
+#define module_unregister_blkdev unregister_blkdev
+
+#define inode_get_rdev(i) i->i_rdev
+#define inode_get_count(i) i->i_count
+#define inode_inc_count(i) i->i_count++
+#define inode_dec_count(i) i->i_count--
+
+#define file_get_flags(f) f->f_flags
+
+#define vma_set_inode(v,i) v->vm_inode = i
+#define vma_get_flags(v) v->vm_flags
+#define vma_get_offset(v) v->vm_offset
+#define vma_get_start(v) v->vm_start
+#define vma_get_end(v) v->vm_end
+#define vma_get_page_prot(v) v->vm_page_prot
+
+#define mem_map_reserve(p) mem_map[p].reserved = 1
+#define mem_map_unreserve(p) mem_map[p].reserved = 0
+#define mem_map_inc_count(p) mem_map[p].count++
+#define mem_map_dec_count(p) mem_map[p].count--
+#endif
index 908360976eafe1ffcea9156353c9d38f09fc96f8..f43419e337bc896b4a1dae6b48f9ec2d505ef719 100644 (file)
@@ -95,6 +95,7 @@ extern struct buffer_head * xiafs_bread(struct inode *, int, int);
 extern void xiafs_truncate(struct inode *);
 extern void xiafs_put_super(struct super_block *);
 extern struct super_block *xiafs_read_super(struct super_block *,void *,int);
+extern int init_xiafs_fs(void);
 extern void xiafs_read_inode(struct inode *);
 extern void xiafs_write_inode(struct inode *);
 extern void xiafs_put_inode(struct inode *);
index 637cc7c18006dc198ff432d83bbaf7a74d3fda51..a2a9c39201f3f302601602c697655af1ffd2793c 100644 (file)
@@ -26,6 +26,8 @@
 #ifndef _ROUTE_H
 #define _ROUTE_H
 
+#include <linux/config.h>
+
 /*
  * 0 - no debugging messages
  * 1 - rare events and bugs situations (default)
index 5e483f7d3ff037b18ac6411e0eb275c3b22d8262..d3bcead2dc722f77bd82fe89cc18b2cf2077e887 100644 (file)
@@ -62,6 +62,7 @@ extern void xd_setup(char *str, int *ints);
 extern void floppy_setup(char *str, int *ints);
 extern void st_setup(char *str, int *ints);
 extern void st0x_setup(char *str, int *ints);
+extern void advansys_setup(char *str, int *ints);
 extern void tmc8xx_setup(char *str, int *ints);
 extern void t128_setup(char *str, int *ints);
 extern void pas16_setup(char *str, int *ints);
@@ -201,6 +202,9 @@ struct {
 #ifdef CONFIG_SCSI
        { "max_scsi_luns=", scsi_luns_setup },
 #endif
+#ifdef CONFIG_SCSI_ADVANSYS
+       { "advansys=", advansys_setup },
+#endif
 #if defined(CONFIG_BLK_DEV_HD)
        { "hd=", hd_setup },
 #endif
@@ -489,6 +493,7 @@ static void parse_options(char *line)
 
 
 extern void setup_arch(char **, unsigned long *, unsigned long *);
+extern void arch_syms_export(void);
 
 #ifndef __SMP__
 
@@ -635,6 +640,7 @@ asmlinkage void start_kernel(void)
        apm_bios_init();
 #endif
        dquot_init();
+       arch_syms_export();
        sti();
        check_bugs();
 
index aad0973ecf45a59c9d4614aebcd576735a0e1b7a..1f131c9544f9cfcf45560d9774d0239549204b71 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -6,7 +6,7 @@
  *
  */
 
-#include <linux/autoconf.h>
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/msg.h>
@@ -190,7 +190,7 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty
                        return -EIDRM;
                if ((msgflg & IPC_KERNELD) == 0)
                        /*
-                        * Non-root processes may recieve from kerneld! 
+                        * Non-root processes may receive from kerneld! 
                         * i.e. no permission check if called from the kernel
                         * otoh we don't want user level non-root snoopers...
                         */
@@ -554,7 +554,7 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
 /*
  * We do perhaps need a "flush" for waiting processes,
  * so that if they are terminated, a call from do_exit
- * will minimize the possibility of orphaned recieved
+ * will minimize the possibility of orphaned received
  * messages in the queue.  For now we just make sure
  * that the queue is shut down whenever kerneld dies.
  */
index c2d3dc883a786f1b52af9ff8521ccb047f646c72..89a7c3359b9f4361bb211ba3ce59b0bbeaa73418 100644 (file)
@@ -118,4 +118,7 @@ asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
        return -ENOSYS;
 }
 
+void kerneld_exit(void)
+{
+}
 #endif /* CONFIG_SYSVIPC */
index e16721d0e7a3cec76155d04dde200607b96e6fce..3c5b4315e72c190cfb5bd4c9ecfa75f0b812a173 100644 (file)
 #include <linux/mount.h>
 #include <linux/pagemap.h>
 #include <linux/sysctl.h>
+#include <linux/genhd.h>
 
 extern unsigned char aux_device_present, kbd_read_mask;
 
-#ifdef __alpha__
-# include <asm/io.h>
-# include <asm/hwrpb.h>
-
-extern void bcopy (const char *src, char *dst, int len);
-extern struct hwrpb_struct *hwrpb;
-
-/* these are C runtime functions with special calling conventions: */
-extern void __divl (void);
-extern void __reml (void);
-extern void __divq (void);
-extern void __remq (void);
-extern void __divlu (void);
-extern void __remlu (void);
-extern void __divqu (void);
-extern void __remqu (void);
-
-#endif
-
 #ifdef CONFIG_NET
 #include <linux/in.h>
 #include <linux/net.h>
@@ -84,9 +66,6 @@ extern void __remqu (void);
 #include <net/tcp.h>
 #include <net/route.h>
 #include <linux/net_alias.h>
-#if defined(CONFIG_PPP) || defined(CONFIG_SLIP)
-#include "../drivers/net/slhc.h"
-#endif
 #endif
 #ifdef CONFIG_NET_ALIAS
 #include <linux/net_alias.h>
@@ -96,10 +75,6 @@ extern void __remqu (void);
 #include <linux/bios32.h>
 #include <linux/pci.h>
 #endif
-#if defined(CONFIG_MSDOS_FS) && !defined(CONFIG_UMSDOS_FS)
-#include <linux/msdos_fs.h>
-#endif
-
 #if defined(CONFIG_PROC_FS)
 #include <linux/proc_fs.h>
 #endif
@@ -111,6 +86,19 @@ extern void __remqu (void);
 #include <linux/smp.h>
 #endif
 
+#ifndef CONFIG_SCSI
+#if defined(CONFIG_PROC_FS)
+/*
+ * This is all required so that if we load all of scsi as a module,
+ * that the scsi code will be able to talk to the /proc/scsi handling
+ * in the procfs.
+ */
+extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
+                               off_t offset, int length, int inout);
+extern struct inode_operations proc_scsi_inode_operations;
+#endif
+#endif
+
 extern char *get_options(char *str, int *ints);
 extern void set_device_ro(int dev,int flag);
 extern struct file_operations * get_blkfops(unsigned int);
@@ -124,17 +112,6 @@ extern void *sys_call_table;
 #include "../drivers/net/8390.h"
 #endif
 
-#ifdef CONFIG_SCSI
-#include "../drivers/scsi/scsi.h"
-#include "../drivers/scsi/scsi_ioctl.h"
-#include "../drivers/scsi/hosts.h"
-#include "../drivers/scsi/constants.h"
-#include "../drivers/scsi/sd.h"
-#include <linux/scsicam.h>
-
-extern int generic_proc_info(char *, char **, off_t, int, int, int);
-#endif
-
 extern int sys_tz;
 extern int request_dma(unsigned int dmanr, char * deviceID);
 extern void free_dma(unsigned int dmanr);
@@ -154,30 +131,6 @@ struct symbol_table symbol_table = {
                SYMBOL_NAME_STR (Using_Versions) },
 #endif
 
-       /* platform dependent support */
-#ifdef __alpha__
-       X(_inb),
-       X(_inw),
-       X(_inl),
-       X(_outb),
-       X(_outw),
-       X(_outl),
-       X(bcopy),       /* generated by gcc-2.7.0 for string assignments */
-       X(hwrpb),
-       X(__divl),
-       X(__reml),
-       X(__divq),
-       X(__remq),
-       X(__divlu),
-       X(__remlu),
-       X(__divqu),
-       X(__remqu),
-       X(strlen),      /* used by ftape */
-       X(memcmp),
-       X(memmove),
-       X(__constant_c_memset),
-#endif
-
        /* stackable module support */
        X(rename_module_symbol),
        X(register_symtab),
@@ -361,9 +314,6 @@ struct symbol_table symbol_table = {
        X(interruptible_sleep_on),
        X(schedule),
        X(current_set),
-#if defined(__i386__) && defined(__SMP__)
-       X(apic_reg),            /* Needed internally for the I386 inlines */
-#endif 
        X(jiffies),
        X(xtime),
        X(do_gettimeofday),
@@ -431,15 +381,6 @@ struct symbol_table symbol_table = {
        X(ethdev_init),
        X(NS8390_init),
 #endif
-#if defined(CONFIG_PPP) || defined(CONFIG_SLIP)
-       /* VJ header compression */
-       X(slhc_init),
-       X(slhc_free),
-       X(slhc_remember),
-       X(slhc_compress),
-       X(slhc_uncompress),
-       X(slhc_toss),
-#endif
 #ifdef CONFIG_NET_ALIAS
 #include <linux/net_alias.h>
 #endif
@@ -484,50 +425,24 @@ struct symbol_table symbol_table = {
        X(tty_register_ldisc),
        X(kill_fasync),
 #endif
-#ifdef CONFIG_SCSI
-       /* Supports loadable scsi drivers 
-        * technically some of this stuff could be moved to scsi.c, but
-        * scsi.c is initialized before the memory manager is set up.
-        * So we add it here too.  There is a duplicate set in scsi.c
-        * that is used when the entire scsi subsystem is a loadable
-        * module.
-        */
-       X(scsi_register_module),
-       X(scsi_unregister_module),
-       X(scsi_free),
-       X(scsi_malloc),
-       X(scsi_register),
-       X(scsi_unregister),
-       X(scsicam_bios_param),
-       X(allocate_device),
-       X(scsi_do_cmd),
-       X(scsi_command_size),
-       X(scsi_init_malloc),
-       X(scsi_init_free),
-       X(scsi_ioctl),
-       X(scsi_mark_host_bus_reset),
-       X(print_command),
-       X(print_msg),
-       X(print_status),
-       X(print_sense),
-       X(dma_free_sectors),
-       X(kernel_scsi_ioctl),
-       X(need_isa_buffer),
-       X(request_queueable),
-       X(generic_proc_info),
-       X(scsi_devices),
-       X(gendisk_head), /* Needed for sd.c */
-       X(resetup_one_dev), /* Needed for sd.c */
-#if defined(CONFIG_PROC_FS)
-       X(proc_print_scsidevice),
-#endif
-#else
+#ifndef CONFIG_SCSI
        /*
         * With no scsi configured, we still need to export a few
         * symbols so that scsi can be loaded later via insmod.
+        * Don't remove this unless you are 100% sure of what you are
+        * doing.  If you want to remove this, you don't know what
+        * you are doing!
         */
        X(gendisk_head),
        X(resetup_one_dev),
+#if defined(CONFIG_PROC_FS)
+       /*
+        * This is required so that if we load scsi later, that the
+        * scsi code can attach to /proc/scsi in the correct manner.
+        */
+       X(proc_scsi_inode_operations),
+       X(dispatch_scsi_info_ptr),
+#endif
 #endif
        /* Added to make file system as module */
        X(set_writetime),
@@ -547,38 +462,6 @@ struct symbol_table symbol_table = {
        X(insert_inode_hash),
        X(event),
        X(__down),
-#if defined(CONFIG_MSDOS_FS) && !defined(CONFIG_UMSDOS_FS)
-       /* support for umsdos fs */
-       X(msdos_bmap),
-       X(msdos_create),
-       X(msdos_file_read),
-       X(msdos_file_write),
-       X(msdos_lookup),
-       X(msdos_mkdir),
-       X(msdos_mmap),
-       X(msdos_put_inode),
-       X(msdos_put_super),
-       X(msdos_read_inode),
-       X(msdos_read_super),
-       X(msdos_readdir),
-       X(msdos_rename),
-       X(msdos_rmdir),
-       X(msdos_smap),
-       X(msdos_statfs),
-       X(msdos_truncate),
-       X(msdos_unlink),
-       X(msdos_unlink_umsdos),
-       X(msdos_write_inode),
-#endif
-#ifdef CONFIG_PROC_FS
-       X(proc_register),
-       X(proc_unregister),
-       X(in_group_p),
-       X(generate_cluster),
-       X(proc_scsi),
-       X(proc_net_inode_operations),
-       X(proc_net),
-#endif
 /* all busmice */
        X(add_mouse_randomness),
        X(fasync_helper),
index 7567374b5a1d0ef21caeb7842858973d7e508c85..116668f6f6b6f5337d5fa489ea6be3995a0abf66 100644 (file)
@@ -38,6 +38,9 @@
 /*
  * kernel variables
  */
+
+int securelevel = 0;                   /* system security level */
+
 long tick = 1000000 / HZ;               /* timer interrupt period */
 volatile struct timeval xtime;         /* The current time */
 int tickadj = 500/HZ;                  /* microsecs */
index 105a89c437e708835becf0b0996c10bb32f1b689..32eb3db8d3567f634821aa3a0dbdec84a6d52978 100644 (file)
@@ -5,7 +5,7 @@
  * Added /proc support, Dec 1995
  */
 
-#include <linux/autoconf.h>
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/sysctl.h>
@@ -81,6 +81,9 @@ static void register_proc_table(ctl_table *, struct proc_dir_entry *);
 static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
 #endif
 
+static int do_securelevel_strategy (ctl_table *, int *, int, void *, size_t *,
+                                   void *, size_t, void **);
+
 /* The default sysctl tables: */
 
 static ctl_table root_table[] = {
@@ -108,6 +111,8 @@ static ctl_table kern_table[] = {
         0444, NULL, &proc_dointvec},
        {KERN_MAXFILE, "file-max", &max_files, sizeof(int),
         0644, NULL, &proc_dointvec},
+       {KERN_SECURELVL, "securelevel", &securelevel, sizeof(int),
+        0444, NULL, &proc_dointvec, (ctl_handler *)&do_securelevel_strategy},
        {0}
 };
 
@@ -293,6 +298,27 @@ int do_sysctl_strategy (ctl_table *table,
        return 0;
 }
 
+/*
+ * This function only checks permission for changing the security level
+ * If the tests are successfull, the actual change is done by
+ * do_sysctl_strategy
+ */
+static int do_securelevel_strategy (ctl_table *table, 
+                                   int *name, int nlen,
+                                   void *oldval, size_t *oldlenp,
+                                   void *newval, size_t newlen, void **context)
+{
+       int level;
+
+       if (newval && newlen) {
+               if (newlen != sizeof (int))
+                       return -EINVAL;
+               memcpy_fromfs (&level, newval, newlen);
+               if (level < securelevel && current->pid != 1)
+                       return -EPERM;
+       }
+       return 0;
+}
 
 struct ctl_table_header *register_sysctl_table(ctl_table * table, 
                                               int insert_at_head)
index d1323e9aab1b2c4c1acca1343662fb305f3dee6f..9774a630e765f87d5ef459bc9c334d3175a53fd4 100644 (file)
@@ -43,14 +43,20 @@ struct page * page_hash_table[PAGE_HASH_SIZE];
 
 void invalidate_inode_pages(struct inode * inode, unsigned long start)
 {
-       struct page ** p = &inode->i_pages;
+       struct page ** p;
        struct page * page;
 
+repeat:
+       p = &inode->i_pages;
        while ((page = *p) != NULL) {
                unsigned long offset = page->offset;
 
                /* page wholly truncated - free it */
                if (offset >= start) {
+                       if (page->locked) {
+                               wait_on_page(page);
+                               goto repeat;
+                       }
                        inode->i_nrpages--;
                        if ((*p = page->next) != NULL)
                                (*p)->prev = page->prev;
@@ -107,7 +113,7 @@ int shrink_mmap(int priority, unsigned long limit)
                        page->referenced = 1;
                else if (page->referenced)
                        page->referenced = 0;
-               else if (page->count) {
+               else if (page->count && !page->locked) {
                        /* The page is an old, unshared page --- try
                            to discard it. */
                        if (page->inode) {
@@ -179,13 +185,15 @@ static unsigned long try_to_read_ahead(struct inode * inode, unsigned long offse
 {
        struct page * page;
 
+       offset &= PAGE_MASK;
        if (!page_cache) {
                page_cache = __get_free_page(GFP_KERNEL);
                if (!page_cache)
                        return 0;
        }
-#ifdef readahead_makes_sense_due_to_asynchronous_reads
-       offset = (offset + PAGE_SIZE) & PAGE_MASK;
+       if (offset >= inode->i_size)
+               return page_cache;
+#if 1
        page = find_page(inode, offset);
        if (page) {
                page->count--;
@@ -202,11 +210,8 @@ static unsigned long try_to_read_ahead(struct inode * inode, unsigned long offse
        add_page_to_inode_queue(inode, page);
        add_page_to_hash_queue(inode, page);
 
-       /* 
-        * And start IO on it..
-        * (this should be asynchronous, but currently isn't)
-        */
        inode->i_op->readpage(inode, page);
+
        free_page(page_cache);
        return 0;
 #else
@@ -214,17 +219,41 @@ static unsigned long try_to_read_ahead(struct inode * inode, unsigned long offse
 #endif
 }
 
+/* 
+ * Wait for IO to complete on a locked page.
+ */
+void __wait_on_page(struct page *page)
+{
+       struct wait_queue wait = { current, NULL };
+
+       page->count++;
+       add_wait_queue(&page->wait, &wait);
+repeat:
+       current->state = TASK_UNINTERRUPTIBLE;
+       if (page->locked) {
+               schedule();
+               goto repeat;
+       }
+       remove_wait_queue(&page->wait, &wait);
+       page->count--;
+       current->state = TASK_RUNNING;
+}
+
+
 /*
  * This is a generic file read routine, and uses the
  * inode->i_op->readpage() function for the actual low-level
  * stuff.
  */
+#define READAHEAD_PAGES 3
+#define MAX_IO_PAGES 4
 int generic_file_read(struct inode * inode, struct file * filp, char * buf, int count)
 {
-       int read = 0;
+       int read = 0, newpage = 0;
        unsigned long pos;
        unsigned long page_cache = 0;
-
+       int pre_read = 0;
+       
        if (count <= 0)
                return 0;
 
@@ -232,6 +261,8 @@ int generic_file_read(struct inode * inode, struct file * filp, char * buf, int
        do {
                struct page *page;
                unsigned long offset, addr, nr;
+               int i;
+               off_t p;
 
                if (pos >= inode->i_size)
                        break;
@@ -278,21 +309,49 @@ int generic_file_read(struct inode * inode, struct file * filp, char * buf, int
                add_page_to_inode_queue(inode, page);
                add_page_to_hash_queue(inode, page);
 
-               /* 
-                * And start IO on it..
-                * (this should be asynchronous, but currently isn't)
-                */
                inode->i_op->readpage(inode, page);
+               /* We only set "newpage" when we encounter a
+                   completely uncached page.  This way, we do no
+                   readahead if we are still just reading data out of
+                   the cache (even if the cached page is not yet
+                   uptodate --- it may be currently being read as a
+                   result of previous readahead).  -- sct */
+               newpage = 1;
 
 found_page:
                addr = page_address(page);
                if (nr > count)
                        nr = count;
-               if (!page->uptodate) {
-                       page_cache = try_to_read_ahead(inode, offset, page_cache);
-                       if (!page->uptodate)
-                               sleep_on(&page->wait);
+               /* We have two readahead cases.  First, do data
+                   pre-read if the current read request is for more
+                   than one page, so we can merge the adjacent
+                   requests. */
+               if (newpage && nr < count) {
+                       if (pre_read > 0)
+                               pre_read -= PAGE_SIZE;
+                       else {
+                               pre_read = (MAX_IO_PAGES-1) * PAGE_SIZE;
+                               if (pre_read > (count - nr))
+                                       pre_read = count - nr;
+                               for (i=0, p=pos; i<pre_read; i+=PAGE_SIZE) {
+                                       p += PAGE_SIZE;
+                                       page_cache = try_to_read_ahead(inode, p, page_cache);
+                               }
+                       }
+               }
+               else
+               /* Second, do readahead at the end of the read, if we
+                   are still waiting on the current IO to complete, if
+                   readahead is flagged for the file, and if we have
+                   finished with the current block. */
+               if (newpage && nr == count && filp->f_reada
+                   && !((pos + nr) & ~PAGE_MASK)) {
+                       for (i=0, p=pos; i<READAHEAD_PAGES; i++) {
+                               p += PAGE_SIZE;
+                               page_cache = try_to_read_ahead(inode, p, page_cache);
+                       }
                }
+               wait_on_page(page);
                if (nr > inode->i_size - pos)
                        nr = inode->i_size - pos;
                memcpy_tofs(buf, (void *) (addr + offset), nr);
@@ -304,6 +363,7 @@ found_page:
        } while (count);
 
        filp->f_pos = pos;
+       filp->f_reada = 1;
        if (page_cache)
                free_page(page_cache);
        if (!IS_RDONLY(inode)) {
@@ -315,7 +375,7 @@ found_page:
 
 /*
  * Find a cached page and wait for it to become up-to-date, return
- * the page address.
+ * the page address.  Increments the page count.
  */
 static inline unsigned long fill_page(struct inode * inode, unsigned long offset)
 {
@@ -344,8 +404,7 @@ static inline unsigned long fill_page(struct inode * inode, unsigned long offset
        add_page_to_hash_queue(inode, page);
        inode->i_op->readpage(inode, page);
 found_page:
-       if (!page->uptodate)
-               sleep_on(&page->wait);
+       wait_on_page(page);
        return page_address(page);
 }
 
index 1e10b326af82b3ecfeaa12ce712e33b5ca3845bd..155d6fb05ed0a84f0c89878a2a654c7b7b9b26fa 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -58,6 +58,8 @@ swap_control_t swap_control = {
        RCL_ROUND_ROBIN         /* Balancing policy */
 };
 
+swapstat_t swapstats = {0};
+
 /* General swap control */
 
 /* Parse the kernel command line "swap=" option at load time: */
index 016d988ba56af3073e6dac7656f2472a264d0a3a..ae24853056c9ff0b34f2d00d2d1954e1bffc18ea 100644 (file)
@@ -3,7 +3,9 @@
  *
  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
  *
- *  Swap reorganised 29.12.95, 
+ *  Swap reorganised 29.12.95, Stephen Tweedie.
+ *  kswapd added: 7.1.96  sct
+ *  Version: $Id: vmscan.c,v 1.3.2.3 1996/01/17 02:43:11 linux Exp $
  */
 
 #include <linux/mm.h>
@@ -357,6 +359,7 @@ int try_to_free_page(int priority, unsigned long limit)
 int kswapd(void *unused)
 {
        int i;
+       char *revision="$Revision: 1.3.2.3 $", *s, *e;
        
        current->session = 1;
        current->pgrp = 1;
@@ -380,15 +383,21 @@ int kswapd(void *unused)
                                    namings for POSIX.4 realtime scheduling
                                    priorities.  */
 
-       printk ("Started kswapd v$Revision: 1.1.2.3 $\n");
        init_swap_timer();
        
+       if ((s = strchr(revision, ':')) &&
+           (e = strchr(s, '$')))
+               s++, i = e - s;
+       else
+               s = revision, i = -1;
+       printk ("Started kswapd v%.*s\n", i, s);
+
        while (1) {
                kswapd_awake = 0;
                current->signal = 0;
                interruptible_sleep_on(&kswapd_wait);
                kswapd_awake = 1;
-               
+               swapstats.wakeups++;
                /* Do the background pageout: */
                for (i=0; i < kswapd_ctl.maxpages; i++)
                        try_to_free_page(GFP_KERNEL, ~0UL);
index 59ec5aca61d42f30696a0255c5d5e37253e9d6f1..9058928e438b8e1c2cbf30ff2e3e503c5e159faf 100644 (file)
@@ -20,3 +20,4 @@ bool 'Kernel/User network link driver(ALPHA)' CONFIG_NETLINK
 if [ "$CONFIG_NETLINK" = "y" ]; then
   bool 'Routing messages' CONFIG_RTNETLINK
 fi
+endmenu
index 0d5550f462a6423546f6c6ac35f351f9bb93f793..0cda2653b19f2621d985dbf9d6f218d477c45a8b 100644 (file)
@@ -30,7 +30,6 @@
  *             2 of the License, or (at your option) any later version.
  */
 #include <asm/system.h>
-#include <linux/autoconf.h>
 #include <linux/sched.h>
 #include <linux/socket.h>
 #include <linux/net.h>
index 2cec29174255fbe70821a2db728341beb4c2d7bc..863024a9d05ad7ad4aebd15e59d6e11a5f8379b4 100644 (file)
  * 
  * Use of PSH (4.2.2.2)
  *   MAY aggregate data sent without the PSH flag. (does)
- *   MAY queue data recieved without the PSH flag. (does)
+ *   MAY queue data received without the PSH flag. (does)
  *   SHOULD collapse successive PSH flags when it packetizes data. (doesn't)
  *   MAY implement PSH on send calls. (doesn't, thus:)
  *     MUST NOT buffer data indefinitely (doesn't [1 second])
  *     [Follows BSD 1 byte of urgent data]
  * 
  * TCP Options (4.2.2.5)
- *   MUST be able to recieve TCP options in any segment. (does)
+ *   MUST be able to receive TCP options in any segment. (does)
  *   MUST ignore unsupported options (does)
  *   
  * Maximum Segment Size Option (4.2.2.6)
  *   MUST implement both sending and receiving MSS. (does)
- *   SHOULD send an MSS with every SYN where recieve MSS != 536 (MAY send
+ *   SHOULD send an MSS with every SYN where receive MSS != 536 (MAY send
  *     it always). (does, even when MSS == 536, which is legal)
  *   MUST assume MSS == 536 if no MSS received at connection setup (does)
  *   MUST calculate "effective send MSS" correctly:
@@ -798,7 +798,7 @@ static void reset_xmit_timer(struct sock *sk, int why, unsigned long when)
 {
        del_timer(&sk->retransmit_timer);
        sk->ip_xmit_timeout = why;
-       if((int)when < 0)
+       if((long)when < 0)
        {
                when=3;
                printk("Error: Negative timer in xmit_timer\n");
@@ -3643,10 +3643,10 @@ extern __inline__ int tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long
                        sk->rto = ((sk->rtt >> 2) + sk->mdev) >> 1;
                        if (sk->rto > 120*HZ)
                                sk->rto = 120*HZ;
-                       if (sk->rto < 20)       /* Was 1*HZ, then 1 - turns out we must allow about
+                       if (sk->rto < HZ/5)     /* Was 1*HZ, then 1 - turns out we must allow about
                                                   .2 of a second because of BSD delayed acks - on a 100Mb/sec link
                                                   .2 of a second is going to need huge windows (SIGH) */
-                       sk->rto = 20;
+                       sk->rto = HZ/5;
                }
        }
 
@@ -3743,8 +3743,8 @@ extern __inline__ int tcp_ack(struct sock *sk, struct tcphdr *th, unsigned long
                                sk->rto = ((sk->rtt >> 2) + sk->mdev) >> 1;
                                if (sk->rto > 120*HZ)
                                        sk->rto = 120*HZ;
-                               if (sk->rto < 20)       /* Was 1*HZ - keep .2 as minimum cos of the BSD delayed acks */
-                                       sk->rto = 20;
+                               if (sk->rto < HZ/5)     /* Was 1*HZ - keep .2 as minimum cos of the BSD delayed acks */
+                                       sk->rto = HZ/5;
                                sk->backoff = 0;
                        }
                        flag |= (2|4);  /* 2 is really more like 'don't adjust the rtt 
index feb8ffdd7095b95eb78a18624429a14a9d81d806..e172e30ffd8c1f483d89be03b97992468b50cd65 100644 (file)
@@ -48,6 +48,9 @@ function mainmenu_option () {
 function mainmenu_name () {
        :
 }
+function endmenu () {
+       :
+}
 
 #
 # help prints the corresponding help text from Configure.help to stdout
@@ -268,6 +271,35 @@ function int () {
           esac
         done
 }
+#
+# define_hex sets the value of a hexadecimal argument
+#
+#      define_hex define value
+#
+function define_hex () {
+       echo "$1=$2" >>$CONFIG
+       echo "#define $1 0x$2" >>$CONFIG_H
+       eval "$1=$2"
+}
+
+#
+# hex processes an hexadecimal argument
+#
+#      hex question define default
+#
+function hex () {
+       def=$(eval echo "\${$2:-$3}")
+        while :; do
+          readln "$1 ($2) [$def] " "$def"
+          case "$ans" in
+             [1-9] | [1-9][0-9] | [1-9][0-9][0-9] | [1-9][0-9][0-9][0-9] ) 
+                 define_hex "$2" "$ans"
+                 break;;
+             * ) help "$2"
+                 ;;
+          esac
+        done
+}
 
 #
 # choice processes a choice list (1-out-of-n)
index 8c30ae82c9eb2e93a72c0bbc78ea263181b42cec..445b76e2d7c77a191b798a78e8b7f84012659631 100644 (file)
@@ -381,6 +381,11 @@ int parse(char * pnt) {
       tok = tok_fi;
       pnt += 2;
     }
+  else if (strncmp(pnt, "endmenu", 7) == 0) 
+    {
+      tok = tok_endmenu;
+      pnt += 7;
+    }
 
   if( tok == tok_unknown)
     {
@@ -476,6 +481,7 @@ int parse(char * pnt) {
     case tok_else:
     case tok_fi:
     case tok_sound:
+    case tok_endmenu:
       break;
     case tok_if:
       /*
@@ -692,6 +698,7 @@ main(int argc, char * argv[])
          dump_if(cfg->cond);
          break;
        case tok_nop:
+       case tok_endmenu:
          break;
        default:
          printf("\n");
index a4c302fbf99cee2c9961e9b8f78bdafcdaf74b14..d2e9f64730c7014dec773dcdc662da2ace62ae84 100644 (file)
@@ -15,7 +15,9 @@ enum token {
   tok_define,
   tok_choose,
   tok_choice,
+  tok_endmenu,
   tok_unknown
+
 };
 
 enum operator {