]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.4.0-test9pre7 2.4.0-test9pre7
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:39:08 +0000 (15:39 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:39:08 +0000 (15:39 -0500)
    - USB: remember to release the kernel lock and other updates..
    - recognize the k6 model 13: it's a K6-2+ mobile processor.
    - file locking deadlock detection bugfix..
    - NFSv3 is not really really experimental any more.
    - don't raise privileges when re-trying a failed NFS RPM request
    - alpha cross-compile fixes..
    - sound init cleanups
    - shm statistics bugfix.
    - nfsd: mark us as a O_LARGEFILE case, so that the VFS allows
      the full 64-bit access..
    - fix up ac97 codec initialization
    - Ingo: clean up VM handling, improve balancing.
    - add SGI PCI ID's.
    - export the new lock copy/init functions
    - cs4281 sound driver
    - official Compaq CISS driver.

71 files changed:
Documentation/Configure.help
MAINTAINERS
arch/alpha/Makefile
arch/alpha/boot/Makefile
arch/i386/defconfig
arch/i386/kernel/setup.c
arch/i386/kernel/signal.c
arch/i386/kernel/traps.c
drivers/block/Config.in
drivers/block/Makefile
drivers/block/cciss.c
drivers/block/cciss.h
drivers/block/ll_rw_blk.c
drivers/char/lp.c
drivers/char/mem.c
drivers/mtd/mapped.c
drivers/net/hamachi.c
drivers/net/ioc3-eth.c
drivers/net/sundance.c
drivers/net/winbond-840.c
drivers/sound/Config.in
drivers/sound/Makefile
drivers/sound/ac97_codec.c
drivers/sound/cmpci.c
drivers/sound/cs4281.c [new file with mode: 0644]
drivers/sound/cs4281_hwdefs.h [new file with mode: 0644]
drivers/sound/dev_table.c
drivers/sound/msnd_pinnacle.c
drivers/sound/sequencer.c
drivers/sound/sequencer_syms.c
drivers/sound/softoss.c [deleted file]
drivers/sound/softoss.h [deleted file]
drivers/sound/softoss_rs.c [deleted file]
drivers/sound/sound_core.c
drivers/sound/sound_syms.c
drivers/sound/soundcard.c
drivers/sound/vidc.c
drivers/sound/vwsnd.c
drivers/usb/dc2xx.c
drivers/usb/devices.c
drivers/usb/devio.c
drivers/usb/usb.c
fs/Config.in
fs/dcache.c
fs/inode.c
fs/locks.c
fs/nfs/inode.c
fs/nfs/nfsroot.c
fs/nfsd/nfssvc.c
fs/nfsd/vfs.c
fs/partitions/check.c
fs/super.c
include/asm-alpha/atomic.h
include/asm-alpha/system.h
include/asm-i386/system.h
include/linux/kmod.h
include/linux/mm.h
include/linux/nfs_mount.h
include/linux/sunrpc/clnt.h
include/linux/usb.h
ipc/shm.c
kernel/kmod.c
kernel/ksyms.c
kernel/signal.c
mm/filemap.c
mm/page_alloc.c
mm/swap_state.c
mm/vmscan.c
net/sunrpc/auth_unix.c
net/sunrpc/clnt.c
scripts/mkdep.c

index 96521960e97ce332e177eef3a3fc4a163fac631e..3441bcdfcd93ca5812828207a6ba22c17fbe6cdd 100644 (file)
@@ -4913,6 +4913,14 @@ CONFIG_PHONE
   it as a module, say M here and read Documentation/modules.txt. The
   module will be called phonedev.o.
 
+Compaq Smart Array support
+CONFIG_BLK_CPQ_CISS_DA
+   This is the driver for Compaq Smart Array controllers.
+   Everyone using these boards should say Y here.
+   See "linux/Documentation/cciss.txt" for the current list of
+   boards supported by this driver, and for further information
+   on the use of this driver.
+
 QuickNet Internet LineJack/PhoneJack support
 CONFIG_PHONE_IXJ
   Say M if you have a telephony card manufactured by Quicknet
index e08a4d582e26bf5f4261545fce2635897ac810f2..3791d67dcaf714f0567c3efeccc9698a5edc7d92 100644 (file)
@@ -210,13 +210,6 @@ M: jgarzik@mandrakesoft.com
 L:     linux-fbdev@vuser.vu.union.edu
 S:     Maintained
 
-COMPAQ SMART CISS RAID DRIVER 
-P:      Charles White
-M:      Charles White <arrays@compaq.com>
-L:      compaqandlinux@cpqlin.van-dijk.net
-W:     ftp.compaq.com/pub/products/drivers/linux       
-S:             Supported 
-
 COMPAQ FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA
 P:      Amy Vanzant-Hodge 
 M:      Amy Vanzant-Hodge (fibrechannel@compaq.com)
@@ -231,6 +224,13 @@ L: compaqandlinux@cpqlin.van-dijk.net
 W:     ftp.compaq.com/pub/products/drivers/linux
 S:     Supported       
 
+COMPAQ SMART CISS RAID DRIVER 
+P:     Charles White
+M:     Charles White <arrays@compaq.com>
+L:     compaqandlinux@cpqlin.van-dijk.net
+W:     ftp.compaq.com/pub/products/drivers/linux       
+S:     Supported 
+
 COMPUTONE INTELLIPORT MULTIPORT CARD
 P:     Doug McNash
 P:     Michael H. Warfield
index 8316683f0c14163a4bcd4860bae8ec2dfc8cb467..44ae94a99b4311d6fcba85e0d9a26e130e46759a 100644 (file)
@@ -8,7 +8,7 @@
 # Copyright (C) 1994 by Linus Torvalds
 #
 
-NM := nm -B
+NM := $(NM) -B
 
 LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N #-relax
 CFLAGS := $(CFLAGS) -pipe -mno-fp-regs -ffixed-8
index 47a4725245eb02fe6ec8007feede61253c865036..23789a91cfd583af207ecce5abdc36acf71802c0 100644 (file)
@@ -68,7 +68,7 @@ vmlinux.nh: $(VMLINUX) $(OBJSTRIP)
        $(OBJSTRIP) -v $(VMLINUX) vmlinux.nh
 
 vmlinux: $(TOPDIR)/vmlinux
-       strip -o vmlinux $(VMLINUX)
+       $(STRIP) -o vmlinux $(VMLINUX)
 
 tools/lxboot: $(OBJSTRIP) bootloader
        $(OBJSTRIP) -p bootloader tools/lxboot
index e0d490bb3558fc36ee6313b07aaf49ee8e729044..993ec1fa0968914657295d644009492166dd1c9a 100644 (file)
@@ -113,10 +113,10 @@ CONFIG_BLK_DEV_FD=y
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_INITRD is not set
 
@@ -599,6 +599,7 @@ CONFIG_SOUND=y
 # CONFIG_SOUND_CMPCI is not set
 # CONFIG_SOUND_EMU10K1 is not set
 # CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
 # CONFIG_SOUND_ES1370 is not set
 CONFIG_SOUND_ES1371=y
 # CONFIG_SOUND_ESSSOLO1 is not set
index f97af6b389f0ec0e92fa0c76a382bc8908839449..03364546b3bd49cc61896ddecde9537a024ec203 100644 (file)
@@ -875,7 +875,8 @@ static int __init amd_model(struct cpuinfo_x86 *c)
         * Set MTRR capability flag if appropriate
         */
        if(boot_cpu_data.x86 == 5) {
-               if((boot_cpu_data.x86_model == 9) ||
+               if((boot_cpu_data.x86_model == 13) ||
+                  (boot_cpu_data.x86_model == 9) ||
                   ((boot_cpu_data.x86_model == 8) && 
                    (boot_cpu_data.x86_mask >= 8)))
                        c->x86_capability |= X86_FEATURE_MTRR;
@@ -916,7 +917,7 @@ static int __init amd_model(struct cpuinfo_x86 *c)
                                }
                                break;
                        }
-                       if (c->x86_model == 8 || c->x86_model == 9)
+                       if (c->x86_model == 8 || c->x86_model == 9 || c->x86_model == 13)
                        {
                                /* The more serious chips .. */
                                
index 497efd6a46da855164d5857215dd527bf322b8d9..2423a8b06ef1690ae73bb6b8bbaa95eed35ad6cb 100644 (file)
@@ -690,6 +690,13 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                        }
                }
 
+               /* Reenable any watchpoints before delivering the
+                * signal to user space. The processor register will
+                * have been cleared if the watchpoint triggered
+                * inside the kernel.
+                */
+               __asm__("movl %0,%%db7" : : "r" (current->thread.debugreg[7]));
+
                /* Whee!  Actually deliver the signal.  */
                handle_signal(signr, ka, &info, oldset, regs);
                return 1;
index 864ae41a5ffdecbdb29fed6275ff9641dbc6e46e..b305a85392ead27191322702400027f3f10f64ef 100644 (file)
@@ -492,17 +492,26 @@ asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
 }
 
 /*
- * Careful - we must not do a lock-kernel until we have checked that the
- * debug fault happened in user mode. Getting debug exceptions while
- * in the kernel has to be handled without locking, to avoid deadlocks..
+ * Our handling of the processor debug registers is non-trivial.
+ * We do not clear them on entry and exit from the kernel. Therefore
+ * it is possible to get a watchpoint trap here from inside the kernel.
+ * However, the code in ./ptrace.c has ensured that the user can
+ * only set watchpoints on userspace addresses. Therefore the in-kernel
+ * watchpoint trap can only occur in code which is reading/writing
+ * from user space. Such code must not hold kernel locks (since it
+ * can equally take a page fault), therefore it is safe to call
+ * force_sig_info even though that claims and releases locks.
+ * 
+ * Code in ./signal.c ensures that the debug control register
+ * is restored before we deliver any signal, and therefore that
+ * user code runs with the correct debug control register even though
+ * we clear it here.
  *
  * Being careful here means that we don't have to be as careful in a
  * lot of more complicated places (task switching can be a bit lazy
  * about restoring all the debug state, and ptrace doesn't have to
  * find every occurrence of the TF bit that could be saved away even
- * by user code - and we don't have to be careful about what values
- * can be written to the debug registers because there are no really
- * bad cases).
+ * by user code)
  */
 asmlinkage void do_debug(struct pt_regs * regs, long error_code)
 {
@@ -539,30 +548,33 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
                        goto clear_TF;
        }
 
-       /* If this is a kernel mode trap, we need to reset db7 to allow us to continue sanely */
-       if ((regs->xcs & 3) == 0)
-               goto clear_dr7;
-
        /* Ok, finally something we can handle */
        tsk->thread.trap_no = 1;
        tsk->thread.error_code = error_code;
        info.si_signo = SIGTRAP;
        info.si_errno = 0;
        info.si_code = TRAP_BRKPT;
-       info.si_addr = (void *)regs->eip;
+       
+       /* If this is a kernel mode trap, save the user PC on entry to 
+        * the kernel, that's what the debugger can make sense of.
+        */
+       info.si_addr = ((regs->xcs & 3) == 0) ? (void *)tsk->thread.eip : 
+                                               (void *)regs->eip;
        force_sig_info(SIGTRAP, &info, tsk);
-       return;
-
-debug_vm86:
-       handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
-       return;
 
+       /* Disable additional traps. They'll be re-enabled when
+        * the signal is delivered.
+        */
 clear_dr7:
        __asm__("movl %0,%%db7"
                : /* no output */
                : "r" (0));
        return;
 
+debug_vm86:
+       handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
+       return;
+
 clear_TF:
        regs->eflags &= ~TF_MASK;
        return;
index c9a3a1334df8dd3452a3d0249a9d6510c741694e..5aa228104b00fe358c5c65b451f53b6d85925131 100644 (file)
@@ -34,15 +34,12 @@ if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then
    source drivers/block/paride/Config.in
 fi
 dep_tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA $CONFIG_PCI
+dep_tristate 'Compaq CISS Array support' CONFIG_BLK_CPQ_CISS_DA $CONFIG_PCI 
 dep_tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 $CONFIG_PCI
 
 tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
 dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
 
-if [ "$CONFIG_PCI" = "y" ]; then
-  tristate 'Compaq CISS Array support' CONFIG_BLK_CPQ_CISS_DA
-fi
-
 tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
 if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
        int '   Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096
index 31678292c99d580305862b58a1715cc2a7c49123..8ce7af56dbe1551f9300b8e839e1062c9a09c066 100644 (file)
@@ -31,7 +31,7 @@ obj-$(CONFIG_BLK_DEV_LOOP)    += loop.o
 obj-$(CONFIG_BLK_DEV_PS2)      += ps2esdi.o
 obj-$(CONFIG_BLK_DEV_XD)       += xd.o
 obj-$(CONFIG_BLK_CPQ_DA)       += cpqarray.o
-obj-$(CONFIG_BLK_CPQ_CISS_DA)  += cciss.o
+obj-$(CONFIG_BLK_CPQ_CISS_DA)  += cciss.o
 obj-$(CONFIG_BLK_DEV_DAC960)   += DAC960.o
 
 obj-$(CONFIG_BLK_DEV_NBD)      += nbd.o
index 332bedab0dc7d6ae77383c135f9eda6419485252..1bc65ce2969387491b6f57d01d99f6a81d5ab7b3 100644 (file)
@@ -20,6 +20,7 @@
  *
  */
 
+#include <linux/config.h>      /* CONFIG_PROC_FS */
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/types.h>
 #include <linux/malloc.h>
 #include <linux/delay.h>
 #include <linux/major.h>
-#include <linux/blkpg.h>
 #include <linux/fs.h>
+#include <linux/blkpg.h>
 #include <linux/timer.h>
 #include <linux/proc_fs.h>
-#include <linux/capability.h>
+#include <linux/init.h> 
 #include <linux/hdreg.h>
 #include <linux/spinlock.h>
 #include <asm/uaccess.h>
@@ -43,8 +44,8 @@
 #include <linux/genhd.h>
 
 #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "Compaq CISS Driver (v 1.0.0)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(1,0,0)
+#define DRIVER_NAME "Compaq CISS Driver (v 2.4.0)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,0)
 
 /* Embedded module documentation macros - see modules.h */
 MODULE_AUTHOR("Charles M. White III - Compaq Computer Corporation");
@@ -83,14 +84,14 @@ static void do_cciss_request(int i);
  */
 #define DO_CCISS_REQUEST(x) { do_cciss_request(x); }
 
-static void do_cciss_request0(request_queue_t *q) DO_CCISS_REQUEST(0);
-static void do_cciss_request1(request_queue_t *q) DO_CCISS_REQUEST(1);
-static void do_cciss_request2(request_queue_t *q) DO_CCISS_REQUEST(2);
-static void do_cciss_request3(request_queue_t *q) DO_CCISS_REQUEST(3);
-static void do_cciss_request4(request_queue_t *q) DO_CCISS_REQUEST(4);
-static void do_cciss_request5(request_queue_t *q) DO_CCISS_REQUEST(5);
-static void do_cciss_request6(request_queue_t *q) DO_CCISS_REQUEST(6);
-static void do_cciss_request7(request_queue_t *q) DO_CCISS_REQUEST(7);
+static void do_cciss_request0(request_queue_t * q) DO_CCISS_REQUEST(0);
+static void do_cciss_request1(request_queue_t * q) DO_CCISS_REQUEST(1);
+static void do_cciss_request2(request_queue_t * q) DO_CCISS_REQUEST(2);
+static void do_cciss_request3(request_queue_t * q) DO_CCISS_REQUEST(3);
+static void do_cciss_request4(request_queue_t * q) DO_CCISS_REQUEST(4);
+static void do_cciss_request5(request_queue_t * q) DO_CCISS_REQUEST(5);
+static void do_cciss_request6(request_queue_t * q) DO_CCISS_REQUEST(6);
+static void do_cciss_request7(request_queue_t * q) DO_CCISS_REQUEST(7);
 
 static int cciss_open(struct inode *inode, struct file *filep);
 static int cciss_release(struct inode *inode, struct file *filep);
@@ -106,17 +107,29 @@ static void cciss_getgeometry(int cntl_num);
 static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c);
 static void start_io( ctlr_info_t *h);
 
+#ifdef CONFIG_PROC_FS
+static int cciss_proc_get_info(char *buffer, char **start, off_t offset, 
+               int length, int *eof, void *data);
+static void cciss_procinit(int i);
+#else
+static int cciss_proc_get_info(char *buffer, char **start, off_t offset, 
+               int length, int *eof, void *data) {}
+static void cciss_procinit(int i) {}
+#endif /* CONFIG_PROC_FS */
+
 static struct block_device_operations cciss_fops  = {
-       ioctl: cciss_ioctl,             /* ioctl */
-       open: cciss_open,               /* open code */
-       release: cciss_release,         /* release */
-       revalidate: frevalidate_logvol, /* revalidate */
+       open:                   cciss_open, 
+       release:                cciss_release,
+        ioctl:                 cciss_ioctl,
+       revalidate:             frevalidate_logvol,
 };
 
 /*
  * Report information about this controller.
  */
-static int cciss_proc_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+#ifdef CONFIG_PROC_FS
+static int cciss_proc_get_info(char *buffer, char **start, off_t offset, 
+               int length, int *eof, void *data)
 {
         off_t pos = 0;
         off_t len = 0;
@@ -170,19 +183,18 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset, int len
  * Get us a file in /proc/cciss that says something about each controller.
  * Create /proc/cciss if it doesn't exist yet.
  */
-static void cciss_procinit(int i)
+static void __init cciss_procinit(int i)
 {
-        struct proc_dir_entry *pd;
-
         if (proc_cciss == NULL) {
-                proc_cciss = proc_mkdir("cciss", NULL);
+                proc_cciss = proc_mkdir("driver/cciss", NULL);
                 if (!proc_cciss) 
                        return;
         }
 
-        pd = create_proc_read_entry(hba[i]->devname, 0, proc_cciss,
-               cciss_proc_get_info, hba[i]);
+        create_proc_read_entry(hba[i]->devname, 0, proc_cciss,
+                       cciss_proc_get_info, hba[i]);
 }
+#endif /* CONFIG_PROC_FS */
 
 /* 
  * For operations that cannot sleep, a command block is allocated at init, 
@@ -264,13 +276,13 @@ static void cmd_free(ctlr_info_t *h, CommandList_struct *c)
 /*  
  * fills in the disk information. 
  */
-static void cciss_geninit(int ctlr)
+static void cciss_geninit( int ctlr)
 {
        drive_info_struct *drv;
        int i,j;
-
+       
        /* Loop through each real device */ 
-       hba[ctlr]->gendisk.nr_real = 0;
+       hba[ctlr]->gendisk.nr_real = 0; 
        for(i=0; i< NWD; i++)
        {
                drv = &(hba[ctlr]->drv[i]);
@@ -336,7 +348,7 @@ static int cciss_release(struct inode *inode, struct file *filep)
        printk(KERN_DEBUG "cciss_release %x (%x:%x)\n", inode->i_rdev, ctlr, dsk);
 #endif /* CCISS_DEBUG */
 
-       fsync_dev(inode->i_rdev);
+       /* fsync_dev(inode->i_rdev); */
 
        hba[ctlr]->drv[dsk].usage_count--;
        hba[ctlr]->usage_count--;
@@ -378,29 +390,25 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                if (!arg) return -EINVAL;
                put_user(hba[ctlr]->hd[MINOR(inode->i_rdev)].nr_sects, (long*)arg);
                return 0;
-       case BLKRASET:
-               if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-               if (!(inode->i_rdev)) return -EINVAL;
-               if (arg>0xff) return -EINVAL;
-               read_ahead[MAJOR(inode->i_rdev)] = arg;
-               return 0;
-       case BLKRAGET:
-               if (!arg) return -EINVAL;
-               put_user(read_ahead[MAJOR(inode->i_rdev)], (int*)arg);
-               return 0;
        case BLKRRPART:
                return revalidate_logvol(inode->i_rdev, 1);
-
+       case BLKFLSBUF:
+       case BLKROSET:
+       case BLKROGET:
+       case BLKRASET:
+       case BLKRAGET:
+       case BLKPG:
+               return( blk_ioctl(inode->i_rdev, cmd, arg));
        case CCISS_GETPCIINFO:
        {
                cciss_pci_info_struct pciinfo;
 
                if (!arg) return -EINVAL;
-               pciinfo.bus = hba[ctlr]->pci_dev->bus->number;
-               pciinfo.dev_fn = hba[ctlr]->pci_dev->devfn;
+               pciinfo.bus = hba[ctlr]->pci_bus;
+               pciinfo.dev_fn = hba[ctlr]->pci_dev_fn;
                pciinfo.board_id = hba[ctlr]->board_id;
-               if(copy_to_user((void *) arg, &pciinfo, sizeof( cciss_pci_info_struct)))
-                       return -EFAULT;
+               if (copy_to_user((void *) arg, &pciinfo,  sizeof( cciss_pci_info_struct ))
+                       return  -EFAULT;
                return(0);
        }       
        case CCISS_GETINTINFO:
@@ -411,8 +419,8 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                if (!arg) return -EINVAL;
                intinfo.delay = readl(&c->cfgtable->HostWrite.CoalIntDelay);
                intinfo.count = readl(&c->cfgtable->HostWrite.CoalIntCount);
-               if(copy_to_user((void *) arg, &intinfo, sizeof( cciss_coalint_struct)))
-                       return  -EFAULT;
+               if (copy_to_user((void *) arg, &intinfo, sizeof( cciss_coalint_struct ))
+                       return -EFAULT;
                 return(0);
         }
        case CCISS_SETINTINFO:
@@ -424,8 +432,8 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
 
                if (!arg) return -EINVAL;       
                if (!capable(CAP_SYS_ADMIN)) return -EPERM;
-               if(copy_from_user(&intinfo, (void *) arg,  sizeof( cciss_coalint_struct)))
-                       return  -EFAULT;
+               if (copy_from_user(&intinfo, (void *) arg, sizeof( cciss_coalint_struct))
+                       return -EFAULT;
                if ( (intinfo.delay == 0 ) && (intinfo.count == 0))
 
                {
@@ -471,8 +479,8 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                if (!arg) return -EINVAL;
                for(i=0;i<16;i++)
                        NodeName[i] = readb(&c->cfgtable->ServerName[i]);
-                if(copy_to_user((void *) arg, NodeName, sizeof(NodeName_type)))
-                       return -EFAULT;
+                if (copy_to_user((void *) arg, NodeName, sizeof( NodeName_type))
+                       return  -EFAULT;
                 return(0);
         }
        case CCISS_SETNODENAME:
@@ -485,7 +493,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                if (!arg) return -EINVAL;
                if (!capable(CAP_SYS_ADMIN)) return -EPERM;
                
-               if(copy_from_user(NodeName, (void *) arg, sizeof( NodeName_type)))
+               if (copy_from_user(NodeName, (void *) arg, sizeof( NodeName_type))
                        return -EFAULT;
 
                spin_lock_irqsave(&io_request_lock, flags);
@@ -506,7 +514,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                }       
                spin_unlock_irqrestore(&io_request_lock, flags);
                if (i >= MAX_CONFIG_WAIT)
-                       return -EIO;
+                       return( -EFAULT);
                 return(0);
         }
 
@@ -517,7 +525,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
 
                if (!arg) return -EINVAL;
                 heartbeat = readl(&c->cfgtable->HeartBeat);
-                if(copy_to_user((void *) arg, &heartbeat, sizeof( Heartbeat_type)))
+                if (copy_to_user((void *) arg, &heartbeat, sizeof( Heartbeat_type))
                        return -EFAULT;
                 return(0);
         }
@@ -528,8 +536,8 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
 
                if (!arg) return -EINVAL;
                 BusTypes = readl(&c->cfgtable->BusTypes);
-                if(copy_to_user((void *) arg, &BusTypes, sizeof( BusTypes_type)))
-                       return -EFAULT;
+                if (copy_to_user((void *) arg, &BusTypes, sizeof( BusTypes_type) )
+                       return  -EFAULT;
                 return(0);
         }
        case CCISS_GETFIRMVER:
@@ -539,7 +547,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                if (!arg) return -EINVAL;
                memcpy(firmware, hba[ctlr]->firm_ver, 4);
 
-                if(copy_to_user((void *) arg, firmware, sizeof( FirmwareVer_type)))
+                if (copy_to_user((void *) arg, firmware, sizeof( FirmwareVer_type))
                        return -EFAULT;
                 return(0);
         }
@@ -549,7 +557,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
 
                 if (!arg) return -EINVAL;
 
-                if(copy_to_user((void *) arg, &DriverVer, sizeof( DriverVer_type)))
+                if (copy_to_user((void *) arg, &DriverVer, sizeof( DriverVer_type) )
                        return -EFAULT;
                 return(0);
         }
@@ -570,8 +578,8 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
        
                if (!capable(CAP_SYS_RAWIO)) return -EPERM;
 
-               if(copy_from_user(&iocommand, (void *) arg, sizeof( IOCTL_Command_struct)))
-                       return -EFAULT; 
+               if (copy_from_user(&iocommand, (void *) arg, sizeof( IOCTL_Command_struct) )
+                       return -EFAULT;
                if((iocommand.buf_size < 1) && 
                                (iocommand.Request.Type.Direction != XFER_NONE))
                {       
@@ -589,7 +597,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                if (iocommand.Request.Type.Direction == XFER_WRITE)
                {
                        /* Copy the data into the buffer we created */ 
-                       if(copy_from_user(buff, iocommand.buf,iocommand.buf_size))
+                       if (copy_from_user(buff, iocommand.buf, iocommand.buf_size))
                                return -EFAULT;
                }
                if ((c = cmd_alloc(NULL)) == NULL)
@@ -635,16 +643,11 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
 
                /* Wait for completion */
                while(c->cmd_type != CMD_IOCTL_DONE)
-               {
-                       set_task_state(current, TASK_UNINTERRUPTIBLE);
                        schedule_timeout(1);
-                       rmb();
-               }
 
                /* Copy the error information out */ 
                iocommand.error_info = *(c->err_info);
-               if ( copy_to_user((void *) arg, &iocommand,
-                        sizeof( IOCTL_Command_struct) ) < 0 )
+               if ( copy_to_user((void *) arg, &iocommand, sizeof( IOCTL_Command_struct) ) )
                {
                        cmd_free(NULL, c);
                        if (buff != NULL) 
@@ -655,8 +658,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                if (iocommand.Request.Type.Direction == XFER_READ)
                 {
                         /* Copy the data out of the buffer we created */
-                        if (copy_to_user(iocommand.buf, buff, 
-                               iocommand.buf_size) < 0) 
+                        if (copy_to_user(iocommand.buf, buff, iocommand.buf_size))
                        {
                                     cmd_free(NULL, c);
                                     kfree(buff);
@@ -668,14 +670,8 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                 return(0);
        } 
 
-       case BLKFLSBUF:
-       case BLKROSET:
-       case BLKROGET:
-       case BLKPG:
-               return blk_ioctl(inode->i_rdev, cmd, arg);
-
        default:
-               return -EINVAL;
+               return -EBADRQC;
        }
        
 }
@@ -721,9 +717,9 @@ static int revalidate_logvol(kdev_t dev, int maxusage)
                 /* reset the blocksize so we can read the partition table */
                 blksize_size[MAJOR_NR+ctlr][minor] = 1024;
         }
-       gdev->part[start].nr_sects =  hba[ctlr]->drv[target].nr_blocks;
-       /* 16 minors per disk... */
-       grok_partitions(gdev, target, 16, hba[ctlr]->drv[target].nr_blocks);
+       /* setup partitions per disk */
+       grok_partitions(gdev, target, MAX_PART, 
+                       hba[ctlr]->drv[target].nr_blocks);
         hba[ctlr]->drv[target].usage_count--;
         return 0;
 }
@@ -1016,13 +1012,13 @@ static int sendcmd(
 /*
  * Map (physical) PCI mem into (virtual) kernel space
  */
-static void *remap_pci_mem(ulong base, ulong size)
+static ulong remap_pci_mem(ulong base, ulong size)
 {
         ulong page_base        = ((ulong) base) & PAGE_MASK;
         ulong page_offs        = ((ulong) base) - page_base;
-        void *page_remapped    = ioremap(page_base, page_offs+size);
+        ulong page_remapped    = (ulong) ioremap(page_base, page_offs+size);
 
-        return (page_remapped ? (page_remapped + page_offs) : NULL);
+        return (ulong) (page_remapped ? (page_remapped + page_offs) : 0UL);
 }
 
 /*
@@ -1191,25 +1187,24 @@ static void do_cciss_request(int ctlr)
        int log_unit, start_blk, seg, sect;
        char *lastdataend;
        struct buffer_head *bh;
-       struct request *creq;
        struct list_head *queue_head;
+       struct request *creq;
        u64bit temp64;
 
-       queue_head = &blk_dev[MAJOR_NR+ctlr].request_queue.queue_head;
-
-       if(list_empty(queue_head))
+       queue_head = &blk_dev[MAJOR_NR+ctlr].request_queue.queue_head;  
+       if (list_empty(queue_head))
+       {
+               /* nothing to do... */
+               start_io(h);
+               return;
+       }
+       creq =  blkdev_entry_next_request(queue_head); 
+       if ((creq == NULL) || (creq->rq_status == RQ_INACTIVE))
        {
                /* nothing to do... restart processing and return */ 
                start_io(h);
                return;
        }
-       creq = blkdev_entry_next_request(queue_head);
-       if (creq->rq_status == RQ_INACTIVE)
-       {       
-                start_io(h);
-                return;
-        }
-
        if ((ctlr != (MAJOR(creq->rq_dev)-MAJOR_NR)) || (ctlr > nr_ctlr)
                || (h == NULL))
        {
@@ -1218,6 +1213,7 @@ static void do_cciss_request(int ctlr)
                        ctlr, creq->rq_dev, creq);
 #endif /* CCISS_DEBUG */
                complete_buffers(creq->bh, 0);
+               start_io(h); 
                return;
        }
        if (( c = cmd_alloc(h)) == NULL)
@@ -1317,8 +1313,9 @@ static void do_cciss_request(int ctlr)
        } else
        {
 #ifdef CCISS_DEBUG
-               printk(KERN_DEBUG "cciss: Done with %p, queueing %p\n", creq, creq->next);
+               printk("cciss: Done with %p, queueing %p\n", creq);
 #endif /* CCISS_DEBUG */
+                       
                blkdev_dequeue_request(creq);
                end_that_request_last(creq);
        }
@@ -1424,28 +1421,37 @@ static void print_cfg_table( CfgTable_struct *tb)
 }
 #endif /* CCISS_DEBUG */
 
-static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
+static int cciss_pci_init(ctlr_info_t *c, unchar bus, unchar device_fn)
 {
        ushort vendor_id, device_id, command;
        unchar cache_line_size, latency_timer;
        unchar irq, revision;
-       unsigned long addr[6];
+       uint addr[6];
        __u32 board_id;
+       struct pci_dev *pdev;
 
        int i;
 
+       pdev = pci_find_slot(bus, device_fn);
        vendor_id = pdev->vendor;
        device_id = pdev->device;
        irq = pdev->irq;
 
        for(i=0; i<6; i++)
-               addr[i] = pci_resource_start(pdev, i);
+               addr[i] = pdev->resource[i].start;
+
+       if (pci_enable_device(pdev))
+               return( -1);
+       
        (void) pci_read_config_word(pdev, PCI_COMMAND,&command);
-       (void) pci_read_config_byte(pdev, PCI_CLASS_REVISION,&revision);
-       (void) pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size);
-       (void) pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_timer);
+       (void) pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
+       (void) pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE,
+                                               &cache_line_size);
+       (void) pci_read_config_byte(pdev, PCI_LATENCY_TIMER,
+                                               &latency_timer);
 
-       (void) pci_read_config_dword(pdev, PCI_SUBSYSTEM_VENDOR_ID, &board_id);
+       (void) pci_read_config_dword(pdev, PCI_SUBSYSTEM_VENDOR_ID, 
+                                               &board_id);
 
 #ifdef CCISS_DEBUG
        printk("vendor_id = %x\n", vendor_id);
@@ -1466,7 +1472,7 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
         * Memory base addr is first addr , the second points to the config
          *   table
         */
-       c->paddr = addr[0];
+       c->paddr = pci_resource_start(pdev, 0);
        c->vaddr = remap_pci_mem(c->paddr, 128);
        c->cfgtable = (CfgTable_struct *) remap_pci_mem(addr[1], 
                                                sizeof(CfgTable_struct));
@@ -1526,21 +1532,23 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
  */
 static int cciss_pci_detect(void)
 {
-       struct pci_dev *pdev;
 
-       pdev = pci_find_device(PCI_VENDOR_ID_COMPAQ,
-                              PCI_DEVICE_ID_COMPAQ_CISS, NULL);
-       while (pdev) {
+       int index;
+       unchar bus=0, dev_fn=0;
+       
+               for(index=0; ; index++) {
+                       if (pcibios_find_device(PCI_VENDOR_ID_COMPAQ,
+                               PCI_DEVICE_ID_COMPAQ_CISS, 
+                                       index, &bus, &dev_fn))
+                               break;
                        printk(KERN_DEBUG "cciss: Device %x has been found at %x %x\n",
-                               PCI_DEVICE_ID_COMPAQ_CISS,
-                               pdev->bus->number, pdev->devfn);
+                               PCI_DEVICE_ID_COMPAQ_CISS, bus, dev_fn);
+                       if (index == 1000000) break;
                        if (nr_ctlr == 8) {
                                printk(KERN_WARNING "cciss: This driver"
                                " supports a maximum of 8 controllers.\n");
                                break;
                        }
-                       if (pci_enable_device(pdev))
-                               continue;
                        hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
                        if(hba[nr_ctlr]==NULL)
                        {
@@ -1548,19 +1556,18 @@ static int cciss_pci_detect(void)
                                continue;
                        }
                        memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));
-                       if (cciss_pci_init(hba[nr_ctlr], pdev) != 0)
+                       if (cciss_pci_init(hba[nr_ctlr], bus, dev_fn) != 0)
                        {
                                kfree(hba[nr_ctlr]);
                                continue;
                        }
                        sprintf(hba[nr_ctlr]->devname, "cciss%d", nr_ctlr);
                        hba[nr_ctlr]->ctlr = nr_ctlr;
-                       hba[nr_ctlr]->pci_dev = pdev;
+                       hba[nr_ctlr]->pci_bus = bus;
+                       hba[nr_ctlr]->pci_dev_fn = dev_fn;
                        nr_ctlr++;
 
-               pdev = pci_find_device(PCI_VENDOR_ID_COMPAQ,
-                                      PCI_DEVICE_ID_COMPAQ_CISS, pdev);
-       }
+               }
        return nr_ctlr;
 
 }
@@ -1747,11 +1754,10 @@ static void cciss_getgeometry(int cntl_num)
  *  stealing all these major device numbers.
  *  returns the number of block devices registered.
  */
-int cciss_init(void)
+int __init cciss_init(void)
 {
        int num_cntlrs_reg = 0;
-       int i;
-       int j;
+       int i,j;
 
        void (*request_fns[MAX_CTLR])(request_queue_t *) = {
                 do_cciss_request0, do_cciss_request1,
@@ -1827,6 +1833,16 @@ int cciss_init(void)
                hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
 
                cciss_procinit(i);
+               
+               blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR+i),
+                               request_fns[i]);
+               blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR+i), 0);
+
+               /* fill in the other Kernel structs */
+               blksize_size[MAJOR_NR+i] = hba[i]->blocksizes;
+                hardsect_size[MAJOR_NR+i] = hba[i]->hardsizes;
+                read_ahead[MAJOR_NR+i] = READ_AHEAD;
+
                /* Fill in the gendisk data */  
                hba[i]->gendisk.major = MAJOR_NR + i;
                hba[i]->gendisk.major_name = "cciss";
@@ -1836,40 +1852,32 @@ int cciss_init(void)
                hba[i]->gendisk.sizes = hba[i]->sizes;
                hba[i]->gendisk.nr_real = hba[i]->num_luns;
 
-               /* fill in the other Kernel structs */ 
-               blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i), 
-                       request_fns[i]);                
-               blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR + i), 0);
-               blksize_size[MAJOR_NR+i] = hba[i]->blocksizes;
-               hardsect_size[MAJOR_NR+i] = hba[i]->hardsizes;
-               read_ahead[MAJOR_NR+i] = READ_AHEAD;
-
                /* Get on the disk list */ 
                hba[i]->gendisk.next = gendisk_head;
                gendisk_head = &(hba[i]->gendisk); 
-               
+
                cciss_geninit(i);
-               for(j=0; j<NWD; j++)    
-                       register_disk(&hba[i]->gendisk, 
-                               MKDEV(MAJOR_NR+i,j<<4),
-                               16, &cciss_fops, hba[i]->drv[j].nr_blocks);
+               for(j=0; j<NWD; j++)
+                       register_disk(&(hba[i]->gendisk),
+                               MKDEV(MAJOR_NR+i, j <<4), 
+                               MAX_PART, &cciss_fops, 
+                               hba[i]->drv[j].nr_blocks);
        }
        return(nr_ctlr);
 }
 
-#ifdef MODULE
 EXPORT_NO_SYMBOLS;
 
-
 /* This is a bit of a hack... */
-int init_module(void)
+static int __init init_cciss_module(void)
 {
+
        if (cciss_init() == 0) /* all the block dev numbers already used */
                return -EIO;      /* or no controllers were found */
        return 0;
 }
 
-void cleanup_module(void)
+static void __exit cleanup_cciss_module(void)
 {
        int i;
        struct gendisk *g;
@@ -1879,9 +1887,8 @@ void cleanup_module(void)
                /* Turn board interrupts off */ 
                hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
                free_irq(hba[i]->intr, hba[i]);
-               iounmap(hba[i]->vaddr);
+               iounmap((void*)hba[i]->vaddr);
                unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
-               blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i));
                remove_proc_entry(hba[i]->devname, proc_cciss); 
 
                /* remove it from the disk list */ 
@@ -1898,7 +1905,7 @@ void cleanup_module(void)
                                }
                        }
                }
-               remove_proc_entry("cciss", &proc_root);
+               remove_proc_entry("driver/cciss", &proc_root);
                kfree(hba[i]->cmd_pool);
                kfree(hba[i]->errinfo_pool);
                 kfree(hba[i]->cmd_pool_bits);
@@ -1906,5 +1913,5 @@ void cleanup_module(void)
        }
 }
 
-#endif /* MODULE */
-
+module_init(init_cciss_module);
+module_exit(cleanup_cciss_module);
index 766761076dbb4daefd3bc723bf904d559ee17f9d..bd03aaea1d15eca859139581031dd930c14dfde8 100644 (file)
@@ -42,10 +42,11 @@ struct ctlr_info
        char    devname[8];
        char    *product_name;
        char    firm_ver[4]; // Firmware version 
-        struct pci_dev *pci_dev;
+       unchar  pci_bus;
+        unchar  pci_dev_fn;
        __u32   board_id;
-       void   *vaddr;
-       unsigned long paddr;    
+       ulong   vaddr;
+       __u32   paddr;  
        CfgTable_struct *cfgtable;
        int     intr;
 
index 07b7cef5a30972a6a65fc59a79afa127046ffab2..db562b8ac1d1d920eb60f7550308bc80aeb555aa 100644 (file)
@@ -600,9 +600,9 @@ static inline void add_request(request_queue_t * q, struct request * req,
        major = MAJOR(req->rq_dev);
        if (major >= COMPAQ_SMART2_MAJOR+0 && major <= COMPAQ_SMART2_MAJOR+7)
                (q->request_fn)(q);
-       if (major >= DAC960_MAJOR+0 && major <= DAC960_MAJOR+7)
-               (q->request_fn)(q);
        if (major >= COMPAQ_CISS_MAJOR+0 && major <= COMPAQ_CISS_MAJOR+7)
+                (q->request_fn)(q);
+       if (major >= DAC960_MAJOR+0 && major <= DAC960_MAJOR+7)
                (q->request_fn)(q);
 }
 
index 5be8baee8e92b2f641cf6d3dd6d82cc023662086..2e9e170c46874cad04beecaee7b884101f129dbf 100644 (file)
@@ -712,11 +712,12 @@ static void lp_attach (struct parport *port)
                if (parport_nr[0] == LP_PARPORT_AUTO &&
                    port->probe_info[0].class != PARPORT_CLASS_PRINTER)
                        return;
-
+               if (lp_count == LP_NO) {
+                       printk("lp: ignoring parallel port (max. %d)\n",LP_NO);
+                       return;
+               }
                if (!lp_register(lp_count, port))
-                       if (++lp_count == LP_NO)
-                               break;
-
+                       lp_count++;
                break;
 
        default:
index f63393a5f682251a537b31bbb1769ef21736933f..7b11c8b70ab0e6fb23b3a14b6ee7ea6f440a791d 100644 (file)
 #ifdef CONFIG_I2C
 extern int i2c_init_all(void);
 #endif
-#ifdef CONFIG_SOUND
-void soundcore_init(void);
-#ifdef CONFIG_SOUND_OSS
-void soundcard_init(void);
-#endif
-#endif
 #ifdef CONFIG_SPARCAUDIO
 extern int sparcaudio_init(void);
 #endif
@@ -641,15 +635,6 @@ int __init chr_dev_init(void)
        lp_m68k_init();
 #endif
        misc_init();
-#ifdef CONFIG_SOUND
-       soundcore_init();
-#ifdef CONFIG_SOUND_OSS
-       soundcard_init();
-#endif
-#endif
-#ifdef CONFIG_SPARCAUDIO
-       sparcaudio_init();
-#endif
 #if CONFIG_QIC02_TAPE
        qic02_tape_init();
 #endif
index ca904a285e8a506f2db4c443802c85cfc625e63c..45db9e442b0f5647173ef6d271c10f255d6c9da5 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
-#include <linux/delay.h>
 #include <asm/io.h>
 
 struct JEDECTable mtd_JEDEC_table[] = 
index a1f7c8cfd0426c155713cb61fd8cab0f90f10aa5..fd00d7c4b9f32f3b9ef6fcf0e2631aa881667aa3 100644 (file)
@@ -150,7 +150,6 @@ static int tx_params[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (5*HZ)
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
index 04c84c99d98fff98f02407a5fe60482640788896..fa5e8558e42cf42553855f3332240156ce40b48e 100644 (file)
@@ -64,7 +64,7 @@
 #include <asm/sn/sn0/hubni.h>
 #include <asm/sn/sn0/hubio.h>
 #include <asm/sn/klconfig.h>
-#include <asm/ioc3.h>
+#include <asm/sn/ioc3.h>
 #include <asm/sn/sn0/ip27.h>
 #include <asm/pci/bridge.h>
 
index e4fb0ed7fe44e024af6684e0a1611c5b41c63a22..a6535df79f3f7cf6d1ff3c86ca48f23100e358ba 100644 (file)
@@ -78,7 +78,6 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 #endif
 
 /* Include files, designed to support most kernel versions 2.0.0 and later. */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
index a5cb2fba73d8a0dc2e5536884b64f66a1184295a..03f79ca2eea04e193b101ec2058bd12eb3636f5b 100644 (file)
@@ -97,7 +97,6 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 #endif
 
 /* Include files, designed to support most kernel versions 2.0.0 and later. */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
index fab74d348b0f3f1e38621c1fa3c7ecfa8c067472..929c9cf0f301f5f829956c545789ba2590460fa7 100644 (file)
@@ -16,6 +16,7 @@ if [ "$CONFIG_SOUND_CMPCI" = "y" -o "$CONFIG_SOUND_CMPCI" = "m" ]; then
 fi
 dep_tristate '  Creative SBLive! (EMU10K1)' CONFIG_SOUND_EMU10K1 $CONFIG_SOUND
 dep_tristate '  Crystal SoundFusion (CS4280/461x)' CONFIG_SOUND_FUSION $CONFIG_SOUND
+dep_tristate '  Crystal Sound CS4281' CONFIG_SOUND_CS4281 $CONFIG_SOUND
 dep_tristate '  Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND
 dep_tristate '  Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND
 dep_tristate '  ESS Technology Solo1' CONFIG_SOUND_ESSSOLO1 $CONFIG_SOUND
@@ -127,12 +128,6 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
       fi
    fi
 
-   dep_tristate '    SoftOSS software wave table engine' CONFIG_SOUND_SOFTOSS $CONFIG_SOUND_OSS
-   if [ "$CONFIG_SOUND_SOFTOSS" = "y" ]; then
-      int 'Sampling rate for SoftOSS 8000 to 48000' CONFIG_SOFTOSS_RATE 22050
-      int 'Max # of concurrent voices for SoftOSS 4 to 32' CONFIG_SOFTOSS_VOICES 32
-   fi
-  
    dep_tristate '    100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' CONFIG_SOUND_SB $CONFIG_SOUND_OSS
    dep_tristate '    AWE32 synth' CONFIG_SOUND_AWE32_SYNTH $CONFIG_SOUND_OSS
    dep_tristate '    Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/soundcards' CONFIG_SOUND_WAVEFRONT $CONFIG_SOUND_OSS m
index ab1e1eb6f2e4cc7699b6cd0068d453accc751318..ad715e752c3316595becd0ef5391d40688a95995 100644 (file)
@@ -43,7 +43,6 @@ obj-$(CONFIG_SOUND_AEDSP16)   += aedsp16.o
 obj-$(CONFIG_SOUND_PSS)                += pss.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_TRIX)       += trix.o ad1848.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_OPL3SA1)    += opl3sa.o ad1848.o uart401.o
-obj-$(CONFIG_SOUND_SOFTOSS)    += softoss2.o
 obj-$(CONFIG_SOUND_SSCAPE)     += sscape.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_MAD16)      += mad16.o ad1848.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_CS4232)     += cs4232.o uart401.o
@@ -79,6 +78,7 @@ obj-$(CONFIG_SOUND_ES1370)    += es1370.o
 obj-$(CONFIG_SOUND_ES1371)     += es1371.o ac97_codec.o
 obj-$(CONFIG_SOUND_ESSSOLO1)   += esssolo1.o
 obj-$(CONFIG_SOUND_FUSION)     += cs46xx.o ac97_codec.o
+obj-$(CONFIG_SOUND_CS4281)     += cs4281.o
 obj-$(CONFIG_SOUND_MAESTRO)    += maestro.o
 obj-$(CONFIG_SOUND_TRIDENT)    += trident.o ac97_codec.o
 
@@ -104,7 +104,7 @@ endif
 
 # Declare multi-part drivers.
 
-list-multi     := sound.o gus.o pas2.o sb.o sb_lib.o softoss2.o vidc_mod.o \
+list-multi     := sound.o gus.o pas2.o sb.o sb_lib.o vidc_mod.o \
     soundcore.o wavefront.o
 
 sound-objs     :=                                                      \
@@ -119,7 +119,6 @@ gus-objs    := gus_card.o gus_midi.o gus_vol.o gus_wave.o ics2101.o
 pas2-objs      := pas2_card.o pas2_midi.o pas2_mixer.o pas2_pcm.o
 sb-objs                := sb_card.o
 sb_lib-objs    := sb_common.o sb_audio.o sb_midi.o sb_mixer.o sb_ess.o
-softoss2-objs  := softoss.o softoss_rs.o
 vidc_mod-objs  := vidc.o vidc_fill.o
 wavefront-objs  := wavfront.o wf_midi.o yss225.o
 
@@ -181,9 +180,6 @@ sb.o: $(sb-objs)
 sb_lib.o: $(sb_lib-objs)
        $(LD) -r -o $@ $(sb_lib-objs)
 
-softoss2.o: $(softoss2-objs)
-       $(LD) -r -o $@ $(softoss2-objs)
-
 vidc_mod.o: $(vidc_mod-objs)
        $(LD) -r -o $@ $(vidc_mod-objs)
 
index 43f67cd41d9214bd1d12517f78ce769c2c553469..81657a6b6e85c75aa27514f0b4bef9db2a03cfe6 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 #include <linux/ac97_codec.h>
 #include <asm/uaccess.h>
 
@@ -566,10 +567,8 @@ int ac97_probe_codec(struct ac97_codec *codec)
        /* also according to spec, we wait for codec-ready state */     
        if (codec->codec_wait)
                codec->codec_wait(codec);
-       else {
-               current->state = TASK_UNINTERRUPTIBLE;
-               schedule_timeout(5);
-       }
+       else
+               udelay(10);
 
        if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) {
                printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n",
@@ -588,7 +587,6 @@ int ac97_probe_codec(struct ac97_codec *codec)
        id2 = codec->codec_read(codec, AC97_VENDOR_ID2);
        for (i = 0; i < arraysize(ac97_codec_ids); i++) {
                if (ac97_codec_ids[i].id == ((id1 << 16) | id2)) {
-                       codec->id = ac97_codec_ids[i].id;
                        codec->name = ac97_codec_ids[i].name;
                        codec->codec_init = ac97_codec_ids[i].init;
                        break;
@@ -630,7 +628,7 @@ static int ac97_init_mixer(struct ac97_codec *codec)
        codec->codec_write(codec, AC97_PCMOUT_VOL, 0L);
 
        /* codec specific initialization for 4-6 channel output or secondary codec stuff */
-       if (codec->id != 0 && codec->codec_init != NULL) {
+       if (codec->codec_init != NULL) {
                codec->codec_init(codec);
        }
 
@@ -649,6 +647,10 @@ static int ac97_init_mixer(struct ac97_codec *codec)
 
 static int sigmatel_init(struct ac97_codec * codec)
 {
+       /* Only set up secondary codec */
+       if (codec->id == 0)
+               return 1;
+
        codec->codec_write(codec, AC97_SURROUND_MASTER, 0L);
 
        /* initialize SigmaTel STAC9721/23 as secondary codec, decoding AC link
index 836579af24dacc193dbc3a307f7cbaab090559f5..76e904e158715fb84f7e156443bf83775a80f2b1 100644 (file)
@@ -2287,8 +2287,6 @@ static int        rear_out = 0;
 MODULE_PARM(spdif_loop, "i");
 MODULE_PARM(four_ch, "i");
 MODULE_PARM(rear_out, "i");
-
-int  __init init_module(void)
 #else
 #ifdef CONFIG_SOUND_CMPCI_SPDIFLOOP
 static int     spdif_loop = 1;
@@ -2305,9 +2303,9 @@ static int        rear_out = 1;
 #else
 static int     rear_out = 0;
 #endif
-
-int __init init_cmpci(void)
 #endif
+
+static int __init init_cmpci(void)
 {
        struct cm_state *s;
        struct pci_dev *pcidev = NULL;
@@ -2499,12 +2497,10 @@ int __init init_cmpci(void)
 
 /* --------------------------------------------------------------------- */
 
-#ifdef MODULE
-
 MODULE_AUTHOR("ChenLi Tien, cltien@home.com");
 MODULE_DESCRIPTION("CMPCI Audio Driver");
 
-void cleanup_module(void)
+static void __exit cleanup_cmpci(void)
 {
        struct cm_state *s;
 
@@ -2538,4 +2534,5 @@ void cleanup_module(void)
        printk(KERN_INFO "cmpci: unloading\n");
 }
 
-#endif /* MODULE */
+module_init(init_cmpci);
+module_exit(cleanup_cmpci);
diff --git a/drivers/sound/cs4281.c b/drivers/sound/cs4281.c
new file mode 100644 (file)
index 0000000..913cf55
--- /dev/null
@@ -0,0 +1,2678 @@
+//*****************************************************************************
+//
+//      "cs4281.c" --  Cirrus Logic-Crystal CS4281 linux audio driver.
+//
+//      Copyright (C) 2000  Cirrus Logic Corp.  
+//            -- adapted from drivers by Thomas Sailer, 
+//            -- but don't bug him; Problems should go to:
+//            -- gw boynton (wesb@crystal.cirrus.com) or
+//            -- tom woller (twoller@crystal.cirrus.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
+//      the Free Software Foundation; either version 2 of the License, or
+//      (at your option) any later version.
+//
+//      This program is distributed in the hope that it will be useful,
+//      but WITHOUT ANY WARRANTY; without even the implied warranty of
+//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//      GNU General Public License for more details.
+//
+//      You should have received a copy of the GNU General Public License
+//      along with this program; if not, write to the Free Software
+//      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// Module command line parameters:
+//   none
+//
+//  Supported devices:
+//  /dev/dsp    standard /dev/dsp device, (mostly) OSS compatible
+//  /dev/mixer  standard /dev/mixer device, (mostly) OSS compatible
+//  /dev/midi   simple MIDI UART interface, no ioctl
+//
+//
+//
+
+// *****************************************************************************
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/sound.h>
+#include <linux/malloc.h>
+#include <linux/soundcard.h>
+#include <linux/pci.h>
+#include <linux/bitops.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <asm/uaccess.h>
+#include <asm/hardirq.h>
+#include <linux/vmalloc.h>
+#include "dm.h"
+#include "cs4281_hwdefs.h"
+
+EXPORT_NO_SYMBOLS;
+
+#undef OSS_DOCUMENTED_MIXER_SEMANTICS
+
+// --------------------------------------------------------------------- 
+
+#ifndef PCI_VENDOR_ID_CIRRUS
+#define PCI_VENDOR_ID_CIRRUS          0x1013
+#endif
+#ifndef PCI_DEVICE_ID_CRYSTAL_CS4281
+#define PCI_DEVICE_ID_CRYSTAL_CS4281  0x6005
+#endif
+
+#define CS4281_MAGIC  ((PCI_DEVICE_ID_CRYSTAL_CS4281<<16) | PCI_VENDOR_ID_CIRRUS)
+
+#define CSDEBUG 1
+//
+// Turn on/off debugging compilation by using 1/0 respectively for CSDEBUG
+//
+//
+// CSDEBUG is usual mode is set to 1, then use the
+// cs_debuglevel and cs_debugmask to turn on or off debugging.
+// Debug level of 1 has been defined to be kernel errors and info
+// that should be printed on any released driver.
+//
+#if CSDEBUG
+extern unsigned cs_debugmask;
+extern unsigned cs_debuglevel;
+#define CS_DBGOUT(mask,level,x) if((cs_debuglevel >= (level)) && ((mask) & cs_debugmask)) {x;} 
+#else
+#define CS_DBGOUT(mask,level,x) 
+#endif
+//
+// cs_debugmask areas
+//
+#define CS_INIT                0x00000001              // initialization and probe functions
+#define CS_ERROR       0x00000002              // tmp debugging bit placeholder
+#define CS_INTERRUPT   0x00000004              // interrupt handler (separate from all other)
+#define CS_FUNCTION    0x00000008              // enter/leave functions 
+#define CS_WAVE_WRITE  0x00000010              // write information for wave
+#define CS_WAVE_READ   0x00000020              // read information for wave
+#define CS_MIDI_WRITE  0x00000040              // write information for midi
+#define CS_MIDI_READ   0x00000080              // read information for midi
+#define CS_MPU401_WRITE 0x00000100             // write information for mpu401
+#define CS_MPU401_READ         0x00000200              // read information for mpu401
+#define CS_OPEN                0x00000400              // all open functions in the driver
+#define CS_RELEASE     0x00000800              // all release functions in the driver
+#define CS_PARMS       0x00001000              // functional and operational parameters
+#define CS_TMP         0x10000000              // tmp debug mask bit
+
+unsigned cs_debuglevel=1;                      // levels range from 1-9
+unsigned cs_debugmask=CS_INIT | CS_ERROR;      // use CS_DBGOUT with various mask values
+#if MODULE
+MODULE_PARM(cs_debuglevel, "i");
+MODULE_PARM(cs_debugmask, "i");
+#endif
+
+// MIDI buffer sizes 
+#define MIDIINBUF  500
+#define MIDIOUTBUF 500
+
+#define FMODE_MIDI_SHIFT 3
+#define FMODE_MIDI_READ  (FMODE_READ << FMODE_MIDI_SHIFT)
+#define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT)
+
+#define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
+        ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
+#define RSRCISMEMORYREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
+        ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY)
+#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
+
+#define CS4281_MAJOR_VERSION   0
+#define CS4281_MINOR_VERSION   4   
+#ifdef __ia64__
+#define CS4281_ARCH            64  //architecture key
+#else
+#define CS4281_ARCH            32  //architecture key
+#endif
+
+struct cs4281_state {
+       // magic 
+       unsigned int magic;
+
+       // we keep the cards in a linked list 
+       struct cs4281_state *next;
+
+       // pcidev is needed to turn off the DDMA controller at driver shutdown 
+       struct pci_dev *pcidev;
+
+       // soundcore stuff 
+       int dev_audio;
+       int dev_mixer;
+       int dev_midi;
+
+       // hardware resources 
+       unsigned int pBA0phys, pBA1phys;
+       char *pBA0, *pBA1; 
+       unsigned int irq;
+       int endofbuffer;
+
+       // mixer registers 
+       struct {
+               unsigned short vol[10];
+               unsigned int recsrc;
+               unsigned int modcnt;
+               unsigned short micpreamp;
+       } mix;
+
+       // wave stuff   // Note that play & record formats must be the same *wb.
+       unsigned fmt;
+       unsigned channels;
+       unsigned rate;
+       unsigned char clkdiv;
+       unsigned ena;
+
+       spinlock_t lock;
+       struct semaphore open_sem;
+       mode_t open_mode;
+       wait_queue_head_t open_wait;
+
+       struct dmabuf {
+               void *rawbuf;            // Physical address of  
+               dma_addr_t dmaaddr; 
+               unsigned buforder;       // Log base 2 of 'rawbuf' size in bytes..
+               unsigned numfrag;        // # of 'fragments' in the buffer.
+               unsigned fragshift;      // Log base 2 of fragment size.
+               unsigned hwptr, swptr;
+               unsigned total_bytes;    // # bytes process since open.
+               unsigned blocks;         // last returned blocks value GETOPTR
+               int count;
+               unsigned error; // over/underrun 
+               wait_queue_head_t wait;
+               // redundant, but makes calculations easier 
+               unsigned fragsize;       // 2**fragshift..
+               unsigned dmasize;        // 2**buforder.
+               unsigned fragsamples;
+               // OSS stuff 
+               unsigned mapped:1;       // Buffer mapped in cs4281_mmap()?
+               unsigned ready:1;        // prog_dmabuf_dac()/adc() successful?
+               unsigned endcleared:1;
+               unsigned ossfragshift;
+               int ossmaxfrags;
+               unsigned subdivision;
+       } dma_dac, dma_adc;
+
+       // midi stuff 
+       struct {
+               unsigned ird, iwr, icnt;
+               unsigned ord, owr, ocnt;
+               wait_queue_head_t iwait;
+               wait_queue_head_t owait;
+               struct timer_list timer;
+               unsigned char ibuf[MIDIINBUF];
+               unsigned char obuf[MIDIOUTBUF];
+       } midi;
+
+};
+
+
+struct cs4281_state *devs = NULL;
+// --------------------------------------------------------------------- 
+//
+//             Hardware Interfaces For the CS4281
+//
+
+
+//******************************************************************************
+// "delayus()-- Delay for the specified # of microseconds.
+//******************************************************************************
+static void delayus(u32 delay)
+{
+       u32 j;   
+       if(delay > 9999)
+       {
+               j = (delay * HZ)/1000000;   /* calculate delay in jiffies  */
+               if(j<1) 
+                       j=1;               /* minimum one jiffy. */
+               current->state = TASK_UNINTERRUPTIBLE;  
+               schedule_timeout(j);       
+       }
+       else
+               udelay(delay);
+       return;                      
+}
+
+
+//******************************************************************************
+// "cs4281_read_ac97" -- Reads a word from the specified location in the
+//               CS4281's address space(based on the BA0 register).
+//
+// 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
+// 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 register,
+//                                            0h for reads.
+// 3. Write ACCTL = Control Register = 460h for initiating the write
+// 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h
+// 5. if DCV not cleared, break and return error
+// 6. Read ACSTS = Status Register = 464h, check VSTS bit
+//****************************************************************************
+static int cs4281_read_ac97(struct cs4281_state *card, u32 offset, u32 *value)
+{
+       u32 count, status;
+
+       // Make sure that there is not data sitting
+       // around from a previous uncompleted access.
+       // ACSDA = Status Data Register = 47Ch
+       status = readl(card->pBA0+BA0_ACSDA);
+
+       // Setup the AC97 control registers on the CS4281 to send the
+       // appropriate command to the AC97 to perform the read.
+       // ACCAD = Command Address Register = 46Ch
+       // ACCDA = Command Data Register = 470h
+       // ACCTL = Control Register = 460h
+       // bit DCV - will clear when process completed
+       // bit CRW - Read command
+       // bit VFRM - valid frame enabled
+       // bit ESYN - ASYNC generation enabled
+
+       // Get the actual AC97 register from the offset
+       writel(offset - BA0_AC97_RESET, card->pBA0+BA0_ACCAD);
+       writel(0, card->pBA0+BA0_ACCDA);
+       writel(ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN, card->pBA0+BA0_ACCTL);
+
+        // Wait for the read to occur.
+       for(count = 0; count < 10; count++)
+       {
+               // First, we want to wait for a short time.
+               udelay(25);
+
+               // Now, check to see if the read has completed.
+               // ACCTL = 460h, DCV should be reset by now and 460h = 17h
+               if( !(readl(card->pBA0+BA0_ACCTL) & ACCTL_DCV))
+                       break;
+       }
+
+        // Make sure the read completed.
+       if(readl(card->pBA0+BA0_ACCTL) & ACCTL_DCV)
+              return 1;
+
+        // Wait for the valid status bit to go active.
+       for(count = 0; count < 10; count++)
+       {
+               // Read the AC97 status register.
+               // ACSTS = Status Register = 464h
+               status = readl(card->pBA0+BA0_ACSTS);
+
+               // See if we have valid status.
+               // VSTS - Valid Status
+               if(status & ACSTS_VSTS)
+                       break;
+               // Wait for a short while.
+               udelay(25);
+       }
+
+        // Make sure we got valid status.
+       if(!(status & ACSTS_VSTS))
+               return 1;
+
+       // Read the data returned from the AC97 register.
+       // ACSDA = Status Data Register = 474h
+       *value = readl(card->pBA0+BA0_ACSDA);
+
+       // Success.
+       return(0);
+}
+
+
+//****************************************************************************
+//
+// "cs4281_write_ac97()"-- writes a word to the specified location in the
+// CS461x's address space (based on the part's base address zero register).
+//
+// 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
+// 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 reg.
+// 3. Write ACCTL = Control Register = 460h for initiating the write
+// 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
+// 5. if DCV not cleared, break and return error
+//
+//****************************************************************************
+static int cs4281_write_ac97(struct cs4281_state *card, u32 offset, u32 value)
+{
+       u32 count, status;
+
+       CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: cs_4281_write_ac97()+ \n") );
+
+        // Setup the AC97 control registers on the CS4281 to send the
+        // appropriate command to the AC97 to perform the read.
+        // ACCAD = Command Address Register = 46Ch
+        // ACCDA = Command Data Register = 470h
+        // ACCTL = Control Register = 460h
+        // set DCV - will clear when process completed
+        // reset CRW - Write command
+        // set VFRM - valid frame enabled
+        // set ESYN - ASYNC generation enabled
+        // set RSTN - ARST# inactive, AC97 codec not reset
+
+        // Get the actual AC97 register from the offset
+
+       writel(offset - BA0_AC97_RESET, card->pBA0+BA0_ACCAD);
+       writel(value, card->pBA0+BA0_ACCDA);
+       writel(ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN, card->pBA0+BA0_ACCTL);
+
+        // Wait for the write to occur.
+       for(count = 0; count < 10; count++)
+       {
+               // First, we want to wait for a short time.
+               udelay(25);
+               // Now, check to see if the write has completed.
+               // ACCTL = 460h, DCV should be reset by now and 460h = 07h
+               status = readl(card->pBA0+BA0_ACCTL);
+               if(!(status & ACCTL_DCV))
+                       break;
+       }
+
+       // Make sure the write completed.
+       if(status & ACCTL_DCV)
+       {
+               CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO 
+                       "cs4281: cs_4281_write_ac97()- unable to write. ACCTL_DCV active\n") );
+               return 1;
+       }
+       CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: cs_4281_write_ac97()- 0\n") );
+       // Success.
+       return 0;
+}
+
+
+//******************************************************************************
+// "Init4281()" -- Bring up the part.
+//******************************************************************************
+static int cs4281_hw_init(struct cs4281_state *card)
+{
+       u32 ac97_slotid;
+       u32 temp1, temp2;
+
+       CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: cs4281_hw_init()+ \n") );
+       //***************************************7
+       //  Set up the Sound System Configuration
+       //***************************************
+
+        // Set the 'Configuration Write Protect' register
+        // to 4281h.  Allows vendor-defined configuration
+        // space between 0e4h and 0ffh to be written.
+
+       writel(0x4281, card->pBA0+BA0_CWPR);                       // (3e0h)
+
+        // (0), Blast the clock control register to zero so that the
+        // PLL starts out in a known state, and blast the master serial
+        // port control register to zero so that the serial ports also
+        // start out in a known state.
+
+       writel(0, card->pBA0+BA0_CLKCR1);                          // (400h)
+       writel(0, card->pBA0+BA0_SERMC);                           // (420h)
+
+
+        // (1), Make ESYN go to zero to turn off
+        // the Sync pulse on the AC97 link.
+
+       writel(0, card->pBA0+BA0_ACCTL);
+       udelay(50);
+
+
+        // (2) Drive the ARST# pin low for a minimum of 1uS (as defined in
+        // the AC97 spec) and then drive it high.  This is done for non
+        // AC97 modes since there might be logic external to the CS461x
+        // that uses the ARST# line for a reset.
+
+       writel(0, card->pBA0+BA0_SPMC);                            // (3ech)
+       udelay(100);
+       writel(SPMC_RSTN, card->pBA0+BA0_SPMC);
+       delayus(50000);     // Wait 50 ms for ABITCLK to become stable.
+
+       // (3) Turn on the Sound System Clocks.
+       writel(CLKCR1_PLLP, card->pBA0+BA0_CLKCR1);                // (400h)
+       delayus(50000);     // Wait for the PLL to stabilize.
+       // Turn on clocking of the core (CLKCR1(400h) = 0x00000030)
+       writel(CLKCR1_PLLP | CLKCR1_SWCE, card->pBA0+BA0_CLKCR1);
+
+       // (4) Power on everything for now..
+       writel(0x7E, card->pBA0 + BA0_SSPM);                       // (740h)
+
+       // (5) Wait for clock stabilization.
+       for(temp1=0; temp1<1000;  temp1++)
+       {
+               udelay(1000);
+               if(readl(card->pBA0+BA0_CLKCR1) & CLKCR1_DLLRDY)
+                       break;
+       }
+       if(!(readl(card->pBA0+BA0_CLKCR1) & CLKCR1_DLLRDY))
+       {
+               CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR "cs4281: DLLRDY failed!\n") );
+               return -EIO;
+       }
+
+       // (6) Enable ASYNC generation.
+       writel(ACCTL_ESYN, card->pBA0+BA0_ACCTL);                  // (460h)
+
+       // Now wait 'for a short while' to allow the  AC97
+       // part to start generating bit clock. (so we don't
+       // Try to start the PLL without an input clock.)
+       delayus(50000);
+
+       // Set the serial port timing configuration, so that the
+       // clock control circuit gets its clock from the right place.
+       writel(SERMC_PTC_AC97, card->pBA0+BA0_SERMC);              // (420h)=2.
+
+       // (7) Wait for the codec ready signal from the AC97 codec.
+
+       for(temp1=0; temp1<1000; temp1++)
+       {
+               // Delay a mil to let things settle out and
+               // to prevent retrying the read too quickly.
+               udelay(1000);
+               if( readl(card->pBA0+BA0_ACSTS) & ACSTS_CRDY )  // If ready,  (464h)
+                       break;                                  //   exit the 'for' loop.
+       }
+       if( !(readl(card->pBA0+BA0_ACSTS) & ACSTS_CRDY) )       // If never came ready,
+       {
+               CS_DBGOUT(CS_FUNCTION, 2, 
+                       printk(KERN_ERR "cs4281: ACSTS never came ready!\n") );
+               return -EIO;                                //   exit initialization.
+       }
+
+        // (8) Assert the 'valid frame' signal so we can
+        // begin sending commands to the AC97 codec.
+       writel(ACCTL_VFRM | ACCTL_ESYN, card->pBA0+BA0_ACCTL);   // (460h)
+
+        // (9), Wait until CODEC calibration is finished.
+        // Print an error message if it doesn't.
+       for(temp1 = 0; temp1 < 1000; temp1++)
+       {
+               delayus(10000);
+               // Read the AC97 Powerdown Control/Status Register.
+               cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp2);
+               if( (temp2 & 0x0000000F) == 0x0000000F )
+                       break;
+       }
+       if ( (temp2 & 0x0000000F) != 0x0000000F )
+       {
+               CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR 
+                       "cs4281: Codec failed to calibrate.  Status = %.8x.\n", temp2) );
+               return -EIO;
+       }
+
+        // (10), Set the serial port timing configuration, so that the
+        // clock control circuit gets its clock from the right place.
+       writel(SERMC_PTC_AC97, card->pBA0+BA0_SERMC);              // (420h)=2.
+
+
+        // (11) Wait until we've sampled input slots 3 & 4 as valid, meaning
+        // that the codec is pumping ADC data across the AC link.
+       for(temp1=0; temp1<1000; temp1++)
+       {
+               // Delay a mil to let things settle out and
+               // to prevent retrying the read too quickly.
+               delayus(1000);    //(test)
+
+               // Read the input slot valid register;  See
+               // if input slots 3 and 4 are valid yet.
+               if( (readl(card->pBA0+BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4) ) 
+                               ==  (ACISV_ISV3 | ACISV_ISV4))
+                       break;    // Exit the 'for' if slots are valid.
+       }
+               // If we never got valid data, exit initialization.
+       if( (readl(card->pBA0+BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4) ) 
+               != (ACISV_ISV3 | ACISV_ISV4))
+       {
+               CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR "cs4281: Never got valid data!\n"));
+                       return -EIO;     // If no valid data, exit initialization.
+       }
+
+       // (12), Start digital data transfer of audio data to the codec.
+       writel(ACOSV_SLV3 | ACOSV_SLV4, card->pBA0+BA0_ACOSV);             // (468h)
+
+
+       //**************************************
+       // Unmute the Master and Alternate
+       // (headphone) volumes.  Set to max.
+       //**************************************
+       cs4281_write_ac97(card,BA0_AC97_HEADPHONE_VOLUME, 0);
+       cs4281_write_ac97(card,BA0_AC97_MASTER_VOLUME, 0);
+
+       //******************************************
+       // Power on the DAC(AddDACUser()from main())
+       //******************************************
+       cs4281_read_ac97(card,BA0_AC97_POWERDOWN, &temp1);
+       cs4281_write_ac97(card,BA0_AC97_POWERDOWN, temp1 &= 0xfdff);
+
+       // Wait until we sample a DAC ready state.
+       for(temp2=0; temp2<32; temp2++)
+       {
+               // Let's wait a mil to let things settle.
+               delayus(1000);
+               // Read the current state of the power control reg.
+               cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1);
+               // If the DAC ready state bit is set, stop waiting.
+               if(temp1 & 0x2)
+                       break;
+       }
+
+       //******************************************
+       // Power on the ADC(AddADCUser()from main())
+       //******************************************
+       cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1);
+       cs4281_write_ac97(card, BA0_AC97_POWERDOWN, temp1 &= 0xfeff);
+
+       // Wait until we sample ADC ready state.
+       for(temp2=0; temp2<32; temp2++)
+       {
+               // Let's wait a mil to let things settle.
+               delayus(1000);
+               // Read the current state of the power control reg.
+               cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1);
+               // If the ADC ready state bit is set, stop waiting.
+               if(temp1 & 0x1)
+                       break;
+       }
+       // Set up 4281 Register contents that
+       // don't change for boot duration.
+
+       // For playback, we map AC97 slot 3 and 4(Left
+       // & Right PCM playback) to DMA Channel 0.
+       // Set the fifo to be 15 bytes at offset zero.
+
+       ac97_slotid = 0x01000f00;       // FCR0.RS[4:0]=1(=>slot4, right PCM playback).
+                                       // FCR0.LS[4:0]=0(=>slot3, left PCM playback).
+                                       // FCR0.SZ[6-0]=15; FCR0.OF[6-0]=0.
+       writel(ac97_slotid, card->pBA0 + BA0_FCR0);                 // (180h)
+       writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR0);      // Turn on FIFO Enable.
+
+       // For capture, we map AC97 slot 10 and 11(Left
+       // and Right PCM Record) to DMA Channel 1.
+       // Set the fifo to be 15 bytes at offset sixteen.
+       ac97_slotid = 0x0B0A0f10;       // FCR1.RS[4:0]=11(=>slot11, right PCM record).
+                                       // FCR1.LS[4:0]=10(=>slot10, left PCM record).
+                                       // FCR1.SZ[6-0]=15; FCR1.OF[6-0]=16.
+       writel(ac97_slotid | FCRn_PSH, card->pBA0 + BA0_FCR1);      // (184h)
+       writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR1);      // Turn on FIFO Enable.
+
+       // Map the Playback SRC to the same AC97 slots(3 & 4--
+       // --Playback left & right)as DMA channel 0.
+       // Map the record SRC to the same AC97 slots(10 & 11--
+       // -- Record left & right) as DMA channel 1.
+
+       ac97_slotid = 0x0b0a0100;       // SCRSA.PRSS[4:0]=1(=>slot4, right PCM playback).
+                                       // SCRSA.PLSS[4:0]=0(=>slot3, left PCM playback).
+                                       // SCRSA.CRSS[4:0]=11(=>slot11, right PCM record)
+                                       // SCRSA.CLSS[4:0]=10(=>slot10, left PCM record).
+       writel(ac97_slotid, card->pBA0 + BA0_SRCSA);                // (75ch)
+
+       // Set 'Half Terminal Count Interrupt Enable' and 'Terminal
+       // Count Interrupt Enable' in DMA Control Registers 0 & 1.
+       // Set 'MSK' flag to 1 to keep the DMA engines paused.
+       temp1 = (DCRn_HTCIE | DCRn_TCIE | DCRn_MSK);     // (00030001h)
+       writel(temp1, card->pBA0 + BA0_DCR0);            // (154h
+       writel(temp1, card->pBA0 + BA0_DCR1);            // (15ch)
+
+       // Set 'Auto-Initialize Control' to 'enabled'; For playback,
+       // set 'Transfer Type Control'(TR[1:0]) to 'read transfer',
+       // for record, set Transfer Type Control to 'write transfer'.
+       // All other bits set to zero;  Some will be changed @ transfer start.
+       temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_READ);   // (20000018h)
+       writel(temp1, card->pBA0 + BA0_DMR0);            // (150h)
+       temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE);  // (20000014h)
+       writel(temp1, card->pBA0 + BA0_DMR1);            // (158h)
+
+       // Enable DMA interrupts generally, and
+       // DMA0 & DMA1 interrupts specifically.
+       temp1 = readl(card->pBA0 + BA0_HIMR) &  0xfffbfcff;
+       writel(temp1, card->pBA0+BA0_HIMR);
+
+       CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: cs4281_hw_init()- 0\n") );
+       return 0;
+}
+
+
+//******************************************************************************
+// "cs4281_play_rate()" --
+//******************************************************************************
+static void cs4281_play_rate(struct cs4281_state *card, u32 playrate)
+{
+       u32 DACSRvalue = 1;
+
+        // Based on the sample rate, program the DACSR register.
+       if(playrate == 8000)
+               DACSRvalue = 5;
+       if(playrate == 11025)
+               DACSRvalue = 4;
+       else if(playrate == 22050)
+               DACSRvalue = 2;
+       else if(playrate == 44100)
+               DACSRvalue = 1;
+       else if((playrate <= 48000) && (playrate >= 6023))
+               DACSRvalue = 24576000/(playrate*16);
+       else if(playrate < 6023)
+               // Not allowed by open.
+               return;
+       else if(playrate > 48000)
+               // Not allowed by open.
+               return;
+       CS_DBGOUT(CS_WAVE_WRITE | CS_PARMS, 2, printk(KERN_INFO 
+               "cs4281: cs4281_play_rate(): DACSRvalue=0x%.8x playrate=%d\n",
+                       DACSRvalue,playrate));
+        //  Write the 'sample rate select code'
+        //  to the 'DAC Sample Rate' register.
+       writel(DACSRvalue, card->pBA0 + BA0_DACSR);           // (744h)
+}
+
+//******************************************************************************
+// "cs4281_record_rate()" -- Initialize the record sample rate converter.
+//******************************************************************************
+static void cs4281_record_rate(struct cs4281_state *card, u32 outrate)
+{
+       u32 ADCSRvalue = 1;
+
+        //
+        // Based on the sample rate, program the ADCSR register
+        //
+       if(outrate == 8000)
+               ADCSRvalue = 5;
+       if(outrate == 11025)
+               ADCSRvalue = 4;
+       else if(outrate == 22050)
+               ADCSRvalue = 2;
+       else if(outrate == 44100)
+               ADCSRvalue = 1;
+       else if((outrate <= 48000) && (outrate >= 6023))
+               ADCSRvalue = 24576000/(outrate*16);
+       else if(outrate < 6023)
+       {
+               // Not allowed by open.
+               return;
+       }
+       else if(outrate > 48000)
+       {
+               // Not allowed by open.
+               return;
+       }
+       CS_DBGOUT(CS_WAVE_READ | CS_PARMS, 2, printk(KERN_INFO 
+               "cs4281: cs4281_record_rate(): ADCSRvalue=0x%.8x outrate=%d\n",
+                       ADCSRvalue,outrate) );
+       //  Write the 'sample rate select code
+       //  to the 'ADC Sample Rate' register.
+       writel(ADCSRvalue, card->pBA0 + BA0_ADCSR);           // (748h)
+}
+
+
+
+static void stop_dac(struct cs4281_state *s)
+{
+       unsigned long flags;
+       unsigned temp1;
+
+       CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO "cs4281: stop_dac():\n") );
+       spin_lock_irqsave(&s->lock, flags);
+       s->ena &= ~FMODE_WRITE;
+       temp1 = readl(s->pBA0+ BA0_DCR0) | DCRn_MSK;     
+       writel(temp1, s->pBA0+BA0_DCR0);         
+
+       spin_unlock_irqrestore(&s->lock, flags);
+}
+
+
+static void start_dac(struct cs4281_state *s)
+{
+       unsigned long flags;
+       unsigned temp1;
+
+       CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO "cs4281: start_dac():\n") );
+       spin_lock_irqsave(&s->lock, flags);
+       if (!(s->ena & FMODE_WRITE) && (s->dma_dac.mapped ||
+             s->dma_dac.count > 0) && s->dma_dac.ready)      {
+               s->ena |= FMODE_WRITE;
+               temp1 = readl(s->pBA0+BA0_DCR0) & ~DCRn_MSK;     // Clear DMA0 channel mask.
+               writel(temp1, s->pBA0+BA0_DCR0);                 // Start DMA'ing.
+               writel(HICR_IEV | HICR_CHGM, s->pBA0+BA0_HICR);     // Enable interrupts.              
+       
+               writel(7, s->pBA0+BA0_PPRVC);
+               writel(7, s->pBA0+BA0_PPLVC);
+       
+       }
+       spin_unlock_irqrestore(&s->lock, flags);
+}
+
+
+static void stop_adc(struct cs4281_state *s)
+{
+       unsigned long flags;
+       unsigned temp1;
+
+       CS_DBGOUT(CS_WAVE_READ, 3, printk(KERN_INFO "cs4281: stop_adc():\n") );
+
+       spin_lock_irqsave(&s->lock, flags);
+       s->ena &= ~FMODE_READ;
+       temp1 = readl(s->pBA0+ BA0_DCR1) | DCRn_MSK;     
+       writel(temp1, s->pBA0+BA0_DCR1);
+       spin_unlock_irqrestore(&s->lock, flags);
+}
+
+
+static void start_adc(struct cs4281_state *s)
+{
+       unsigned long flags;
+       unsigned temp1;
+
+       CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO "cs4281: start_adc():\n") );
+
+       spin_lock_irqsave(&s->lock, flags);
+       if (!(s->ena & FMODE_READ) && (s->dma_adc.mapped
+             || s->dma_adc.count <= 
+                (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize))
+             && s->dma_adc.ready)
+       {
+               s->ena |= FMODE_READ;
+               temp1 = readl(s->pBA0+BA0_DCR1) & ~ DCRn_MSK;         // Clear DMA1 channel mask bit.
+               writel(temp1, s->pBA0+BA0_DCR1);                      // Start recording
+               writel(HICR_IEV | HICR_CHGM, s->pBA0+BA0_HICR);       // Enable interrupts.
+       }
+       spin_unlock_irqrestore(&s->lock, flags);
+
+}
+
+
+// --------------------------------------------------------------------- 
+#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)     // == 3(for PC), = log base 2( buff sz = 32k).
+#define DMABUF_MINORDER 1                       // ==> min buffer size = 8K.
+
+
+extern  void dealloc_dmabuf(struct cs4281_state *s, struct dmabuf *db)
+{
+       struct page *map, *mapend;
+
+       if (db->rawbuf) {
+               // Undo prog_dmabuf()'s marking the pages as reserved 
+               mapend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
+               for (map = virt_to_page(db->rawbuf); map <= mapend; map++)
+                       clear_bit(PG_reserved, &map->flags);
+               pci_free_consistent(s->pcidev,PAGE_SIZE<<db->buforder,
+                       db->rawbuf,db->dmaaddr);
+       }
+       db->rawbuf = NULL;
+       db->mapped = db->ready = 0;
+}
+
+static int prog_dmabuf(struct cs4281_state *s, struct dmabuf *db)
+{
+       int order;
+       unsigned bytespersec, temp1;
+       unsigned bufs, sample_shift = 0;
+       struct page *map, *mapend;
+
+       db->hwptr = db->swptr = db->total_bytes = db->count = 
+               db->error = db->endcleared = db->blocks = 0;
+       if (!db->rawbuf) {
+               db->ready = db->mapped = 0;
+               for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
+                       if ((db->rawbuf = (void *)pci_alloc_consistent(
+                               s->pcidev, PAGE_SIZE << order, &db->dmaaddr)))
+                               break;
+               if (!db->rawbuf)
+               {
+                       CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR 
+                               "cs4281: prog_dmabuf(): unable to allocate rawbuf\n") );
+                       return -ENOMEM;
+               }
+               db->buforder = order;
+               // Now mark the pages as reserved; otherwise the 
+               // remap_page_range() in cs4281_mmap doesn't work.
+                    // 1. get index to last page in mem_map array for rawbuf.
+               mapend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
+               
+                    // 2. mark each physical page in range as 'reserved'.
+               for (map = virt_to_page(db->rawbuf); map <= mapend; map++)
+                       set_bit(PG_reserved, &map->flags);
+       }
+       if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE))
+               sample_shift++;
+       if (s->channels > 1)
+               sample_shift++;
+       bytespersec = s->rate << sample_shift;
+       bufs = PAGE_SIZE << db->buforder;
+
+
+#define INTERRUPT_RATE_MS       100                      // Interrupt rate in milliseconds.
+       db->numfrag = 2;
+       temp1 = bytespersec/(1000/INTERRUPT_RATE_MS);    // Nominal frag size(bytes/interrupt)
+       db->fragshift = 8;                               // Min 256 bytes.
+       while( 1 << db->fragshift  < temp1)              // Calc power of 2 frag size.
+               db->fragshift +=1;
+       db->fragsize = 1 << db->fragshift;               
+       db->dmasize = db->fragsize * 2;
+               // If the calculated size is larger than the allocated
+               //  buffer, divide the allocated buffer into 2 fragments.
+       if(db->dmasize > bufs) {
+               db->numfrag = 2;                                 // Two fragments.
+               db->fragsize = bufs >> 1;                        // Each 1/2 the alloc'ed buffer.
+               db->fragsamples = db->fragsize >> sample_shift;  // # samples/fragment.
+               db->dmasize =  bufs;                             // Use all the alloc'ed buffer.
+               
+               db->fragshift = 0;                               // Calculate 'fragshift'.
+               temp1 = db->fragsize;                            // update_ptr() uses it 
+               while( (temp1 >>=1) > 1)                         // to calc 'total-bytes'
+                    db->fragshift +=1;                          // returned in DSP_GETI/OPTR. 
+       }
+       CS_DBGOUT(CS_PARMS, 3, printk(KERN_INFO 
+                   "cs4281: prog_dmabuf(): numfrag=%d fragsize=%d fragsamples=%d fragshift=%d\n",
+                       db->numfrag,db->fragsize,db->fragsamples,db->fragshift) );
+       return 0;
+}    
+
+
+static int prog_dmabuf_adc(struct cs4281_state *s)
+{
+       unsigned long va;
+       unsigned count;      
+       int c;
+       stop_adc(s);
+       if ((c = prog_dmabuf(s, &s->dma_adc)))
+               return c;
+            
+       va = virt_to_bus(s->dma_adc.rawbuf);
+       
+       count = s->dma_adc.dmasize;       
+       
+       if(s->fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE))
+               count /= 2;                      // 16-bit.
+                       
+       if(s->channels > 1)
+               count /= 2;                      // Assume stereo.
+         
+       CS_DBGOUT(CS_WAVE_READ, 3, printk(KERN_INFO 
+           "cs4281: prog_dmabuf_adc(): count=%d va=0x%.8x\n", count,(unsigned)va) );
+
+       writel(va, s->pBA0+BA0_DBA1);            // Set buffer start address.
+       writel(count-1, s->pBA0+BA0_DBC1);       // Set count. 
+       s->dma_adc.ready = 1;
+       return 0;
+}
+
+
+static int prog_dmabuf_dac(struct cs4281_state *s)
+{
+       unsigned long va;
+       unsigned count;
+       int c;
+       stop_dac(s);
+       if ((c = prog_dmabuf(s, &s->dma_dac)))
+               return c;
+       memset(s->dma_dac.rawbuf, (s->fmt & (AFMT_U8 | AFMT_U16_LE))
+                                  ? 0x80 : 0, s->dma_dac.dmasize);      
+
+       va = virt_to_bus(s->dma_dac.rawbuf);
+
+       count = s->dma_dac.dmasize;       
+       if(s->fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE))
+               count /= 2;                      // 16-bit.
+      
+       if(s->channels > 1)
+               count /= 2;                      // Assume stereo.
+          
+       writel(va, s->pBA0+BA0_DBA0);               // Set buffer start address.
+       writel(count-1, s->pBA0+BA0_DBC0);       // Set count.             
+
+       CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO 
+           "cs4281: prog_dmabuf_dac(): count=%d va=0x%.8x\n", count,(unsigned)va) );
+
+       s->dma_dac.ready = 1;
+       return 0;
+}
+
+
+static void clear_advance(void *buf, unsigned bsize, unsigned bptr, unsigned len, unsigned char c)
+{
+       if (bptr + len > bsize) {
+               unsigned x = bsize - bptr;
+               memset(((char *)buf) + bptr, c, x);
+               bptr = 0;
+               len -= x;
+       }
+       CS_DBGOUT(CS_WAVE_WRITE, 4, printk(KERN_INFO 
+           "cs4281: clear_advance(): memset %d at 0x%.8x for %d size \n", 
+               (unsigned)c,(unsigned)((char *)buf) + bptr, len) );
+       memset(((char *)buf) + bptr, c, len);
+}
+
+
+
+// call with spinlock held! 
+static void cs4281_update_ptr(struct cs4281_state *s)
+{
+       int diff;
+       unsigned hwptr, va, temp1;
+
+       // update ADC pointer 
+       if (s->ena & FMODE_READ) {
+               hwptr = readl(s->pBA0+BA0_DCA1);          // Read capture DMA address.
+               va = virt_to_bus(s->dma_adc.rawbuf);
+               hwptr -= (unsigned)va;                 
+               diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize;
+               s->dma_adc.hwptr = hwptr;
+               s->dma_adc.total_bytes += diff;
+               s->dma_adc.count += diff;
+               if (s->dma_adc.mapped) {
+                       if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
+                               wake_up(&s->dma_adc.wait);
+               } else {
+                       if (s->dma_adc.count > 0)
+                               wake_up(&s->dma_adc.wait);
+               }
+               CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO 
+                 "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n", 
+                    (unsigned)s,s->dma_adc.hwptr,s->dma_adc.total_bytes,s->dma_adc.count) );
+       }
+       // update DAC pointer 
+       //
+       // check for end of buffer, means that we are going to wait for another interrupt
+       // to allow silence to fill the fifos on the part, to keep pops down to a minimum.
+       //
+       if ( (s->ena & FMODE_WRITE) && (!s->endofbuffer) )
+       {
+               hwptr = readl(s->pBA0+BA0_DCA0);          // Read play DMA address.
+               va = virt_to_bus(s->dma_dac.rawbuf);
+               hwptr -= (unsigned)va;
+               diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize;
+               s->dma_dac.hwptr = hwptr;
+               s->dma_dac.total_bytes += diff;
+               if (s->dma_dac.mapped) {
+                       s->dma_dac.count += diff;
+                       if (s->dma_dac.count >= (signed)s->dma_dac.fragsize)
+                               wake_up(&s->dma_dac.wait);
+               } else {
+                       s->dma_dac.count -= diff;
+                       if (s->dma_dac.count <= 0) {
+                               s->ena &= ~FMODE_WRITE;
+                               temp1 = readl(s->pBA0+BA0_DCR0);
+                       //
+                       // fill with silence, and wait on turning off the DAC until interrupt routine.
+                       // wait on "Poke(pBA0+BA0_DCR0, temp1 | DCRn_MSK);    // Stop Play DMA"
+                       //
+                               CS_DBGOUT(CS_WAVE_WRITE, 6, printk(KERN_INFO 
+                                   "cs4281: cs4281_update_ptr(): memset %d at 0x%.8x for %d size \n", 
+                                       (unsigned)(s->fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, 
+                                       (unsigned)s->dma_dac.rawbuf, s->dma_dac.dmasize) );
+                               memset(s->dma_dac.rawbuf, (s->fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, 
+                                       s->dma_dac.dmasize); 
+                               s->endofbuffer = 1;
+                       } else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize
+                                                        && !s->dma_dac.endcleared) {
+                               clear_advance(s->dma_dac.rawbuf, 
+                                             s->dma_dac.dmasize, s->dma_dac.swptr,
+                                             s->dma_dac.fragsize,
+                                             (s->fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0);
+                               s->dma_dac.endcleared = 1;
+                       }
+                       if (s->dma_dac.count < (signed)s->dma_dac.dmasize)
+                               wake_up(&s->dma_dac.wait);
+               }
+               CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO 
+                 "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n", 
+                    (unsigned)s,s->dma_dac.hwptr,s->dma_dac.total_bytes,s->dma_dac.count) );
+       }
+}
+
+
+// --------------------------------------------------------------------- 
+
+static void prog_codec(struct cs4281_state *s)
+{
+       unsigned long flags;
+       unsigned temp1, format;
+
+       CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO "cs4281: prog_codec()+ \n") );
+
+       spin_lock_irqsave(&s->lock, flags);
+       temp1 = readl(s->pBA0+BA0_DCR0);
+       writel(temp1 | DCRn_MSK, s->pBA0+BA0_DCR0);   // Stop play DMA, if active.
+       temp1 = readl(s->pBA0+BA0_DCR1);
+       writel(temp1 | DCRn_MSK, s->pBA0+BA0_DCR1);   // Stop capture DMA, if active.
+       // program sampling rates  
+       // Note, for CS4281, capture & play rates can be set independently.
+       cs4281_record_rate(s, s->rate); 
+              
+       // program ADC parameters 
+       format = DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE;
+       if(s->fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) { // 16-bit
+       if(s->fmt & (AFMT_S16_BE | AFMT_U16_BE))  // Big-endian?
+               format |= DMRn_BEND;  
+               if(s->fmt & (AFMT_U16_LE  | AFMT_U16_BE)) 
+                       format |= DMRn_USIGN;         // Unsigned.      
+       }          
+       else
+               format |= DMRn_SIZE8 | DMRn_USIGN;    // 8-bit, unsigned
+       if(s->channels < 2)
+               format |= DMRn_MONO;
+
+       writel(format, s->pBA0+BA0_DMR1);       
+       
+  
+       // program DAC parameters 
+       format = DMRn_DMA | DMRn_AUTO | DMRn_TR_READ;
+       if(s->fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) { // 16-bit
+               if(s->fmt & (AFMT_S16_BE | AFMT_U16_BE))  
+                       format |= DMRn_BEND;          // Big Endian.
+               if(s->fmt & (AFMT_U16_LE  | AFMT_U16_BE)) 
+                       format |= DMRn_USIGN;         // Unsigned.      
+       }          
+       else
+               format |= DMRn_SIZE8 | DMRn_USIGN;    // 8-bit, unsigned
+       
+       if(s->channels < 2)
+               format |= DMRn_MONO;
+
+       writel(format, s->pBA0+BA0_DMR0);       
+
+       CS_DBGOUT(CS_PARMS, 2, printk(KERN_INFO 
+           "cs4281: prog_codec(): format=0x%.8x rate=%d\n", format,s->rate) );
+
+       cs4281_play_rate(s, s->rate);
+
+       s->ena = 0;     // Neither writing or reading.
+       spin_unlock_irqrestore(&s->lock, flags);
+}
+
+
+// --------------------------------------------------------------------- 
+
+static const char invalid_magic[] = KERN_CRIT "cs4281: invalid magic value\n";
+
+#define VALIDATE_STATE(s)                         \
+({                                                \
+       if (!(s) || (s)->magic != CS4281_MAGIC) { \
+               printk(invalid_magic);            \
+               return -ENXIO;                    \
+       }                                         \
+})
+
+// --------------------------------------------------------------------- 
+
+
+static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd, unsigned long arg)
+{
+       // Index to mixer_src[] is value of AC97 Input Mux Select Reg.
+       // Value of array member is recording source Device ID Mask.
+       static const unsigned int mixer_src[8] = {
+               SOUND_MASK_MIC, SOUND_MASK_CD, 0, SOUND_MASK_LINE1,
+               SOUND_MASK_LINE, SOUND_MASK_VOLUME, 0, 0
+       };
+            
+       // Index of mixtable1[] member is Device ID 
+       // and must be <= SOUND_MIXER_NRDEVICES.
+       // Value of array member is index into s->mix.vol[]
+       static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = {
+               [SOUND_MIXER_PCM]     = 1,   // voice 
+               [SOUND_MIXER_LINE1]   = 2,   // AUX
+               [SOUND_MIXER_CD]      = 3,   // CD 
+               [SOUND_MIXER_LINE]    = 4,   // Line 
+               [SOUND_MIXER_SYNTH]   = 5,   // FM
+               [SOUND_MIXER_MIC]     = 6,   // Mic 
+               [SOUND_MIXER_SPEAKER] = 7,   // Speaker 
+               [SOUND_MIXER_RECLEV]  = 8,   // Recording level 
+               [SOUND_MIXER_VOLUME]  = 9    // Master Volume 
+       };
+       
+       
+       static const unsigned mixreg[] = {
+               BA0_AC97_PCM_OUT_VOLUME,
+               BA0_AC97_AUX_VOLUME, 
+               BA0_AC97_CD_VOLUME, 
+               BA0_AC97_LINE_IN_VOLUME
+       };
+       unsigned char l, r, rl, rr, vidx;
+       unsigned char attentbl[11] = {63,42,26,17,14,11,8,6,4,2,0};
+       unsigned temp1;
+       int i, val;
+
+       VALIDATE_STATE(s);
+       if (cmd == SOUND_MIXER_PRIVATE1) {
+               // enable/disable/query mixer preamp 
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               if (val != -1) {
+                       cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1);
+                       temp1 = val ? (temp1 | 0x40) : (temp1 & 0xffbf);
+                       cs4281_write_ac97(s, BA0_AC97_MIC_VOLUME, temp1);
+               }
+               cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1);
+               val = (temp1 & 0x40) ? 1 : 0;
+               return put_user(val, (int *)arg);
+       }
+       if (cmd == SOUND_MIXER_PRIVATE2) {
+               // enable/disable/query spatializer 
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               if (val != -1) {
+                       temp1 = (val & 0x3f) >> 2;
+                       cs4281_write_ac97(s, BA0_AC97_3D_CONTROL, temp1);
+                       cs4281_read_ac97(s, BA0_AC97_GENERAL_PURPOSE, &temp1);
+                       cs4281_write_ac97(s, BA0_AC97_GENERAL_PURPOSE,temp1 | 0x2000);
+               }
+               cs4281_read_ac97(s, BA0_AC97_3D_CONTROL, &temp1);
+               return put_user((temp1 << 2) | 3, (int *)arg);
+       }
+       if (cmd == SOUND_MIXER_INFO) {
+               mixer_info info;
+               strncpy(info.id, "CS4281", sizeof(info.id));
+               strncpy(info.name, "Crystal CS4281", sizeof(info.name));
+               info.modify_counter = s->mix.modcnt;
+               if (copy_to_user((void *)arg, &info, sizeof(info)))
+                       return -EFAULT;
+               return 0;
+       }
+       if (cmd == SOUND_OLD_MIXER_INFO) {
+               _old_mixer_info info;
+               strncpy(info.id, "CS4281", sizeof(info.id));
+               strncpy(info.name, "Crystal CS4281", sizeof(info.name));
+               if (copy_to_user((void *)arg, &info, sizeof(info)))
+                       return -EFAULT;
+               return 0;
+       }
+       if (cmd == OSS_GETVERSION)
+               return put_user(SOUND_VERSION, (int *)arg);
+       
+       if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
+               return -EINVAL;
+       
+            // If ioctl has only the IOC_READ bit(bit 31)
+            // on, process the only-read commands. 
+       if (_IOC_DIR(cmd) == _IOC_READ) {
+               switch (_IOC_NR(cmd)) {
+               case SOUND_MIXER_RECSRC: // Arg contains a bit for each recording source 
+                   cs4281_read_ac97(s, BA0_AC97_RECORD_SELECT, &temp1);
+                   return put_user(mixer_src[temp1 & 7], (int *)arg);
+
+               case SOUND_MIXER_DEVMASK: // Arg contains a bit for each supported device 
+                       return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH | SOUND_MASK_CD |
+                                       SOUND_MASK_LINE | SOUND_MASK_LINE1 | SOUND_MASK_MIC |
+                                       SOUND_MASK_VOLUME | SOUND_MASK_RECLEV |
+                                       SOUND_MASK_SPEAKER, (int *)arg);
+
+               case SOUND_MIXER_RECMASK: // Arg contains a bit for each supported recording source 
+                       return put_user(SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD 
+                                     | SOUND_MASK_VOLUME | SOUND_MASK_LINE1, (int *)arg);
+
+               case SOUND_MIXER_STEREODEVS: // Mixer channels supporting stereo 
+                       return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH | SOUND_MASK_CD |
+                                       SOUND_MASK_LINE | SOUND_MASK_LINE1 | SOUND_MASK_MIC |
+                                       SOUND_MASK_VOLUME | SOUND_MASK_RECLEV, (int *)arg);
+
+               case SOUND_MIXER_CAPS:
+                       return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg);
+
+               default:
+                       i = _IOC_NR(cmd);
+                       if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i]))
+                               return -EINVAL;
+                       return put_user(s->mix.vol[vidx-1], (int *)arg);
+               }
+       }
+       
+            // If ioctl doesn't have both the IOC_READ and 
+            // the IOC_WRITE bit set, return invalid.
+       if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE))
+               return -EINVAL;
+       
+            // Increment the count of volume writes.
+       s->mix.modcnt++;
+            
+            // Isolate the command; it must be a write.
+       switch (_IOC_NR(cmd)) {
+       
+       case SOUND_MIXER_RECSRC: // Arg contains a bit for each recording source 
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               i = hweight32(val);                 // i = # bits on in val.
+               if (i != 1)                         // One & only 1 bit must be on.
+                       return 0;
+               for(i=0; i<sizeof(mixer_src)/sizeof(int); i++) {
+                       if(val == mixer_src[i]) {
+                               temp1 = (i << 8) | i;  
+                               cs4281_write_ac97(s, BA0_AC97_RECORD_SELECT, temp1);
+                               return 0;
+                       }
+               }
+               return 0;
+
+       case SOUND_MIXER_VOLUME:
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               l = val & 0xff;
+               if(l > 100)
+                       l = 100;                    // Max soundcard.h vol is 100.
+               if(l < 6) {
+                       rl = 63;
+                       l  = 0;
+               }
+               else 
+                       rl = attentbl[(10*l)/100];  // Convert 0-100 vol to 63-0 atten.
+                       
+                       r = (val >> 8) & 0xff;
+                       if (r > 100)
+                               r = 100;            // Max right volume is 100, too
+                       if(r < 6) {
+                               rr = 63;
+                               r  = 0;
+                       }
+                       else 
+                              rr = attentbl[(10*r)/100];   // Convert volume to attenuation.
+               
+               if ((rl > 60 ) && (rr > 60))        // If both l & r are 'low',          
+                       temp1 = 0x8000;             //  turn on the mute bit.
+               else
+                       temp1 = 0;
+               
+               temp1 |= (rl << 8) | rr;
+               
+               cs4281_write_ac97(s, BA0_AC97_MASTER_VOLUME, temp1);
+               cs4281_write_ac97(s, BA0_AC97_HEADPHONE_VOLUME, temp1);
+
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+               s->mix.vol[8] = ((unsigned int)r << 8) | l;
+#else
+               s->mix.vol[8] = val;
+#endif
+               return put_user(s->mix.vol[8], (int *)arg);
+
+       case SOUND_MIXER_SPEAKER:
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               l = val & 0xff;
+               if (l > 100)
+                       l = 100;
+               if(l < 3 ) {
+                       rl = 0;
+                       l = 0;
+               }
+               else {
+                       rl = (l*2 - 5)/13;          // Convert 0-100 range to 0-15.
+                       l = (rl*13 +5)/2;
+               }
+
+               if (rl < 3){
+                      temp1 = 0x8000;
+                      rl     = 0;
+               }
+               else
+                      temp1 = 0;
+               rl = 15 - rl;                       // Convert volume to attenuation.
+               temp1 |= rl << 1;
+               cs4281_write_ac97(s, BA0_AC97_PC_BEEP_VOLUME, temp1);
+
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+               s->mix.vol[6] = l << 8;
+#else
+               s->mix.vol[6] = val;
+#endif
+               return put_user(s->mix.vol[6], (int *)arg);
+
+       case SOUND_MIXER_RECLEV:
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               l = val & 0xff;
+               if (l > 100)
+                       l = 100;
+               r = (val >> 8) & 0xff;
+               if (r > 100)
+                       r = 100;
+               rl = (l*2 - 5) / 13;                // Convert 0-100 scale to 0-15.
+               rr = (r*2 - 5) / 13;
+               if (rl <3 && rr <3)
+                       temp1 = 0x8000;
+               else
+                       temp1 = 0;
+
+               temp1 = temp1 | (rl << 8) | rr;
+               cs4281_write_ac97(s, BA0_AC97_RECORD_GAIN, temp1); 
+
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+               s->mix.vol[7] = ((unsigned int)r << 8) | l;
+#else
+               s->mix.vol[7] = val;
+#endif
+               return put_user(s->mix.vol[7], (int *)arg);
+
+       case SOUND_MIXER_MIC:
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               l = val & 0xff;
+               if (l > 100)
+                       l = 100;
+               if (l < 1) {
+                       l = 0;
+                       rl = 0;
+               }
+               else {
+                       rl = ((unsigned)l*5 - 4)/16; // Convert 0-100 range to 0-31.
+                       l  = (rl*16 +4)/5;
+               }
+               cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1);
+               temp1 &= 0x40;                      // Isolate 20db gain bit.
+               if (rl < 3){
+                      temp1 |= 0x8000;
+                      rl     = 0;
+               }
+               rl = 31 - rl;                       // Convert volume to attenuation.
+               temp1 |= rl; 
+               cs4281_write_ac97(s, BA0_AC97_MIC_VOLUME, temp1);
+
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+               s->mix.vol[5] = val << 8;
+#else
+               s->mix.vol[5] = val;
+#endif
+               return put_user(s->mix.vol[5], (int *)arg);
+       
+       
+       case SOUND_MIXER_SYNTH:
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               l = val & 0xff;
+               if (l > 100)
+                       l = 100;
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               r = (val >> 8) & 0xff;
+               if (r > 100)
+                       r = 100;
+               rl = (l * 2 - 11)/3;        // Convert 0-100 range to 0-63.
+               rr = (r * 2 - 11)/3;
+               if (rl < 3)                 // If l is low, turn on
+                       temp1 = 0x0080;     //  the mute bit.
+               else
+                       temp1 = 0;
+
+               rl = 63 - rl;               // Convert vol to attenuation.
+               writel(temp1|rl, s->pBA0+BA0_FMLVC);
+               if (rr < 3)                 //  If rr is low, turn on
+                       temp1 = 0x0080;     //   the mute bit.
+               else
+                       temp1 = 0;
+               rr = 63 - rr;               // Convert vol to attenuation.
+               writel(temp1 | rr, s->pBA0+BA0_FMRVC);
+
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+               s->mix.vol[4] = (r << 8) | l;
+#else
+               s->mix.vol[4] = val;
+#endif
+               return put_user(s->mix.vol[4], (int *)arg);
+
+               
+       default:
+               i = _IOC_NR(cmd);
+               if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i]))
+                       return -EINVAL;
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               l = val & 0xff;
+               if (l > 100)
+                       l = 100;
+               if (l < 1) {
+                       l = 0;
+                       rl = 31;
+               }
+               else 
+                       rl = (attentbl[(l*10)/100])>>1;
+               
+               r = (val >> 8) & 0xff;
+               if (r > 100)
+                       r = 100;
+               if (r < 1) {
+                       r = 0;
+                       rr = 31;
+               }
+               else 
+                       rr = (attentbl[(r*10)/100])>>1;                        
+               if ((rl > 30) && (rr > 30))
+                       temp1 = 0x8000;
+               else
+                       temp1 = 0;
+               temp1 = temp1 | (rl << 8) | rr;              
+               cs4281_write_ac97(s, mixreg[vidx-1], temp1);
+               
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+               s->mix.vol[vidx-1] = ((unsigned int)r << 8) | l;
+#else
+               s->mix.vol[vidx-1] = val;
+#endif
+               return put_user(s->mix.vol[vidx-1], (int *)arg);
+       }
+}
+
+
+// --------------------------------------------------------------------- 
+
+static loff_t cs4281_llseek(struct file *file, loff_t offset, int origin)
+{
+       return -ESPIPE;
+}
+
+
+// --------------------------------------------------------------------- 
+
+static int cs4281_open_mixdev(struct inode *inode, struct file *file)
+{
+       int minor = MINOR(inode->i_rdev);
+       struct cs4281_state *s = devs;
+
+       while (s && s->dev_mixer != minor)
+               s = s->next;
+       if (!s)
+               return -ENODEV;
+       VALIDATE_STATE(s);
+       file->private_data = s;
+       MOD_INC_USE_COUNT;
+       return 0;
+}
+
+
+static int cs4281_release_mixdev(struct inode *inode, struct file *file)
+{
+       struct cs4281_state *s = (struct cs4281_state *)file->private_data;
+
+       VALIDATE_STATE(s);
+       MOD_DEC_USE_COUNT;
+       return 0;
+}
+
+
+static int cs4281_ioctl_mixdev(struct inode *inode, struct file *file,
+                              unsigned int cmd, unsigned long arg)
+{
+       return mixer_ioctl((struct cs4281_state *)file->private_data, cmd, arg);
+}
+
+
+// ******************************************************************************************
+//   Mixer file operations struct.
+// ******************************************************************************************
+static /*const*/ struct file_operations cs4281_mixer_fops = {
+       llseek:         cs4281_llseek,
+       ioctl:          cs4281_ioctl_mixdev,
+       open:           cs4281_open_mixdev,
+       release:        cs4281_release_mixdev,
+};
+
+// --------------------------------------------------------------------- 
+
+static int drain_dac(struct cs4281_state *s, int nonblock)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       unsigned long flags;
+       int count;
+       unsigned tmo;
+
+       if (s->dma_dac.mapped)
+               return 0;
+       current->state = TASK_INTERRUPTIBLE;
+       add_wait_queue(&s->dma_dac.wait, &wait);
+       for (;;) {
+               spin_lock_irqsave(&s->lock, flags);
+               count = s->dma_dac.count;
+               spin_unlock_irqrestore(&s->lock, flags);
+               if (count <= 0)
+                       break;
+               if (signal_pending(current))
+                       break;
+               if (nonblock) {
+                       remove_wait_queue(&s->dma_dac.wait, &wait);
+                       current->state = TASK_RUNNING;
+                       return -EBUSY;
+               }
+               tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->rate;
+               if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE))
+                       tmo >>= 1;
+               if (s->channels > 1)
+                       tmo >>= 1;
+               if (!schedule_timeout(tmo + 1))
+                       printk(KERN_DEBUG "cs4281: dma timed out??\n");
+       }
+       remove_wait_queue(&s->dma_dac.wait, &wait);
+       current->state = TASK_RUNNING;
+       if (signal_pending(current))
+               return -ERESTARTSYS;
+       return 0;
+}
+
+
+// --------------------------------------------------------------------- 
+
+static ssize_t cs4281_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+       struct cs4281_state *s = (struct cs4281_state *)file->private_data;
+       ssize_t ret;
+       unsigned long flags;
+       unsigned swptr;
+       int cnt;
+
+       CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2, 
+               printk(KERN_INFO "cs4281: cs4281_read()+ \n") );
+
+       VALIDATE_STATE(s);
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+       if (s->dma_adc.mapped)
+               return -ENXIO;
+       if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
+               return ret;
+       if (!access_ok(VERIFY_WRITE, buffer, count))
+               return -EFAULT;
+       ret = 0;
+       while (count > 0) {
+               spin_lock_irqsave(&s->lock, flags);
+               swptr = s->dma_adc.swptr;
+               cnt = s->dma_adc.dmasize-swptr;
+               if (s->dma_adc.count < cnt)
+                       cnt = s->dma_adc.count;
+               spin_unlock_irqrestore(&s->lock, flags);
+               if (cnt > count)
+                       cnt = count;
+               if (cnt <= 0) {
+                       start_adc(s);
+                        if (file->f_flags & O_NONBLOCK)
+                               return ret ? ret : -EAGAIN;
+                       interruptible_sleep_on(&s->dma_adc.wait);
+                       if (signal_pending(current))
+                               return ret ? ret : -ERESTARTSYS;
+                       continue;
+               }
+               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
+                       return ret ? ret : -EFAULT;
+               swptr = (swptr + cnt) % s->dma_adc.dmasize;
+               spin_lock_irqsave(&s->lock, flags);
+               s->dma_adc.swptr = swptr;
+               s->dma_adc.count -= cnt;
+               spin_unlock_irqrestore(&s->lock, flags);
+               count -= cnt;
+               buffer += cnt;
+               ret += cnt;
+               start_adc(s);
+       }
+       CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2, 
+               printk(KERN_INFO "cs4281: cs4281_read()- %d\n",ret) );
+       return ret;
+}
+
+
+static ssize_t cs4281_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+       struct cs4281_state *s = (struct cs4281_state *)file->private_data;
+       ssize_t ret;
+       unsigned long flags;
+       unsigned swptr;
+       int cnt;
+
+       CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2, 
+               printk(KERN_INFO "cs4281: cs4281_write()+ \n") );
+       VALIDATE_STATE(s);
+
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+       if (s->dma_dac.mapped)
+               return -ENXIO;
+       if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s)))
+               return ret;
+       if (!access_ok(VERIFY_READ, buffer, count))
+               return -EFAULT;
+       ret = 0;
+       while (count > 0) {
+               spin_lock_irqsave(&s->lock, flags);
+               if (s->dma_dac.count < 0) {
+                       s->dma_dac.count = 0;
+                       s->dma_dac.swptr = s->dma_dac.hwptr;
+               }
+               swptr = s->dma_dac.swptr;
+               cnt = s->dma_dac.dmasize-swptr;
+               if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
+                       cnt = s->dma_dac.dmasize - s->dma_dac.count;
+               spin_unlock_irqrestore(&s->lock, flags);
+               if (cnt > count)
+                       cnt = count;
+               if (cnt <= 0) {
+                       start_dac(s);
+                       if (file->f_flags & O_NONBLOCK)
+                               return ret ? ret : -EAGAIN;
+                       interruptible_sleep_on(&s->dma_dac.wait);
+                       if (signal_pending(current))
+                               return ret ? ret : -ERESTARTSYS;
+                       continue;
+               }
+               if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt))
+                       return ret ? ret : -EFAULT;
+               swptr = (swptr + cnt) % s->dma_dac.dmasize;
+               spin_lock_irqsave(&s->lock, flags);
+               s->dma_dac.swptr = swptr;
+               s->dma_dac.count += cnt;
+               s->dma_dac.endcleared = 0;
+               spin_unlock_irqrestore(&s->lock, flags);
+               count -= cnt;
+               buffer += cnt;
+               ret += cnt;
+               start_dac(s);
+       }
+       CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2, 
+               printk(KERN_INFO "cs4281: cs4281_write()- %d\n",ret) );
+       return ret;
+}
+
+
+static unsigned int cs4281_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct cs4281_state *s = (struct cs4281_state *)file->private_data;
+       unsigned long flags;
+       unsigned int mask = 0;
+
+       CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, 
+               printk(KERN_INFO "cs4281: cs4281_poll()+\n") );
+       VALIDATE_STATE(s);
+       if (file->f_mode & FMODE_WRITE)
+               poll_wait(file, &s->dma_dac.wait, wait);
+       if (file->f_mode & FMODE_READ)
+               poll_wait(file, &s->dma_adc.wait, wait);
+       spin_lock_irqsave(&s->lock, flags);
+       cs4281_update_ptr(s);
+       if (file->f_mode & FMODE_READ) {
+               if (s->dma_adc.mapped) {
+                       if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
+                               mask |= POLLIN | POLLRDNORM;
+               } else {
+                       if (s->dma_adc.count > 0)
+                               mask |= POLLIN | POLLRDNORM;
+               }
+       }
+       if (file->f_mode & FMODE_WRITE) {
+               if (s->dma_dac.mapped) {
+                       if (s->dma_dac.count >= (signed)s->dma_dac.fragsize)
+                               mask |= POLLOUT | POLLWRNORM;
+               } else {
+                       if ((signed)s->dma_dac.dmasize > s->dma_dac.count)
+                               mask |= POLLOUT | POLLWRNORM;
+               }
+       }
+       spin_unlock_irqrestore(&s->lock, flags);
+       CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, 
+               printk(KERN_INFO "cs4281: cs4281_poll()- 0x%.8x\n",mask) );
+       return mask;
+}
+
+
+static int cs4281_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct cs4281_state *s = (struct cs4281_state *)file->private_data;
+       struct dmabuf *db;
+       int ret;
+       unsigned long size;
+
+       CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4, 
+               printk(KERN_INFO "cs4281: cs4281_mmap()+\n") );
+
+       VALIDATE_STATE(s);
+       if (vma->vm_flags & VM_WRITE) {
+               if ((ret = prog_dmabuf_dac(s)) != 0)
+                       return ret;
+               db = &s->dma_dac;
+       } else if (vma->vm_flags & VM_READ) {
+               if ((ret = prog_dmabuf_adc(s)) != 0)
+                       return ret;
+               db = &s->dma_adc;
+       } else
+               return -EINVAL;
+       if (vma->vm_pgoff != 0)
+               return -EINVAL;
+       size = vma->vm_end - vma->vm_start;
+       if (size > (PAGE_SIZE << db->buforder))
+               return -EINVAL;
+       if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
+               return -EAGAIN;
+       db->mapped = 1;
+
+       CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4, 
+               printk(KERN_INFO "cs4281: cs4281_mmap()- 0 size=%d\n",
+                       (unsigned)size) );
+
+       return 0;
+}
+
+
+static int cs4281_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct cs4281_state *s = (struct cs4281_state *)file->private_data;
+       unsigned long flags;
+       audio_buf_info abinfo;
+       count_info cinfo;
+       int val, mapped, ret;
+  
+       CS_DBGOUT(CS_FUNCTION, 4, 
+               printk(KERN_INFO "cs4281: cs4281_ioctl(): file=0x%.8x cmd=0x%.8x\n",
+                       (unsigned)file,cmd) );
+       VALIDATE_STATE(s);
+       mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) ||
+               ((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
+       switch (cmd) {
+       case OSS_GETVERSION:
+               CS_DBGOUT(CS_FUNCTION | CS_PARMS, 4, printk(KERN_INFO 
+                       "cs4281: cs4281_ioctl(): SOUND_VERSION=0x%.8x\n", SOUND_VERSION) );
+               return put_user(SOUND_VERSION, (int *)arg);
+
+       case SNDCTL_DSP_SYNC:
+               if (file->f_mode & FMODE_WRITE)
+                       return drain_dac(s, 0/*file->f_flags & O_NONBLOCK*/);
+               return 0;
+
+       case SNDCTL_DSP_SETDUPLEX:
+               return 0;
+
+       case SNDCTL_DSP_GETCAPS:
+               return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg);
+
+       case SNDCTL_DSP_RESET:
+               if (file->f_mode & FMODE_WRITE) {
+                       stop_dac(s);
+                       synchronize_irq();
+                       s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count = 
+                               s->dma_dac.total_bytes = s->dma_dac.blocks = 0;
+               }
+               if (file->f_mode & FMODE_READ) {
+                       stop_adc(s);
+                       synchronize_irq();
+                       s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = 
+                               s->dma_adc.total_bytes = s->dma_adc.blocks = 0;
+               }
+               prog_codec(s);
+               return 0;
+
+       case SNDCTL_DSP_SPEED:
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               if (val >= 0) {
+                       stop_adc(s);
+                       stop_dac(s);
+                       s->dma_adc.ready = s->dma_dac.ready = 0;
+                       // program sampling rates 
+                       if (val > 48000)
+                               val = 48000;
+                       if (val < 6300)
+                               val = 6300;
+                       s->rate = val;
+                       prog_codec(s);
+               }
+               return put_user(s->rate, (int *)arg);
+
+       case SNDCTL_DSP_STEREO:
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               stop_adc(s);
+               stop_dac(s);
+               s->dma_adc.ready = s->dma_dac.ready = 0;
+               // program channels 
+               s->channels = val ? 2 : 1;
+               prog_codec(s);
+               return 0;
+
+       case SNDCTL_DSP_CHANNELS:
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               if (val != 0) {
+                       stop_adc(s);
+                       stop_dac(s);
+                       s->dma_adc.ready = s->dma_dac.ready = 0;
+                       // program channels 
+                       s->channels = val ? 2 : 1;
+                       prog_codec(s);
+               }
+               return put_user(s->channels, (int *)arg);
+
+       case SNDCTL_DSP_GETFMTS: // Returns a mask 
+               return put_user(AFMT_S16_LE|AFMT_U16_LE|AFMT_S8|AFMT_U8, (int *)arg);
+
+       case SNDCTL_DSP_SETFMT: // Selects ONE fmt
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               if (val != AFMT_QUERY) {
+                       stop_adc(s);
+                       stop_dac(s);
+                       s->dma_adc.ready = s->dma_dac.ready = 0;
+                       // program format 
+                       if (val != AFMT_S16_LE && val != AFMT_U16_LE &&
+                           val != AFMT_S8 && val != AFMT_U8)
+                               val = AFMT_U8;
+                       s->fmt = val;
+                       prog_codec(s);
+               }
+               return put_user(s->fmt, (int *)arg);
+
+       case SNDCTL_DSP_POST:
+               return 0;
+
+       case SNDCTL_DSP_GETTRIGGER:
+               val = 0;
+               if (file->f_mode & s->ena & FMODE_READ)
+                       val |= PCM_ENABLE_INPUT;
+               if (file->f_mode & s->ena & FMODE_WRITE)
+                       val |= PCM_ENABLE_OUTPUT;
+               return put_user(val, (int *)arg);
+
+       case SNDCTL_DSP_SETTRIGGER:
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               if (file->f_mode & FMODE_READ) {
+                       if (val & PCM_ENABLE_INPUT) {
+                               if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
+                                       return ret;
+                               start_adc(s);
+                       } else
+                               stop_adc(s);
+               }
+               if (file->f_mode & FMODE_WRITE) {
+                       if (val & PCM_ENABLE_OUTPUT) {
+                               if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s)))
+                                       return ret;
+                               start_dac(s);
+                       } else
+                               stop_dac(s);
+               }
+               return 0;
+
+       case SNDCTL_DSP_GETOSPACE:
+               if (!(file->f_mode & FMODE_WRITE))
+                       return -EINVAL;
+               if (!(s->ena & FMODE_WRITE) && (val = prog_dmabuf_dac(s)) != 0)
+                       return val;
+               spin_lock_irqsave(&s->lock, flags);
+               cs4281_update_ptr(s);
+               abinfo.fragsize = s->dma_dac.fragsize;
+               abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count;
+               abinfo.fragstotal = s->dma_dac.numfrag;
+               abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;  
+               spin_unlock_irqrestore(&s->lock, flags);
+               return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+
+       case SNDCTL_DSP_GETISPACE:
+               if (!(file->f_mode & FMODE_READ))
+                       return -EINVAL;
+               if (!(s->ena & FMODE_READ) && (val = prog_dmabuf_adc(s)) != 0)
+                       return val;
+               spin_lock_irqsave(&s->lock, flags);
+               cs4281_update_ptr(s);
+               abinfo.fragsize = s->dma_adc.fragsize;
+               abinfo.bytes = s->dma_adc.count;
+               abinfo.fragstotal = s->dma_adc.numfrag;
+               abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;
+               spin_unlock_irqrestore(&s->lock, flags);
+               return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+
+       case SNDCTL_DSP_NONBLOCK:
+               file->f_flags |= O_NONBLOCK;
+               return 0;
+
+       case SNDCTL_DSP_GETODELAY:
+               if (!(file->f_mode & FMODE_WRITE))
+                       return -EINVAL;
+               spin_lock_irqsave(&s->lock, flags);
+               cs4281_update_ptr(s);
+               val = s->dma_dac.count;
+               spin_unlock_irqrestore(&s->lock, flags);
+               return put_user(val, (int *)arg);
+
+       case SNDCTL_DSP_GETIPTR:
+               if (!(file->f_mode & FMODE_READ))
+                       return -EINVAL;
+               spin_lock_irqsave(&s->lock, flags);
+               cs4281_update_ptr(s);
+               cinfo.bytes = s->dma_adc.total_bytes;
+               cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
+               cinfo.ptr = s->dma_adc.hwptr;
+               if (s->dma_adc.mapped)
+                       s->dma_adc.count &= s->dma_adc.fragsize-1;
+               spin_unlock_irqrestore(&s->lock, flags);
+               return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+
+       case SNDCTL_DSP_GETOPTR:
+               if (!(file->f_mode & FMODE_WRITE))
+                       return -EINVAL;
+               spin_lock_irqsave(&s->lock, flags);
+               cs4281_update_ptr(s);
+               cinfo.bytes = s->dma_dac.total_bytes;
+               if (s->dma_dac.mapped)
+               {
+                       cinfo.blocks = (cinfo.bytes >> s->dma_dac.fragshift) 
+                                               - s->dma_adc.blocks;
+                       s->dma_dac.blocks = cinfo.bytes >> s->dma_dac.fragshift;
+               }
+               else
+               {
+                       cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift;
+               }
+               cinfo.ptr = s->dma_dac.hwptr;
+               if (s->dma_dac.mapped)
+                       s->dma_dac.count &= s->dma_dac.fragsize-1;
+               spin_unlock_irqrestore(&s->lock, flags);
+               return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+
+       case SNDCTL_DSP_GETBLKSIZE:
+               if (file->f_mode & FMODE_WRITE) {
+                       if ((val = prog_dmabuf_dac(s)))
+                               return val;
+                       return put_user(s->dma_dac.fragsize, (int *)arg);
+               }
+               if ((val = prog_dmabuf_adc(s)))
+                       return val;
+               return put_user(s->dma_adc.fragsize, (int *)arg);
+
+       case SNDCTL_DSP_SETFRAGMENT:
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               return 0;              // Say OK, but do nothing.
+
+       case SNDCTL_DSP_SUBDIVIDE:
+               if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
+                   (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
+                       return -EINVAL;
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               if (val != 1 && val != 2 && val != 4)
+                       return -EINVAL;
+               if (file->f_mode & FMODE_READ)
+                       s->dma_adc.subdivision = val;
+               if (file->f_mode & FMODE_WRITE)
+                       s->dma_dac.subdivision = val;
+               return 0;
+
+       case SOUND_PCM_READ_RATE:
+               return put_user(s->rate, (int *)arg);
+
+       case SOUND_PCM_READ_CHANNELS:
+               return put_user(s->channels, (int *)arg);
+
+       case SOUND_PCM_READ_BITS:
+               return put_user((s->fmt & (AFMT_S8|AFMT_U8)) ? 8 : 16, (int *)arg);
+
+       case SOUND_PCM_WRITE_FILTER:
+       case SNDCTL_DSP_SETSYNCRO:
+       case SOUND_PCM_READ_FILTER:
+               return -EINVAL;
+
+       }
+       return mixer_ioctl(s, cmd, arg);
+}
+
+
+static int cs4281_release(struct inode *inode, struct file *file)
+{
+       struct cs4281_state *s = (struct cs4281_state *)file->private_data;
+
+       CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, 
+               printk(KERN_INFO "cs4281: cs4281_release(): inode=0x%.8x file=0x%.8x\n",
+                       (unsigned)inode,(unsigned)file) );
+
+       VALIDATE_STATE(s);
+
+       if (file->f_mode & FMODE_WRITE)
+               drain_dac(s, file->f_flags & O_NONBLOCK);
+       down(&s->open_sem);
+       if (file->f_mode & FMODE_WRITE) {
+               stop_dac(s);
+               dealloc_dmabuf(s,&s->dma_dac);
+       }
+       if (file->f_mode & FMODE_READ) {
+               stop_adc(s);
+               dealloc_dmabuf(s,&s->dma_adc);
+       }
+       s->open_mode &= ~(FMODE_READ | FMODE_WRITE);
+       up(&s->open_sem);
+       wake_up(&s->open_wait);
+       MOD_DEC_USE_COUNT;
+       return 0;
+}
+
+static int cs4281_open(struct inode *inode, struct file *file)
+{
+       int minor = MINOR(inode->i_rdev);
+       struct cs4281_state *s = devs;
+
+       CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, 
+               printk(KERN_INFO "cs4281: cs4281_open(): inode=0x%.8x file=0x%.8x\n",
+                       (unsigned)inode,(unsigned)file) );
+       while (s && ((s->dev_audio ^ minor) & ~0xf))
+               s = s->next;
+       if (!s)
+       {
+               CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO 
+                       "cs4281: cs4281_open(): ERROR unable to find audio state struct\n") );
+               return -ENODEV;
+       }
+       VALIDATE_STATE(s);
+       file->private_data = s;
+       
+               // wait for device to become free 
+       down(&s->open_sem);
+       while (s->open_mode & (FMODE_READ | FMODE_WRITE)) {
+               if (file->f_flags & O_NONBLOCK) {
+                       up(&s->open_sem);
+                       return -EBUSY;
+               }
+               up(&s->open_sem);
+               interruptible_sleep_on(&s->open_wait);
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
+               down(&s->open_sem);
+       }
+       s->fmt = AFMT_U8;
+       s->channels = 1;
+       s->rate = 8000;
+       s->clkdiv = 96 | 0x80;
+       s->ena = s->endofbuffer = 0;
+       s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0;
+       s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0;
+       s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
+       up(&s->open_sem);
+       MOD_INC_USE_COUNT;
+
+       if (prog_dmabuf_dac(s) || prog_dmabuf_adc(s)) {
+               
+            printk(KERN_ERR "cs4281: Program dmabufs failed.\n");
+            cs4281_release(inode, file);
+               
+            return -ENOMEM;
+       }
+       prog_codec(s);
+       CS_DBGOUT(CS_INIT | CS_FUNCTION | CS_OPEN, 2, 
+               printk(KERN_INFO "cs4281: cs4281_open()- 0\n") );
+       return 0;
+}
+
+
+// ******************************************************************************************
+//   Wave (audio) file operations struct.
+// ******************************************************************************************
+static /*const*/ struct file_operations cs4281_audio_fops = {
+       llseek:         cs4281_llseek,
+       read:           cs4281_read,
+       write:          cs4281_write,
+       poll:           cs4281_poll,
+       ioctl:          cs4281_ioctl,
+       mmap:           cs4281_mmap,
+       open:           cs4281_open,
+       release:        cs4281_release,
+};
+
+// --------------------------------------------------------------------- 
+
+// hold spinlock for the following! 
+static void cs4281_handle_midi(struct cs4281_state *s)
+{
+       unsigned char ch;
+       int wake;
+       unsigned temp1;
+
+       wake = 0;
+       while (!(readl(s->pBA0+ BA0_MIDSR) & 0x80)) {
+               ch = readl(s->pBA0+BA0_MIDRP);
+               if (s->midi.icnt < MIDIINBUF) {
+                       s->midi.ibuf[s->midi.iwr] = ch;
+                       s->midi.iwr = (s->midi.iwr + 1) % MIDIINBUF;
+                       s->midi.icnt++;
+               }
+               wake = 1;
+       }
+       if (wake)
+               wake_up(&s->midi.iwait);
+       wake = 0;
+       while (!(readl(s->pBA0+ BA0_MIDSR) & 0x40) && s->midi.ocnt > 0) {
+               temp1 = ( s->midi.obuf[s->midi.ord] ) & 0x000000ff;
+               writel(temp1, s->pBA0+BA0_MIDWP);
+               s->midi.ord = (s->midi.ord + 1) % MIDIOUTBUF;
+               s->midi.ocnt--;
+               if (s->midi.ocnt < MIDIOUTBUF-16)
+                       wake = 1;
+       }
+       if (wake)
+               wake_up(&s->midi.owait);
+}
+
+
+
+static void cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct cs4281_state *s = (struct cs4281_state *)dev_id;
+       unsigned int temp1;
+
+       // fastpath out, to ease interrupt sharing 
+       temp1 = readl(s->pBA0+BA0_HISR);                          // Get Int Status reg.
+
+       CS_DBGOUT(CS_INTERRUPT, 6, printk(KERN_INFO 
+               "cs4281: cs4281_interrupt() BA0_HISR=0x%.8x\n",temp1) );
+
+       if (!(temp1 & (HISR_DMA0 | HISR_DMA1 | HISR_MIDI))) {     // If not DMA or MIDI int,
+               writel(HICR_IEV| HICR_CHGM, s->pBA0+BA0_HICR);    //  reenable interrupts
+               CS_DBGOUT(CS_INTERRUPT, 4, printk(KERN_INFO 
+                       "cs4281: cs4281_interrupt(): returning not cs4281 interrupt.\n") );
+               return;                                           //   and return.
+       }
+       
+       if(temp1 & HISR_DMA0)                      // If play interrupt,
+               readl(s->pBA0+BA0_HDSR0);              //   clear the source.
+
+       if(temp1 & HISR_DMA1)                      // Same for play.
+               readl(s->pBA0+BA0_HDSR1);        
+       writel(HICR_IEV| HICR_CHGM, s->pBA0+BA0_HICR);  // Local EOI
+       
+       spin_lock(&s->lock);
+       //
+       // ok, at this point we assume that the fifos have been filled
+       // with silence and so we now turn off the DMA engine.
+       // if FMODE_WRITE is set that means that some thread
+       // attempted to start_dac, which probably means that an open
+       // occurred, so do not stop the dac in this case.
+       //
+       if(s->endofbuffer && !(s->ena & FMODE_WRITE))
+       {
+               CS_DBGOUT(CS_INTERRUPT, 2, printk(KERN_INFO 
+                       "cs4281: cs4281_interrupt() stopping play DMA\n") );
+               writel(temp1|DCRn_MSK, s->pBA0+BA0_DCR0);    // Stop Play DMA
+               s->endofbuffer = 0;
+       }
+       else
+       {
+               cs4281_update_ptr(s);
+       }
+       cs4281_handle_midi(s);
+       spin_unlock(&s->lock);
+}
+
+// **************************************************************************
+
+static void cs4281_midi_timer(unsigned long data)
+{
+       struct cs4281_state *s = (struct cs4281_state *)data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&s->lock, flags);
+       cs4281_handle_midi(s);
+       spin_unlock_irqrestore(&s->lock, flags);
+       s->midi.timer.expires = jiffies+1;
+       add_timer(&s->midi.timer);
+}
+
+
+// --------------------------------------------------------------------- 
+
+static ssize_t cs4281_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+       struct cs4281_state *s = (struct cs4281_state *)file->private_data;
+       ssize_t ret;
+       unsigned long flags;
+       unsigned ptr;
+       int cnt;
+
+       VALIDATE_STATE(s);
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+       if (!access_ok(VERIFY_WRITE, buffer, count))
+               return -EFAULT;
+       ret = 0;
+       while (count > 0) {
+               spin_lock_irqsave(&s->lock, flags);
+               ptr = s->midi.ird;
+               cnt = MIDIINBUF - ptr;
+               if (s->midi.icnt < cnt)
+                       cnt = s->midi.icnt;
+               spin_unlock_irqrestore(&s->lock, flags);
+               if (cnt > count)
+                       cnt = count;
+               if (cnt <= 0) {
+                       if (file->f_flags & O_NONBLOCK)
+                               return ret ? ret : -EAGAIN;
+                       interruptible_sleep_on(&s->midi.iwait);
+                       if (signal_pending(current))
+                               return ret ? ret : -ERESTARTSYS;
+                       continue;
+               }
+               if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt))
+                       return ret ? ret : -EFAULT;
+               ptr = (ptr + cnt) % MIDIINBUF;
+               spin_lock_irqsave(&s->lock, flags);
+               s->midi.ird = ptr;
+               s->midi.icnt -= cnt;
+               spin_unlock_irqrestore(&s->lock, flags);
+               count -= cnt;
+               buffer += cnt;
+               ret += cnt;
+       }
+       return ret;
+}
+
+
+static ssize_t cs4281_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+       struct cs4281_state *s = (struct cs4281_state *)file->private_data;
+       ssize_t ret;
+       unsigned long flags;
+       unsigned ptr;
+       int cnt;
+
+       VALIDATE_STATE(s);
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+       if (!access_ok(VERIFY_READ, buffer, count))
+               return -EFAULT;
+       ret = 0;
+       while (count > 0) {
+               spin_lock_irqsave(&s->lock, flags);
+               ptr = s->midi.owr;
+               cnt = MIDIOUTBUF - ptr;
+               if (s->midi.ocnt + cnt > MIDIOUTBUF)
+                       cnt = MIDIOUTBUF - s->midi.ocnt;
+               if (cnt <= 0)
+                       cs4281_handle_midi(s);
+               spin_unlock_irqrestore(&s->lock, flags);
+               if (cnt > count)
+                       cnt = count;
+               if (cnt <= 0) {
+                       if (file->f_flags & O_NONBLOCK)
+                               return ret ? ret : -EAGAIN;
+                       interruptible_sleep_on(&s->midi.owait);
+                       if (signal_pending(current))
+                               return ret ? ret : -ERESTARTSYS;
+                       continue;
+               }
+               if (copy_from_user(s->midi.obuf + ptr, buffer, cnt))
+                       return ret ? ret : -EFAULT;
+               ptr = (ptr + cnt) % MIDIOUTBUF;
+               spin_lock_irqsave(&s->lock, flags);
+               s->midi.owr = ptr;
+               s->midi.ocnt += cnt;
+               spin_unlock_irqrestore(&s->lock, flags);
+               count -= cnt;
+               buffer += cnt;
+               ret += cnt;
+               spin_lock_irqsave(&s->lock, flags);
+               cs4281_handle_midi(s);
+               spin_unlock_irqrestore(&s->lock, flags);
+       }
+       return ret;
+}
+
+
+static unsigned int cs4281_midi_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct cs4281_state *s = (struct cs4281_state *)file->private_data;
+       unsigned long flags;
+       unsigned int mask = 0;
+
+       VALIDATE_STATE(s);
+       if (file->f_flags & FMODE_WRITE)
+               poll_wait(file, &s->midi.owait, wait);
+       if (file->f_flags & FMODE_READ)
+               poll_wait(file, &s->midi.iwait, wait);
+       spin_lock_irqsave(&s->lock, flags);
+       if (file->f_flags & FMODE_READ) {
+               if (s->midi.icnt > 0)
+                       mask |= POLLIN | POLLRDNORM;
+       }
+       if (file->f_flags & FMODE_WRITE) {
+               if (s->midi.ocnt < MIDIOUTBUF)
+                       mask |= POLLOUT | POLLWRNORM;
+       }
+       spin_unlock_irqrestore(&s->lock, flags);
+       return mask;
+}
+
+
+static int cs4281_midi_open(struct inode *inode, struct file *file)
+{
+       int minor = MINOR(inode->i_rdev);
+       struct cs4281_state *s = devs;
+       unsigned long flags,temp1;
+       while (s && s->dev_midi != minor)
+               s = s->next;
+       if (!s)
+               return -ENODEV;
+       VALIDATE_STATE(s);
+       file->private_data = s;
+       // wait for device to become free 
+       down(&s->open_sem);
+       while (s->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) {
+               if (file->f_flags & O_NONBLOCK) {
+                       up(&s->open_sem);
+                       return -EBUSY;
+               }
+               up(&s->open_sem);
+               interruptible_sleep_on(&s->open_wait);
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
+               down(&s->open_sem);
+       }
+       spin_lock_irqsave(&s->lock, flags);
+       if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
+               s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
+               s->midi.ord = s->midi.owr = s->midi.ocnt = 0;
+               writel(1, s->pBA0+BA0_MIDCR);   // Reset the interface.
+               writel(0, s->pBA0+BA0_MIDCR);   // Return to normal mode.
+               s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
+               writel(0x0000000f, s->pBA0+BA0_MIDCR);                // Enable transmit, record, ints.
+               temp1 = readl(s->pBA0+BA0_HIMR);
+               writel(temp1 & 0xffbfffff, s->pBA0+BA0_HIMR);         // Enable midi int. recognition.
+               writel(HICR_IEV | HICR_CHGM, s->pBA0+BA0_HICR);       // Enable interrupts
+               init_timer(&s->midi.timer);
+               s->midi.timer.expires = jiffies+1;
+               s->midi.timer.data = (unsigned long)s;
+               s->midi.timer.function = cs4281_midi_timer;
+               add_timer(&s->midi.timer);
+       }
+       if (file->f_mode & FMODE_READ) {
+               s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
+       }
+       if (file->f_mode & FMODE_WRITE) {
+               s->midi.ord = s->midi.owr = s->midi.ocnt = 0;
+       }
+       spin_unlock_irqrestore(&s->lock, flags);
+       s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE);
+       up(&s->open_sem);
+       MOD_INC_USE_COUNT;
+       return 0;
+}
+
+
+static int cs4281_midi_release(struct inode *inode, struct file *file)
+{
+       struct cs4281_state *s = (struct cs4281_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
+       unsigned long flags;
+       unsigned count, tmo;
+
+       VALIDATE_STATE(s);
+
+       if (file->f_mode & FMODE_WRITE) {
+               current->state = TASK_INTERRUPTIBLE;
+               add_wait_queue(&s->midi.owait, &wait);
+               for (;;) {
+                       spin_lock_irqsave(&s->lock, flags);
+                       count = s->midi.ocnt;
+                       spin_unlock_irqrestore(&s->lock, flags);
+                       if (count <= 0)
+                               break;
+                       if (signal_pending(current))
+                               break;
+                       if (file->f_flags & O_NONBLOCK) {
+                               remove_wait_queue(&s->midi.owait, &wait);
+                               current->state = TASK_RUNNING;
+                               return -EBUSY;
+                       }
+                       tmo = (count * HZ) / 3100;
+                       if (!schedule_timeout(tmo ? : 1) && tmo)
+                               printk(KERN_DEBUG "cs4281: midi timed out??\n");
+               }
+               remove_wait_queue(&s->midi.owait, &wait);
+               current->state = TASK_RUNNING;
+       }
+       down(&s->open_sem);
+       s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE);
+       spin_lock_irqsave(&s->lock, flags);
+       if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
+               writel(0, s->pBA0+BA0_MIDCR);    // Disable Midi interrupts.  
+               del_timer(&s->midi.timer);
+       }
+       spin_unlock_irqrestore(&s->lock, flags);
+       up(&s->open_sem);
+       wake_up(&s->open_wait);
+       MOD_DEC_USE_COUNT;
+       return 0;
+}
+
+// ******************************************************************************************
+//   Midi file operations struct.
+// ******************************************************************************************
+static /*const*/ struct file_operations cs4281_midi_fops = {
+       llseek:         cs4281_llseek,
+       read:           cs4281_midi_read,
+       write:          cs4281_midi_write,
+       poll:           cs4281_midi_poll,
+       open:           cs4281_midi_open,
+       release:        cs4281_midi_release,
+};
+
+
+// --------------------------------------------------------------------- 
+
+// maximum number of devices 
+#define NR_DEVICE 8          // Only eight devices supported currently.
+
+// --------------------------------------------------------------------- 
+
+static struct initvol {
+       int mixch;
+       int vol;
+} initvol[] __initdata = {
+       { SOUND_MIXER_WRITE_VOLUME, 0x4040 },
+       { SOUND_MIXER_WRITE_PCM, 0x4040 },
+       { SOUND_MIXER_WRITE_SYNTH, 0x4040 },
+       { SOUND_MIXER_WRITE_CD, 0x4040 },
+       { SOUND_MIXER_WRITE_LINE, 0x4040 },
+       { SOUND_MIXER_WRITE_LINE1, 0x4040 },
+       { SOUND_MIXER_WRITE_RECLEV, 0x0000 },
+       { SOUND_MIXER_WRITE_SPEAKER, 0x4040 },
+       { SOUND_MIXER_WRITE_MIC, 0x0000 }
+};
+
+
+static int __devinit cs4281_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
+{
+       struct cs4281_state *s;
+       dma_addr_t dma_mask;
+       mm_segment_t fs;
+       int i, val, index = 0;
+       unsigned int temp1, temp2;
+       CS_DBGOUT(CS_INIT, 2, printk(KERN_INFO "cs4281: probe()+\n") );
+
+       if (!RSRCISMEMORYREGION(pcidev, 0) ||
+           !RSRCISMEMORYREGION(pcidev, 1))
+       {
+               CS_DBGOUT(CS_ERROR, 1,
+                       printk(KERN_ERR "cs4281: probe()- Memory region not assigned\n") );
+               return -1;
+       }
+       if (pcidev->irq == 0) {
+               CS_DBGOUT(CS_ERROR, 1,
+                       printk(KERN_ERR "cs4281: probe() IRQ not assigned\n") );
+               return -1;
+       } 
+       if (!pci_dma_supported(pcidev, 0xffffffff)) {
+               CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR 
+                   "cs4281: probe() architecture does not support 32bit PCI busmaster DMA\n") );
+               return -1;
+       } 
+       dma_mask = 0xffffffff; /* this enables playback and recording */
+       if (!(s = kmalloc(sizeof(struct cs4281_state), GFP_KERNEL))) {
+               CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR 
+                       "cs4281: probe() no memory for state struct.\n") );
+               return -1;
+       }
+       memset(s, 0, sizeof(struct cs4281_state));
+       init_waitqueue_head(&s->dma_adc.wait);
+       init_waitqueue_head(&s->dma_dac.wait);
+       init_waitqueue_head(&s->open_wait);
+       init_waitqueue_head(&s->midi.iwait);
+       init_waitqueue_head(&s->midi.owait);
+       init_MUTEX(&s->open_sem);
+       spin_lock_init(&s->lock);
+       s->pBA0phys = RSRCADDRESS(pcidev, 0);
+       s->pBA1phys = RSRCADDRESS(pcidev, 1);
+       s->pBA0 = ioremap_nocache(s->pBA0phys, 4096);   // Convert phys 
+       s->pBA1 = ioremap_nocache(s->pBA1phys, 65536);  //  to linear. 
+       temp1 = readl(s->pBA0+ BA0_PCICFG00);
+       temp2 = readl(s->pBA0+ BA0_PCICFG04);
+
+       CS_DBGOUT(CS_INIT, 2, 
+           printk(KERN_INFO "cs4281: probe() BA0=0x%.8x BA1=0x%.8x pBA0=0x%.8x pBA1=0x%.8x \n",
+               (unsigned)temp1,(unsigned)temp2,(unsigned)s->pBA0,(unsigned)s->pBA1) );
+
+       CS_DBGOUT(CS_INIT, 2, 
+           printk(KERN_INFO "cs4281: probe() pBA0phys=0x%.8x pBA1phys=0x%.8x\n",
+               (unsigned)s->pBA0phys,(unsigned)s->pBA1phys) );
+
+       temp1 = cs4281_hw_init(s);
+       if(temp1){
+               CS_DBGOUT(CS_ERROR | CS_INIT, 1, 
+                   printk(KERN_ERR "cs4281: cs4281_hw_init() failed. Skipping part.\n") );
+               return -1;
+       }       
+       s->magic = CS4281_MAGIC;
+       s->pcidev = pcidev;
+       s->irq = pcidev->irq;
+       if (pci_enable_device(pcidev))
+       {
+               CS_DBGOUT(CS_INIT | CS_ERROR, 1, 
+                       printk(KERN_ERR "cs4281: pci_enable_device() failed\n") );
+               goto err_irq;
+       }
+       if(request_irq(s->irq, cs4281_interrupt, SA_SHIRQ, "Crystal CS4281", s)){
+               CS_DBGOUT(CS_INIT | CS_ERROR, 1, 
+                       printk(KERN_ERR "cs4281: irq %u in use\n", s->irq) );
+               goto err_irq;
+       }
+       if ((s->dev_audio = register_sound_dsp(&cs4281_audio_fops, -1)) < 0)
+       {
+               CS_DBGOUT(CS_INIT | CS_ERROR, 1, 
+                       printk(KERN_ERR "cs4281: probe() register_sound_dsp() failed.\n") );
+               goto err_dev1;
+       }
+       if ((s->dev_mixer = register_sound_mixer(&cs4281_mixer_fops, -1)) < 0)
+       {
+               CS_DBGOUT(CS_INIT | CS_ERROR, 1, 
+                       printk(KERN_ERR "cs4281: probe() register_sound_mixer() failed.\n") );
+               goto err_dev2;
+       }
+       if ((s->dev_midi = register_sound_midi(&cs4281_midi_fops, -1)) < 0)
+       {
+               CS_DBGOUT(CS_INIT | CS_ERROR, 1, 
+                       printk(KERN_ERR "cs4281: probe() register_sound_midi() failed.\n") );
+               goto err_dev3;
+       }
+                           
+       pci_set_master(pcidev);           // enable bus mastering 
+
+       fs = get_fs();
+       set_fs(KERNEL_DS);
+       val = SOUND_MASK_LINE;
+       mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
+       for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
+               val = initvol[i].vol;
+               mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
+       }
+       val = 1; // enable mic preamp 
+       mixer_ioctl(s, SOUND_MIXER_PRIVATE1, (unsigned long)&val);
+       set_fs(fs);
+       
+       // queue it for later freeing 
+       s->next = devs;
+       pcidev->driver_data = s;
+       pcidev->dma_mask = dma_mask;
+       devs = s;
+       index++;
+       return 0;
+
+err_dev3:
+       unregister_sound_mixer(s->dev_mixer);
+err_dev2:
+       unregister_sound_dsp(s->dev_audio);
+err_dev1:
+       free_irq(s->irq, s);
+err_irq:
+       kfree(s);
+
+       if (!devs)
+       {
+               CS_DBGOUT(CS_INIT | CS_ERROR, 1,
+                       printk(KERN_INFO "cs4281: probe()- no device allocated\n") );
+               return -ENODEV;
+       }
+       CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
+               printk(KERN_INFO "cs4281: probe()- device allocated successfully\n") );
+       return 0;
+} // probe_cs4281
+
+
+// --------------------------------------------------------------------- 
+
+static void __devinit cs4281_remove(struct pci_dev *dev)
+{
+       struct cs4281_state *s = (struct cs4281_state *)dev->driver_data;
+       // stop DMA controller 
+       synchronize_irq();
+       free_irq(s->irq, s);
+       unregister_sound_dsp(s->dev_audio);
+       unregister_sound_mixer(s->dev_mixer);
+       unregister_sound_midi(s->dev_midi);
+       kfree(s);
+       dev->driver_data = NULL;        
+       CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, 
+               printk(KERN_INFO "cs4281: cs4281_remove(): remove successful\n") );
+}
+
+static struct pci_device_id id_table[] __devinitdata = {
+       { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CRYSTAL_CS4281, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
+       { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, id_table);
+
+static struct pci_driver cs4281_driver = {
+       name: "cs4281",
+       id_table: id_table,
+       probe: cs4281_probe,
+       remove: cs4281_remove
+};
+
+static int __init init_cs4281(void)
+{
+       
+       CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO "cs4281: init_cs4281()+ \n") );
+       if (!pci_present())   /* No PCI bus in this machine! */
+       {
+               CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, 
+                       printk(KERN_INFO "cs4281: init_cs4281()- no pci bus found\n") );
+               return -ENODEV;
+       }
+       printk(KERN_INFO "cs4281: version v%d.%02d.%d time " __TIME__ " " __DATE__ "\n",
+               CS4281_MAJOR_VERSION, CS4281_MINOR_VERSION, CS4281_ARCH);
+       if (!pci_register_driver(&cs4281_driver)) {
+               pci_unregister_driver(&cs4281_driver);
+               CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, 
+                       printk(KERN_INFO "cs4281: init_cs4281()- unable to register pci device \n") );
+               return -ENODEV;
+       }
+       CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO "cs4281: init_cs4281()- 0\n") );
+       return 0;
+}
+
+
+// --------------------------------------------------------------------- 
+
+
+MODULE_AUTHOR("gw boynton, wesb@crystal.cirrus.com");
+MODULE_DESCRIPTION("Cirrus Logic CS4281 Driver");
+
+static void __exit cleanup_cs4281(void)
+{
+       pci_unregister_driver(&cs4281_driver);
+       CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, 
+               printk(KERN_INFO "cs4281: cleanup_cs4281() finished\n") );
+}
+
+// --------------------------------------------------------------------- 
+
+module_init(init_cs4281);
+module_exit(cleanup_cs4281);
+
diff --git a/drivers/sound/cs4281_hwdefs.h b/drivers/sound/cs4281_hwdefs.h
new file mode 100644 (file)
index 0000000..efcdc76
--- /dev/null
@@ -0,0 +1,1234 @@
+//****************************************************************************
+//
+// HWDEFS.H - Definitions of the registers and data structures used by the
+//            CS4281
+//
+// Copyright (c) 1999 Crystal Semiconductor Corp.
+//
+//****************************************************************************
+
+#ifndef _H_HWDEFS
+#define _H_HWDEFS
+
+//****************************************************************************
+//
+// The following define the offsets of the registers located in the PCI
+// configuration space of the CS4281 part.
+//
+//****************************************************************************
+#define PCICONFIG_DEVID_VENID                   0x00000000L
+#define PCICONFIG_STATUS_COMMAND                0x00000004L
+#define PCICONFIG_CLASS_REVISION                0x00000008L
+#define PCICONFIG_LATENCY_TIMER                 0x0000000CL
+#define PCICONFIG_BA0                           0x00000010L
+#define PCICONFIG_BA1                           0x00000014L
+#define PCICONFIG_SUBSYSID_SUBSYSVENID          0x0000002CL
+#define PCICONFIG_INTERRUPT                     0x0000003CL
+
+//****************************************************************************
+//
+// The following define the offsets of the registers accessed via base address
+// register zero on the CS4281 part.
+//
+//****************************************************************************
+#define BA0_HISR                                0x00000000L
+#define BA0_HICR                                0x00000008L
+#define BA0_HIMR                                0x0000000CL
+#define BA0_IIER                                0x00000010L
+#define BA0_HDSR0                               0x000000F0L
+#define BA0_HDSR1                               0x000000F4L
+#define BA0_HDSR2                               0x000000F8L
+#define BA0_HDSR3                               0x000000FCL
+#define BA0_DCA0                                0x00000110L
+#define BA0_DCC0                                0x00000114L
+#define BA0_DBA0                                0x00000118L
+#define BA0_DBC0                                0x0000011CL
+#define BA0_DCA1                                0x00000120L
+#define BA0_DCC1                                0x00000124L
+#define BA0_DBA1                                0x00000128L
+#define BA0_DBC1                                0x0000012CL
+#define BA0_DCA2                                0x00000130L
+#define BA0_DCC2                                0x00000134L
+#define BA0_DBA2                                0x00000138L
+#define BA0_DBC2                                0x0000013CL
+#define BA0_DCA3                                0x00000140L
+#define BA0_DCC3                                0x00000144L
+#define BA0_DBA3                                0x00000148L
+#define BA0_DBC3                                0x0000014CL
+#define BA0_DMR0                                0x00000150L
+#define BA0_DCR0                                0x00000154L
+#define BA0_DMR1                                0x00000158L
+#define BA0_DCR1                                0x0000015CL
+#define BA0_DMR2                                0x00000160L
+#define BA0_DCR2                                0x00000164L
+#define BA0_DMR3                                0x00000168L
+#define BA0_DCR3                                0x0000016CL
+#define BA0_DLMR                                0x00000170L
+#define BA0_DLSR                                0x00000174L
+#define BA0_FCR0                                0x00000180L
+#define BA0_FCR1                                0x00000184L
+#define BA0_FCR2                                0x00000188L
+#define BA0_FCR3                                0x0000018CL
+#define BA0_FPDR0                               0x00000190L
+#define BA0_FPDR1                               0x00000194L
+#define BA0_FPDR2                               0x00000198L
+#define BA0_FPDR3                               0x0000019CL
+#define BA0_FCHS                                0x0000020CL
+#define BA0_FSIC0                               0x00000210L
+#define BA0_FSIC1                               0x00000214L
+#define BA0_FSIC2                               0x00000218L
+#define BA0_FSIC3                               0x0000021CL
+#define BA0_PCICFG00                            0x00000300L
+#define BA0_PCICFG04                            0x00000304L
+#define BA0_PCICFG08                            0x00000308L
+#define BA0_PCICFG0C                            0x0000030CL
+#define BA0_PCICFG10                            0x00000310L
+#define BA0_PCICFG14                            0x00000314L
+#define BA0_PCICFG18                            0x00000318L
+#define BA0_PCICFG1C                            0x0000031CL
+#define BA0_PCICFG20                            0x00000320L
+#define BA0_PCICFG24                            0x00000324L
+#define BA0_PCICFG28                            0x00000328L
+#define BA0_PCICFG2C                            0x0000032CL
+#define BA0_PCICFG30                            0x00000330L
+#define BA0_PCICFG34                            0x00000334L
+#define BA0_PCICFG38                            0x00000338L
+#define BA0_PCICFG3C                            0x0000033CL
+#define BA0_PCICFG40                            0x00000340L
+#define BA0_PMCS                                0x00000344L
+#define BA0_CWPR                                0x000003E0L
+#define BA0_EPPMC                               0x000003E4L
+#define BA0_GPIOR                               0x000003E8L
+#define BA0_SPMC                                0x000003ECL
+#define BA0_CFLR                                0x000003F0L
+#define BA0_IISR                                0x000003F4L
+#define BA0_TMS                                 0x000003F8L
+#define BA0_SSVID                               0x000003FCL
+#define BA0_CLKCR1                              0x00000400L
+#define BA0_FRR                                 0x00000410L
+#define BA0_SLT12O                              0x0000041CL
+#define BA0_SERMC                               0x00000420L
+#define BA0_SERC1                               0x00000428L
+#define BA0_SERC2                               0x0000042CL
+#define BA0_SLT12M                              0x0000045CL
+#define BA0_ACCTL                               0x00000460L
+#define BA0_ACSTS                               0x00000464L
+#define BA0_ACOSV                               0x00000468L
+#define BA0_ACCAD                               0x0000046CL
+#define BA0_ACCDA                               0x00000470L
+#define BA0_ACISV                               0x00000474L
+#define BA0_ACSAD                               0x00000478L
+#define BA0_ACSDA                               0x0000047CL
+#define BA0_JSPT                                0x00000480L
+#define BA0_JSCTL                               0x00000484L
+#define BA0_MIDCR                               0x00000490L
+#define BA0_MIDCMD                              0x00000494L
+#define BA0_MIDSR                               0x00000494L
+#define BA0_MIDWP                               0x00000498L
+#define BA0_MIDRP                               0x0000049CL
+#define BA0_AODSD1                              0x000004A8L
+#define BA0_AODSD2                              0x000004ACL
+#define BA0_CFGI                                0x000004B0L
+#define BA0_SLT12M2                             0x000004DCL
+#define BA0_ACSTS2                              0x000004E4L
+#define BA0_ACISV2                              0x000004F4L
+#define BA0_ACSAD2                              0x000004F8L
+#define BA0_ACSDA2                              0x000004FCL
+#define BA0_IOTGP                               0x00000500L
+#define BA0_IOTSB                               0x00000504L
+#define BA0_IOTFM                               0x00000508L
+#define BA0_IOTDMA                              0x0000050CL
+#define BA0_IOTAC0                              0x00000500L
+#define BA0_IOTAC1                              0x00000504L
+#define BA0_IOTAC2                              0x00000508L
+#define BA0_IOTAC3                              0x0000050CL
+#define BA0_IOTPCP                              0x0000052CL
+#define BA0_IOTCC                               0x00000530L
+#define BA0_IOTCR                               0x0000058CL
+#define BA0_PCPRR                               0x00000600L
+#define BA0_PCPGR                               0x00000604L
+#define BA0_PCPCR                               0x00000608L
+#define BA0_PCPCIEN                             0x00000608L
+#define BA0_SBMAR                               0x00000700L
+#define BA0_SBMDR                               0x00000704L
+#define BA0_SBRR                                0x00000708L
+#define BA0_SBRDP                               0x0000070CL
+#define BA0_SBWDP                               0x00000710L
+#define BA0_SBWBS                               0x00000710L
+#define BA0_SBRBS                               0x00000714L
+#define BA0_FMSR                                0x00000730L
+#define BA0_B0AP                                0x00000730L
+#define BA0_FMDP                                0x00000734L
+#define BA0_B1AP                                0x00000738L
+#define BA0_B1DP                                0x0000073CL
+#define BA0_SSPM                                0x00000740L
+#define BA0_DACSR                               0x00000744L
+#define BA0_ADCSR                               0x00000748L
+#define BA0_SSCR                                0x0000074CL
+#define BA0_FMLVC                               0x00000754L
+#define BA0_FMRVC                               0x00000758L
+#define BA0_SRCSA                               0x0000075CL
+#define BA0_PPLVC                               0x00000760L
+#define BA0_PPRVC                               0x00000764L
+#define BA0_PASR                                0x00000768L
+#define BA0_CASR                                0x0000076CL
+
+//****************************************************************************
+//
+// The following define the offsets of the AC97 shadow registers, which appear
+// as a virtual extension to the base address register zero memory range.
+//
+//****************************************************************************
+#define AC97_REG_OFFSET_MASK                    0x0000007EL
+#define AC97_CODEC_NUMBER_MASK                  0x00003000L
+
+#define BA0_AC97_RESET                          0x00001000L
+#define BA0_AC97_MASTER_VOLUME                  0x00001002L
+#define BA0_AC97_HEADPHONE_VOLUME               0x00001004L
+#define BA0_AC97_MASTER_VOLUME_MONO             0x00001006L
+#define BA0_AC97_MASTER_TONE                    0x00001008L
+#define BA0_AC97_PC_BEEP_VOLUME                 0x0000100AL
+#define BA0_AC97_PHONE_VOLUME                   0x0000100CL
+#define BA0_AC97_MIC_VOLUME                     0x0000100EL
+#define BA0_AC97_LINE_IN_VOLUME                 0x00001010L
+#define BA0_AC97_CD_VOLUME                      0x00001012L
+#define BA0_AC97_VIDEO_VOLUME                   0x00001014L
+#define BA0_AC97_AUX_VOLUME                     0x00001016L
+#define BA0_AC97_PCM_OUT_VOLUME                 0x00001018L
+#define BA0_AC97_RECORD_SELECT                  0x0000101AL
+#define BA0_AC97_RECORD_GAIN                    0x0000101CL
+#define BA0_AC97_RECORD_GAIN_MIC                0x0000101EL
+#define BA0_AC97_GENERAL_PURPOSE                0x00001020L
+#define BA0_AC97_3D_CONTROL                     0x00001022L
+#define BA0_AC97_MODEM_RATE                     0x00001024L
+#define BA0_AC97_POWERDOWN                      0x00001026L
+#define BA0_AC97_EXT_AUDIO_ID                   0x00001028L
+#define BA0_AC97_EXT_AUDIO_POWER                0x0000102AL
+#define BA0_AC97_PCM_FRONT_DAC_RATE             0x0000102CL
+#define BA0_AC97_PCM_SURR_DAC_RATE              0x0000102EL
+#define BA0_AC97_PCM_LFE_DAC_RATE               0x00001030L
+#define BA0_AC97_PCM_LR_ADC_RATE                0x00001032L
+#define BA0_AC97_MIC_ADC_RATE                   0x00001034L
+#define BA0_AC97_6CH_VOL_C_LFE                  0x00001036L
+#define BA0_AC97_6CH_VOL_SURROUND               0x00001038L
+#define BA0_AC97_RESERVED_3A                    0x0000103AL
+#define BA0_AC97_EXT_MODEM_ID                   0x0000103CL
+#define BA0_AC97_EXT_MODEM_POWER                0x0000103EL
+#define BA0_AC97_LINE1_CODEC_RATE               0x00001040L
+#define BA0_AC97_LINE2_CODEC_RATE               0x00001042L
+#define BA0_AC97_HANDSET_CODEC_RATE             0x00001044L
+#define BA0_AC97_LINE1_CODEC_LEVEL              0x00001046L
+#define BA0_AC97_LINE2_CODEC_LEVEL              0x00001048L
+#define BA0_AC97_HANDSET_CODEC_LEVEL            0x0000104AL
+#define BA0_AC97_GPIO_PIN_CONFIG                0x0000104CL
+#define BA0_AC97_GPIO_PIN_TYPE                  0x0000104EL
+#define BA0_AC97_GPIO_PIN_STICKY                0x00001050L
+#define BA0_AC97_GPIO_PIN_WAKEUP                0x00001052L
+#define BA0_AC97_GPIO_PIN_STATUS                0x00001054L
+#define BA0_AC97_MISC_MODEM_AFE_STAT            0x00001056L
+#define BA0_AC97_RESERVED_58                    0x00001058L
+#define BA0_AC97_CRYSTAL_REV_N_FAB_ID           0x0000105AL
+#define BA0_AC97_TEST_AND_MISC_CTRL             0x0000105CL
+#define BA0_AC97_AC_MODE                        0x0000105EL
+#define BA0_AC97_MISC_CRYSTAL_CONTROL           0x00001060L
+#define BA0_AC97_LINE1_HYPRID_CTRL              0x00001062L
+#define BA0_AC97_VENDOR_RESERVED_64             0x00001064L
+#define BA0_AC97_VENDOR_RESERVED_66             0x00001066L
+#define BA0_AC97_SPDIF_CONTROL                  0x00001068L
+#define BA0_AC97_VENDOR_RESERVED_6A             0x0000106AL
+#define BA0_AC97_VENDOR_RESERVED_6C             0x0000106CL
+#define BA0_AC97_VENDOR_RESERVED_6E             0x0000106EL
+#define BA0_AC97_VENDOR_RESERVED_70             0x00001070L
+#define BA0_AC97_VENDOR_RESERVED_72             0x00001072L
+#define BA0_AC97_VENDOR_RESERVED_74             0x00001074L
+#define BA0_AC97_CAL_ADDRESS                    0x00001076L
+#define BA0_AC97_CAL_DATA                       0x00001078L
+#define BA0_AC97_VENDOR_RESERVED_7A             0x0000107AL
+#define BA0_AC97_VENDOR_ID1                     0x0000107CL
+#define BA0_AC97_VENDOR_ID2                     0x0000107EL
+
+//****************************************************************************
+//
+// The following define the offsets of the registers and memories accessed via
+// base address register one on the CS4281 part.
+//
+//****************************************************************************
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PCI device ID/vendor ID
+// register.
+//
+//****************************************************************************
+#define PDV_VENID_MASK                          0x0000FFFFL
+#define PDV_DEVID_MASK                          0xFFFF0000L
+#define PDV_VENID_SHIFT                         0L
+#define PDV_DEVID_SHIFT                         16L
+#define VENID_CIRRUS_LOGIC                      0x1013L
+#define DEVID_CS4281                            0x6005L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PCI status and command
+// register.
+//
+//****************************************************************************
+#define PSC_IO_SPACE_ENABLE                     0x00000001L
+#define PSC_MEMORY_SPACE_ENABLE                 0x00000002L
+#define PSC_BUS_MASTER_ENABLE                   0x00000004L
+#define PSC_SPECIAL_CYCLES                      0x00000008L
+#define PSC_MWI_ENABLE                          0x00000010L
+#define PSC_VGA_PALETTE_SNOOP                   0x00000020L
+#define PSC_PARITY_RESPONSE                     0x00000040L
+#define PSC_WAIT_CONTROL                        0x00000080L
+#define PSC_SERR_ENABLE                         0x00000100L
+#define PSC_FAST_B2B_ENABLE                     0x00000200L
+#define PSC_UDF_MASK                            0x007F0000L
+#define PSC_FAST_B2B_CAPABLE                    0x00800000L
+#define PSC_PARITY_ERROR_DETECTED               0x01000000L
+#define PSC_DEVSEL_TIMING_MASK                  0x06000000L
+#define PSC_TARGET_ABORT_SIGNALLED              0x08000000L
+#define PSC_RECEIVED_TARGET_ABORT               0x10000000L
+#define PSC_RECEIVED_MASTER_ABORT               0x20000000L
+#define PSC_SIGNALLED_SERR                      0x40000000L
+#define PSC_DETECTED_PARITY_ERROR               0x80000000L
+#define PSC_UDF_SHIFT                           16L
+#define PSC_DEVSEL_TIMING_SHIFT                 25L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PCI class/revision ID
+// register.
+//
+//****************************************************************************
+#define PCR_REVID_MASK                          0x000000FFL
+#define PCR_INTERFACE_MASK                      0x0000FF00L
+#define PCR_SUBCLASS_MASK                       0x00FF0000L
+#define PCR_CLASS_MASK                          0xFF000000L
+#define PCR_REVID_SHIFT                         0L
+#define PCR_INTERFACE_SHIFT                     8L
+#define PCR_SUBCLASS_SHIFT                      16L
+#define PCR_CLASS_SHIFT                         24L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PCI latency timer register.
+//
+//****************************************************************************
+#define PLT_CACHE_LINE_SIZE_MASK                0x000000FFL
+#define PLT_LATENCY_TIMER_MASK                  0x0000FF00L
+#define PLT_HEADER_TYPE_MASK                    0x00FF0000L
+#define PLT_BIST_MASK                           0xFF000000L
+#define PLT_CACHE_LINE_SIZE_SHIFT               0L
+#define PLT_LATENCY_TIMER_SHIFT                 8L
+#define PLT_HEADER_TYPE_SHIFT                   16L
+#define PLT_BIST_SHIFT                          24L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PCI base address registers.
+//
+//****************************************************************************
+#define PBAR_MEMORY_SPACE_INDICATOR             0x00000001L
+#define PBAR_LOCATION_TYPE_MASK                 0x00000006L
+#define PBAR_NOT_PREFETCHABLE                   0x00000008L
+#define PBAR_ADDRESS_MASK                       0xFFFFFFF0L
+#define PBAR_LOCATION_TYPE_SHIFT                1L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PCI subsystem ID/subsystem
+// vendor ID register.
+//
+//****************************************************************************
+#define PSS_SUBSYSTEM_VENDOR_ID_MASK            0x0000FFFFL
+#define PSS_SUBSYSTEM_ID_MASK                   0xFFFF0000L
+#define PSS_SUBSYSTEM_VENDOR_ID_SHIFT           0L
+#define PSS_SUBSYSTEM_ID_SHIFT                  16L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PCI interrupt register.
+//
+//****************************************************************************
+#define PI_LINE_MASK                            0x000000FFL
+#define PI_PIN_MASK                             0x0000FF00L
+#define PI_MIN_GRANT_MASK                       0x00FF0000L
+#define PI_MAX_LATENCY_MASK                     0xFF000000L
+#define PI_LINE_SHIFT                           0L
+#define PI_PIN_SHIFT                            8L
+#define PI_MIN_GRANT_SHIFT                      16L
+#define PI_MAX_LATENCY_SHIFT                    24L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the host interrupt status
+// register.
+//
+//****************************************************************************
+#define HISR_HVOLMASK                            0x00000003L
+#define HISR_VDNI                                0x00000001L
+#define HISR_VUPI                                0x00000002L
+#define HISR_GP1I                                0x00000004L
+#define HISR_GP3I                                0x00000008L
+#define HISR_GPSI                                0x00000010L
+#define HISR_GPPI                                0x00000020L
+#define HISR_DMAI                                0x00040000L
+#define HISR_FIFOI                               0x00100000L
+#define HISR_HVOL                                0x00200000L
+#define HISR_MIDI                                0x00400000L
+#define HISR_SBINT                               0x00800000L
+#define HISR_INTENA                              0x80000000L
+#define HISR_DMA_MASK                            0x00000F00L
+#define HISR_FIFO_MASK                           0x0000F000L
+#define HISR_DMA_SHIFT                           8L
+#define HISR_FIFO_SHIFT                          12L
+#define HISR_FIFO0                               0x00001000L
+#define HISR_FIFO1                               0x00002000L
+#define HISR_FIFO2                               0x00004000L
+#define HISR_FIFO3                               0x00008000L
+#define HISR_DMA0                                0x00000100L
+#define HISR_DMA1                                0x00000200L
+#define HISR_DMA2                                0x00000400L
+#define HISR_DMA3                                0x00000800L
+#define HISR_RESERVED                            0x40000000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the host interrupt control
+// register.
+//
+//****************************************************************************
+#define HICR_IEV                                 0x00000001L
+#define HICR_CHGM                                0x00000002L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the DMA Mode Register n
+// (DMRn)
+//
+//****************************************************************************
+#define DMRn_TR_MASK                             0x0000000CL
+#define DMRn_TR_SHIFT                            2L
+#define DMRn_AUTO                                0x00000010L
+#define DMRn_TR_READ                             0x00000008L
+#define DMRn_TR_WRITE                            0x00000004L
+#define DMRn_TYPE_MASK                           0x000000C0L
+#define DMRn_TYPE_SHIFT                          6L
+#define DMRn_SIZE8                               0x00010000L
+#define DMRn_MONO                                0x00020000L
+#define DMRn_BEND                                0x00040000L
+#define DMRn_USIGN                               0x00080000L
+#define DMRn_SIZE20                              0x00100000L
+#define DMRn_SWAPC                               0x00400000L
+#define DMRn_CBC                                 0x01000000L
+#define DMRn_TBC                                 0x02000000L
+#define DMRn_POLL                                0x10000000L
+#define DMRn_DMA                                 0x20000000L
+#define DMRn_FSEL_MASK                           0xC0000000L
+#define DMRn_FSEL_SHIFT                          30L
+#define DMRn_FSEL0                               0x00000000L
+#define DMRn_FSEL1                               0x40000000L
+#define DMRn_FSEL2                               0x80000000L
+#define DMRn_FSEL3                               0xC0000000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the DMA Command Register n
+// (DCRn)
+//
+//****************************************************************************
+#define DCRn_HTCIE                               0x00020000L
+#define DCRn_TCIE                                0x00010000L
+#define DCRn_MSK                                 0x00000001L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the FIFO Control 
+// register n.(FCRn)
+//
+//****************************************************************************
+#define FCRn_OF_MASK                            0x0000007FL
+#define FCRn_OF_SHIFT                           0L
+#define FCRn_SZ_MASK                            0x00007F00L
+#define FCRn_SZ_SHIFT                           8L
+#define FCRn_LS_MASK                            0x001F0000L
+#define FCRn_LS_SHIFT                           16L
+#define FCRn_RS_MASK                            0x1F000000L
+#define FCRn_RS_SHIFT                           24L
+#define FCRn_FEN                                0x80000000L
+#define FCRn_PSH                                0x20000000L
+#define FCRn_DACZ                               0x40000000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the serial port Power Management
+// control register.(SPMC)
+//
+//****************************************************************************
+#define SPMC_RSTN                               0x00000001L
+#define SPMC_ASYN                               0x00000002L
+#define SPMC_WUP1                               0x00000004L
+#define SPMC_WUP2                               0x00000008L
+#define SPMC_ASDI2E                             0x00000100L
+#define SPMC_ESSPD                              0x00000200L
+#define SPMC_GISPEN                             0x00004000L
+#define SPMC_GIPPEN                             0x00008000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the Configuration Load register.
+// (CFLR)
+//
+//****************************************************************************
+#define CFLR_CLOCK_SOURCE_MASK                  0x00000003L
+#define CFLR_CLOCK_SOURCE_AC97                  0x00000001L
+
+#define CFLR_CB0_MASK                            0x000000FFL
+#define CFLR_CB1_MASK                            0x0000FF00L
+#define CFLR_CB2_MASK                            0x00FF0000L
+#define CFLR_CB3_MASK                            0xFF000000L
+#define CFLR_CB0_SHIFT                           0L
+#define CFLR_CB1_SHIFT                           8L
+#define CFLR_CB2_SHIFT                           16L
+#define CFLR_CB3_SHIFT                           24L
+
+#define IOTCR_DMA0                              0x00000000L
+#define IOTCR_DMA1                              0x00000400L
+#define IOTCR_DMA2                              0x00000800L
+#define IOTCR_DMA3                              0x00000C00L
+#define IOTCR_CCLS                              0x00000100L
+#define IOTCR_PCPCI                             0x00000200L
+#define IOTCR_DDMA                              0x00000300L
+
+#define SBWBS_WBB                               0x00000080L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the SRC Slot Assignment Register
+// (SRCSA)
+//
+//****************************************************************************
+#define SRCSA_PLSS_MASK                         0x0000001FL
+#define SRCSA_PLSS_SHIFT                        0L
+#define SRCSA_PRSS_MASK                         0x00001F00L
+#define SRCSA_PRSS_SHIFT                        8L
+#define SRCSA_CLSS_MASK                         0x001F0000L
+#define SRCSA_CLSS_SHIFT                        16L
+#define SRCSA_CRSS_MASK                         0x1F000000L
+#define SRCSA_CRSS_SHIFT                        24L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the Sound System Power Management
+// register.(SSPM)
+//
+//****************************************************************************
+#define SSPM_FPDN                               0x00000080L
+#define SSPM_MIXEN                              0x00000040L
+#define SSPM_CSRCEN                             0x00000020L
+#define SSPM_PSRCEN                             0x00000010L
+#define SSPM_JSEN                               0x00000008L
+#define SSPM_ACLEN                              0x00000004L
+#define SSPM_FMEN                               0x00000002L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the Sound System Control
+// Register. (SSCR)
+//
+//****************************************************************************
+#define SSCR_SB                                 0x00000004L
+#define SSCR_HVC                                0x00000008L
+#define SSCR_LPFIFO                             0x00000040L
+#define SSCR_LPSRC                              0x00000080L
+#define SSCR_XLPSRC                             0x00000100L
+#define SSCR_MVMD                               0x00010000L
+#define SSCR_MVAD                               0x00020000L
+#define SSCR_MVLD                               0x00040000L
+#define SSCR_MVCS                               0x00080000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the Clock Control Register 1. 
+// (CLKCR1)
+//
+//****************************************************************************
+#define CLKCR1_DLLSS_MASK                       0x0000000CL
+#define CLKCR1_DLLSS_SHIFT                      2L
+#define CLKCR1_DLLP                             0x00000010L
+#define CLKCR1_SWCE                             0x00000020L
+#define CLKCR1_DLLOS                            0x00000040L
+#define CLKCR1_CKRA                             0x00010000L
+#define CLKCR1_CKRN                             0x00020000L
+#define CLKCR1_DLLRDY                           0x01000000L
+#define CLKCR1_CLKON                            0x02000000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the Sound Blaster Read Buffer
+// Status.(SBRBS)
+//
+//****************************************************************************
+#define SBRBS_RD_MASK                           0x0000007FL
+#define SBRBS_RD_SHIFT                          0L
+#define SBRBS_RBF                               0x00000080L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the serial port master control
+// register.(SERMC)
+//
+//****************************************************************************
+#define SERMC_MSPE                              0x00000001L
+#define SERMC_PTC_MASK                          0x0000000EL
+#define SERMC_PTC_SHIFT                         1L
+#define SERMC_PTC_AC97                          0x00000002L
+#define SERMC_PLB                               0x00000010L
+#define SERMC_PXLB                              0x00000020L
+#define SERMC_LOFV                              0x00080000L
+#define SERMC_SLB                               0x00100000L
+#define SERMC_SXLB                              0x00200000L
+#define SERMC_ODSEN1                            0x01000000L
+#define SERMC_ODSEN2                            0x02000000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the General Purpose I/O Register. 
+// (GPIOR)
+//
+//****************************************************************************
+#define GPIOR_VDNS                              0x00000001L
+#define GPIOR_VUPS                              0x00000002L
+#define GPIOR_GP1S                              0x00000004L
+#define GPIOR_GP3S                              0x00000008L
+#define GPIOR_GPSS                              0x00000010L
+#define GPIOR_GPPS                              0x00000020L
+#define GPIOR_GP1D                              0x00000400L
+#define GPIOR_GP3D                              0x00000800L
+#define GPIOR_VDNLT                             0x00010000L
+#define GPIOR_VDNPO                             0x00020000L
+#define GPIOR_VDNST                             0x00040000L
+#define GPIOR_VDNW                              0x00080000L
+#define GPIOR_VUPLT                             0x00100000L
+#define GPIOR_VUPPO                             0x00200000L
+#define GPIOR_VUPST                             0x00400000L
+#define GPIOR_VUPW                              0x00800000L
+#define GPIOR_GP1OE                             0x01000000L
+#define GPIOR_GP1PT                             0x02000000L
+#define GPIOR_GP1ST                             0x04000000L
+#define GPIOR_GP1W                              0x08000000L
+#define GPIOR_GP3OE                             0x10000000L
+#define GPIOR_GP3PT                             0x20000000L
+#define GPIOR_GP3ST                             0x40000000L
+#define GPIOR_GP3W                              0x80000000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the clock control register 1.
+//
+//****************************************************************************
+#define CLKCR1_PLLSS_MASK                       0x0000000CL
+#define CLKCR1_PLLSS_SERIAL                     0x00000000L
+#define CLKCR1_PLLSS_CRYSTAL                    0x00000004L
+#define CLKCR1_PLLSS_PCI                        0x00000008L
+#define CLKCR1_PLLSS_RESERVED                   0x0000000CL
+#define CLKCR1_PLLP                             0x00000010L
+#define CLKCR1_SWCE                             0x00000020L
+#define CLKCR1_PLLOS                            0x00000040L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the feature reporting register.
+//
+//****************************************************************************
+#define FRR_FAB_MASK                            0x00000003L
+#define FRR_MASK_MASK                           0x0000001CL
+#define FRR_ID_MASK                             0x00003000L
+#define FRR_FAB_SHIFT                           0L
+#define FRR_MASK_SHIFT                          2L
+#define FRR_ID_SHIFT                            12L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the serial port 1 configuration
+// register.
+//
+//****************************************************************************
+#define SERC1_VALUE                             0x00000003L
+#define SERC1_SO1EN                             0x00000001L
+#define SERC1_SO1F_MASK                         0x0000000EL
+#define SERC1_SO1F_CS423X                       0x00000000L
+#define SERC1_SO1F_AC97                         0x00000002L
+#define SERC1_SO1F_DAC                          0x00000004L
+#define SERC1_SO1F_SPDIF                        0x00000006L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the serial port 2 configuration
+// register.
+//
+//****************************************************************************
+#define SERC2_VALUE                             0x00000003L
+#define SERC2_SI1EN                             0x00000001L
+#define SERC2_SI1F_MASK                         0x0000000EL
+#define SERC2_SI1F_CS423X                       0x00000000L
+#define SERC2_SI1F_AC97                         0x00000002L
+#define SERC2_SI1F_ADC                          0x00000004L
+#define SERC2_SI1F_SPDIF                        0x00000006L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 control register.
+//
+//****************************************************************************
+#define ACCTL_ESYN                              0x00000002L
+#define ACCTL_VFRM                              0x00000004L
+#define ACCTL_DCV                               0x00000008L
+#define ACCTL_CRW                               0x00000010L
+#define ACCTL_TC                                0x00000040L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 status register.
+//
+//****************************************************************************
+#define ACSTS_CRDY                              0x00000001L
+#define ACSTS_VSTS                              0x00000002L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 output slot valid
+// register.
+//
+//****************************************************************************
+#define ACOSV_SLV3                              0x00000001L
+#define ACOSV_SLV4                              0x00000002L
+#define ACOSV_SLV5                              0x00000004L
+#define ACOSV_SLV6                              0x00000008L
+#define ACOSV_SLV7                              0x00000010L
+#define ACOSV_SLV8                              0x00000020L
+#define ACOSV_SLV9                              0x00000040L
+#define ACOSV_SLV10                             0x00000080L
+#define ACOSV_SLV11                             0x00000100L
+#define ACOSV_SLV12                             0x00000200L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 command address
+// register.
+//
+//****************************************************************************
+#define ACCAD_CI_MASK                           0x0000007FL
+#define ACCAD_CI_SHIFT                          0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 command data register.
+//
+//****************************************************************************
+#define ACCDA_CD_MASK                           0x0000FFFFL
+#define ACCDA_CD_SHIFT                          0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 input slot valid
+// register.
+//
+//****************************************************************************
+#define ACISV_ISV3                              0x00000001L
+#define ACISV_ISV4                              0x00000002L
+#define ACISV_ISV5                              0x00000004L
+#define ACISV_ISV6                              0x00000008L
+#define ACISV_ISV7                              0x00000010L
+#define ACISV_ISV8                              0x00000020L
+#define ACISV_ISV9                              0x00000040L
+#define ACISV_ISV10                             0x00000080L
+#define ACISV_ISV11                             0x00000100L
+#define ACISV_ISV12                             0x00000200L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 status address
+// register.
+//
+//****************************************************************************
+#define ACSAD_SI_MASK                           0x0000007FL
+#define ACSAD_SI_SHIFT                          0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 status data register.
+//
+//****************************************************************************
+#define ACSDA_SD_MASK                           0x0000FFFFL
+#define ACSDA_SD_SHIFT                          0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the I/O trap address and control
+// registers (all 12).
+//
+//****************************************************************************
+#define IOTAC_SA_MASK                           0x0000FFFFL
+#define IOTAC_MSK_MASK                          0x000F0000L
+#define IOTAC_IODC_MASK                         0x06000000L
+#define IOTAC_IODC_16_BIT                       0x00000000L
+#define IOTAC_IODC_10_BIT                       0x02000000L
+#define IOTAC_IODC_12_BIT                       0x04000000L
+#define IOTAC_WSPI                              0x08000000L
+#define IOTAC_RSPI                              0x10000000L
+#define IOTAC_WSE                               0x20000000L
+#define IOTAC_WE                                0x40000000L
+#define IOTAC_RE                                0x80000000L
+#define IOTAC_SA_SHIFT                          0L
+#define IOTAC_MSK_SHIFT                         16L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PC/PCI master enable
+// register.
+//
+//****************************************************************************
+#define PCPCIEN_EN                              0x00000001L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the joystick poll/trigger
+// register.
+//
+//****************************************************************************
+#define JSPT_CAX                                0x00000001L
+#define JSPT_CAY                                0x00000002L
+#define JSPT_CBX                                0x00000004L
+#define JSPT_CBY                                0x00000008L
+#define JSPT_BA1                                0x00000010L
+#define JSPT_BA2                                0x00000020L
+#define JSPT_BB1                                0x00000040L
+#define JSPT_BB2                                0x00000080L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the joystick control register.
+// The TBF bit has been moved from MIDSR register to JSCTL register bit 8.
+//
+//****************************************************************************
+#define JSCTL_SP_MASK                           0x00000003L
+#define JSCTL_SP_SLOW                           0x00000000L
+#define JSCTL_SP_MEDIUM_SLOW                    0x00000001L
+#define JSCTL_SP_MEDIUM_FAST                    0x00000002L
+#define JSCTL_SP_FAST                           0x00000003L
+#define JSCTL_ARE                               0x00000004L
+#define JSCTL_TBF                               0x00000100L
+
+
+//****************************************************************************
+//
+// The following defines are for the flags in the MIDI control register.
+//
+//****************************************************************************
+#define MIDCR_TXE                               0x00000001L
+#define MIDCR_RXE                               0x00000002L
+#define MIDCR_RIE                               0x00000004L
+#define MIDCR_TIE                               0x00000008L
+#define MIDCR_MLB                               0x00000010L
+#define MIDCR_MRST                              0x00000020L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the MIDI status register.
+//
+//****************************************************************************
+#define MIDSR_RBE                               0x00000080L
+#define MIDSR_RDA                               0x00008000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the MIDI write port register.
+//
+//****************************************************************************
+#define MIDWP_MWD_MASK                          0x000000FFL
+#define MIDWP_MWD_SHIFT                         0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the MIDI read port register.
+//
+//****************************************************************************
+#define MIDRP_MRD_MASK                          0x000000FFL
+#define MIDRP_MRD_SHIFT                         0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the configuration interface
+// register.
+//
+//****************************************************************************
+#define CFGI_CLK                                0x00000001L
+#define CFGI_DOUT                               0x00000002L
+#define CFGI_DIN_EEN                            0x00000004L
+#define CFGI_EELD                               0x00000008L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the subsystem ID and vendor ID
+// register.
+//
+//****************************************************************************
+#define SSVID_VID_MASK                          0x0000FFFFL
+#define SSVID_SID_MASK                          0xFFFF0000L
+#define SSVID_VID_SHIFT                         0L
+#define SSVID_SID_SHIFT                         16L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the GPIO pin interface register.
+//
+//****************************************************************************
+#define GPIOR_VOLDN                             0x00000001L
+#define GPIOR_VOLUP                             0x00000002L
+#define GPIOR_SI2D                              0x00000004L
+#define GPIOR_SI2OE                             0x00000008L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 status register 2.
+//
+//****************************************************************************
+#define ACSTS2_CRDY                             0x00000001L
+#define ACSTS2_VSTS                             0x00000002L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 input slot valid
+// register 2.
+//
+//****************************************************************************
+#define ACISV2_ISV3                             0x00000001L
+#define ACISV2_ISV4                             0x00000002L
+#define ACISV2_ISV5                             0x00000004L
+#define ACISV2_ISV6                             0x00000008L
+#define ACISV2_ISV7                             0x00000010L
+#define ACISV2_ISV8                             0x00000020L
+#define ACISV2_ISV9                             0x00000040L
+#define ACISV2_ISV10                            0x00000080L
+#define ACISV2_ISV11                            0x00000100L
+#define ACISV2_ISV12                            0x00000200L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 status address
+// register 2.
+//
+//****************************************************************************
+#define ACSAD2_SI_MASK                          0x0000007FL
+#define ACSAD2_SI_SHIFT                         0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 status data register 2.
+//
+//****************************************************************************
+#define ACSDA2_SD_MASK                          0x0000FFFFL
+#define ACSDA2_SD_SHIFT                         0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the I/O trap control register.
+//
+//****************************************************************************
+#define IOTCR_ITD                               0x00000001L
+#define IOTCR_HRV                               0x00000002L
+#define IOTCR_SRV                               0x00000004L
+#define IOTCR_DTI                               0x00000008L
+#define IOTCR_DFI                               0x00000010L
+#define IOTCR_DDP                               0x00000020L
+#define IOTCR_JTE                               0x00000040L
+#define IOTCR_PPE                               0x00000080L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the I/O trap address and control
+// registers for Hardware Master Volume.  
+//
+//****************************************************************************
+#define IOTGP_SA_MASK                           0x0000FFFFL
+#define IOTGP_MSK_MASK                          0x000F0000L
+#define IOTGP_IODC_MASK                         0x06000000L
+#define IOTGP_IODC_16_BIT                       0x00000000L
+#define IOTGP_IODC_10_BIT                       0x02000000L
+#define IOTGP_IODC_12_BIT                       0x04000000L
+#define IOTGP_WSPI                              0x08000000L
+#define IOTGP_RSPI                              0x10000000L
+#define IOTGP_WSE                               0x20000000L
+#define IOTGP_WE                                0x40000000L
+#define IOTGP_RE                                0x80000000L
+#define IOTGP_SA_SHIFT                          0L
+#define IOTGP_MSK_SHIFT                         16L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the I/O trap address and control
+// registers for Sound Blaster
+//
+//****************************************************************************
+#define IOTSB_SA_MASK                           0x0000FFFFL
+#define IOTSB_MSK_MASK                          0x000F0000L
+#define IOTSB_IODC_MASK                         0x06000000L
+#define IOTSB_IODC_16_BIT                       0x00000000L
+#define IOTSB_IODC_10_BIT                       0x02000000L
+#define IOTSB_IODC_12_BIT                       0x04000000L
+#define IOTSB_WSPI                              0x08000000L
+#define IOTSB_RSPI                              0x10000000L
+#define IOTSB_WSE                               0x20000000L
+#define IOTSB_WE                                0x40000000L
+#define IOTSB_RE                                0x80000000L
+#define IOTSB_SA_SHIFT                          0L
+#define IOTSB_MSK_SHIFT                         16L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the I/O trap address and control
+// registers for FM.
+//
+//****************************************************************************
+#define IOTFM_SA_MASK                           0x0000FFFFL
+#define IOTFM_MSK_MASK                          0x000F0000L
+#define IOTFM_IODC_MASK                         0x06000000L
+#define IOTFM_IODC_16_BIT                       0x00000000L
+#define IOTFM_IODC_10_BIT                       0x02000000L
+#define IOTFM_IODC_12_BIT                       0x04000000L
+#define IOTFM_WSPI                              0x08000000L
+#define IOTFM_RSPI                              0x10000000L
+#define IOTFM_WSE                               0x20000000L
+#define IOTFM_WE                                0x40000000L
+#define IOTFM_RE                                0x80000000L
+#define IOTFM_SA_SHIFT                          0L
+#define IOTFM_MSK_SHIFT                         16L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PC/PCI request register.
+//
+//****************************************************************************
+#define PCPRR_RDC_MASK                         0x00000007L
+#define PCPRR_REQ                              0x00008000L
+#define PCPRR_RDC_SHIFT                        0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PC/PCI grant register.
+//
+//****************************************************************************
+#define PCPGR_GDC_MASK                         0x00000007L
+#define PCPGR_VL                               0x00008000L
+#define PCPGR_GDC_SHIFT                        0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PC/PCI Control Register.
+//
+//****************************************************************************
+#define PCPCR_EN                               0x00000001L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the debug index register.
+//
+//****************************************************************************
+#define DREG_REGID_MASK                         0x0000007FL
+#define DREG_DEBUG                              0x00000080L
+#define DREG_RGBK_MASK                          0x00000700L
+#define DREG_TRAP                               0x00000800L
+#if !defined(NO_CS4612)
+#if !defined(NO_CS4615)
+#define DREG_TRAPX                              0x00001000L
+#endif
+#endif
+#define DREG_REGID_SHIFT                        0L
+#define DREG_RGBK_SHIFT                         8L
+#define DREG_RGBK_REGID_MASK                    0x0000077FL
+#define DREG_REGID_R0                           0x00000010L
+#define DREG_REGID_R1                           0x00000011L
+#define DREG_REGID_R2                           0x00000012L
+#define DREG_REGID_R3                           0x00000013L
+#define DREG_REGID_R4                           0x00000014L
+#define DREG_REGID_R5                           0x00000015L
+#define DREG_REGID_R6                           0x00000016L
+#define DREG_REGID_R7                           0x00000017L
+#define DREG_REGID_R8                           0x00000018L
+#define DREG_REGID_R9                           0x00000019L
+#define DREG_REGID_RA                           0x0000001AL
+#define DREG_REGID_RB                           0x0000001BL
+#define DREG_REGID_RC                           0x0000001CL
+#define DREG_REGID_RD                           0x0000001DL
+#define DREG_REGID_RE                           0x0000001EL
+#define DREG_REGID_RF                           0x0000001FL
+#define DREG_REGID_RA_BUS_LOW                   0x00000020L
+#define DREG_REGID_RA_BUS_HIGH                  0x00000038L
+#define DREG_REGID_YBUS_LOW                     0x00000050L
+#define DREG_REGID_YBUS_HIGH                    0x00000058L
+#define DREG_REGID_TRAP_0                       0x00000100L
+#define DREG_REGID_TRAP_1                       0x00000101L
+#define DREG_REGID_TRAP_2                       0x00000102L
+#define DREG_REGID_TRAP_3                       0x00000103L
+#define DREG_REGID_TRAP_4                       0x00000104L
+#define DREG_REGID_TRAP_5                       0x00000105L
+#define DREG_REGID_TRAP_6                       0x00000106L
+#define DREG_REGID_TRAP_7                       0x00000107L
+#define DREG_REGID_INDIRECT_ADDRESS             0x0000010EL
+#define DREG_REGID_TOP_OF_STACK                 0x0000010FL
+#if !defined(NO_CS4612)
+#if !defined(NO_CS4615)
+#define DREG_REGID_TRAP_8                       0x00000110L
+#define DREG_REGID_TRAP_9                       0x00000111L
+#define DREG_REGID_TRAP_10                      0x00000112L
+#define DREG_REGID_TRAP_11                      0x00000113L
+#define DREG_REGID_TRAP_12                      0x00000114L
+#define DREG_REGID_TRAP_13                      0x00000115L
+#define DREG_REGID_TRAP_14                      0x00000116L
+#define DREG_REGID_TRAP_15                      0x00000117L
+#define DREG_REGID_TRAP_16                      0x00000118L
+#define DREG_REGID_TRAP_17                      0x00000119L
+#define DREG_REGID_TRAP_18                      0x0000011AL
+#define DREG_REGID_TRAP_19                      0x0000011BL
+#define DREG_REGID_TRAP_20                      0x0000011CL
+#define DREG_REGID_TRAP_21                      0x0000011DL
+#define DREG_REGID_TRAP_22                      0x0000011EL
+#define DREG_REGID_TRAP_23                      0x0000011FL
+#endif
+#endif
+#define DREG_REGID_RSA0_LOW                     0x00000200L
+#define DREG_REGID_RSA0_HIGH                    0x00000201L
+#define DREG_REGID_RSA1_LOW                     0x00000202L
+#define DREG_REGID_RSA1_HIGH                    0x00000203L
+#define DREG_REGID_RSA2                         0x00000204L
+#define DREG_REGID_RSA3                         0x00000205L
+#define DREG_REGID_RSI0_LOW                     0x00000206L
+#define DREG_REGID_RSI0_HIGH                    0x00000207L
+#define DREG_REGID_RSI1                         0x00000208L
+#define DREG_REGID_RSI2                         0x00000209L
+#define DREG_REGID_SAGUSTATUS                   0x0000020AL
+#define DREG_REGID_RSCONFIG01_LOW               0x0000020BL
+#define DREG_REGID_RSCONFIG01_HIGH              0x0000020CL
+#define DREG_REGID_RSCONFIG23_LOW               0x0000020DL
+#define DREG_REGID_RSCONFIG23_HIGH              0x0000020EL
+#define DREG_REGID_RSDMA01E                     0x0000020FL
+#define DREG_REGID_RSDMA23E                     0x00000210L
+#define DREG_REGID_RSD0_LOW                     0x00000211L
+#define DREG_REGID_RSD0_HIGH                    0x00000212L
+#define DREG_REGID_RSD1_LOW                     0x00000213L
+#define DREG_REGID_RSD1_HIGH                    0x00000214L
+#define DREG_REGID_RSD2_LOW                     0x00000215L
+#define DREG_REGID_RSD2_HIGH                    0x00000216L
+#define DREG_REGID_RSD3_LOW                     0x00000217L
+#define DREG_REGID_RSD3_HIGH                    0x00000218L
+#define DREG_REGID_SRAR_HIGH                    0x0000021AL
+#define DREG_REGID_SRAR_LOW                     0x0000021BL
+#define DREG_REGID_DMA_STATE                    0x0000021CL
+#define DREG_REGID_CURRENT_DMA_STREAM           0x0000021DL
+#define DREG_REGID_NEXT_DMA_STREAM              0x0000021EL
+#define DREG_REGID_CPU_STATUS                   0x00000300L
+#define DREG_REGID_MAC_MODE                     0x00000301L
+#define DREG_REGID_STACK_AND_REPEAT             0x00000302L
+#define DREG_REGID_INDEX0                       0x00000304L
+#define DREG_REGID_INDEX1                       0x00000305L
+#define DREG_REGID_DMA_STATE_0_3                0x00000400L
+#define DREG_REGID_DMA_STATE_4_7                0x00000404L
+#define DREG_REGID_DMA_STATE_8_11               0x00000408L
+#define DREG_REGID_DMA_STATE_12_15              0x0000040CL
+#define DREG_REGID_DMA_STATE_16_19              0x00000410L
+#define DREG_REGID_DMA_STATE_20_23              0x00000414L
+#define DREG_REGID_DMA_STATE_24_27              0x00000418L
+#define DREG_REGID_DMA_STATE_28_31              0x0000041CL
+#define DREG_REGID_DMA_STATE_32_35              0x00000420L
+#define DREG_REGID_DMA_STATE_36_39              0x00000424L
+#define DREG_REGID_DMA_STATE_40_43              0x00000428L
+#define DREG_REGID_DMA_STATE_44_47              0x0000042CL
+#define DREG_REGID_DMA_STATE_48_51              0x00000430L
+#define DREG_REGID_DMA_STATE_52_55              0x00000434L
+#define DREG_REGID_DMA_STATE_56_59              0x00000438L
+#define DREG_REGID_DMA_STATE_60_63              0x0000043CL
+#define DREG_REGID_DMA_STATE_64_67              0x00000440L
+#define DREG_REGID_DMA_STATE_68_71              0x00000444L
+#define DREG_REGID_DMA_STATE_72_75              0x00000448L
+#define DREG_REGID_DMA_STATE_76_79              0x0000044CL
+#define DREG_REGID_DMA_STATE_80_83              0x00000450L
+#define DREG_REGID_DMA_STATE_84_87              0x00000454L
+#define DREG_REGID_DMA_STATE_88_91              0x00000458L
+#define DREG_REGID_DMA_STATE_92_95              0x0000045CL
+#define DREG_REGID_TRAP_SELECT                  0x00000500L
+#define DREG_REGID_TRAP_WRITE_0                 0x00000500L
+#define DREG_REGID_TRAP_WRITE_1                 0x00000501L
+#define DREG_REGID_TRAP_WRITE_2                 0x00000502L
+#define DREG_REGID_TRAP_WRITE_3                 0x00000503L
+#define DREG_REGID_TRAP_WRITE_4                 0x00000504L
+#define DREG_REGID_TRAP_WRITE_5                 0x00000505L
+#define DREG_REGID_TRAP_WRITE_6                 0x00000506L
+#define DREG_REGID_TRAP_WRITE_7                 0x00000507L
+#if !defined(NO_CS4612)
+#if !defined(NO_CS4615)
+#define DREG_REGID_TRAP_WRITE_8                 0x00000510L
+#define DREG_REGID_TRAP_WRITE_9                 0x00000511L
+#define DREG_REGID_TRAP_WRITE_10                0x00000512L
+#define DREG_REGID_TRAP_WRITE_11                0x00000513L
+#define DREG_REGID_TRAP_WRITE_12                0x00000514L
+#define DREG_REGID_TRAP_WRITE_13                0x00000515L
+#define DREG_REGID_TRAP_WRITE_14                0x00000516L
+#define DREG_REGID_TRAP_WRITE_15                0x00000517L
+#define DREG_REGID_TRAP_WRITE_16                0x00000518L
+#define DREG_REGID_TRAP_WRITE_17                0x00000519L
+#define DREG_REGID_TRAP_WRITE_18                0x0000051AL
+#define DREG_REGID_TRAP_WRITE_19                0x0000051BL
+#define DREG_REGID_TRAP_WRITE_20                0x0000051CL
+#define DREG_REGID_TRAP_WRITE_21                0x0000051DL
+#define DREG_REGID_TRAP_WRITE_22                0x0000051EL
+#define DREG_REGID_TRAP_WRITE_23                0x0000051FL
+#endif
+#endif
+#define DREG_REGID_MAC0_ACC0_LOW                0x00000600L
+#define DREG_REGID_MAC0_ACC1_LOW                0x00000601L
+#define DREG_REGID_MAC0_ACC2_LOW                0x00000602L
+#define DREG_REGID_MAC0_ACC3_LOW                0x00000603L
+#define DREG_REGID_MAC1_ACC0_LOW                0x00000604L
+#define DREG_REGID_MAC1_ACC1_LOW                0x00000605L
+#define DREG_REGID_MAC1_ACC2_LOW                0x00000606L
+#define DREG_REGID_MAC1_ACC3_LOW                0x00000607L
+#define DREG_REGID_MAC0_ACC0_MID                0x00000608L
+#define DREG_REGID_MAC0_ACC1_MID                0x00000609L
+#define DREG_REGID_MAC0_ACC2_MID                0x0000060AL
+#define DREG_REGID_MAC0_ACC3_MID                0x0000060BL
+#define DREG_REGID_MAC1_ACC0_MID                0x0000060CL
+#define DREG_REGID_MAC1_ACC1_MID                0x0000060DL
+#define DREG_REGID_MAC1_ACC2_MID                0x0000060EL
+#define DREG_REGID_MAC1_ACC3_MID                0x0000060FL
+#define DREG_REGID_MAC0_ACC0_HIGH               0x00000610L
+#define DREG_REGID_MAC0_ACC1_HIGH               0x00000611L
+#define DREG_REGID_MAC0_ACC2_HIGH               0x00000612L
+#define DREG_REGID_MAC0_ACC3_HIGH               0x00000613L
+#define DREG_REGID_MAC1_ACC0_HIGH               0x00000614L
+#define DREG_REGID_MAC1_ACC1_HIGH               0x00000615L
+#define DREG_REGID_MAC1_ACC2_HIGH               0x00000616L
+#define DREG_REGID_MAC1_ACC3_HIGH               0x00000617L
+#define DREG_REGID_RSHOUT_LOW                   0x00000620L
+#define DREG_REGID_RSHOUT_MID                   0x00000628L
+#define DREG_REGID_RSHOUT_HIGH                  0x00000630L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 S/PDIF Control register.
+//
+//****************************************************************************
+#define SPDIF_CONTROL_SPDIF_EN                 0x00008000L
+#define SPDIF_CONTROL_VAL                      0x00004000L
+#define SPDIF_CONTROL_COPY                     0x00000004L
+#define SPDIF_CONTROL_CC0                      0x00000010L
+#define SPDIF_CONTROL_CC1                      0x00000020L
+#define SPDIF_CONTROL_CC2                      0x00000040L
+#define SPDIF_CONTROL_CC3                      0x00000080L
+#define SPDIF_CONTROL_CC4                      0x00000100L
+#define SPDIF_CONTROL_CC5                      0x00000200L
+#define SPDIF_CONTROL_CC6                      0x00000400L
+#define SPDIF_CONTROL_L                        0x00000800L
+
+#endif // _H_HWDEFS
index 4a1a395064c44107d21ce5919ecbed066df565da..96e8fd9eef17d76588d3f27dbf0176accecc2891 100644 (file)
@@ -16,8 +16,6 @@
 #define _DEV_TABLE_C_
 #include "sound_config.h"
 
-int softoss_dev = 0;
-
 int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver,
                        int driver_size, int flags, unsigned int format_mask,
                        void *devc, int dma1, int dma2)
index 59d805c7be4d115b57567562898e6db83181c433..dc3e548c6eb34be64ee90f4ad32f1a25c4933e96 100644 (file)
@@ -1610,10 +1610,6 @@ static int digital __initdata;
 static int fifosize __initdata =       DEFFIFOSIZE;
 static int calibrate_signal __initdata;
 
-/* If we're a module, this is just init_module */
-
-int init_module(void)
-
 #else /* not a module */
 
 static int write_ndelay __initdata =   -1;
@@ -1692,14 +1688,10 @@ static int fifosize __initdata =        CONFIG_MSND_FIFOSIZE;
 #endif
 static int
 calibrate_signal __initdata =          CONFIG_MSND_CALSIGNAL;
+#endif /* MODULE */
 
-#ifdef MSND_CLASSIC
-int __init msnd_classic_init(void)
-#else
-int __init msnd_pinnacle_init(void)
-#endif /* MSND_CLASSIC */
 
-#endif /* MODULE */
+static int __init msnd_init(void)
 {
        int err;
 #ifndef MSND_CLASSIC
@@ -1875,11 +1867,12 @@ int __init msnd_pinnacle_init(void)
        return 0;
 }
 
-#ifdef MODULE
-void cleanup_module(void)
+static void __exit msdn_cleanup(void)
 {
        unload_multisound();
        msnd_fifo_free(&dev.DAPF);
        msnd_fifo_free(&dev.DARF);
 }
-#endif
+
+module_init(msnd_init);
+module_exit(msdn_cleanup);
index 117280d1ab86dd79d939aa24cb065441a4c88ccd..d6f4998ff31b2ca18c49f137bf2e11c9b30741db 100644 (file)
@@ -18,9 +18,6 @@
 
 #define SEQUENCER_C
 #include "sound_config.h"
-#include "softoss.h"
-
-int             (*softsynthp) (int cmd, int parm1, int parm2, unsigned long parm3) = NULL;
 
 #include "midi_ctrl.h"
 
@@ -170,10 +167,7 @@ static void sequencer_midi_input(int dev, unsigned char data)
        if (data == 0xfe)       /* Ignore active sensing */
                return;
 
-       if (softsynthp != NULL)
-               tstamp = softsynthp(SSYN_GETTIME, 0, 0, 0);
-       else
-               tstamp = jiffies - seq_time;
+       tstamp = jiffies - seq_time;
 
        if (tstamp != prev_input_time)
        {
@@ -195,8 +189,6 @@ void seq_input_event(unsigned char *event_rec, int len)
 
        if (seq_mode == SEQ_2)
                this_time = tmr->get_time(tmr_no);
-       else if (softsynthp != NULL)
-               this_time = softsynthp(SSYN_GETTIME, 0, 0, 0);
        else
                this_time = jiffies - seq_time;
 
@@ -659,10 +651,7 @@ static int seq_timing_event(unsigned char *event_rec)
                                prev_event_time = time;
 
                                seq_playing = 1;
-                               if (softsynthp != NULL)
-                                       softsynthp(SSYN_REQUEST, time, 0, 0);
-                               else
-                                       request_sound_timer(time);
+                               request_sound_timer(time);
 
                                if ((SEQ_MAX_QUEUE - qlen) >= output_threshold)
                                        wake_up(&seq_sleeper);
@@ -671,13 +660,7 @@ static int seq_timing_event(unsigned char *event_rec)
                        break;
 
                case TMR_START:
-                       if (softsynthp != NULL)
-                       {
-                               softsynthp(SSYN_START, 0, 0, 0);
-                               seq_time = 0;
-                       }
-                       else
-                               seq_time = jiffies;
+                       seq_time = jiffies;
                        prev_input_time = 0;
                        prev_event_time = 0;
                        break;
@@ -785,10 +768,7 @@ static int play_event(unsigned char *q)
                                time = *delay;
                                prev_event_time = time;
 
-                               if (softsynthp != NULL)
-                                       softsynthp(SSYN_REQUEST, time, 0, 0);
-                               else
-                                       request_sound_timer(time);
+                               request_sound_timer(time);
 
                                if ((SEQ_MAX_QUEUE - qlen) >= output_threshold)
                                        wake_up(&seq_sleeper);
@@ -809,14 +789,9 @@ static int play_event(unsigned char *q)
                case SEQ_SYNCTIMER:     /*
                                         * Reset timer
                                         */
-                       if (softsynthp != NULL)
-                               seq_time = 0;
-                       else
-                               seq_time = jiffies;
+                       seq_time = jiffies;
                        prev_input_time = 0;
                        prev_event_time = 0;
-                       if (softsynthp != NULL)
-                               softsynthp(SSYN_START, 0, 0, 0);
                        break;
 
                case SEQ_MIDIPUTC:      /*
@@ -838,10 +813,7 @@ static int play_event(unsigned char *q)
                                         */
 
                                        seq_playing = 1;
-                                       if (softsynthp != NULL)
-                                               softsynthp(SSYN_REQUEST, -1, 0, 0);
-                                       else
-                                               request_sound_timer(-1);
+                                       request_sound_timer(-1);
                                        return 2;
                                }
                                else
@@ -1085,15 +1057,10 @@ int sequencer_open(int dev, struct file *file)
                }
        }
 
-       if (softsynthp != NULL)
-               seq_time = 0;
-       else
-               seq_time = jiffies;
+       seq_time = jiffies;
 
        prev_input_time = 0;
        prev_event_time = 0;
-       if (softsynthp != NULL)
-               softsynthp(SSYN_START, 0, 0, 0);
 
        if (seq_mode == SEQ_1 && (mode == OPEN_READ || mode == OPEN_READWRITE))
        {
@@ -1280,10 +1247,7 @@ static void seq_reset(void)
        int chn;
        unsigned long flags;
 
-       if (softsynthp != NULL)
-               softsynthp(SSYN_STOP, 0, 0, 0);
-       else
-               sound_stop_timer();
+       sound_stop_timer();
 
        seq_time = jiffies;
        prev_input_time = 0;
@@ -1449,10 +1413,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
                case SNDCTL_SEQ_GETTIME:
                        if (seq_mode == SEQ_2)
                                return tmr->ioctl(tmr_no, cmd, arg);
-                       if (softsynthp != NULL)
-                               val = softsynthp(SSYN_GETTIME, 0, 0, 0);
-                       else
-                               val = jiffies - seq_time;
+                       val = jiffies - seq_time;
                        break;
 
                case SNDCTL_SEQ_CTRLRATE:
index 014d77841a652037bdbdb3fbac29f0d3a6ed86b3..2d8bd22e8bb2a0fe182061c8a607bd8b08856680 100644 (file)
@@ -23,10 +23,6 @@ EXPORT_SYMBOL(sound_timer_interrupt);
 EXPORT_SYMBOL(sound_timer_syncinterval);
 EXPORT_SYMBOL(reprogram_timer);
 
-#include "softoss.h"
-
-EXPORT_SYMBOL(softsynthp);
-
 /* Tuning */
 
 #define _SEQUENCER_C_
diff --git a/drivers/sound/softoss.c b/drivers/sound/softoss.c
deleted file mode 100644 (file)
index 7288b3b..0000000
+++ /dev/null
@@ -1,1535 +0,0 @@
-/* 
- * sound/softoss.c
- *
- * Software based MIDI synthsesizer driver.
- *
- *
- * Copyright (C) by Hannu Savolainen 1993-1997
- *
- * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
- * Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info.
- *
- *
- * Thomas Sailer       : ioctl code reworked (vmalloc/vfree removed)
- * Christoph Hellwig   : adapted to module_init/module_exit
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/module.h>
-
-/*
- * When POLLED_MODE is defined, the resampling loop is run using a timer
- * callback routine. Normally the resampling loop is executed inside
- * audio buffer interrupt handler which doesn't work with single mode DMA.
- */
-#define SOFTSYN_MAIN
-#undef  POLLED_MODE
-#define HANDLE_LFO
-
-#define ENVELOPE_SCALE         8
-#define NO_SAMPLE              0xffff
-
-#include "sound_config.h"
-#include "softoss.h"
-#include <linux/ultrasound.h>
-
-int softsynth_disabled = 0;
-
-static volatile int intr_pending = 0;
-
-#ifdef POLLED_MODE
-
-static struct timer_list poll_timer = {
-       NULL, NULL, 0, 0, softsyn_poll
-};
-
-#else
-#endif
-
-#ifdef HANDLE_LFO
-/*
- * LFO table. Playback at 128 Hz gives 1 Hz LFO frequency.
- */
-static int      tremolo_table[128] =
-{
-       0, 39, 158, 355, 630, 982, 1411, 1915,
-       2494, 3146, 3869, 4662, 5522, 6448, 7438, 8489,
-       9598, 10762, 11980, 13248, 14563, 15922, 17321, 18758,
-       20228, 21729, 23256, 24806, 26375, 27960, 29556, 31160,
-       32768, 34376, 35980, 37576, 39161, 40730, 42280, 43807,
-       45308, 46778, 48215, 49614, 50973, 52288, 53556, 54774,
-       55938, 57047, 58098, 59088, 60014, 60874, 61667, 62390,
-       63042, 63621, 64125, 64554, 64906, 65181, 65378, 65497,
-       65536, 65497, 65378, 65181, 64906, 64554, 64125, 63621,
-       63042, 62390, 61667, 60874, 60014, 59087, 58098, 57047,
-       55938, 54774, 53556, 52288, 50973, 49614, 48215, 46778,
-       45308, 43807, 42280, 40730, 39161, 37576, 35980, 34376,
-       32768, 31160, 29556, 27960, 26375, 24806, 23256, 21729,
-       20228, 18758, 17321, 15922, 14563, 13248, 11980, 10762,
-       9598, 8489, 7438, 6448, 5522, 4662, 3869, 3146,
-       2494, 1915, 1411, 982, 630, 355, 158, 39
-};
-
-static int      vibrato_table[128] =
-{
-       0, 1608, 3212, 4808, 6393, 7962, 9512, 11039,
-       12540, 14010, 15447, 16846, 18205, 19520, 20788, 22006,
-       23170, 24279, 25330, 26320, 27246, 28106, 28899, 29622,
-       30274, 30853, 31357, 31786, 32138, 32413, 32610, 32729,
-       32768, 32729, 32610, 32413, 32138, 31786, 31357, 30853,
-       30274, 29622, 28899, 28106, 27246, 26320, 25330, 24279,
-       23170, 22006, 20788, 19520, 18205, 16846, 15447, 14010,
-       12540, 11039, 9512, 7962, 6393, 4808, 3212, 1608,
-       0, -1608, -3212, -4808, -6393, -7962, -9512, -11039,
-       -12540, -14010, -15447, -16846, -18205, -19520, -20788, -22006,
-       -23170, -24279, -25330, -26320, -27246, -28106, -28899, -29622,
-       -30274, -30853, -31357, -31786, -32138, -32413, -32610, -32729,
-       -32768, -32729, -32610, -32413, -32138, -31786, -31357, -30853,
-       -30274, -29622, -28899, -28106, -27246, -26320, -25330, -24279,
-       -23170, -22006, -20788, -19520, -18205, -16846, -15447, -14010,
-       -12540, -11039, -9512, -7962, -6393, -4808, -3212, -1608
-};
-
-#endif
-
-static unsigned long last_resample_jiffies;
-static unsigned long resample_counter;
-
-extern int     *sound_osp;
-
-static volatile int is_running = 0;
-static int      softsynth_loaded = 0;
-
-static struct synth_info softsyn_info = {
-       "SoftOSS", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_GUS, 0, 16, 0, MAX_PATCH
-};
-
-static struct softsyn_devc sdev_info = {
-       0
-};
-
-softsyn_devc   *devc = &sdev_info;     /* used in softoss_rs.c */
-
-static struct voice_alloc_info *voice_alloc;
-
-static int      softsyn_open(int synthdev, int mode);
-static void     init_voice(softsyn_devc * devc, int voice);
-static void     compute_step(int voice);
-
-static volatile int tmr_running = 0;
-static int      voice_limit = 24;
-
-
-static void set_max_voices(int nr)
-{
-       int i;
-
-       if (nr < 4)
-               nr = 4;
-
-       if (nr > voice_limit)
-               nr = voice_limit;
-
-       voice_alloc->max_voice = devc->maxvoice = nr;
-       devc->afterscale = 5;
-
-       for (i = 31; i > 0; i--)
-               if (nr & (1 << i))
-               {
-                       devc->afterscale = i + 1;
-                       return;
-               }
-}
-
-static void update_vibrato(int voice)
-{
-       voice_info *v = &softoss_voices[voice];
-
-#ifdef HANDLE_LFO
-       int x;
-
-       x = vibrato_table[v->vibrato_phase >> 8];
-       v->vibrato_phase = (v->vibrato_phase + v->vibrato_step) & 0x7fff;
-
-       x = (x * v->vibrato_depth) >> 15;
-       v->vibrato_level = (x * 600) >> 8;
-
-       compute_step(voice);
-#else
-       v->vibrato_level = 0;
-#endif
-}
-
-#ifdef HANDLE_LFO
-static void update_tremolo(int voice)
-{
-       voice_info *v = &softoss_voices[voice];
-       int x;
-
-       x = tremolo_table[v->tremolo_phase >> 8];
-       v->tremolo_phase = (v->tremolo_phase + v->tremolo_step) & 0x7fff;
-
-       v->tremolo_level = (x * v->tremolo_depth) >> 20;
-}
-#endif
-
-static void start_vibrato(int voice)
-{
-       voice_info *v = &softoss_voices[voice];
-       int rate;
-
-       if (!v->vibrato_depth)
-               return;
-
-       rate = v->vibrato_rate * 6 * 128;
-       v->vibrato_step = (rate * devc->control_rate) / devc->speed;
-
-       devc->vibratomap |= (1 << voice);       /* Enable vibrato */
-}
-
-static void start_tremolo(int voice)
-{
-       voice_info *v = &softoss_voices[voice];
-       int rate;
-
-       if (!v->tremolo_depth)
-               return;
-
-       rate = v->tremolo_rate * 6 * 128;
-       v->tremolo_step = (rate * devc->control_rate) / devc->speed;
-
-       devc->tremolomap |= (1 << voice);       /* Enable tremolo */
-}
-
-static void update_volume(int voice)
-{
-       voice_info *v = &softoss_voices[voice];
-       unsigned int vol;
-
-       /*
-        *      Compute plain volume
-        */
-
-       vol = (v->velocity * v->expression_vol * v->main_vol) >> 12;
-
-#ifdef HANDLE_LFO
-       /*
-        *      Handle LFO
-        */
-
-       if (devc->tremolomap & (1 << voice))
-       {
-               int t;
-
-               t = 32768 - v->tremolo_level;
-               vol = (vol * t) >> 15;
-               update_tremolo(voice);
-       }
-#endif
-       /*
-        *      Envelope
-        */
-        
-       if (v->mode & WAVE_ENVELOPES && !v->percussive_voice)
-               vol = (vol * (v->envelope_vol >> 16)) >> 19;
-       else
-               vol >>= 4;
-
-       /*
-        * Handle panning
-        */
-
-       if (v->panning < 0)     /* Pan left */
-               v->rightvol = (vol * (128 + v->panning)) / 128;
-       else
-               v->rightvol = vol;
-
-       if (v->panning > 0)     /* Pan right */
-               v->leftvol = (vol * (128 - v->panning)) / 128;
-       else
-               v->leftvol = vol;
-}
-
-static void step_envelope(int voice, int do_release, int velocity)
-{
-       voice_info *v = &softoss_voices[voice];
-       int r, rate, time, dif;
-       unsigned int vol;
-       unsigned long flags;
-
-       save_flags(flags);
-       cli();
-
-       if (!voice_active[voice] || v->sample == NULL)
-       {
-               restore_flags(flags);
-               return;
-       }
-       if (!do_release)
-       {
-               if (v->mode & WAVE_SUSTAIN_ON && v->envelope_phase == 2)
-               {       
-                       /* Stop envelope until note off */
-                       v->envelope_volstep = 0;
-                       v->envelope_time = 0x7fffffff;
-                       if (v->mode & WAVE_VIBRATO)
-                               start_vibrato(voice);
-                       if (v->mode & WAVE_TREMOLO)
-                               start_tremolo(voice);
-                       restore_flags(flags);
-                       return;
-               }
-       }
-       if (do_release)
-               v->envelope_phase = 3;
-       else
-               v->envelope_phase++;
-
-       if (v->envelope_phase >= 5)     /* Finished */
-       {
-               init_voice(devc, voice);
-               restore_flags(flags);
-               return;
-       }
-       vol = v->envelope_target = v->sample->env_offset[v->envelope_phase] << 22;
-
-
-       rate = v->sample->env_rate[v->envelope_phase];
-       r = 3 - ((rate >> 6) & 0x3);
-       r *= 3;
-       r = (int) (rate & 0x3f) << r;
-       rate = (((r * 44100) / devc->speed) * devc->control_rate) << 8;
-
-       if (rate < (1 << 20))   /* Avoid infinitely "releasing" voices */
-               rate = 1 << 20;
-
-       dif = (v->envelope_vol - vol);
-       if (dif < 0)
-               dif *= -1;
-       if (dif < rate * 2)     /* Too close */
-       {
-               step_envelope(voice, 0, 60);
-               restore_flags(flags);
-               return;
-       }
-
-       if (vol > v->envelope_vol)
-       {
-               v->envelope_volstep = rate;
-               time = (vol - v->envelope_vol) / rate;
-       }
-       else
-       {
-               v->envelope_volstep = -rate;
-               time = (v->envelope_vol - vol) / rate;
-       }
-
-       time--;
-       if (time <= 0)
-               time = 1;
-       v->envelope_time = time;
-       restore_flags(flags);
-}
-
-static void step_envelope_lfo(int voice)
-{
-       voice_info *v = &softoss_voices[voice];
-
-       /*
-        * Update pitch (vibrato) LFO 
-        */
-
-       if (devc->vibratomap & (1 << voice))
-               update_vibrato(voice);
-
-       /* 
-        * Update envelope
-        */
-
-       if (v->mode & WAVE_ENVELOPES)
-       {
-               v->envelope_vol += v->envelope_volstep;
-               /* Overshoot protection */
-               if (v->envelope_vol < 0)
-               {
-                       v->envelope_vol = v->envelope_target;
-                       v->envelope_volstep = 0;
-               }
-               if (v->envelope_time-- <= 0)
-               {
-                       v->envelope_vol = v->envelope_target;
-                       step_envelope(voice, 0, 60);
-               }
-       }
-}
-
-static void compute_step(int voice)
-{
-       voice_info *v = &softoss_voices[voice];
-
-       /*
-        *      Since the pitch bender may have been set before playing the note, we
-        *      have to calculate the bending now.
-        */
-
-       v->current_freq = compute_finetune(v->orig_freq,
-                                          v->bender,
-                                          v->bender_range,
-                                          v->vibrato_level);
-       v->step = (((v->current_freq << 9) + (devc->speed >> 1)) / devc->speed);
-
-       if (v->mode & WAVE_LOOP_BACK)
-               v->step *= -1;  /* Reversed playback */
-}
-
-static void init_voice(softsyn_devc * devc, int voice)
-{
-       voice_info *v = &softoss_voices[voice];
-       unsigned long flags;
-
-       save_flags(flags);
-       cli();
-       voice_active[voice] = 0;
-       devc->vibratomap &= ~(1 << voice);
-       devc->tremolomap &= ~(1 << voice);
-       v->mode = 0;
-       v->wave = NULL;
-       v->sample = NULL;
-       v->ptr = 0;
-       v->step = 0;
-       v->startloop = 0;
-       v->startbackloop = 0;
-       v->endloop = 0;
-       v->looplen = 0;
-       v->bender = 0;
-       v->bender_range = 200;
-       v->panning = 0;
-       v->main_vol = 127;
-       v->expression_vol = 127;
-       v->patch_vol = 127;
-       v->percussive_voice = 0;
-       v->sustain_mode = 0;
-       v->envelope_phase = 1;
-       v->envelope_vol = 1 << 24;
-       v->envelope_volstep = 256;
-       v->envelope_time = 0;
-       v->vibrato_phase = 0;
-       v->vibrato_step = 0;
-       v->vibrato_level = 0;
-       v->vibrato_rate = 0;
-       v->vibrato_depth = 0;
-       v->tremolo_phase = 0;
-       v->tremolo_step = 0;
-       v->tremolo_level = 0;
-       v->tremolo_rate = 0;
-       v->tremolo_depth = 0;
-       voice_alloc->map[voice] = 0;
-       voice_alloc->alloc_times[voice] = 0;
-       restore_flags(flags);
-}
-
-static void reset_samples(softsyn_devc * devc)
-{
-       int i;
-
-       for (i = 0; i < MAX_VOICE; i++)
-               voice_active[i] = 0;
-       for (i = 0; i < devc->maxvoice; i++)
-       {
-               init_voice(devc, i);
-               softoss_voices[i].instr = 0;
-       }
-
-       devc->ram_used = 0;
-
-       for (i = 0; i < MAX_PATCH; i++)
-               devc->programs[i] = NO_SAMPLE;
-
-       for (i = 0; i < devc->nrsamples; i++)
-       {
-               vfree(devc->samples[i]);
-               vfree(devc->wave[i]);
-               devc->samples[i] = NULL;
-               devc->wave[i] = NULL;
-       }
-       devc->nrsamples = 0;
-}
-
-static void init_engine(softsyn_devc * devc)
-{
-       int i, fz, srate, sz = devc->channels;
-
-       set_max_voices(devc->default_max_voices);
-       voice_alloc->timestamp = 0;
-
-       if (devc->bits == 16)
-               sz *= 2;
-
-       fz = devc->fragsize / sz;       /* Samples per fragment */
-       devc->samples_per_fragment = fz;
-
-       devc->usecs = 0;
-       devc->usecs_per_frag = (1000000 * fz) / devc->speed;
-
-       for (i = 0; i < devc->maxvoice; i++)
-       {
-               init_voice(devc, i);
-               softoss_voices[i].instr = 0;
-       }
-       devc->engine_state = ES_STOPPED;
-
-       /*
-        *    Initialize delay
-        */
-
-       for (i = 0; i < DELAY_SIZE; i++)
-               left_delay[i] = right_delay[i] = 0;
-       delayp = 0;
-       srate = (devc->speed / 10000);  /* 1 to 4 */
-       if (srate <= 0)
-               srate = 1;
-       devc->delay_size = (DELAY_SIZE * srate) / 4;
-       if (devc->delay_size == 0 || devc->delay_size > DELAY_SIZE)
-               devc->delay_size = DELAY_SIZE;
-}
-
-void softsyn_control_loop(void)
-{
-       int voice;
-
-       /*
-        *    Recompute envlope, LFO, etc.
-        */
-       for (voice = 0; voice < devc->maxvoice; voice++)
-       {
-               if (voice_active[voice])
-               {
-                       update_volume(voice);
-                       step_envelope_lfo(voice);
-               }
-               else
-                       voice_alloc->map[voice] = 0;
-       }
-}
-
-static void start_engine(softsyn_devc * devc);
-
-static void do_resample(int dummy)
-{
-       struct dma_buffparms *dmap = audio_devs[devc->audiodev]->dmap_out;
-       struct voice_info *vinfo;
-       unsigned long   flags, jif;
-
-       int voice, loops;
-       short *buf;
-
-       if (softsynth_disabled)
-               return;
-
-       save_flags(flags);
-       cli();
-
-       if (is_running)
-       {
-               printk(KERN_WARNING "SoftOSS: Playback overrun\n");
-               restore_flags(flags);
-               return;
-       }
-       jif = jiffies;
-       if (jif == last_resample_jiffies)
-       {
-               if (resample_counter++ > 50)
-               {
-                       for (voice = 0; voice < devc->maxvoice; voice++)
-                               init_voice(devc, voice);
-                       voice_limit--;
-                       resample_counter = 0;
-                       printk(KERN_WARNING "SoftOSS: CPU overload. Limiting # of voices to %d\n", voice_limit);
-
-                       if (voice_limit < 10)
-                       {
-                               voice_limit = 10;
-                               devc->speed = (devc->speed * 2) / 3;
-
-                               printk(KERN_WARNING "SoftOSS: Dropping sampling rate and stopping the device.\n");
-                               softsynth_disabled = 1;
-                       }
-               }
-       }
-       else
-       {
-               last_resample_jiffies = jif;
-               resample_counter = 0;
-       }
-
-       /* is_running = 1; */
-
-       if (dmap->qlen > devc->max_playahead)
-       {
-               printk(KERN_WARNING "SoftOSS: audio buffers full\n");
-               is_running = 0;
-               restore_flags(flags);
-               return;
-       }
-       /*
-        * First verify that all active voices are valid (do this just once per block).
-        */
-
-       for (voice = 0; voice < devc->maxvoice; voice++)
-       {
-               if (voice_active[voice])
-               {
-                       int ptr;
-
-                       vinfo = &softoss_voices[voice];
-                       ptr = vinfo->ptr >> 9;
-
-                       if (vinfo->wave == NULL || ptr < 0 || ptr > vinfo->sample->len)
-                               init_voice(devc, voice);
-                       else if (!(vinfo->mode & WAVE_LOOPING) && (vinfo->ptr + vinfo->step) > vinfo->endloop)
-                                 voice_active[voice] = 0;
-               }
-       }
-       
-       /*
-        *    Start the resampling process
-        */
-
-       loops = devc->samples_per_fragment;
-       buf = (short *) (dmap->raw_buf + (dmap->qtail * dmap->fragment_size));
-
-       softsynth_resample_loop(buf, loops);    /* In Xsoftsynth_rs.c */
-
-       dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
-       dmap->qlen++;
-       dmap->user_counter += dmap->fragment_size;
-
-       devc->usecs += devc->usecs_per_frag;
-
-       if (tmr_running)
-               sound_timer_interrupt();
-       /*
-        *    Execute timer
-        */
-
-       if (!tmr_running)
-       {
-               if (devc->usecs >= devc->next_event_usecs)
-               {
-                       devc->next_event_usecs = ~0;
-                       sequencer_timer(0);
-               }
-       }
-       
-       is_running = 0;
-       restore_flags(flags);
-}
-
-static void delayed_resample(int dummy)
-{
-       struct dma_buffparms *dmap = audio_devs[devc->audiodev]->dmap_out;
-       int n = 0;
-
-       if (is_running)
-               return;
-
-       while (devc->engine_state != ES_STOPPED && dmap->qlen < devc->max_playahead && n++ < 2)
-               do_resample(0);
-       intr_pending = 0;
-}
-
-#ifdef POLLED_MODE
-static void softsyn_poll(unsigned long dummy)
-{
-       delayed_resample(0);
-
-       if (devc->engine_state != ES_STOPPED)
-       {
-                 poll_timer.expires = jiffies+1;
-                 add_timer(&poll_timer);
-       }
-}
-
-#else
-static void softsyn_callback(int dev, int parm)
-{
-       delayed_resample(0);
-}
-#endif
-
-static void start_engine(softsyn_devc * devc)
-{
-       struct dma_buffparms *dmap;
-       int trig, n;
-       mm_segment_t fs;
-
-       if (!devc->audio_opened)
-               if (softsyn_open(devc->synthdev, 0) < 0)
-                       return;
-
-       if (devc->audiodev >= num_audiodevs)
-               return;
-       
-       dmap = audio_devs[devc->audiodev]->dmap_out;
-       
-       devc->usecs = 0;
-       devc->next_event_usecs = ~0;
-       devc->control_rate = 64;
-       devc->control_counter = 0;
-
-       if (devc->engine_state == ES_STOPPED) 
-       {
-               n = trig = 0;
-               fs = get_fs();
-               set_fs(get_ds());
-               dma_ioctl(devc->audiodev, SNDCTL_DSP_SETTRIGGER, (caddr_t)&trig);
-#ifdef POLLED_MODE
-               poll_timer.expires = jiffies+1;
-               add_timer(&poll_timer);
-               /* Start polling */
-#else
-               dmap->audio_callback = softsyn_callback;
-               dmap->qhead = dmap->qtail = dmap->qlen = 0;
-#endif
-               while (dmap->qlen < devc->max_playahead && n++ < 2)
-                       do_resample(0);
-               devc->engine_state = ES_STARTED;
-               last_resample_jiffies = jiffies;
-               resample_counter = 0;
-               trig = PCM_ENABLE_OUTPUT;
-               if (dma_ioctl(devc->audiodev, SNDCTL_DSP_SETTRIGGER, (caddr_t)&trig) < 0)
-                       printk(KERN_ERR "SoftOSS: Trigger failed\n");
-               set_fs(fs);
-       }
-}
-
-static void stop_engine(softsyn_devc * devc)
-{
-}
-
-static void request_engine(softsyn_devc * devc, int ticks)
-{
-       if (ticks < 0)          /* Relative time */
-               devc->next_event_usecs = devc->usecs - ticks * (1000000 / HZ);
-       else
-               devc->next_event_usecs = ticks * (1000000 / HZ);
-}
-
-/*
- * Softsync hook serves mode1 (timing) calls made by sequencer.c
- */
-static int softsynth_hook(int cmd, int parm1, int parm2, unsigned long parm3)
-{
-       switch (cmd)
-       {
-               case SSYN_START:
-                       start_engine(devc);
-                       break;
-
-               case SSYN_STOP:
-                       stop_engine(devc);
-                       break;
-
-               case SSYN_REQUEST:
-                       request_engine(devc, parm1);
-                       break;
-
-               case SSYN_GETTIME:
-                       return devc->usecs / (1000000 / HZ);
-                       break;
-
-               default:
-                       printk(KERN_WARNING "SoftOSS: Unknown request %d\n", cmd);
-       }
-       return 0;
-}
-
-static int softsyn_ioctl(int dev, unsigned int cmd, caddr_t arg)
-{
-       switch (cmd) 
-       {
-               case SNDCTL_SYNTH_INFO:
-                       softsyn_info.nr_voices = devc->maxvoice;
-                       if (copy_to_user(arg, &softsyn_info, sizeof(softsyn_info)))
-                               return -EFAULT;
-                       return 0;
-
-               case SNDCTL_SEQ_RESETSAMPLES:
-                       stop_engine(devc);
-                       reset_samples(devc);
-                       return 0;
-                 
-               case SNDCTL_SYNTH_MEMAVL:
-                       return devc->ram_size - devc->ram_used;
-
-               default:
-                       return -EINVAL;
-       }
-}
-
-static int softsyn_kill_note(int devno, int voice, int note, int velocity)
-{
-       if (voice < 0 || voice > devc->maxvoice)
-               return 0;
-       voice_alloc->map[voice] = 0xffff;       /* Releasing */
-
-       if (softoss_voices[voice].sustain_mode & 1)     /* Sustain controller on */
-       {
-               softoss_voices[voice].sustain_mode = 3; /* Note off pending */
-               return 0;
-       }
-       if (velocity > 127 || softoss_voices[voice].mode & WAVE_FAST_RELEASE)
-       {
-               init_voice(devc, voice);        /* Mark it inactive */
-               return 0;
-       }
-       if (softoss_voices[voice].mode & WAVE_ENVELOPES)
-               step_envelope(voice, 1, velocity);      /* Enter sustain phase */
-       else
-               init_voice(devc, voice);        /* Mark it inactive */
-       return 0;
-}
-
-static int softsyn_set_instr(int dev, int voice, int instr)
-{
-       if (voice < 0 || voice > devc->maxvoice)
-               return 0;
-
-       if (instr < 0 || instr > MAX_PATCH)
-       {
-               printk(KERN_ERR "SoftOSS: Invalid instrument number %d\n", instr);
-               return 0;
-       }
-       softoss_voices[voice].instr = instr;
-       return 0;
-}
-
-static int softsyn_start_note(int dev, int voice, int note, int volume)
-{
-       int instr = 0;
-       int best_sample, best_delta, delta_freq, selected;
-       unsigned long note_freq, freq, base_note, flags;
-       voice_info *v = &softoss_voices[voice];
-
-       struct patch_info *sample;
-
-       if (voice < 0 || voice > devc->maxvoice)
-               return 0;
-
-       if (volume == 0)        /* Actually note off */
-               softsyn_kill_note(dev, voice, note, volume);
-
-       save_flags(flags);
-       cli();
-
-       if (note == 255)
-       {                       /* Just volume update */
-               v->velocity = volume;
-               if (voice_active[voice])
-                       update_volume(voice);
-               restore_flags(flags);
-               return 0;
-       }
-       voice_active[voice] = 0;        /* Stop the voice for a while */
-       devc->vibratomap &= ~(1 << voice);
-       devc->tremolomap &= ~(1 << voice);
-
-       instr = v->instr;
-       if (instr < 0 || instr > MAX_PATCH || devc->programs[instr] == NO_SAMPLE)
-       {
-               printk(KERN_WARNING "SoftOSS: Undefined MIDI instrument %d\n", instr);
-               restore_flags(flags);
-               return 0;
-       }
-       instr = devc->programs[instr];
-
-       if (instr < 0 || instr >= devc->nrsamples)
-       {
-               printk(KERN_WARNING "SoftOSS: Corrupted MIDI instrument %d (%d)\n", v->instr, instr);
-               restore_flags(flags);
-               return 0;
-       }
-       note_freq = note_to_freq(note);
-
-       selected = -1;
-
-       best_sample = instr;
-       best_delta = 1000000;
-
-       while (instr != NO_SAMPLE && instr >= 0 && selected == -1)
-       {
-               delta_freq = note_freq - devc->samples[instr]->base_note;
-
-               if (delta_freq < 0)
-                       delta_freq = -delta_freq;
-               if (delta_freq < best_delta)
-               {
-                       best_sample = instr;
-                       best_delta = delta_freq;
-               }
-               if (devc->samples[instr]->low_note <= note_freq &&
-                       note_freq <= devc->samples[instr]->high_note)
-               {
-                       selected = instr;
-               }
-               else instr = devc->samples[instr]->key; /* Link to next sample */
-
-               if (instr < 0 || instr >= devc->nrsamples)
-                       instr = NO_SAMPLE;
-       }
-
-       if (selected == -1)
-               instr = best_sample;
-       else
-               instr = selected;
-
-       if (instr < 0 || instr == NO_SAMPLE || instr > devc->nrsamples)
-       {
-               printk(KERN_WARNING "SoftOSS: Unresolved MIDI instrument %d\n", v->instr);
-               restore_flags(flags);
-               return 0;
-       }
-       sample = devc->samples[instr];
-       v->sample = sample;
-
-       if (v->percussive_voice)        /* No key tracking */
-                 v->orig_freq = sample->base_freq;     /* Fixed pitch */
-       else
-       {
-               base_note = sample->base_note / 100;
-               note_freq /= 100;
-
-               freq = sample->base_freq * note_freq / base_note;
-               v->orig_freq = freq;
-       }
-
-       if (!(sample->mode & WAVE_LOOPING))
-               sample->loop_end = sample->len;
-
-       v->wave = devc->wave[instr];
-       if (volume < 0)
-               volume = 0;
-       else if (volume > 127)
-               volume = 127;
-       v->ptr = 0;
-       v->startloop = sample->loop_start * 512;
-       v->startbackloop = 0;
-       v->endloop = sample->loop_end * 512;
-       v->looplen = (sample->loop_end - sample->loop_start) * 512;
-       v->leftvol = 64;
-       v->rightvol = 64;
-       v->patch_vol = sample->volume;
-       v->velocity = volume;
-       v->mode = sample->mode;
-       v->vibrato_phase = 0;
-       v->vibrato_step = 0;
-       v->vibrato_level = 0;
-       v->vibrato_rate = 0;
-       v->vibrato_depth = 0;
-       v->tremolo_phase = 0;
-       v->tremolo_step = 0;
-       v->tremolo_level = 0;
-       v->tremolo_rate = 0;
-       v->tremolo_depth = 0;
-
-       if (!(v->mode & WAVE_LOOPING))
-               v->mode &= ~(WAVE_BIDIR_LOOP | WAVE_LOOP_BACK);
-       else if (v->mode & WAVE_LOOP_BACK)
-       {
-               v->ptr = sample->len;
-               v->startbackloop = v->startloop;
-       }
-       if (v->mode & WAVE_VIBRATO)
-       {
-               v->vibrato_rate = sample->vibrato_rate;
-               v->vibrato_depth = sample->vibrato_depth;
-       }
-       if (v->mode & WAVE_TREMOLO)
-       {
-               v->tremolo_rate = sample->tremolo_rate;
-               v->tremolo_depth = sample->tremolo_depth;
-       }
-       if (v->mode & WAVE_ENVELOPES)
-       {
-               v->envelope_phase = -1;
-               v->envelope_vol = 0;
-               step_envelope(voice, 0, 60);
-       }
-       update_volume(voice);
-       compute_step(voice);
-
-       voice_active[voice] = 1;        /* Mark it active */
-       restore_flags(flags);
-       return 0;
-}
-
-static int softsyn_open(int synthdev, int mode)
-{
-       int err;
-       extern int softoss_dev;
-       int frags = 0x7fff0007; /* fragment size of 128 bytes */
-       mm_segment_t fs;
-
-       if (devc->audio_opened) /* Already opened */
-               return 0;
-
-       softsynth_disabled = 0;
-       devc->finfo.f_mode = FMODE_WRITE;
-       devc->finfo.f_flags = 0;
-
-       if (softoss_dev >= num_audiodevs)
-               softoss_dev = num_audiodevs - 1;
-
-       if (softoss_dev < 0)
-               softoss_dev = 0;
-       if (softoss_dev >= num_audiodevs)
-               return -ENXIO;
-       devc->audiodev = softoss_dev;
-
-       if (!(audio_devs[devc->audiodev]->format_mask & AFMT_S16_LE))
-       {
-/*             printk(KERN_ERR "SoftOSS: The audio device doesn't support 16 bits\n"); */
-               return -ENXIO;
-       }
-       if ((err = audio_open((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo)) < 0)
-               return err;
-
-       devc->speed = audio_devs[devc->audiodev]->d->set_speed(
-                                           devc->audiodev, devc->speed);
-       devc->channels = audio_devs[devc->audiodev]->d->set_channels(
-                                        devc->audiodev, devc->channels);
-       devc->bits = audio_devs[devc->audiodev]->d->set_bits(
-                                            devc->audiodev, devc->bits);
-
-
-       DDB(printk("SoftOSS: Using audio dev %d, speed %d, bits %d, channels %d\n", devc->audiodev, devc->speed, devc->bits, devc->channels));
-       fs = get_fs();
-       set_fs(get_ds());
-       dma_ioctl(devc->audiodev, SNDCTL_DSP_SETFRAGMENT, (caddr_t) & frags);
-       dma_ioctl(devc->audiodev, SNDCTL_DSP_GETBLKSIZE, (caddr_t) & devc->fragsize);
-       set_fs(fs);
-
-       if (devc->bits != 16 || devc->channels != 2)
-       {
-               audio_release((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo);
-/*             printk("SoftOSS: A 16 bit stereo sound card is required\n");*/
-               return -EINVAL;
-       }
-       if (devc->max_playahead >= audio_devs[devc->audiodev]->dmap_out->nbufs)
-               devc->max_playahead = audio_devs[devc->audiodev]->dmap_out->nbufs;
-
-       DDB(printk("SoftOSS: Using %d fragments of %d bytes\n", devc->max_playahead, devc->fragsize));
-
-       init_engine(devc);
-       devc->audio_opened = 1;
-       devc->sequencer_mode = mode;
-       return 0;
-}
-
-static void softsyn_close(int synthdev)
-{
-       mm_segment_t fs;
-
-       devc->engine_state = ES_STOPPED;
-#ifdef POLLED_MODE
-       del_timer(&poll_timer);
-#endif
-       fs = get_fs();
-       set_fs(get_ds());
-       dma_ioctl(devc->audiodev, SNDCTL_DSP_RESET, 0);
-       set_fs(fs);
-       if (devc->audio_opened)
-               audio_release((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo);
-       devc->audio_opened = 0;
-}
-
-static void softsyn_hw_control(int dev, unsigned char *event_rec)
-{
-       int voice, cmd;
-       unsigned short p1, p2;
-       unsigned int plong;
-
-       cmd = event_rec[2];
-       voice = event_rec[3];
-       p1 = *(unsigned short *) &event_rec[4];
-       p2 = *(unsigned short *) &event_rec[6];
-       plong = *(unsigned int *) &event_rec[4];
-
-       switch (cmd)
-       {
-
-               case _GUS_NUMVOICES:
-                       set_max_voices(p1);
-                       break;
-
-               default:;
-       }
-}
-
-static int softsyn_load_patch(int dev, int format, const char *addr,
-                  int offs, int count, int pmgr_flag)
-{
-       struct patch_info *patch = NULL;
-
-       int i, p, instr;
-       long sizeof_patch;
-       int memlen, adj;
-       unsigned short  data;
-       short *wave = NULL;
-
-       sizeof_patch = (long) &patch->data[0] - (long) patch;   /* Header size */
-
-       if (format != GUS_PATCH)
-       {
-/*             printk(KERN_ERR "SoftOSS: Invalid patch format (key) 0x%x\n", format);*/
-               return -EINVAL;
-       }
-       if (count < sizeof_patch)
-       {
-/*             printk(KERN_ERR "SoftOSS: Patch header too short\n");*/
-               return -EINVAL;
-       }
-       count -= sizeof_patch;
-
-       if (devc->nrsamples >= MAX_SAMPLE)
-       {
-/*               printk(KERN_ERR "SoftOSS: Sample table full\n");*/
-                 return -ENOBUFS;
-       }
-       
-       /*
-        * Copy the header from user space but ignore the first bytes which have
-        * been transferred already.
-        */
-
-       patch = vmalloc(sizeof(*patch));
-
-       if (patch == NULL)
-       {
-/*             printk(KERN_ERR "SoftOSS: Out of memory\n");*/
-               return -ENOMEM;
-       }
-       if(copy_from_user(&((char *) patch)[offs], &(addr)[offs], sizeof_patch - offs))
-       {
-               vfree(patch);
-               return -EFAULT;
-       }
-
-       if (patch->mode & WAVE_ROM)
-       {
-               vfree(patch);
-               return -EINVAL;
-       }
-       instr = patch->instr_no;
-
-       if (instr < 0 || instr > MAX_PATCH)
-       {
-/*             printk(KERN_ERR "SoftOSS: Invalid patch number %d\n", instr);*/
-               vfree(patch);
-               return -EINVAL;
-       }
-       if (count < patch->len)
-       {
-/*             printk(KERN_ERR "SoftOSS: Patch record too short (%d<%d)\n", count, (int) patch->len);*/
-               patch->len = count;
-       }
-       if (patch->len <= 0 || patch->len > (devc->ram_size - devc->ram_used))
-       {
-/*             printk(KERN_ERR "SoftOSS: Invalid sample length %d\n", (int) patch->len); */
-               vfree(patch);
-               return -EINVAL;
-       }
-       if (patch->mode & WAVE_LOOPING)
-       {
-               if (patch->loop_start < 0 || patch->loop_start >= patch->len)
-               {
-/*                     printk(KERN_ERR "SoftOSS: Invalid loop start %d\n", patch->loop_start);*/
-                       vfree(patch);
-                       return -EINVAL;
-               }
-               if (patch->loop_end < patch->loop_start || patch->loop_end > patch->len)
-               {
-/*                     printk(KERN_ERR "SoftOSS: Invalid loop start or end point (%d, %d)\n", patch->loop_start, patch->loop_end);*/
-                       vfree(patch);
-                       return -EINVAL;
-               }
-       }
-       /* 
-        *      Next load the wave data to memory
-        */
-
-       memlen = patch->len;
-       adj = 1;
-
-       if (!(patch->mode & WAVE_16_BITS))
-               memlen *= 2;
-       else
-               adj = 2;
-
-       wave = vmalloc(memlen);
-
-       if (wave == NULL)
-       {
-/*             printk(KERN_ERR "SoftOSS: Can't allocate %d bytes of mem for a sample\n", memlen);*/
-               vfree(patch);
-               return -ENOMEM;
-       }
-       p = 0;
-       for (i = 0; i < memlen / 2; i++)        /* Handle words */
-       {
-               unsigned char tmp;
-               data = 0;
-               if (patch->mode & WAVE_16_BITS)
-               {
-                       get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++]));             /* Get lsb */
-                       data = tmp;
-                       get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++]));             /* Get msb */
-                       if (patch->mode & WAVE_UNSIGNED)
-                               tmp ^= 0x80;    /* Convert to signed */
-                       data |= (tmp << 8);
-               }
-               else
-               {
-                       get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++]));
-                       if (patch->mode & WAVE_UNSIGNED)
-                               tmp ^= 0x80;    /* Convert to signed */
-                           data = (tmp << 8);  /* Convert to 16 bits */
-               }
-               wave[i] = (short) data;
-       }
-
-       devc->ram_used += patch->len;
-
-       /*
-        * Convert pointers to 16 bit indexes
-        */
-       patch->len /= adj;
-       patch->loop_start /= adj;
-       patch->loop_end /= adj;
-
-       /*
-        * Finally link the loaded patch to the chain
-        */
-
-       patch->key = devc->programs[instr];
-       devc->programs[instr] = devc->nrsamples;
-       devc->wave[devc->nrsamples] = (short *) wave;
-       devc->samples[devc->nrsamples++] = patch;
-
-       return 0;
-}
-
-static void softsyn_panning(int dev, int voice, int pan)
-{
-       if (voice < 0 || voice > devc->maxvoice)
-               return;
-
-       if (pan < -128)
-               pan = -128;
-       if (pan > 127)
-               pan = 127;
-
-       softoss_voices[voice].panning = pan;
-       if (voice_active[voice])
-               update_volume(voice);
-}
-
-static void softsyn_volume_method(int dev, int mode)
-{
-}
-
-static void softsyn_aftertouch(int dev, int voice, int pressure)
-{
-       if (voice < 0 || voice > devc->maxvoice)
-               return;
-
-       if (voice_active[voice])
-               update_volume(voice);
-}
-
-static void softsyn_controller(int dev, int voice, int ctrl_num, int value)
-{
-       unsigned long flags;
-
-       if (voice < 0 || voice > devc->maxvoice)
-               return;
-       save_flags(flags);
-       cli();
-
-       switch (ctrl_num)
-       {
-               case CTRL_PITCH_BENDER:
-                       softoss_voices[voice].bender = value;
-                       if (voice_active[voice])
-                               compute_step(voice);    /* Update pitch */
-                       break;
-
-
-               case CTRL_PITCH_BENDER_RANGE:
-                       softoss_voices[voice].bender_range = value;
-                       break;
-                       
-               case CTL_EXPRESSION:
-                       value /= 128;
-               case CTRL_EXPRESSION:
-                       softoss_voices[voice].expression_vol = value;
-                       if (voice_active[voice])
-                               update_volume(voice);
-                       break;
-
-               case CTL_PAN:
-                       softsyn_panning(dev, voice, (value * 2) - 128);
-                       break;
-
-               case CTL_MAIN_VOLUME:
-                       value = (value * 100) / 16383;
-
-               case CTRL_MAIN_VOLUME:
-                       softoss_voices[voice].main_vol = value;
-                       if (voice_active[voice])
-                               update_volume(voice);
-                       break;
-
-               default:
-                       break;
-       }
-       restore_flags(flags);
-}
-
-static void softsyn_bender(int dev, int voice, int value)
-{
-       if (voice < 0 || voice > devc->maxvoice)
-               return;
-
-       softoss_voices[voice].bender = value - 8192;
-       if (voice_active[voice])
-               compute_step(voice);    /* Update pitch */
-}
-
-static int softsyn_alloc_voice(int dev, int chn, int note, struct voice_alloc_info *alloc)
-{
-       int i, p, best = -1, best_time = 0x7fffffff;
-
-       p = alloc->ptr;
-
-       /*
-        * First look for a completely stopped voice
-        */
-
-       for (i = 0; i < alloc->max_voice; i++)
-       {
-               if (alloc->map[p] == 0)
-               {
-                       alloc->ptr = p;
-                       voice_active[p] = 0;
-                       return p;
-               }
-               if (alloc->alloc_times[p] < best_time)
-               {
-                       best = p;
-                       best_time = alloc->alloc_times[p];
-               }
-               p = (p + 1) % alloc->max_voice;
-       }
-
-       /*
-        * Then look for a releasing voice
-        */
-
-       for (i = 0; i < alloc->max_voice; i++)
-       {
-               if (alloc->map[p] == 0xffff)
-               {
-                       alloc->ptr = p;
-                       voice_active[p] = 0;
-                       return p;
-               }
-               p = (p + 1) % alloc->max_voice;
-       }
-
-       if (best >= 0)
-               p = best;
-
-       alloc->ptr = p;
-       voice_active[p] = 0;
-       return p;
-}
-
-static void softsyn_setup_voice(int dev, int voice, int chn)
-{
-       unsigned long flags;
-
-       struct channel_info *info = &synth_devs[dev]->chn_info[chn];
-
-       save_flags(flags);
-       cli();
-
-       /* init_voice(devc, voice); */
-       softsyn_set_instr(dev, voice, info->pgm_num);
-
-       softoss_voices[voice].expression_vol = info->controllers[CTL_EXPRESSION];       /* Just MSB */
-       softoss_voices[voice].main_vol = (info->controllers[CTL_MAIN_VOLUME] * 100) / (unsigned) 128;
-       softsyn_panning(dev, voice, (info->controllers[CTL_PAN] * 2) - 128);
-       softoss_voices[voice].bender = 0;       /* info->bender_value; */
-       softoss_voices[voice].bender_range = info->bender_range;
-
-       if (chn == 9)
-               softoss_voices[voice].percussive_voice = 1;
-       restore_flags(flags);
-}
-
-static void softsyn_reset(int devno)
-{
-       int i;
-       unsigned long flags;
-
-       save_flags(flags);
-       cli();
-
-       for (i = 0; i < devc->maxvoice; i++)
-               init_voice(devc, i);
-       restore_flags(flags);
-}
-
-static struct synth_operations softsyn_operations =
-{
-       owner:          THIS_MODULE,
-       id:             "SoftOSS",
-       info:           &softsyn_info,
-       midi_dev:       0,
-       synth_type:     SYNTH_TYPE_SAMPLE,
-       synth_subtype:  0,
-       open:           softsyn_open,
-       close:          softsyn_close,
-       ioctl:          softsyn_ioctl,
-       kill_note:      softsyn_kill_note,
-       start_note:     softsyn_start_note,
-       set_instr:      softsyn_set_instr,
-       reset:          softsyn_reset,
-       hw_control:     softsyn_hw_control,
-       load_patch:     softsyn_load_patch,
-       aftertouch:     softsyn_aftertouch,
-       controller:     softsyn_controller,
-       panning:        softsyn_panning,
-       volume_method:  softsyn_volume_method,
-       bender:         softsyn_bender,
-       alloc_voice:    softsyn_alloc_voice,
-       setup_voice:    softsyn_setup_voice
-};
-
-/*
- * Timer stuff (for /dev/music).
- */
-
-static unsigned int soft_tmr_start(int dev, unsigned int usecs)
-{
-       tmr_running = 1;
-       start_engine(devc);
-       return devc->usecs_per_frag;
-}
-
-static void soft_tmr_disable(int dev)
-{
-       stop_engine(devc);
-       tmr_running = 0;
-}
-
-static void soft_tmr_restart(int dev)
-{
-       tmr_running = 1;
-}
-
-static struct sound_lowlev_timer soft_tmr =
-{
-       0,
-       9999,
-       soft_tmr_start,
-       soft_tmr_disable,
-       soft_tmr_restart
-};
-
-static int __init probe_softsyn(struct address_info *hw_config)
-{
-       int i;
-
-       if (softsynth_loaded)
-               return 0;
-
-       devc->ram_size = 8 * 1024 * 1024;
-       devc->ram_used = 0;
-       devc->nrsamples = 0;
-       for (i = 0; i < MAX_PATCH; i++)
-       {
-               devc->programs[i] = NO_SAMPLE;
-               devc->wave[i] = NULL;
-       }
-
-       devc->maxvoice = DEFAULT_VOICES;
-
-       devc->audiodev = 0;
-       devc->audio_opened = 0;
-       devc->channels = 2;
-       devc->bits = 16;
-       devc->max_playahead = 32;
-
-#ifdef CONFIG_SOFTOSS_RATE
-       devc->speed = CONFIG_SOFTOSS_RATE;
-#else
-       devc->speed = 32000;
-#endif
-
-#ifdef CONFIG_SOFTOSS_VOICES
-       devc->default_max_voices = CONFIG_SOFTOSS_VOICES;
-#else
-       devc->default_max_voices = 32;
-#endif
-       softsynth_loaded = 1;
-       return 1;
-}
-
-static void __init attach_softsyn_card(struct address_info *hw_config)
-{
-       voice_alloc = &softsyn_operations.alloc;
-       synth_devs[devc->synthdev = num_synths++] = &softsyn_operations;
-       sequencer_init();
-       sound_timer_init(&soft_tmr, "SoftOSS");
-       devc->timerdev = num_sound_timers;
-       softsynthp = softsynth_hook;
-
-#ifndef POLLED_MODE
-#endif
-}
-
-static void __exit unload_softsyn(struct address_info *hw_config)
-{
-       if (!softsynth_loaded)
-               return;
-       softsynthp = NULL;
-       softsynth_loaded = 0;
-       reset_samples(devc);
-}
-
-static struct address_info cfg;
-
-static int __init init_softoss(void)
-{
-       printk(KERN_INFO "SoftOSS driver Copyright (C) by Hannu Savolainen 1993-1997\n");
-       if (!probe_softsyn(&cfg))
-               return -ENODEV;
-       attach_softsyn_card(&cfg);
-
-       return 0;
-}
-
-static void __exit cleanup_softoss(void)
-{
-       unload_softsyn(&cfg);
-       sound_unload_synthdev(devc->synthdev);
-       sound_unload_timerdev(devc->timerdev);
-}
-
-module_init(init_softoss);
-module_exit(cleanup_softoss);
diff --git a/drivers/sound/softoss.h b/drivers/sound/softoss.h
deleted file mode 100644 (file)
index 42dab13..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * softoss.h   - Definitions for Software MIDI Synthesizer.
- */
-/*
- * Copyright (C) by Hannu Savolainen 1993-1997
- *
- * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
- * Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info.
- */
-
-
-/*
- * Sequencer mode1 timer calls made by sequencer.c
- */
-extern int (*softsynthp) (int cmd, int parm1, int parm2, unsigned long parm3);
-
-#define SSYN_START     1
-#define SSYN_REQUEST   2       /* parm1 = time */
-#define SSYN_STOP      3
-#define SSYN_GETTIME   4       /* Returns number of ticks since reset */
-
-#define MAX_PATCH 256
-#define MAX_SAMPLE 512
-#define MAX_VOICE 32
-#define DEFAULT_VOICES 16
-
-typedef struct voice_info
-{
-/*
- * Don't change anything in the beginning of this struct. These fields are used
- * by the resampling loop which may have been written in assembly for some
- * architectures. Any change may make the resampling code incompatible
- */
-  int instr;
-  short *wave;
-  struct patch_info *sample;
-
-  unsigned int ptr; int step; /* Pointer to the wave data and pointer increment */
-
-  int mode;
-  int startloop, startbackloop, endloop, looplen;
-
-  unsigned int leftvol, rightvol;
-/***** Don't change anything above this */
-
-  volatile unsigned long orig_freq, current_freq;
-  volatile int bender, bender_range, panning;
-  volatile int main_vol, expression_vol, patch_vol, velocity;
-
-/* Envelope parameters */
-
-  int envelope_phase;
-  volatile int envelope_vol;
-  volatile int envelope_volstep;
-  int envelope_time; /* Number of remaining envelope steps */
-  unsigned int envelope_target;
-  int percussive_voice;
-  int sustain_mode; /* 0=off, 1=sustain on, 2=sustain on+key released */
-
-/*     Vibrato */
-  int vibrato_rate;
-  int vibrato_depth;
-  int vibrato_phase;
-  int vibrato_step;
-  int vibrato_level;
-
-/*     Tremolo */
-  int tremolo_rate;
-  int tremolo_depth;
-  int tremolo_phase;
-  int tremolo_step;
-  int tremolo_level;
-} voice_info;
-
-extern voice_info softoss_voices[MAX_VOICE]; /* Voice spesific info */
-
-typedef struct softsyn_devc
-{
-/*
- * Don't change anything in the beginning of this struct. These fields are used
- * by the resampling loop which may have been written in assembly for some
- * architectures. Any change may make the resampling code incompatible
- */
-       int maxvoice;           /* # of voices to be processed */
-       int afterscale;
-       int delay_size;
-       int control_rate, control_counter;
-/***** Don't change anything above this */
-
-       int ram_size;
-       int ram_used;
-
-       int synthdev;
-       int timerdev;
-       int sequencer_mode;
-/*
- *     Audio parameters
- */
-
-       int audiodev;
-       int audio_opened;
-       int speed;
-       int channels;
-       int bits;
-       int default_max_voices;
-       int max_playahead;
-       struct file finfo;
-       int fragsize;
-       int samples_per_fragment;
-       
-/*
- *     Sample storage
- */
-       int nrsamples;
-       struct patch_info *samples[MAX_SAMPLE];
-       short *wave[MAX_SAMPLE];
-
-/*
- *     Programs
- */
-       int programs[MAX_PATCH];
-
-/*
- *     Timer parameters
- */
-       volatile unsigned long usecs;
-       volatile unsigned long usecs_per_frag;
-       volatile unsigned long next_event_usecs;
-
-/*
- *     Engine state
- */
-
-       volatile int engine_state;
-#define ES_STOPPED                     0
-#define ES_STARTED                     1
-
-       /* Voice spesific bitmaps */
-       volatile int tremolomap; 
-       volatile int vibratomap;
-
-} softsyn_devc;
-
-void softsynth_resample_loop(short *buf, int loops);
-extern void softsyn_control_loop(void);
-
-#define DELAY_SIZE     4096
-
-#ifdef SOFTSYN_MAIN
-  short voice_active[MAX_VOICE] = {0};
-  voice_info softoss_voices[MAX_VOICE] = {{0}}; /* Voice spesific info */
-  int left_delay[DELAY_SIZE]={0}, right_delay[DELAY_SIZE]={0};
-  int delayp=0;
-#else
-  extern softsyn_devc *devc;
-
-  extern int left_delay[DELAY_SIZE], right_delay[DELAY_SIZE];
-  extern int delayp;
-  extern short voice_active[MAX_VOICE];
-#endif
diff --git a/drivers/sound/softoss_rs.c b/drivers/sound/softoss_rs.c
deleted file mode 100644 (file)
index 627ff9b..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-
-/*
- * sound/softoss_rs.c
- *
- * Software based MIDI synthsesizer driver, the actual mixing loop.
- * Keep the loop as simple as possible to make it easier to rewrite this 
- * routine in assembly.
- *
- *
- * Copyright (C) by Hannu Savolainen 1993-1997
- *
- * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
- * Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info.
- */
-#include "sound_config.h"
-#include "softoss.h"
-
-void softsynth_resample_loop(short *buf, int loops)
-{
-       int iloop, voice;
-       volatile voice_info *v;
-
-#ifdef OSS_BIG_ENDIAN
-       unsigned char  *cbuf = (unsigned char *) buf;
-
-#endif
-
-       for (iloop = 0; iloop < loops; iloop++)
-       {                       /* Mix one sample */
-               int accum, left = 0, right = 0;
-               int ix, position;
-
-               for (voice = 0; voice < devc->maxvoice; voice++)
-               {
-                       if (voice_active[voice])
-                       {       /* Compute voice */
-                               v = &softoss_voices[voice];
-#ifdef SOFTOSS_TEST
-                               ix = iloop << 3;
-                               position = v->ptr;
-#else
-                               ix = (position = v->ptr) >> 9;
-#endif
-                               /* Interpolation (resolution of 512 steps) */
-                               {
-                                       int fract = v->ptr & 0x1ff;     /* 9 bits */
-
-                                       /* This method works with less arithmetic operations */
-                                       register int v1 = v->wave[ix];
-                                       accum = v1 + ((((v->wave[ix + 1] - v1)) * (fract)) >> 9);
-                               }
-
-                               left += (accum * v->leftvol);
-                               right += (accum * v->rightvol);
-
-                               /* Update sample pointer */
-                               position += v->step;
-                               if (position <= v->endloop)
-                                       v->ptr = position;
-                               else if (v->mode & WAVE_LOOPING)
-                               {
-                                       if (v->mode & WAVE_BIDIR_LOOP)
-                                       {                                                       v->mode ^= WAVE_LOOP_BACK;      /* Turn around */
-                                               v->step *= -1;
-                                       }
-                                       else
-                                       {
-                                               position -= v->looplen;
-                                               v->ptr = position;
-                                       }
-                               }
-                               /*  else leave the voice looping the current sample */
-
-                               if (v->mode & WAVE_LOOP_BACK && position < v->startloop)
-                               {
-                                       if (v->mode & WAVE_BIDIR_LOOP)
-                                       {                                                       v->mode ^= WAVE_LOOP_BACK;      /* Turn around */
-                                               v->step *= -1;
-                                       }
-                                       else
-                                       {
-                                               position += v->looplen;
-                                               v->ptr = position;
-                                       }
-                               }
-                       }       /* Compute voice */
-               }
-#if 1                          /* Delay */
-               left += left_delay[delayp];
-               right += right_delay[delayp];
-
-               left_delay[delayp] = right >> 2;
-               right_delay[delayp] = left >> 2;
-               delayp = (delayp + 1) % devc->delay_size;
-#endif
-
-#define AFTERSCALE devc->afterscale;
-
-               left >>= AFTERSCALE;
-               right >>= AFTERSCALE;
-
-               if (left > 32767)
-                       left = 32767;
-               if (left < -32768)
-                       left = -32768;
-               if (right > 32767)
-                       right = 32767;
-               if (right < -32768)
-                       right = -32768;
-
-#ifdef OSS_BIG_ENDIAN
-               *cbuf++ = left & 0xff;
-               *cbuf++ = (left >> 8) & 0xff;
-               *cbuf++ = right & 0xff;
-               *cbuf++ = (right >> 8) & 0xff;
-#else
-               *buf++ = left;
-               *buf++ = right;
-#endif
-               if (devc->control_counter++ >= devc->control_rate)
-               {
-                       devc->control_counter = 0;
-                       softsyn_control_loop();
-               }
-       }                       /* Mix one sample */
-}
index 8a85d4c424eedcd5fd50c2c9e3cc27b11d862214..dd174bfa687037da95e0e78cbfa09088104e85b3 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/init.h>
 #include <linux/malloc.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -62,9 +63,6 @@ extern int msnd_classic_init(void);
 #ifdef CONFIG_SOUND_MSNDPIN
 extern int msnd_pinnacle_init(void);
 #endif
-#ifdef CONFIG_SOUND_CMPCI
-extern int init_cmpci(void);
-#endif
 
 /*
  *     Low level list operator. Scan the ordered list, find a hole and
@@ -545,12 +543,11 @@ int soundcore_open(struct inode *inode, struct file *file)
 extern int mod_firmware_load(const char *, char **);
 EXPORT_SYMBOL(mod_firmware_load);
 
-#ifdef MODULE
 
 MODULE_DESCRIPTION("Core sound module");
 MODULE_AUTHOR("Alan Cox");
 
-void cleanup_module(void)
+static void __exit cleanup_soundcore(void)
 {
        /* We have nothing to really do here - we know the lists must be
           empty */
@@ -558,10 +555,7 @@ void cleanup_module(void)
        devfs_unregister (devfs_handle);
 }
 
-int init_module(void)
-#else
-int soundcore_init(void)
-#endif
+static int __init init_soundcore(void)
 {
        if(devfs_register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops)==-1)
        {
@@ -569,20 +563,9 @@ int soundcore_init(void)
                return -EBUSY;
        }
        devfs_handle = devfs_mk_dir (NULL, "sound", NULL);
-       /*
-        *      Now init non OSS drivers
-        */
-#ifdef CONFIG_SOUND_CMPCI
-       init_cmpci();
-#endif
-#ifdef CONFIG_SOUND_MSNDCLAS
-       msnd_classic_init();
-#endif
-#ifdef CONFIG_SOUND_MSNDPIN
-       msnd_pinnacle_init();
-#endif
-#ifdef CONFIG_SOUND_VWSND
-       init_vwsnd();
-#endif
+
        return 0;
 }
+
+module_init(init_soundcore);
+module_exit(cleanup_soundcore);
index 764687756ee88afb955e5d0f0ecb9ad670393347..30ca5db36217ab1ed4f97e87aa33d98e4c777108 100644 (file)
@@ -49,8 +49,5 @@ EXPORT_SYMBOL(load_mixer_volumes);
 EXPORT_SYMBOL(conf_printf);
 EXPORT_SYMBOL(conf_printf2);
 
-extern int softoss_dev;
-EXPORT_SYMBOL(softoss_dev);
-
 MODULE_DESCRIPTION("OSS Sound subsystem");
 MODULE_AUTHOR("Hannu Savolainen, et al.");
index ae77b1f74cb3379dd7fab47dbf8c092bfecd4d93..87ec7f181421199cccab76a8bf3d69727eb94691 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/config.h>
 
 #include "sound_config.h"
+#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
@@ -51,8 +52,6 @@
 #define valid_dma(n) ((n) >= 0 && (n) < MAX_DMA_CHANNELS && (n) != 4)
 #endif
 
-static int      chrdev_registered = 0;
-
 /*
  * Table for permanently allocated memory (used when unloading the module)
  */
@@ -583,34 +582,6 @@ static void soundcard_register_devfs (int do_register)
        }
 }
 
-#ifdef MODULE
-static void
-#else
-void
-#endif
-soundcard_init(void)
-{
-       /* drag in sound_syms.o */
-       {
-               extern char sound_syms_symbol;
-               sound_syms_symbol = 0;
-       }
-
-#ifndef MODULE
-       create_special_devices();
-       chrdev_registered = 1;
-#endif
-
-       soundcard_register_devfs(1); /* register after we know # of devices */
-}
-
-#ifdef MODULE
-
-static void destroy_special_devices(void)
-{
-       unregister_sound_special(1);
-       unregister_sound_special(8);
-}
 
 static int dmabuf = 0;
 static int dmabug = 0;
@@ -618,14 +589,21 @@ static int dmabug = 0;
 MODULE_PARM(dmabuf, "i");
 MODULE_PARM(dmabug, "i");
 
-int init_module(void)
+static int __init oss_init(void)
 {
        int             err;
+       
+       /* drag in sound_syms.o */
+       {
+               extern char sound_syms_symbol;
+               sound_syms_symbol = 0;
+       }
 
 #ifdef CONFIG_PCI
        if(dmabug)
                isa_dma_bridge_buggy = dmabug;
 #endif
+
        err = create_special_devices();
        if (err) {
                printk(KERN_ERR "sound: driver already loaded/included in kernel\n");
@@ -635,8 +613,7 @@ int init_module(void)
        /* Protecting the innocent */
        sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
 
-       chrdev_registered = 1;
-       soundcard_init();
+       soundcard_register_devfs(1);
 
        if (sound_nblocks >= 1024)
                printk(KERN_ERR "Sound warning: Deallocation table was too small.\n");
@@ -644,7 +621,7 @@ int init_module(void)
        return 0;
 }
 
-void cleanup_module(void)
+static void __exit oss_cleanup(void)
 {
        int i;
 
@@ -652,8 +629,9 @@ void cleanup_module(void)
                return;
 
        soundcard_register_devfs (0);
-       if (chrdev_registered)
-               destroy_special_devices();
+       
+       unregister_sound_special(1);
+       unregister_sound_special(8);
 
        sound_stop_timer();
 
@@ -669,7 +647,10 @@ void cleanup_module(void)
                vfree(sound_mem_blocks[i]);
 
 }
-#endif
+
+module_init(oss_init);
+module_exit(oss_cleanup);
+
 
 int sound_alloc_dma(int chn, char *deviceID)
 {
index 7a553020afe80f28b84fd766a0d627765c0bd1ea..0fb310dd047e92f668b8c90203a72551d4cfbbfa 100644 (file)
@@ -83,7 +83,6 @@ static unsigned int   vidc_audio_volume_r;    /* right PCM vol, 0 - 65536 */
 static void    (*old_mksound)(unsigned int hz, unsigned int ticks);
 extern void    (*kd_mksound)(unsigned int hz, unsigned int ticks);
 extern void    vidc_update_filler(int bits, int channels);
-extern int     softoss_dev;
 
 static void
 vidc_mksound(unsigned int hz, unsigned int ticks)
@@ -475,9 +474,6 @@ static void __init attach_vidc(struct address_info *hw_config)
        vidc_adev = adev;
        vidc_mixer_set(SOUND_MIXER_VOLUME, (85 | 85 << 8));
 
-#if defined(CONFIG_SOUND_SOFTOSS) || defined(CONFIG_SOUND_SOFTOSS_MODULE)
-       softoss_dev = adev;
-#endif
        return;
 
 irq_failed:
index 3ba0479627646265d8b300f89419ad68deec0d7c..be2cdf6783b2de58c0ead5d20ac3c7c21802ebbd 100644 (file)
  */
 
 #include <linux/module.h>
+#include <linux/init.h>
+
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
@@ -3452,12 +3454,10 @@ static struct address_info the_hw_config = {
        CO_IRQ(CO_APIC_LI_AUDIO)        /* irq */
 };
 
-#ifdef MODULE
-
 MODULE_DESCRIPTION("SGI Visual Workstation sound module");
 MODULE_AUTHOR("Bob Miller <kbob@sgi.com>");
 
-extern int init_module(void)
+static int __init init_vwsnd(void)
 {
        int err;
 
@@ -3472,23 +3472,15 @@ extern int init_module(void)
        return 0;
 }
 
-extern void cleanup_module(void)
+static void __exit cleanup_vwsnd(void)
 {
        DBGX("sound::vwsnd::cleanup_module()\n");
 
        unload_vwsnd(&the_hw_config);
 }
 
-#else
-
-extern void init_vwsnd(void)
-{
-       DBGX("sound::vwsnd::init_vwsnd()\n");
-       if (probe_vwsnd(&the_hw_config))
-               (void) attach_vwsnd(&the_hw_config);
-}
-
-#endif /* !MODULE */
+module_init(init_vwsnd);
+module_exit(cleanup_vwsnd);
 
 /*
  * Local variables:
index 67a55ab463e67bf5c353271f7e95fc0229a247b1..db236778def72fa373134da440407f33b1c8cc72 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1999-2000 by David Brownell <david-b@pacbell.net>
+ * Copyright (C) 1999-2000 by David Brownell <dbrownell@users.sourceforge.net>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -90,6 +90,7 @@ static const struct camera {
        /* These have the same application level protocol */  
     { 0x040a, 0x0120 },                // Kodak DC-240
     { 0x040a, 0x0130 },                // Kodak DC-280
+    { 0x040a, 0x0132 },                // Kodak DC-3400
 
        /* These have a different application level protocol which
         * is part of the Flashpoint "DigitaOS".  That supports some
@@ -498,7 +499,7 @@ void __exit usb_dc2xx_cleanup(void)
 }
 
 
-MODULE_AUTHOR("David Brownell, david-b@pacbell.net");
+MODULE_AUTHOR("David Brownell, <dbrownell@users.sourceforge.net>");
 MODULE_DESCRIPTION("USB Camera Driver for Kodak DC-2xx series cameras");
 
 module_init (usb_dc2xx_init);
index 70e0150cbfb50de67f8d15e874d917d892387b67..e2b53b45cd65ec46c98701ba1a6caa7429ce4b2e 100644 (file)
@@ -496,8 +496,10 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct
        lock_kernel();
        if (!st) {
                st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
-               if (!st)
+               if (!st) {
+                       unlock_kernel();
                        return POLLIN;
+               }
                /*
                 * need to prevent the module from being unloaded, since
                 * proc_unregister does not call the release method and
index 885e636bd38f3fc08db05587056d32b023540c2f..77fbf496cf8638ffb95ec215e10eb3a628cb95eb 100644 (file)
@@ -182,6 +182,8 @@ static void free_async(struct async *as)
 {
         if (as->urb.transfer_buffer)
                 kfree(as->urb.transfer_buffer);
+        if (as->urb.setup_packet)
+                kfree(as->urb.setup_packet);
         kfree(as);
 }
 
@@ -429,6 +431,28 @@ static int finddriver(struct usb_driver **driver, char *name)
 }
 #endif
 
+static int check_ctrlrecip(struct dev_state *ps, unsigned int recip, unsigned int index)
+{
+       int ret;
+
+       switch (recip & USB_RECIP_MASK) {
+       case USB_RECIP_ENDPOINT:
+               if ((ret = findintfep(ps->dev, index & 0xff)) < 0)
+                       return ret;
+               if ((ret = checkintf(ps, ret)))
+                       return ret;
+               break;
+
+       case USB_RECIP_INTERFACE:
+               if ((ret = findintfif(ps->dev, index & 0xff)) < 0)
+                       return ret;
+               if ((ret = checkintf(ps, ret)))
+                       return ret;
+               break;
+       }
+       return 0;
+}
+
 /*
  * file operations
  */
@@ -502,21 +526,8 @@ static int proc_control(struct dev_state *ps, void *arg)
 
        if (copy_from_user(&ctrl, (void *)arg, sizeof(ctrl)))
                return -EFAULT;
-       switch (ctrl.requesttype & 0x1f) {
-       case USB_RECIP_ENDPOINT:
-               if ((ret = findintfep(ps->dev, ctrl.index & 0xff)) < 0)
-                       return ret;
-               if ((ret = checkintf(ps, ret)))
-                       return ret;
-               break;
-
-       case USB_RECIP_INTERFACE:
-               if ((ret = findintfif(ps->dev, ctrl.index & 0xff)) < 0)
-                       return ret;
-               if ((ret = checkintf(ps, ret)))
-                       return ret;
-               break;
-       }
+       if ((ret = check_ctrlrecip(ps, ctrl.requesttype, ctrl.index)))
+               return ret;
        if (ctrl.length > PAGE_SIZE)
                return -EINVAL;
        if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
@@ -733,7 +744,9 @@ static int proc_submiturb(struct dev_state *ps, void *arg)
 {
        struct usbdevfs_urb uurb;
        struct usbdevfs_iso_packet_desc *isopkt = NULL;
+       struct usb_endpoint_descriptor *ep_desc;
        struct async *as;
+       devrequest *dr = NULL;
        unsigned int u, totlen, isofrmlen;
        int ret;
 
@@ -745,11 +758,47 @@ static int proc_submiturb(struct dev_state *ps, void *arg)
                return -EINVAL;
        if (uurb.signr != 0 && (uurb.signr < SIGRTMIN || uurb.signr > SIGRTMAX))
                return -EINVAL;
-       if ((ret = findintfep(ps->dev, uurb.endpoint)) < 0)
-               return ret;
-       if ((ret = checkintf(ps, ret)))
-               return ret;
+       if (!(uurb.type == USBDEVFS_URB_TYPE_CONTROL && (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
+               if ((ret = findintfep(ps->dev, uurb.endpoint)) < 0)
+                       return ret;
+               if ((ret = checkintf(ps, ret)))
+                       return ret;
+       }
        switch(uurb.type) {
+       case USBDEVFS_URB_TYPE_CONTROL:
+               if ((uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) != 0) {
+                       if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint)))
+                               return -ENOENT;
+                       if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_CONTROL)
+                               return -EINVAL;
+               }
+               /* min 8 byte setup packet, max arbitrary */
+               if (uurb.buffer_length < 8 || uurb.buffer_length > PAGE_SIZE)
+                       return -EINVAL;
+               if (!(dr = kmalloc(sizeof(devrequest), GFP_KERNEL)))
+                       return -ENOMEM;
+               if (copy_from_user(dr, (unsigned char*)uurb.buffer, 8)) {
+                       kfree(dr);
+                       return -EFAULT;
+               }
+               if (uurb.buffer_length < (le16_to_cpup(&dr->length) + 8)) {
+                       kfree(dr);
+                       return -EINVAL;
+               }
+               if ((ret = check_ctrlrecip(ps, dr->requesttype, le16_to_cpup(&dr->index)))) {
+                       kfree(dr);
+                       return ret;
+               }
+               uurb.endpoint = (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) | (dr->requesttype & USB_ENDPOINT_DIR_MASK);
+               uurb.number_of_packets = 0;
+               uurb.buffer_length = le16_to_cpup(&dr->length);
+               uurb.buffer += 8;
+               if (!access_ok((uurb.endpoint & USB_DIR_IN) ?  VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length)) {
+                       kfree(dr);
+                       return -EFAULT;
+               }
+               break;
+
        case USBDEVFS_URB_TYPE_BULK:
                uurb.number_of_packets = 0;
                if (uurb.buffer_length > 16384)
@@ -789,11 +838,15 @@ static int proc_submiturb(struct dev_state *ps, void *arg)
        if (!(as = alloc_async(uurb.number_of_packets))) {
                if (isopkt)
                        kfree(isopkt);
+               if (dr)
+                       kfree(dr);
                return -ENOMEM;
        }
        if (!(as->urb.transfer_buffer = kmalloc(uurb.buffer_length, GFP_KERNEL))) {
                if (isopkt)
                        kfree(isopkt);
+               if (dr)
+                       kfree(dr);
                free_async(as);
                return -ENOMEM;
        }
@@ -802,6 +855,7 @@ static int proc_submiturb(struct dev_state *ps, void *arg)
         as->urb.pipe = (uurb.type << 30) | __create_pipe(ps->dev, uurb.endpoint & 0xf) | (uurb.endpoint & USB_DIR_IN);
         as->urb.transfer_flags = uurb.flags;
        as->urb.transfer_buffer_length = uurb.buffer_length;
+       as->urb.setup_packet = (unsigned char*)dr;
        as->urb.start_frame = uurb.start_frame;
        as->urb.number_of_packets = uurb.number_of_packets;
         as->urb.context = as;
index 2ebbc383e6fe754d6465d4bc8c5d0eb683b8aab6..36d1c743bbee7a198675af9ff094ba0bb85825c2 100644 (file)
 #include <linux/bitops.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>  /* for in_interrupt() */
-
-
-#if    defined(CONFIG_KMOD) && defined(CONFIG_HOTPLUG)
 #include <linux/kmod.h>
-#include <linux/sched.h>
-#include <asm/uaccess.h>
-
-#define __KERNEL_SYSCALLS__
-#include <linux/unistd.h>
-
-/* waitpid() call glue uses this */
-static int errno;
-#endif
 
 
 #ifdef CONFIG_USB_DEBUG
@@ -187,6 +175,19 @@ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
        return NULL;
 }
 
+struct usb_endpoint_descriptor *usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum)
+{
+       int i, j, k;
+
+       for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
+               for (j = 0; j < dev->actconfig->interface[i].num_altsetting; j++)
+                       for (k = 0; k < dev->actconfig->interface[i].altsetting[j].bNumEndpoints; k++)
+                               if (epnum == dev->actconfig->interface[i].altsetting[j].endpoint[k].bEndpointAddress)
+                                       return &dev->actconfig->interface[i].altsetting[j].endpoint[k];
+
+       return NULL;
+}
+
 /*
  * usb_calc_bus_time:
  *
@@ -504,40 +505,6 @@ static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum)
  * (normally /sbin/hotplug) when USB devices get added or removed.
  */
 
-static int exec_helper (void *arg)
-{
-       void **params = (void **) arg;
-       char *path = (char *) params [0];
-       char **argv = (char **) params [1];
-       char **envp = (char **) params [2];
-       return exec_usermodehelper (path, argv, envp);
-}
-
-int call_usermodehelper (char *path, char **argv, char **envp)
-{
-       void *params [3] = { path, argv, envp };
-       int pid, pid2, retval;
-       mm_segment_t fs;
-
-       if ((pid = kernel_thread (exec_helper, (void *) params, 0)) < 0) {
-               err ("failed fork of %s, errno = %d", argv [0], -pid);
-               return -1;
-       }
-
-       /* set signal mask? */
-       fs = get_fs ();
-       set_fs (KERNEL_DS);                             /* retval is in kernel space. */
-       pid2 = waitpid (pid, &retval, __WCLONE);        /* "errno" gets assigned */
-       set_fs (fs);
-       /* restore signal mask? */
-
-       if (pid2 != pid) {
-               err ("waitpid(%d) failed, returned %d\n", pid, pid2);
-                       return -1;
-       }
-       return retval;
-}
-
 static int to_bcd (char *buf, __u16 *bcdValue)
 {
        int     retval = 0;
@@ -700,7 +667,8 @@ static void call_policy (char *verb, struct usb_device *dev)
        value = call_usermodehelper (argv [0], argv, envp);
        kfree (buf);
        kfree (envp);
-       dbg ("kusbd policy returned 0x%x", value);
+       if (value != 0)
+               dbg ("kusbd policy returned 0x%x", value);
 }
 
 #else
@@ -1455,8 +1423,6 @@ void usb_disconnect(struct usb_device **pdev)
 
        info("USB disconnect on device %d", dev->devnum);
 
-       call_policy ("remove", dev);
-
        if (dev->actconfig) {
                for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
                        struct usb_interface *interface = &dev->actconfig->interface[i];
@@ -1477,6 +1443,9 @@ void usb_disconnect(struct usb_device **pdev)
                        usb_disconnect(child);
        }
 
+       /* Let policy agent unload modules etc */
+       call_policy ("remove", dev);
+
        /* Free the device number and remove the /proc/bus/usb entry */
        if (dev->devnum > 0) {
                clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
@@ -2046,6 +2015,7 @@ struct list_head *usb_bus_get_list(void)
  * then these symbols need to be exported for the modules to use.
  */
 EXPORT_SYMBOL(usb_ifnum_to_if);
+EXPORT_SYMBOL(usb_epnum_to_ep_desc);
 
 EXPORT_SYMBOL(usb_register);
 EXPORT_SYMBOL(usb_deregister);
index 50d28469de5c6439e584e91df218203cd8bbf3b5..d728d2166d308d3b1f4f9122cb97fb0b68affa17 100644 (file)
@@ -76,7 +76,7 @@ if [ "$CONFIG_NET" = "y" ]; then
 
    dep_tristate 'Coda file system support (advanced network fs)' CONFIG_CODA_FS $CONFIG_INET
    dep_tristate 'NFS file system support' CONFIG_NFS_FS $CONFIG_INET
-   dep_mbool '  Provide NFSv3 client support (EXPERIMENTAL)' CONFIG_NFS_V3 $CONFIG_NFS_FS
+   dep_mbool '  Provide NFSv3 client support' CONFIG_NFS_V3 $CONFIG_NFS_FS
    dep_bool '  Root file system on NFS' CONFIG_ROOT_NFS $CONFIG_NFS_FS $CONFIG_IP_PNP
 
    dep_tristate 'NFS server support' CONFIG_NFSD $CONFIG_INET
index b7505aea6f6ce36383cd745c5c2ce76d38b81f54..79a1797b57ed6744b18bfb3eb09061269cc5d85e 100644 (file)
@@ -554,6 +554,21 @@ void shrink_dcache_parent(struct dentry * parent)
 int shrink_dcache_memory(int priority, unsigned int gfp_mask)
 {
        int count = 0;
+
+       /*
+        * Nasty deadlock avoidance.
+        *
+        * ext2_new_block->getblk->GFP->shrink_dcache_memory->prune_dcache->
+        * prune_one_dentry->dput->dentry_iput->iput->inode->i_sb->s_op->
+        * put_inode->ext2_discard_prealloc->ext2_free_blocks->lock_super->
+        * DEADLOCK.
+        *
+        * We should make sure we don't hold the superblock lock over
+        * block allocations, but for now:
+        */
+       if (!(gfp_mask & __GFP_IO))
+               return 0;
+
        if (priority)
                count = dentry_stat.nr_unused / priority;
        prune_dcache(count);
index 6a55380437ade3841ce45a733b69c3ee6420cfbe..923a2113c4c24ac5c1b56b4fefab0df5d725d08e 100644 (file)
@@ -457,7 +457,17 @@ void prune_icache(int goal)
 int shrink_icache_memory(int priority, int gfp_mask)
 {
        int count = 0;
-               
+
+       /*
+        * Nasty deadlock avoidance..
+        *
+        * We may hold various FS locks, and we don't
+        * want to recurse into the FS that called us
+        * in clear_inode() and friends..
+        */
+       if (!(gfp_mask & __GFP_IO))
+               return 0;
+
        if (priority)
                count = inodes_stat.nr_unused / priority;
        prune_icache(count);
index 9c9cc1e41d999a057e0e036a747854bdf52c1cdc..ae4e4c6be4a36e9012112af2880c0e39e6d92a09 100644 (file)
@@ -653,8 +653,10 @@ next_task:
                if ((fl->fl_owner == blocked_owner)
                    && (fl->fl_pid == blocked_pid)) {
                        fl = fl->fl_next;
-                       blocked_owner = fl->fl_owner;
-                       blocked_pid = fl->fl_pid;
+                       if (fl) {
+                               blocked_owner = fl->fl_owner;
+                               blocked_pid = fl->fl_pid;
+                       }
                        goto next_task;
                }
        }
index 5e7ced09e05f92834dae87d0232a0b9c84af5f4b..b21592528f09c29e82a1c0517a70366ed04407a4 100644 (file)
@@ -353,6 +353,7 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
 
        clnt->cl_intr     = (data->flags & NFS_MOUNT_INTR)? 1 : 0;
        clnt->cl_softrtry = (data->flags & NFS_MOUNT_SOFT)? 1 : 0;
+       clnt->cl_droppriv = (data->flags & NFS_MOUNT_BROKEN_SUID) ? 1 : 0;
        clnt->cl_chatty   = 1;
        server->client    = clnt;
 
index 7c3a7a0cc5462839f40b6a03e48cbe15f099a495..ce05e1843b4b18c96cbbe8cf63bd69dbff42faa0 100644 (file)
@@ -157,6 +157,7 @@ static struct nfs_bool_opts {
 #endif
        { "udp",        ~NFS_MOUNT_TCP,         0 },
        { "tcp",        ~NFS_MOUNT_TCP,         NFS_MOUNT_TCP },
+       { "broken_suid",~NFS_MOUNT_BROKEN_SUID, NFS_MOUNT_BROKEN_SUID },
        { NULL,         0,                      0 }
 };
 
index 7fa97f65655a8e546a751412ffda37083b2fe4d8..7673b08b100389dc60769b270be70f863d80a0d2 100644 (file)
@@ -155,6 +155,8 @@ nfsd(struct svc_rqst *rqstp)
        sprintf(current->comm, "nfsd");
        current->fs->umask = 0;
 
+       current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; 
+
        nfsdstats.th_cnt++;
        /* Let svc_process check client's authentication. */
        rqstp->rq_auth = 1;
index 4e5716b4f51995779c3e6a3c14575b6291987edc..a796885e385fd6947d60a1055919115cf362318e 100644 (file)
@@ -469,11 +469,11 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
        atomic_set(&filp->f_count, 1);
        filp->f_dentry = dentry;
        if (access & MAY_WRITE) {
-               filp->f_flags = O_WRONLY;
+               filp->f_flags = O_WRONLY|O_LARGEFILE;
                filp->f_mode  = FMODE_WRITE;
                DQUOT_INIT(inode);
        } else {
-               filp->f_flags = O_RDONLY;
+               filp->f_flags = O_RDONLY|O_LARGEFILE;
                filp->f_mode  = FMODE_READ;
        }
 
index c542aad4f2a74cc4024708c73912e115e74c1252..8d4283772f146e1f34c75fb7922a9dc5029f51dd 100644 (file)
@@ -146,6 +146,16 @@ char *disk_name (struct gendisk *hd, int minor, char *buf)
                        sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, disk, part);
                return buf;
        }
+       if (hd->major >= COMPAQ_CISS_MAJOR && hd->major <= COMPAQ_CISS_MAJOR+7) {
+                int ctlr = hd->major - COMPAQ_CISS_MAJOR;
+                int disk = minor >> hd->minor_shift;
+                int part = minor & (( 1 << hd->minor_shift) - 1);
+                if (part == 0)
+                        sprintf(buf, "%s/c%dd%d", maj, ctlr, disk);
+                else
+                        sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, disk, part);
+                return buf;
+       }
        if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {
                int ctlr = hd->major - DAC960_MAJOR;
                int disk = minor >> hd->minor_shift;
@@ -181,6 +191,10 @@ void add_gd_partition(struct gendisk *hd, int minor, int start, int size)
                printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
        else
                printk(" %s", disk_name(hd, minor, buf));
+       if (hd->major >= COMPAQ_CISS_MAJOR+0 && hd->major <= COMPAQ_CISS_MAJOR+7)
+                printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
+        else
+                printk(" %s", disk_name(hd, minor, buf));
 #endif
 }
 
index f789dd6209bece92ea86e30b39c6fa030a0bc99e..fb5c5895ccd86321b49d6b048667a30d527d7c70 100644 (file)
@@ -483,6 +483,7 @@ static struct proc_nfs_info {
        { NFS_MOUNT_NOCTO, ",nocto", "" },
        { NFS_MOUNT_NOAC, ",noac", "" },
        { NFS_MOUNT_NONLM, ",nolock", ",lock" },
+       { NFS_MOUNT_BROKEN_SUID, ",broken_suid", "" },
        { 0, NULL, NULL }
 };
 
index c4f1c9624de012e961b6e55582db63b25d771305..4e8d0c41067fa5994af999ca8acba2c2cd4cef91 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _ALPHA_ATOMIC_H
 #define _ALPHA_ATOMIC_H
 
-#include <linux/config.h>
-
 /*
  * Atomic operations that C can't guarantee us.  Useful for
  * resource counting etc...
index 98e6d3a33aebd54b767ec0cd270abbb63b61197d..b97d0c5b65ec54acb52865002abf8bc8541ba523 100644 (file)
@@ -137,7 +137,7 @@ __asm__ __volatile__("mb": : :"memory")
 #define wmb() \
 __asm__ __volatile__("wmb": : :"memory")
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 #define smp_mb()       mb()
 #define smp_rmb()      rmb()
 #define smp_wmb()      wmb()
index 05e54c4009bbc3c7461dd14f17d7df8fbc632467..d3b01ab8bb8e396e93d78354d7300ed54e48d918 100644 (file)
@@ -279,7 +279,7 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
 #define rmb()  mb()
 #define wmb()  __asm__ __volatile__ ("": : :"memory")
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 #define smp_mb()       mb()
 #define smp_rmb()      rmb()
 #define smp_wmb()      wmb()
index 4bc6187b3b8de75b0c2455e7664b68a50970651b..bab12889830206be7439ba0f0ce9055f9a299641 100644 (file)
@@ -10,6 +10,7 @@ extern int request_module(const char * name);
 extern int exec_usermodehelper(char *program_path, char *argv[], char *envp[]);
 #ifdef CONFIG_HOTPLUG
 extern char hotplug_path [];
+extern int call_usermodehelper(char *path, char *argv[], char *envp[]);
 #endif
 #else
 static inline int request_module(const char * name) { return -ENOSYS; }
index 1890fd1f7095fcfbcc8dcc0dc0c607b033a8770f..28129a68f54196b5a8f67f83bf40954169ac0b95 100644 (file)
@@ -441,7 +441,6 @@ struct zone_t;
 /* filemap.c */
 extern void remove_inode_page(struct page *);
 extern unsigned long page_unuse(struct page *);
-extern int shrink_mmap(int, int);
 extern void truncate_inode_pages(struct address_space *, loff_t);
 
 /* generic vm_area_ops exported for stackable file systems */
@@ -469,11 +468,11 @@ extern struct page *filemap_nopage(struct vm_area_struct * area,
 
 #define GFP_BUFFER     (__GFP_HIGH | __GFP_WAIT)
 #define GFP_ATOMIC     (__GFP_HIGH)
-#define GFP_USER       (__GFP_WAIT | __GFP_IO)
-#define GFP_HIGHUSER   (GFP_USER | __GFP_HIGHMEM)
+#define GFP_USER       (             __GFP_WAIT | __GFP_IO)
+#define GFP_HIGHUSER   (             __GFP_WAIT | __GFP_IO | __GFP_HIGHMEM)
 #define GFP_KERNEL     (__GFP_HIGH | __GFP_WAIT | __GFP_IO)
 #define GFP_NFS                (__GFP_HIGH | __GFP_WAIT | __GFP_IO)
-#define GFP_KSWAPD     (__GFP_IO)
+#define GFP_KSWAPD     (                          __GFP_IO)
 
 /* Flag - indicates that the buffer will be suitable for DMA.  Ignored on some
    platforms, used as appropriate on others */
index 7b7df5b06f2039bc489e5692a43bca7913e7ca8f..2b552936eecab4a01ef86500d902c2d4a97fe533 100644 (file)
@@ -52,6 +52,7 @@ struct nfs_mount_data {
 #define NFS_MOUNT_VER3         0x0080  /* 3 */
 #define NFS_MOUNT_KERBEROS     0x0100  /* 3 */
 #define NFS_MOUNT_NONLM                0x0200  /* 3 */
+#define NFS_MOUNT_BROKEN_SUID  0x0400  /* 4 */
 #define NFS_MOUNT_FLAGMASK     0xFFFF
 
 #endif
index 4cc0f16ad649b8217c0d2f1c9614fb6ac2b0f8c7..3f8d354bd0f820f4c87e02b799bc66657e17d39d 100644 (file)
@@ -45,6 +45,7 @@ struct rpc_clnt {
                                cl_chatty   : 1,/* be verbose */
                                cl_autobind : 1,/* use getport() */
                                cl_binding  : 1,/* doing a getport() */
+                               cl_droppriv : 1,/* enable NFS suid hack */
                                cl_oneshot  : 1,/* dispose after use */
                                cl_dead     : 1;/* abandoned */
        unsigned int            cl_flags;       /* misc client flags */
index 35495a408fa2eb2e0fa6ef2507c198a35fbb0a52..91c971b8f342ba808babd20e7020f2b640f7208a 100644 (file)
@@ -29,6 +29,7 @@
 /*
  * USB recipients
  */
+#define USB_RECIP_MASK                 0x1f
 #define USB_RECIP_DEVICE               0x00
 #define USB_RECIP_INTERFACE            0x01
 #define USB_RECIP_ENDPOINT             0x02
@@ -553,6 +554,7 @@ struct usb_device {
 };
 
 extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum);
+extern struct usb_endpoint_descriptor *usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum);
 
 extern int usb_register(struct usb_driver *);
 extern void usb_deregister(struct usb_driver *);
index efe6568f9c42949b6d4320206829b22a3e6a5c67..6205bc2d1b3c9cb108f008663a8c1378103a2fc9 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -206,7 +206,6 @@ static int shm_swp; /* number of shared memory pages that are in swap */
 /* some statistics */
 static ulong swap_attempts;
 static ulong swap_successes;
-static ulong used_segs;
 
 void __init shm_init (void)
 {
@@ -364,7 +363,9 @@ static int shm_statfs(struct super_block *sb, struct statfs *buf)
        buf->f_blocks = shm_ctlall;
        buf->f_bavail = buf->f_bfree = shm_ctlall - shm_tot;
        buf->f_files = shm_ctlmni;
-       buf->f_ffree = shm_ctlmni - used_segs;
+       shm_lockall();
+       buf->f_ffree = shm_ctlmni - shm_ids.in_use + 1;
+       shm_unlockall();
        buf->f_namelen = SHM_NAME_LEN;
        return 0;
 }
@@ -593,7 +594,6 @@ static pte_t **shm_alloc(unsigned long pages, int doacc)
        if (doacc) {
                shm_lockall();
                shm_tot += pages;
-               used_segs++;
                shm_unlockall();
        }
        return ret;
@@ -646,7 +646,6 @@ static void shm_free(pte_t** dir, unsigned long pages, int doacc)
                shm_rss -= rss;
                shm_swp -= swp;
                shm_tot -= pages;
-               used_segs--;
                shm_unlockall();
        }
 }
@@ -970,7 +969,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
 
                memset(&shm_info,0,sizeof(shm_info));
                shm_lockall();
-               shm_info.used_ids = shm_ids.in_use;
+               shm_info.used_ids = shm_ids.in_use - 1; /* correct the /dev/zero hack */
                shm_info.shm_rss = shm_rss;
                shm_info.shm_tot = shm_tot;
                shm_info.shm_swp = shm_swp;
@@ -1536,6 +1535,12 @@ int shm_swap (int prio, int gfp_mask)
        int counter;
        struct page * page_map;
 
+       /*
+        * Push this inside:
+        */
+       if (!(gfp_mask & __GFP_IO))
+               return 0;
+
        zshm_swap(prio, gfp_mask);
        counter = shm_rss >> prio;
        if (!counter)
index 4941840a7fcf4027973458dd80b8046d28ae302a..3fff3ed3d902a8bef1268edecd7ee8aa119f117e 100644 (file)
@@ -247,5 +247,44 @@ int request_module(const char * module_name)
 */
 char hotplug_path[256] = "/sbin/hotplug";
 
+
+static int exec_helper (void *arg)
+{
+       void **params = (void **) arg;
+       char *path = (char *) params [0];
+       char **argv = (char **) params [1];
+       char **envp = (char **) params [2];
+       return exec_usermodehelper (path, argv, envp);
+}
+
+
+int call_usermodehelper (char *path, char **argv, char **envp)
+{
+       void *params [3] = { path, argv, envp };
+       int pid, pid2, retval;
+       mm_segment_t fs;
+
+       if ( ! current->fs->root ) {
+               printk(KERN_ERR "call_usermodehelper[%s]: no root fs\n",
+                       path);
+               return -EPERM;
+       }
+       if ((pid = kernel_thread (exec_helper, (void *) params, 0)) < 0) {
+               printk(KERN_ERR "failed fork %s, errno = %d", argv [0], -pid);
+               return -1;
+       }
+
+       fs = get_fs ();
+       set_fs (KERNEL_DS);
+       pid2 = waitpid (pid, &retval, __WCLONE);
+       set_fs (fs);
+
+       if (pid2 != pid) {
+               printk(KERN_ERR "waitpid(%d) failed, %d\n", pid, pid2);
+                       return -1;
+       }
+       return retval;
+}
+
 #endif
 
index 3d3e8dd8bedfc8e3e68e14499a3df775003d651e..2a8882dbc600d7a1b09f5b051db9b58127a8e41a 100644 (file)
@@ -76,6 +76,7 @@ EXPORT_SYMBOL(request_module);
 EXPORT_SYMBOL(exec_usermodehelper);
 #ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(hotplug_path);
+EXPORT_SYMBOL(call_usermodehelper);
 #endif
 #endif
 
@@ -215,6 +216,8 @@ EXPORT_SYMBOL(page_hash_bits);
 EXPORT_SYMBOL(page_hash_table);
 EXPORT_SYMBOL(file_lock_list);
 EXPORT_SYMBOL(file_lock_sem);
+EXPORT_SYMBOL(locks_init_lock);
+EXPORT_SYMBOL(locks_copy_lock);
 EXPORT_SYMBOL(posix_lock_file);
 EXPORT_SYMBOL(posix_test_lock);
 EXPORT_SYMBOL(posix_block_lock);
index a3105ec8e6e51a6b649ab1bf89f13f7d248799ce..b4a1dee278df9cc0814226a09dfb4caf5e7aaa14 100644 (file)
@@ -191,6 +191,7 @@ static int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
                /* Ok, it wasn't in the queue.  We must have
                   been out of queue space.  So zero out the
                   info.  */
+               sigdelset(&list->signal, sig);
                info->si_signo = sig;
                info->si_errno = 0;
                info->si_code = 0;
index 9b68883a63d695fc49ea13dc1236e7193f5c0619..f27892d1b1ca4e1c7016de61af0ff7c279d09160 100644 (file)
@@ -1925,10 +1925,10 @@ static long madvise_willneed(struct vm_area_struct * vma,
  * Application no longer needs these pages.  If the pages are dirty,
  * it's OK to just throw them away.  The app will be more careful about
  * data it wants to keep.  Be sure to free swap resources too.  The
- * zap_page_range call sets things up for shrink_mmap to actually free
+ * zap_page_range call sets things up for refill_inactive to actually free
  * these pages later if no one else has touched them in the meantime,
  * although we could add these pages to a global reuse list for
- * shrink_mmap to pick up before reclaiming other pages.
+ * refill_inactive to pick up before reclaiming other pages.
  *
  * NB: This interface discards data rather than pushes it out to swap,
  * as some implementations do.  This has performance implications for
index ada767e0302c7b9900c71ed60e35a6f535e32552..d364d6dc57322c3c74749dced0417b76c0faa72e 100644 (file)
@@ -444,6 +444,13 @@ try_again:
                 * processes, etc).
                 */
                if (gfp_mask & __GFP_WAIT) {
+                       /*
+                        * Give other processes a chance to run:
+                        */
+                       if (current->need_resched) {
+                               __set_current_state(TASK_RUNNING);
+                               schedule();
+                       }
                        try_to_free_pages(gfp_mask);
                        memory_pressure++;
                        goto try_again;
index 570a669d052df8039769c3ecfd5aeb32e6f2e282..d26c66f54dfda9d5fa953996991b34e4ab3d6eaa 100644 (file)
@@ -166,7 +166,7 @@ repeat:
                        return 0;
                /*
                 * Though the "found" page was in the swap cache an instant
-                * earlier, it might have been removed by shrink_mmap etc.
+                * earlier, it might have been removed by refill_inactive etc.
                 * Re search ... Since find_lock_page grabs a reference on
                 * the page, it can not be reused for anything else, namely
                 * it can not be associated with another swaphandle, so it
index b11d8a1f392e373f54a2a94607bee1014e0d2537..f408e98fe10c3b11fa5f3af5e6fe3796e0ae7582 100644 (file)
@@ -119,7 +119,7 @@ drop_pte:
         * our scan.
         *
         * Basically, this just makes it possible for us to do
-        * some real work in the future in "shrink_mmap()".
+        * some real work in the future in "refill_inactive()".
         */
        if (!pte_dirty(pte)) {
                flush_cache_page(vma, address);
@@ -159,7 +159,7 @@ drop_pte:
         * NOTE NOTE NOTE! This should just set a
         * dirty bit in 'page', and just drop the
         * pte. All the hard work would be done by
-        * shrink_mmap().
+        * refill_inactive().
         *
         * That would get rid of a lot of problems.
         */
@@ -891,7 +891,7 @@ static int refill_inactive(unsigned int gfp_mask, int user)
        do {
                made_progress = 0;
 
-               if (current->need_resched && (gfp_mask & __GFP_IO)) {
+               if (current->need_resched) {
                        __set_current_state(TASK_RUNNING);
                        schedule();
                }
@@ -899,34 +899,32 @@ static int refill_inactive(unsigned int gfp_mask, int user)
                while (refill_inactive_scan(priority, 1) ||
                                swap_out(priority, gfp_mask, idle_time)) {
                        made_progress = 1;
-                       if (!--count)
+                       if (--count <= 0)
                                goto done;
                }
 
-               /* Try to get rid of some shared memory pages.. */
-               if (gfp_mask & __GFP_IO) {
-                       /*
-                        * don't be too light against the d/i cache since
-                        * shrink_mmap() almost never fail when there's
-                        * really plenty of memory free. 
-                        */
-                       count -= shrink_dcache_memory(priority, gfp_mask);
-                       count -= shrink_icache_memory(priority, gfp_mask);
-                       /*
-                        * Not currently working, see fixme in shrink_?cache_memory
-                        * In the inner funtions there is a comment:
-                        * "To help debugging, a zero exit status indicates
-                        *  all slabs were released." (-arca?)
-                        * lets handle it in a primitive but working way...
-                        *      if (count <= 0)
-                        *              goto done;
-                        */
+               /*
+                * don't be too light against the d/i cache since
+                * refill_inactive() almost never fail when there's
+                * really plenty of memory free. 
+                */
+               count -= shrink_dcache_memory(priority, gfp_mask);
+               count -= shrink_icache_memory(priority, gfp_mask);
+               /*
+                * Not currently working, see fixme in shrink_?cache_memory
+                * In the inner funtions there is a comment:
+                * "To help debugging, a zero exit status indicates
+                *  all slabs were released." (-arca?)
+                * lets handle it in a primitive but working way...
+                *      if (count <= 0)
+                *              goto done;
+                */
 
-                       while (shm_swap(priority, gfp_mask)) {
-                               made_progress = 1;
-                               if (!--count)
-                                       goto done;
-                       }
+               /* Try to get rid of some shared memory pages.. */
+               while (shm_swap(priority, gfp_mask)) {
+                       made_progress = 1;
+                       if (--count <= 0)
+                               goto done;
                }
 
                /*
@@ -934,7 +932,7 @@ static int refill_inactive(unsigned int gfp_mask, int user)
                 */
                while (swap_out(priority, gfp_mask, 0)) {
                        made_progress = 1;
-                       if (!--count)
+                       if (--count <= 0)
                                goto done;
                }
 
@@ -955,9 +953,9 @@ static int refill_inactive(unsigned int gfp_mask, int user)
                        priority--;
        } while (priority >= 0);
 
-       /* Always end on a shrink_mmap.., may sleep... */
+       /* Always end on a refill_inactive.., may sleep... */
        while (refill_inactive_scan(0, 1)) {
-               if (!--count)
+               if (--count <= 0)
                        goto done;
        }
 
@@ -969,11 +967,6 @@ static int do_try_to_free_pages(unsigned int gfp_mask, int user)
 {
        int ret = 0;
 
-       /*
-        * First, reclaim unused slab cache memory.
-        */
-       kmem_cache_reap(gfp_mask);
-
        /*
         * If we're low on free pages, move pages from the
         * inactive_dirty list to the inactive_clean list.
@@ -992,13 +985,14 @@ static int do_try_to_free_pages(unsigned int gfp_mask, int user)
         * the inode and dentry cache whenever we do this.
         */
        if (free_shortage() || inactive_shortage()) {
-               if (gfp_mask & __GFP_IO) {
-                       ret += shrink_dcache_memory(6, gfp_mask);
-                       ret += shrink_icache_memory(6, gfp_mask);
-               }
-
+               ret += shrink_dcache_memory(6, gfp_mask);
+               ret += shrink_icache_memory(6, gfp_mask);
                ret += refill_inactive(gfp_mask, user);
        } else {
+               /*
+                * Reclaim unused slab cache memory.
+                */
+               kmem_cache_reap(gfp_mask);
                ret = 1;
        }
 
@@ -1153,9 +1147,8 @@ int try_to_free_pages(unsigned int gfp_mask)
 {
        int ret = 1;
 
-       if (gfp_mask & __GFP_WAIT) {
+       if (gfp_mask & __GFP_WAIT)
                ret = do_try_to_free_pages(gfp_mask, 1);
-       }
 
        return ret;
 }
index 8033ed6c16955e5cb9448cfb32757009b33bdf96..3da9ff39227f7438cbb9e3fd75e1625b6977ddcd 100644 (file)
@@ -180,7 +180,8 @@ unx_marshal(struct rpc_task *task, u32 *p, int ruid)
        memcpy(p, clnt->cl_nodename, n);
        p += (n + 3) >> 2;
 
-       if (ruid) {
+       /* Note: we don't use real uid if it involves raising priviledge */
+       if (ruid && cred->uc_uid != 0 && cred->uc_gid != 0) {
                *p++ = htonl((u32) cred->uc_uid);
                *p++ = htonl((u32) cred->uc_gid);
        } else {
index 1e74af96b20fee3d54706d73ba55e82427c3403b..b384b754c12c4a6f96ce9ae6adb75b824eef2a14 100644 (file)
@@ -708,7 +708,7 @@ call_decode(struct rpc_task *task)
         * The following is an NFS-specific hack to cater for setuid
         * processes whose uid is mapped to nobody on the server.
         */
-       if (task->tk_client->cl_prog == NFS_PROGRAM && 
+       if (task->tk_client->cl_droppriv && 
             (ntohl(*p) == NFSERR_ACCES || ntohl(*p) == NFSERR_PERM)) {
                if (RPC_IS_SETUID(task) && task->tk_suid_retry) {
                        dprintk("RPC: %4d retry squashed uid\n", task->tk_pid);
index 433fba27c9decc7ff44ecb892d2e0c4db855ef58..5d739f378e33d33a43c66aec78603b2dc51fa15a 100644 (file)
@@ -294,6 +294,7 @@ void use_config(const char * name, int len)
  * The state machine looks for (approximately) these Perl regular expressions:
  *
  *    m|\/\*.*?\*\/|
+ *    m|\/\/.*|
  *    m|'.*?'|
  *    m|".*?"|
  *    m|#\s*include\s*"(.*?)"|
@@ -326,9 +327,18 @@ __start:
        CASE('C',  cee);
        goto start;
 
+/* // */
+slash_slash:
+       GETNEXT
+       CASE('\n', start);
+       NOTCASE('\\', slash_slash);
+       GETNEXT
+       goto slash_slash;
+
 /* / */
 slash:
        GETNEXT
+       CASE('/',  slash_slash);
        NOTCASE('*', __start);
 slash_star_dot_star:
        GETNEXT