]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.117pre1 2.1.117pre1
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:16:22 +0000 (15:16 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:16:22 +0000 (15:16 -0500)
93 files changed:
CREDITS
Documentation/Configure.help
Documentation/sound/Soundblaster
Makefile
arch/i386/kernel/entry.S
drivers/char/Makefile
drivers/char/adbmouse.c
drivers/char/amigamouse.c
drivers/char/atarimouse.c
drivers/char/atixlmouse.c
drivers/char/bt848.h
drivers/char/bttv.c
drivers/char/busmouse.c
drivers/char/dn_keyb.c
drivers/char/macmouse.c
drivers/char/msbusmouse.c
drivers/char/msp3400.c
drivers/char/msp3400.h
drivers/char/pc110pad.c
drivers/char/psaux.c
drivers/char/radio-aimslab.c
drivers/char/radio-aztech.c
drivers/char/radio-rtrack2.c
drivers/char/radio-sf16fmi.c
drivers/char/radio-zoltrix.c
drivers/char/tty_io.c
drivers/net/ppp.c
drivers/sound/Config.in
drivers/sound/Makefile
drivers/sound/es1370.c
drivers/sound/es1371.c
drivers/sound/gus_wave.c
drivers/sound/lowlevel/aci.c
drivers/sound/msnd.h
drivers/sound/msnd_pinnacle.c
drivers/sound/opl3.c
drivers/sound/sb.h
drivers/sound/sb_card.c
drivers/sound/sb_common.c
drivers/sound/sequencer.c
drivers/sound/sonicvibes.c
drivers/sound/soundcard.c
drivers/sound/wavfront.c
drivers/sound/wf_midi.c
fs/binfmt_elf.c
fs/dcache.c
fs/fcntl.c
fs/inode.c
fs/nfs/dir.c
fs/nfs/mount_clnt.c
fs/nfs/nfs2xdr.c
fs/nfs/write.c
fs/proc/array.c
fs/super.c
fs/vfat/namei.c
include/asm-alpha/fcntl.h
include/asm-alpha/siginfo.h
include/asm-arm/fcntl.h
include/asm-arm/siginfo.h
include/asm-i386/fcntl.h
include/asm-i386/siginfo.h
include/asm-m68k/fcntl.h
include/asm-m68k/siginfo.h
include/asm-mips/fcntl.h
include/asm-mips/siginfo.h
include/asm-ppc/fcntl.h
include/asm-ppc/siginfo.h
include/asm-sparc/fcntl.h
include/asm-sparc/siginfo.h
include/asm-sparc64/fcntl.h
include/asm-sparc64/siginfo.h
include/linux/fs.h
include/linux/sunrpc/clnt.h
include/linux/sunrpc/sched.h
include/linux/sunrpc/xprt.h
include/linux/swap.h
include/linux/sysctl.h
include/linux/videodev.h
kernel/fork.c
kernel/sched.c
kernel/signal.c
kernel/sysctl.c
mm/filemap.c
mm/swap.c
mm/swap_state.c
mm/swapfile.c
mm/vmscan.c
net/core/dev.c
net/socket.c
net/sunrpc/clnt.c
net/sunrpc/sched.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/xprt.c

diff --git a/CREDITS b/CREDITS
index 2035ac51a84dfb296474dc935f8637133dd1a36d..d7ee2925775bf4e01b85703448db5f92e17119f4 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1193,13 +1193,12 @@ S: D-90453 Nuernberg
 S: Germany
 
 N: Michael Meskes
-E: meskes@topsystem.de
+E: meskes@debian.org
 P: 1024/04B6E8F5 6C 77 33 CA CC D6 22 03  AB AB 15 A3 AE AD 39 7D
-D: Kernel hacker. Software watchdog daemon.
+D: Kernel hacker. PostgreSQL hacker. Software watchdog daemon.
 D: Maintainer of several Debian packages
-S: topsystem Systemhaus GmbH
-S: Europark A2, Adenauerstr. 20
-S: D-52146 Wuerselen
+S: Th.-Heuss-Str. 61 
+S: D-41812 Erkelenz
 S: Germany
 
 N: Nigel Metheringham
@@ -1945,6 +1944,14 @@ S: 4/36 Trevelyan St
 S: Wayville SA 5034
 S: Australia
 
+N: Clifford Wolf
+E: god@clifford.at
+W: http://www.clifford.at/
+D: Menuconfig/lxdialog improvement
+S: Foehrengasse 16
+S: A-2333 Leopoldsdorf b. Wien
+S: Austria
+
 N: Roger E. Wolff
 E: R.E.Wolff@BitWizard.nl
 D: Written kmalloc/kfree
index 813080ebcc00a7f04496772be3a507de96d2b84e..f04f14bbf37e32866f38ec698f3067d5d7368121 100644 (file)
@@ -4354,6 +4354,58 @@ CONFIG_WAVELAN
   module, say M here and read Documentation/modules.txt as well as
   Documentation/networking/net-modules.txt.
 
+AIMSlab RadioTrack (aka RadioReveal) support
+CONFIG_RADIO_RTRACK
+  Choose Y here if you have one of these FM radio cards, and then fill
+  in the port address below.
+
+  In order to control your radio card, you will need to use programs
+  that are compatible with the Video for Linux API.  Information on 
+  this API and pointers to "v4l" programs may be found on the WWW at
+  http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW,
+  you need to have access to a machine on the Internet that has a 
+  program like lynx or netscape.
+
+  If you want to compile this driver as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called radio-aimslab.o.
+
+RadioTrack i/o port
+CONFIG_RADIO_RTRACK_PORT
+  Enter either 0x30f or 0x20f here.  The card default is 0x30f, if you
+  haven't changed the jumper setting on the card.
+
+Aztech/Packard Bell Radio
+CONFIG_RADIO_AZTECH
+  Choose Y here if you have one of these FM radio cards, and then fill
+  in the port address below.
+  
+  If you want to compile this driver as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called radio-aztech.o.
+
+Aztech/Packard Bell radio card i/o port
+CONFIG_RADIO_AZTECH_PORT
+  Enter either 0x350 or 0x358 here.  The card default is 0x350, if you
+  haven't changed the setting of jumper JP3 on the card.  Removing the
+  jumper sets the card to 0x358.
+
+SF16FMI Radio
+CONFIG_RADIO_SF16FMI
+  Choose Y here if you have one of these FM radio cards, and then fill
+  in the port address below.
+
+  If you want to compile this driver as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called radio-sf16fmi.o
+
+SF16FMI I/O port (0x284 or 0x384)
+CONFIG_RADIO_SF16FMI_PORT
+  Enter the I/O port of your SF16FMI radio card.
+
 LAPB over Ethernet driver
 CONFIG_LAPBETHER
   This is a driver for a pseudo device (typically called /dev/lapb0)
@@ -9244,6 +9296,10 @@ CONFIG_RADIO_RTRACK
   Choose Y here if you have one of these FM radio cards, and then fill
   in the port address below.
 
+  Note that newer AIMSlab RadioTrack cards have a different chipset,
+  not supported by this driver.  For these cards, use the RadioTrack II
+  driver below.  
+
   In order to control your radio card, you will need to use programs
   that are compatible with the Video for Linux API.  Information on 
   this API and pointers to "v4l" programs may be found on the WWW at
@@ -9261,6 +9317,28 @@ CONFIG_RADIO_RTRACK_PORT
   Enter either 0x30f or 0x20f here.  The card default is 0x30f, if you
   haven't changed the jumper setting on the card.
 
+AIMSlab RadioTrack II support
+CONFIG_RADIO_RTRACK2
+  Choose Y here if you have this FM radio card, and then fill in the 
+  port address below.
+
+  In order to control your radio card, you will need to use programs
+  that are compatible with the Video for Linux API.  Information on 
+  this API and pointers to "v4l" programs may be found on the WWW at
+  http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW,
+  you need to have access to a machine on the Internet that has a 
+  program like lynx or netscape.
+
+  If you want to compile this driver as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called radio-rtrack2.o.
+
+RadioTrack II i/o port
+CONFIG_RADIO_RTRACK2_PORT
+  Enter either 0x30c or 0x20c here.  The card default is 0x30c, if you
+  haven't changed the jumper setting on the card.
+
 Aztech/Packard Bell Radio
 CONFIG_RADIO_AZTECH
   Choose Y here if you have one of these FM radio cards, and then fill
index ad4cb5567109beb3b619410758873cf14d979abe..160763f53c42a061f0f9a09eaabd907637012ca1 100644 (file)
@@ -7,11 +7,11 @@ are covered by other drivers should not be using this driver.
 
 The Sound Blaster module takes the following arguments
 
-io             I/O address of the Sound Blaster chip
-irq            IRQ of the Sound Blaster chip
-dma            8-bit DMA channel for the Sound Blaster
-dma16          16-bit DMA channel for SB16 and equivalent cards
-mpu_io         I/O for MPU chip if present
+io             I/O address of the Sound Blaster chip (0x220,0x240,0x260,0x280)
+irq            IRQ of the Sound Blaster chip (5,7,9,10)
+dma            8-bit DMA channel for the Sound Blaster (0,1,3)
+dma16          16-bit DMA channel for SB16 and equivalent cards (5,6,7)
+mpu_io         I/O for MPU chip if present (0x300,0x330)
 
 mad16=1        Set when loading this as part of the MAD16 setup only
 trix=1         Set when loading this as part of the Audiotrix setup only
index 2291847750a2ab4ec95011535de6d4f74932a4a4..1b52ea5b6c57a9038371f217e6a9e305fc425122 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 116
+SUBLEVEL = 117
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
index aac4866c13cc24066b082dcac993e10d851b2ffe..dd9bf98530038cd472bd5979aa957eec95f6edbb 100644 (file)
@@ -556,7 +556,13 @@ ENTRY(sys_call_table)
        .long SYMBOL_NAME(sys_sendfile)
        .long SYMBOL_NAME(sys_ni_syscall)               /* streams1 */
        .long SYMBOL_NAME(sys_ni_syscall)               /* streams2 */
-       
-       .rept NR_syscalls-187
+
+       /*
+        * NOTE!! This doesn' thave to be exact - we just have
+        * to make sure we have _enough_ of the "sys_ni_syscall"
+        * entries. Don't panic if you notice that this hasn't
+        * been shrunk every time we add a new system call.
+        */
+       .rept NR_syscalls-189
                .long SYMBOL_NAME(sys_ni_syscall)
        .endr
index 358fbd3bbd23c377a3a8ad06be7ab42b175d5855..baa7c859ac9ce6de8fc5c2189de039e640472e0f 100644 (file)
@@ -391,6 +391,14 @@ else
   endif
 endif                                             
 
+ifeq ($(CONFIG_RADIO_RTRACK2),y)
+L_OBJS += radio-rtrack2.o
+else
+  ifeq ($(CONFIG_RADIO_RTRACK2),m)
+  M_OBJS += radio-rtrack2.o
+  endif
+endif                                             
+
 ifeq ($(CONFIG_RADIO_ZOLTRIX),y)
 L_OBJS += radio-zoltrix.o
 else
index 35e0c833b2430dc4645cb13bb54e8d334db8c1af..2703baac041874e997c58c403c3b443ab130b03f 100644 (file)
@@ -144,11 +144,11 @@ static void adb_mouse_interrupt(char *buf, int nb)
 
 }
 
-static int fasync_mouse(struct file *filp, int on)
+static int fasync_mouse(int fd, struct file *filp, int on)
 {
        int retval;
 
-       retval = fasync_helper(filp, on, &mouse.fasyncptr);
+       retval = fasync_helper(fd, filp, on, &mouse.fasyncptr);
        if (retval < 0)
                return retval;
        return 0;
@@ -156,7 +156,7 @@ static int fasync_mouse(struct file *filp, int on)
 
 static int release_mouse(struct inode *inode, struct file *file)
 {
-    fasync_mouse(file, 0);
+    fasync_mouse(-1, file, 0);
     if (--mouse.active)
       return 0;
 
index a3cbd737e4bccbbddd0d70cedc8846f684244f75..45eaa0a73df35aa377602b837f862cb5eb57f250 100644 (file)
@@ -159,10 +159,10 @@ static void mouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
        AMI_MSE_INT_ON();
 }
 
-static int fasync_mouse(struct file *filp, int on)
+static int fasync_mouse(int fd, struct file *filp, int on)
 {
        int retval;
-       retval = fasync_helper(filp, on, &mouse.fasyncptr);
+       retval = fasync_helper(fd, filp, on, &mouse.fasyncptr);
        if (retval < 0)
                return retval;
        return 0;
@@ -174,7 +174,7 @@ static int fasync_mouse(struct file *filp, int on)
 
 static int release_mouse(struct inode * inode, struct file * file)
 {
-       fasync_mouse(file, 0);
+       fasync_mouse(-1, file, 0);
        if (--mouse.active)
                return 0;
        free_irq(IRQ_AMIGA_VERTB, mouse_interrupt);
index 113395dbac1ed2d477bd54e74835f01dc7dc7b52..683d6de80ff5dcc5d019033c11422a2404e4f55c 100644 (file)
@@ -54,10 +54,10 @@ static void atari_mouse_interrupt(char *buf)
 /*    ikbd_mouse_rel_pos(); */
 }
 
-static int fasync_mouse(struct file *filp, int on)
+static int fasync_mouse(int fd, struct file *filp, int on)
 {
        int retval;
-       retval = fasync_helper(filp, on, &mouse.fasyncptr);
+       retval = fasync_helper(fd, filp, on, &mouse.fasyncptr);
        if (retval < 0)
                return retval;
        return 0;
@@ -65,7 +65,7 @@ static int fasync_mouse(struct file *filp, int on)
 
 static int release_mouse(struct inode *inode, struct file *file)
 {
-    fasync_mouse(file, 0);
+    fasync_mouse(-1, file, 0);
     if (--mouse.active)
       return 0;
     ikbd_mouse_disable();
index 9ccb06ca6b30d86e9e096eb5633878010aa55ce9..4a25dc4b1751d32427fcff48288f76abecaec6ee 100644 (file)
@@ -95,10 +95,10 @@ void mouse_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        ATIXL_MSE_ENABLE_UPDATE();
 }
 
-static int fasync_mouse(struct file *filp, int on)
+static int fasync_mouse(int fd, struct file *filp, int on)
 {
        int retval;
-       retval = fasync_helper(filp, on, &mouse.fasync);
+       retval = fasync_helper(fd, filp, on, &mouse.fasync);
        if (retval < 0)
                return retval;
        return 0;
@@ -106,7 +106,7 @@ static int fasync_mouse(struct file *filp, int on)
 
 static int release_mouse(struct inode * inode, struct file * file)
 {
-       fasync_mouse(file, 0);
+       fasync_mouse(-1, file, 0);
        if (--mouse.active)
                return 0;
        ATIXL_MSE_INT_OFF(); /* Interrupts are really shut down here */
index a50e31a5c404b6ba202929c950ed236b8cb97fdb..79ea691c28afe94cc43e0aa244721c55cce6ed74 100644 (file)
 #define BT848_RISC_COUNT       0x120
 #define BT848_GPIO_DATA        0x200
 
+/* Bt878 register */
+
+#define BT878_DEVCTRL 0x40
+#define BT878_NTBF 0x02
 
 /* Bt848 RISC commands */
 
index 8bb3f203efd2df90a01f84b3f894eed369e8395d..58d8fadc154e31ece77ac15adb00037d71701794 100644 (file)
@@ -1888,6 +1888,41 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                                return -EFAULT;
                        return vgrab(btv, &vm);
                }
+               
+               case VIDIOCGMBUF:
+               {
+                       struct video_mbuf vm;
+                       memset(&vm, 0 , sizeof(vm));
+                       vm.size=BTTV_MAX_FBUF*2;
+                       vm.frames=2;
+                       vm.offsets[0]=0;
+                       vm.offsets[1]=BTTV_MAX_FBUF;
+                       if(copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
+                               return -EFAULT;
+                       return 0;
+               }
+               
+               case VIDIOCGUNIT:
+               {
+                       struct video_unit vu;
+                       vu.video=btv->video_dev.minor;
+                       vu.vbi=btv->vbi_dev.minor;
+                       if(btv->radio_dev.minor!=-1)
+                               vu.radio=btv->radio_dev.minor;
+                       else
+                               vu.radio=VIDEO_NO_UNIT;
+                       vu.audio=VIDEO_NO_UNIT;
+                       if(btv->have_msp3400)
+                       {
+                               i2c_control_device(&(btv->i2c), I2C_DRIVERID_MSP3400,
+                                       MSP_GET_UNIT, &vu.audio);
+                       }
+                       vu.teletext=VIDEO_NO_UNIT;
+                       if(copy_to_user((void *)arg, (void *)&vu, sizeof(vu)))
+                               return -EFAULT;
+                       return 0;
+               }
+               
                default:
                        return -ENOIOCTLCMD;
        }
@@ -1949,7 +1984,7 @@ static struct video_device bttv_template=
        bttv_init_done,
        NULL,
        0,
-       0
+       -1
 };
 
 
@@ -2054,7 +2089,7 @@ static struct video_device vbi_template=
        bttv_init_done,
        NULL,
        0,
-       0
+       -1
 };
 
 
@@ -2151,7 +2186,7 @@ static struct video_device radio_template=
        bttv_init_done,      /* just returns 0 */
        NULL,
        0,
-       0
+       -1
 };
 
 
@@ -2979,9 +3014,11 @@ static void release_bttv(void)
                if (btv->bt848_mem)
                        iounmap(btv->bt848_mem);
 
-               video_unregister_device(&btv->video_dev);
-               video_unregister_device(&btv->vbi_dev);
-               if (radio)
+               if(btv->video_dev.minor!=-1)
+                       video_unregister_device(&btv->video_dev);
+               if(btv->vbi_dev.minor!=-1)
+                       video_unregister_device(&btv->vbi_dev);
+               if (radio && btv->radio_dev.minor != -1)
                        video_unregister_device(&btv->radio_dev);
        }
 }
index e8eb8ec8a4928812f6355b67533fe93b1a0cf8a0..f86a73e9e00a65b1a06bcc26b24e0df6f10bb832 100644 (file)
@@ -106,11 +106,11 @@ static void mouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        MSE_INT_ON();
 }
 
-static int fasync_mouse(struct file *filp, int on)
+static int fasync_mouse(int fd, struct file *filp, int on)
 {
        int retval;
 
-       retval = fasync_helper(filp, on, &mouse.fasyncptr);
+       retval = fasync_helper(fd, filp, on, &mouse.fasyncptr);
        if (retval < 0)
                return retval;
        return 0;
@@ -122,7 +122,7 @@ static int fasync_mouse(struct file *filp, int on)
 
 static int close_mouse(struct inode * inode, struct file * file)
 {
-       fasync_mouse(file, 0);
+       fasync_mouse(-1, file, 0);
        if (--mouse.active)
                return 0;
        MSE_INT_OFF();
index a694d9346a3872dd7c6b63a14f3d1e757373d4d3..5fb05738fc8b8f63be75ade0efecf4598f6a0f38 100644 (file)
@@ -360,11 +360,11 @@ static ssize_t read_mouse(struct file * file, char * buffer,
        return count;
 }
 
-static int fasync_mouse(struct file *filp, int on)
+static int fasync_mouse(int fd, struct file *filp, int on)
 {
         int retval;
 
-        retval = fasync_helper(filp, on, &mouse_fasyncptr);
+        retval = fasync_helper(fd, filp, on, &mouse_fasyncptr);
         if (retval < 0)
                 return retval;
         return 0;
@@ -373,7 +373,7 @@ static int fasync_mouse(struct file *filp, int on)
 
 static int release_mouse(struct inode * inode, struct file * file)
 {
-        fasync_mouse(file, 0);
+        fasync_mouse(-1, file, 0);
         if (--mouse_active)
                 return 0;
         MSE_UPDATE_OFF();
index 2d7145203b828f31e4bed87fa61767120de533e4..e14c235cf5002d1811f66ab1deeadfcdcb3e0bc1 100644 (file)
@@ -150,11 +150,11 @@ static void mac_mouse_interrupt(char *buf, int nb)
 
 }
 
-static int fasync_mouse(struct file *filp, int on)
+static int fasync_mouse(int fd, struct file *filp, int on)
 {
        int retval;
 
-       retval = fasync_helper(filp, on, &mouse.fasyncptr);
+       retval = fasync_helper(fd, filp, on, &mouse.fasyncptr);
        if (retval < 0)
                return retval;
        return 0;
@@ -162,7 +162,7 @@ static int fasync_mouse(struct file *filp, int on)
 
 static int release_mouse(struct inode *inode, struct file *file)
 {
-    fasync_mouse(file, 0);
+    fasync_mouse(-1, file, 0);
     if (--mouse.active)
       return 0;
 
index 9ef067ccc73090d5256d165b35b8c84439230cbd..6937597738e6853f811ac1d34d42f5966a736e30 100644 (file)
@@ -89,11 +89,11 @@ static void ms_mouse_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        }
 }
 
-static int fasync_mouse(struct file *filp, int on)
+static int fasync_mouse(int fd, struct file *filp, int on)
 {
        int retval;
 
-       retval = fasync_helper(filp, on, &mouse.fasyncptr);
+       retval = fasync_helper(fd, filp, on, &mouse.fasyncptr);
        if (retval < 0)
                return retval;
        return 0;
@@ -101,7 +101,7 @@ static int fasync_mouse(struct file *filp, int on)
 
 static int release_mouse(struct inode * inode, struct file * file)
 {
-       fasync_mouse(file, 0);
+       fasync_mouse(-1, file, 0);
        if (--mouse.active)
                return 0;
        MS_MSE_INT_OFF();
index 18cce49dd474f50438b9c0a2aef609fdd60b8217..6068ff3d70cbc8e026f7c3071383aad30a16a422 100644 (file)
@@ -1070,6 +1070,10 @@ static int msp3400c_command(struct i2c_device *device,
                        (int)msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1c);
                UNLOCK_I2C_BUS(msp->bus);
                break;
+               
+       case MSP_GET_UNIT:
+               *iarg = msp->mixer;
+               break;
        
        default:
                return -EINVAL;
index e4029c03ee4b387af9000504ccba7b3a35f17cc5..8b093ff05e1bcba18c898e1caad5cf05da8d2dc5 100644 (file)
@@ -20,4 +20,6 @@
 #define MSP_GET_TREBLE     _IOR('m',11,int)
 #define MSP_SET_TREBLE     _IOW('m',12,int)
 
+#define MSP_GET_UNIT      _IOR('m',13,int)
+
 #endif /* MSP3400_H */
index 85ea0fbb4ee834e1f36929c6c703cb41db89d568..3921235e2976afe7cdacab8405ecf4029b327709 100644 (file)
@@ -474,11 +474,11 @@ static void sample_ps2(int d[3])
 
 
 
-static int fasync_pad(struct file *filp, int on)
+static int fasync_pad(int fd, struct file *filp, int on)
 {
        int retval;
 
-       retval = fasync_helper(filp, on, &asyncptr);
+       retval = fasync_helper(fd, filp, on, &asyncptr);
        if (retval < 0)
                return retval;
        return 0;
@@ -490,7 +490,7 @@ static int fasync_pad(struct file *filp, int on)
  */
 static int close_pad(struct inode * inode, struct file * file)
 {
-       fasync_pad(file, 0);
+       fasync_pad(-1, file, 0);
        if (--active)
                return 0;
        outb(0x30, current_params.io+2);        /* switch off digitiser */
index 21e753100cc8577731fc2ce57e312d860d41db66..50c0b63c44afe5361980e544a9a5693cde199e8b 100644 (file)
@@ -105,11 +105,11 @@ static inline int queue_empty(void)
        return queue->head == queue->tail;
 }
 
-static int fasync_aux(struct file *filp, int on)
+static int fasync_aux(int fd, struct file *filp, int on)
 {
        int retval;
 
-       retval = fasync_helper(filp, on, &queue->fasync);
+       retval = fasync_helper(fd, filp, on, &queue->fasync);
        if (retval < 0)
                return retval;
        return 0;
@@ -242,7 +242,7 @@ static void aux_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
 
 static int release_aux(struct inode * inode, struct file * file)
 {
-       fasync_aux(file, 0);
+       fasync_aux(-1, file, 0);
        if (--aux_count)
                return 0;
        aux_start_atomic();
@@ -390,7 +390,7 @@ static int release_qp(struct inode * inode, struct file * file)
 {
        unsigned char status;
 
-       fasync_aux(file, 0);
+       fasync_aux(-1, file, 0);
        if (!--qp_count) {
                if (!poll_qp_status())
                        printk("Warning: Mouse device busy in release_qp()\n");
index 014def0c49cccb9ea105d003c43871a3c6bfb7e5..08fc6116d0239fd9104c3c56ba4f6d6bb9e91723 100644 (file)
@@ -261,6 +261,7 @@ static int rt_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        memset(&v,0, sizeof(v));
                        v.flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
                        v.volume=rt->curvol * 6554;
+                       v.step=6554;
                        strcpy(v.name, "Radio");
                        if(copy_to_user(arg,&v, sizeof(v)))
                                return -EFAULT;
index aaeaa726558c271c94381fb51e4dce48ae770476..caaa60c7c9646c9a72c8b71d2615df4206cafa57 100644 (file)
@@ -218,6 +218,7 @@ static int az_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        else
                                v.mode=VIDEO_SOUND_MONO;
                        v.volume=az->curvol;
+                       v.step=16384;
                        strcpy(v.name, "Radio");
                        if(copy_to_user(arg,&v, sizeof(v)))
                                return -EFAULT;
index 7daeb4e0167db6e1686adb042e594345dc19e9c7..c035efe293e31fb4affca278466591e7c5f94529 100644 (file)
@@ -158,6 +158,7 @@ static int rt_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        memset(&v,0, sizeof(v));
                        v.flags|=VIDEO_AUDIO_MUTABLE;
                        v.volume=1;
+                       v.step=65535;
                        strcpy(v.name, "Radio");
                        if(copy_to_user(arg,&v, sizeof(v)))
                                return -EFAULT;
index 13659fd85eb6101007bf789ec8e966c65df55805..d8dee777d62e3087d65bc8d891aa613a6316d21f 100644 (file)
@@ -176,6 +176,7 @@ static int fmi_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        v.flags|=VIDEO_AUDIO_MUTABLE;
                        v.mode=VIDEO_SOUND_MONO;
                        v.volume=fmi->curvol;
+                       v.step=65535;
                        strcpy(v.name, "Radio");
                        if(copy_to_user(arg,&v, sizeof(v)))
                                return -EFAULT;
index c820c8a36e1ad85c561a0081f36174a1c106c1a8..8c28247b999acadb201d0ff7ed307fb255d284d4 100644 (file)
@@ -220,7 +220,8 @@ static int zol_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        struct video_audio v;
                        memset(&v, 0, sizeof(v));
                        v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
-                       v.volume = rt->curvol * 4095;
+                       v.volume = rt->curvol * 4096;
+                       v.step = 4096;
                        strcpy(v.name, "Radio");
                        if (copy_to_user(arg, &v, sizeof(v)))
                                return -EFAULT;
index 5120d07be1619b3f0619d17b0534da4ab4994659..ff5fe5d5a1924a8549f8afc30b6388ceede97cc6 100644 (file)
@@ -128,7 +128,7 @@ static int tty_open(struct inode *, struct file *);
 static int tty_release(struct inode *, struct file *);
 static int tty_ioctl(struct inode * inode, struct file * file,
                     unsigned int cmd, unsigned long arg);
-static int tty_fasync(struct file * filp, int on);
+static int tty_fasync(int fd, struct file * filp, int on);
 #ifdef CONFIG_8xx
 extern long console_8xx_init(void);
 extern int rs_8xx_init(void);
@@ -409,7 +409,7 @@ void do_tty_hangup(void *data)
                        continue;
                if (filp->f_op != &tty_fops)
                        continue;
-               tty_fasync(filp, 0);
+               tty_fasync(-1, filp, 0);
                filp->f_op = &hung_up_tty_fops;
        }
        
@@ -983,7 +983,7 @@ static void release_dev(struct file * filp)
 
        check_tty_count(tty, "release_dev");
 
-       tty_fasync(filp, 0);
+       tty_fasync(-1, filp, 0);
 
        idx = MINOR(tty->device) - tty->driver.minor_start;
        pty_master = (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
@@ -1352,7 +1352,7 @@ static unsigned int tty_poll(struct file * filp, poll_table * wait)
  * to set up the fasync queue. It returns negative on error, 0 if it did
  * no changes and positive if it added/deleted the entry.
  */
-int fasync_helper(struct file * filp, int on, struct fasync_struct **fapp)
+int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)
 {
        struct fasync_struct *fa, **fp;
        unsigned long flags;
@@ -1363,13 +1363,16 @@ int fasync_helper(struct file * filp, int on, struct fasync_struct **fapp)
        }
 
        if (on) {
-               if (fa)
+               if (fa) {
+                       fa->fa_fd = fd;
                        return 0;
+               }
                fa = (struct fasync_struct *)kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);
                if (!fa)
                        return -ENOMEM;
                fa->magic = FASYNC_MAGIC;
                fa->fa_file = filp;
+               fa->fa_fd = fd;
                save_flags(flags);
                cli();
                fa->fa_next = *fapp;
@@ -1387,7 +1390,7 @@ int fasync_helper(struct file * filp, int on, struct fasync_struct **fapp)
        return 1;
 }
 
-static int tty_fasync(struct file * filp, int on)
+static int tty_fasync(int fd, struct file * filp, int on)
 {
        struct tty_struct * tty;
        int retval;
@@ -1396,7 +1399,7 @@ static int tty_fasync(struct file * filp, int on)
        if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "tty_fasync"))
                return 0;
        
-       retval = fasync_helper(filp, on, &tty->fasync);
+       retval = fasync_helper(fd, filp, on, &tty->fasync);
        if (retval <= 0)
                return retval;
 
index 6d3c23dfb879b172b359c33a34c1415ed87a8f8e..590a0df97d661a79f5f84d18e78bdd5ef3be20a1 100644 (file)
@@ -1977,8 +1977,8 @@ ppp_rcv_rx(struct ppp *ppp, __u16 proto, struct sk_buff *skb)
         */
        skb->dev      = ppp2dev(ppp);   /* We are the device */
        skb->protocol = htons(proto);
-       skb->mac.raw  = skb->data;
        skb_pull(skb, PPP_HDRLEN);      /* pull off ppp header */
+       skb->mac.raw   = skb->data;
        ppp->last_recv = jiffies;
        netif_rx (skb);
        return 1;
index 4f511f3abf36e5828d18cd32eadfd81125bb4031..95a89cdb6eb94e4b3d5b47987cfe5e25e2adc5ce 100644 (file)
@@ -205,7 +205,7 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
   dep_tristate 'Loopback MIDI device support' CONFIG_SOUND_VMIDI $CONFIG_SOUND_OSS
   
   dep_tristate '6850 UART support' CONFIG_SOUND_UART6850 $CONFIG_SOUND_OSS
-  if [ "$CONFIG_UART6850" = "y" ]; then
+  if [ "$CONFIG_SOUND_UART6850" = "y" ]; then
       hex 'I/O base for UART 6850 MIDI port (Unknown)' CONFIG_U6850_BASE 0
       int 'UART6850 IRQ (Unknown)' CONFIG_U6850_IRQ -1
   fi
index d04efe300901ee08e705c8f3e3db7f3cb9cf77c5..f072b7fad39111dd865aa3a01403775b61781b69 100644 (file)
@@ -79,7 +79,7 @@ obj-$(CONFIG_SOUND_SOFTOSS)   += softoss2.o
 obj-$(CONFIG_SOUND_SGALAXY)    += sgalaxy.o
 obj-$(CONFIG_SOUND_SSCAPE)     += sscape.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_TRIX)       += trix.o ad1848.o sb.o uart401.o
-obj-$(CONFIG_SOUND_UART6850)   += uart6850.c
+obj-$(CONFIG_SOUND_UART6850)   += uart6850.o
 obj-$(CONFIG_SOUND_VMIDI)      += v_midi.o
 obj-$(CONFIG_SOUND_YM3812)     += adlib_card.o opl3.o
 obj-$(CONFIG_VIDC_SOUND)       += vidc_mod.o
@@ -92,7 +92,6 @@ obj-$(CONFIG_SOUND_SONICVIBES)        += sonicvibes.o
 endif
 endif
 
-
 # Declare multi-part drivers.
 
 list-multi     := sound.o gus.o pas2.o sb.o softoss2.o vidc_mod.o \
index 5a9b4ec9e0d5982bfeaad30f33c04a3695905845..2e6abb3d66d3560825e18a18182d18361905b469 100644 (file)
  *                     settings (not sure if this should be standard)
  *                     Fixed many references: f_flags should be f_mode
  *                     -- Gerald Britton <gbritton@mit.edu>
+ *    03.08.98   0.11  Now mixer behaviour can basically be selected between
+ *                     "OSS documented" and "OSS actual" behaviour
+ *                     Fixed mixer table thanks to Hakan.Lennestal@lu.erisoft.se
+ *                     On module startup, set DAC2 to 11kSPS instead of 5.5kSPS,
+ *                     as it produces an annoying ssssh in the lower sampling rate
+ *                     Do not include modversions.h
  *
  * some important things missing in Ensoniq documentation:
  *
@@ -91,7 +97,6 @@
       
 #include <linux/version.h>
 #include <linux/module.h>
-#include <linux/modversions.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
 
 /* --------------------------------------------------------------------- */
 
+#undef OSS_DOCUMENTED_MIXER_SEMANTICS
+
+/* --------------------------------------------------------------------- */
+
 #ifndef PCI_VENDOR_ID_ENSONIQ
 #define PCI_VENDOR_ID_ENSONIQ        0x1274    
 #endif
@@ -316,7 +325,7 @@ struct es1370_state {
 
 /* --------------------------------------------------------------------- */
 
-struct es1370_state *devs = NULL;
+static struct es1370_state *devs = NULL;
 
 /* --------------------------------------------------------------------- */
 
@@ -464,10 +473,9 @@ static void start_adc(struct es1370_state *s)
 
 /* --------------------------------------------------------------------- */
 
-#define DMABUF_DEFAULTORDER 8
+#define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
 #define DMABUF_MINORDER 1
 
-
 extern inline void dealloc_dmabuf(struct dmabuf *db)
 {
        unsigned long map, mapend;
@@ -478,6 +486,7 @@ extern inline void dealloc_dmabuf(struct dmabuf *db)
                for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
                        clear_bit(PG_reserved, &mem_map[map].flags);    
                free_pages((unsigned long)db->rawbuf, db->buforder);
+               printk(KERN_DEBUG "es: freeing dmabuf %8.8lx order %d\n", (unsigned long)db->rawbuf, db->buforder);
        }
        db->rawbuf = NULL;
        db->mapped = db->ready = 0;
@@ -502,6 +511,7 @@ static int prog_dmabuf(struct es1370_state *s, struct dmabuf *db, unsigned rate,
                mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
                for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
                        set_bit(PG_reserved, &mem_map[map].flags);
+               printk(KERN_DEBUG "es: allocating dmabuf %8.8lx order %d\n", (unsigned long)db->rawbuf, db->buforder);
        }
        fmt &= ES1370_FMT_MASK;
        bytepersec = rate << sample_shift[fmt];
@@ -734,20 +744,22 @@ static const struct {
        [SOUND_MIXER_CD]     = { 3, 0x6, 0x7, 1, 0x0006, 1 },   /* CD */
        [SOUND_MIXER_LINE]   = { 4, 0x8, 0x9, 1, 0x0018, 1 },   /* Line */
        [SOUND_MIXER_LINE1]  = { 5, 0xa, 0xb, 1, 0x1800, 1 },   /* AUX */
-       [SOUND_MIXER_LINE2]  = { 6, 0xc, 0x0, 1, 0x0100, 1 },   /* Mono1 */
-       [SOUND_MIXER_LINE3]  = { 7, 0xd, 0x0, 1, 0x0200, 1 },   /* Mono2 */
-       [SOUND_MIXER_MIC]    = { 8, 0xe, 0x0, 1, 0x0001, 1 },   /* Mic */
-       [SOUND_MIXER_OGAIN]  = { 9, 0xf, 0x0, 1, 0x0000, 1 }    /* mono out */
+       [SOUND_MIXER_LINE2]  = { 6, 0xc, 0x0, 0, 0x0100, 1 },   /* Mono1 */
+       [SOUND_MIXER_LINE3]  = { 7, 0xd, 0x0, 0, 0x0200, 1 },   /* Mono2 */
+       [SOUND_MIXER_MIC]    = { 8, 0xe, 0x0, 0, 0x0001, 1 },   /* Mic */
+       [SOUND_MIXER_OGAIN]  = { 9, 0xf, 0x0, 0, 0x0000, 1 }    /* mono out */
 };
 
 static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long arg)
 {
+       unsigned long flags;
        int i, val, j;
-       unsigned char l, r, rl, rr, sr, sl;
+       unsigned char l, r, rl, rr;
 
        VALIDATE_STATE(s);
 
        if (cmd == SOUND_MIXER_PRIVATE1) {
+               /* enable/disable/query mixer preamp */
                get_user_ret(val, (int *)arg, -EFAULT);
                if (val != -1) {
                        s->mix.micpreamp = !!val;
@@ -755,6 +767,34 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
                }
                return put_user(s->mix.micpreamp, (int *)arg);
        }
+       if (cmd == SOUND_MIXER_PRIVATE2) {
+               /* enable/disable/query use of linein as second lineout */
+               get_user_ret(val, (int *)arg, -EFAULT);
+               if (val != -1) {
+                       spin_lock_irqsave(&s->lock, flags);
+                       if (val)
+                               s->ctrl |= CTRL_XCTL0;
+                       else
+                               s->ctrl &= ~CTRL_XCTL0;
+                       outl(s->ctrl, s->io+ES1370_REG_CONTROL);
+                       spin_unlock_irqrestore(&s->lock, flags);
+               }
+               return put_user((s->ctrl & CTRL_XCTL0) ? 1 : 0, (int *)arg);
+       }
+       if (cmd == SOUND_MIXER_PRIVATE3) {
+               /* enable/disable/query microphone impedance setting */
+               get_user_ret(val, (int *)arg, -EFAULT);
+               if (val != -1) {
+                       spin_lock_irqsave(&s->lock, flags);
+                       if (val)
+                               s->ctrl |= CTRL_XCTL1;
+                       else
+                               s->ctrl &= ~CTRL_XCTL1;
+                       outl(s->ctrl, s->io+ES1370_REG_CONTROL);
+                       spin_unlock_irqrestore(&s->lock, flags);
+               }
+               return put_user((s->ctrl & CTRL_XCTL1) ? 1 : 0, (int *)arg);
+       }
         if (cmd == SOUND_MIXER_INFO) {
                mixer_info info;
                strncpy(info.id, "ES1370", sizeof(info.id));
@@ -842,12 +882,10 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
                l = val & 0xff;
                if (l > 100)
                        l = 100;
-               sl = sr = l;
                if (mixtable[i].stereo) {
                        r = (val >> 8) & 0xff;
                        if (r > 100)
                                r = 100;
-                       sr = r;
                        if (l < 10) {
                                rl = 0x80;
                                l = 0;
@@ -881,9 +919,13 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
                                        r = l = (15 - rl) * 6 + 10;
                                }
                        }
-               }                       
+               }
                wrcodec(s, mixtable[i].left, rl);
-               s->mix.vol[mixtable[i].volidx] = ((unsigned int)sr << 8) | sl;
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+               s->mix.vol[mixtable[i].volidx] = ((unsigned int)r << 8) | l;
+#else
+               s->mix.vol[mixtable[i].volidx] = val;
+#endif
                 return put_user(s->mix.vol[mixtable[i].volidx], (int *)arg);
        }
 }
@@ -2267,7 +2309,7 @@ __initfunc(int init_es1370(void))
                        goto err_irq;
                }
                /* initialize codec registers */
-               s->ctrl = CTRL_CDC_EN | CTRL_SERR_DIS | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV);
+               s->ctrl = CTRL_CDC_EN | CTRL_SERR_DIS | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL);
                if (joystick[index]) {
                        if (check_region(0x200, JOY_EXTENT))
                                printk(KERN_ERR "es1370: io port 0x200 in use\n");
@@ -2356,7 +2398,7 @@ void cleanup_module(void)
 
        while ((s = devs)) {
                devs = devs->next;
-               outl(CTRL_SERR_DIS, s->io+ES1370_REG_CONTROL); /* switch everything off */
+               outl(CTRL_SERR_DIS | (1 << CTRL_SH_WTSRSEL), s->io+ES1370_REG_CONTROL); /* switch everything off */
                outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */
                synchronize_irq();
                free_irq(s->irq, s);
index 8fcc035418bd23feaf28f00bd09448afc3937530..6a510d9d4db41450262c51ff0222aa94c3cf44ae 100644 (file)
@@ -45,8 +45,9 @@
  *                     should be detected. This results in strange behaviour of some mixer
  *                     settings, like master volume and mic.
  *    08.06.98   0.2   First release using Alan Cox' soundcore instead of miscdevice
- *
- *
+ *    03.08.98   0.3   Do not include modversions.h
+ *                     Now mixer behaviour can basically be selected between
+ *                     "OSS documented" and "OSS actual" behaviour
  *
  */
 
@@ -54,7 +55,6 @@
       
 #include <linux/version.h>
 #include <linux/module.h>
-#include <linux/modversions.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
 
 /* --------------------------------------------------------------------- */
 
+#undef OSS_DOCUMENTED_MIXER_SEMANTICS
+
+/* --------------------------------------------------------------------- */
+
 #ifndef PCI_VENDOR_ID_ENSONIQ
 #define PCI_VENDOR_ID_ENSONIQ        0x1274    
 #endif
@@ -325,6 +329,9 @@ struct es1371_state {
        struct {
                unsigned short codec_id;
                unsigned int modcnt;
+#ifndef OSS_DOCUMENTED_MIXER_SEMANTICS
+               unsigned short vol[13];
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
        } mix;
 
        /* wave stuff */
@@ -373,7 +380,7 @@ struct es1371_state {
 
 /* --------------------------------------------------------------------- */
 
-struct es1371_state *devs = NULL;
+static struct es1371_state *devs = NULL;
 
 /* --------------------------------------------------------------------- */
 
@@ -704,7 +711,7 @@ static void start_adc(struct es1371_state *s)
 
 /* --------------------------------------------------------------------- */
 
-#define DMABUF_DEFAULTORDER 8
+#define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
 #define DMABUF_MINORDER 1
 
 
@@ -982,7 +989,7 @@ static const unsigned int recsrc[8] =
        SOUND_MASK_PHONEIN
 };
 
-static const unsigned char volreg[] = 
+static const unsigned char volreg[SOUND_MIXER_NRDEVICES] = 
 {
        /* 5 bit stereo */
        [SOUND_MIXER_LINE] = 0x10,
@@ -1006,6 +1013,8 @@ static const unsigned char volreg[] =
        [SOUND_MIXER_IGAIN] = 0x1e
 };
 
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+
 #define swab(x) ((((x) >> 8) & 0xff) | (((x) << 8) & 0xff00))
 
 static int mixer_rdch(struct es1371_state *s, unsigned int ch, int *arg)
@@ -1093,6 +1102,34 @@ static int mixer_rdch(struct es1371_state *s, unsigned int ch, int *arg)
        }
 }
 
+#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+
+static const unsigned char volidx[SOUND_MIXER_NRDEVICES] = 
+{
+       /* 5 bit stereo */
+       [SOUND_MIXER_LINE] = 1,
+       [SOUND_MIXER_CD] = 2,
+       [SOUND_MIXER_VIDEO] = 3,
+       [SOUND_MIXER_LINE1] = 4,
+       [SOUND_MIXER_PCM] = 5,
+       /* 6 bit stereo */
+       [SOUND_MIXER_VOLUME] = 6,
+       [SOUND_MIXER_PHONEOUT] = 7,
+       /* 6 bit mono */
+       [SOUND_MIXER_OGAIN] = 8,
+       [SOUND_MIXER_PHONEIN] = 9,
+       /* 4 bit mono but shifted by 1 */
+       [SOUND_MIXER_SPEAKER] = 10,
+       /* 6 bit mono + preamp */
+       [SOUND_MIXER_MIC] = 11,
+       /* 4 bit stereo */
+       [SOUND_MIXER_RECLEV] = 12,
+       /* 4 bit mono */
+       [SOUND_MIXER_IGAIN] = 13
+};
+
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+
 static int mixer_wrch(struct es1371_state *s, unsigned int ch, int val)
 {
        int i;
@@ -1295,7 +1332,13 @@ static int mixer_ioctl(struct es1371_state *s, unsigned int cmd, unsigned long a
                        i = _IOC_NR(cmd);
                         if (i >= SOUND_MIXER_NRDEVICES)
                                 return -EINVAL;
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
                        return mixer_rdch(s, i, (int *)arg);
+#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+                       if (!volidx[i])
+                               return -EINVAL;
+                       return put_user(s->mix.vol[volidx[i]-1], (int *)arg);
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
                }
        }
         if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) 
@@ -1324,7 +1367,14 @@ static int mixer_ioctl(struct es1371_state *s, unsigned int cmd, unsigned long a
                get_user_ret(val, (int *)arg, -EFAULT);
                if (mixer_wrch(s, i, val))
                        return -EINVAL;
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
                return mixer_rdch(s, i, (int *)arg);
+#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+               if (!volidx[i])
+                       return -EINVAL;
+               s->mix.vol[volidx[i]-1] = val;
+               return put_user(s->mix.vol[volidx[i]-1], (int *)arg);
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
        }
 }
 
@@ -2662,7 +2712,7 @@ __initfunc(int init_es1371(void))
 
        if (!pci_present())   /* No PCI bus in this machine! */
                return -ENODEV;
-       printk(KERN_INFO "es1371: version v0.2 time " __TIME__ " " __DATE__ "\n");
+       printk(KERN_INFO "es1371: version v0.3 time " __TIME__ " " __DATE__ "\n");
        while (index < NR_DEVICE && 
               (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
                if (pcidev->base_address[0] == 0 || 
@@ -2818,11 +2868,7 @@ __initfunc(int init_es1371(void))
 #ifdef MODULE
 
 MODULE_PARM(joystick, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(joystick, "if 1 enables joystick interface (still need separate driver)");
-MODULE_PARM(lineout, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(lineout, "if 1 the LINE input is converted to LINE out");
-MODULE_PARM(micz, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(micz, "changes (??) the microphone impedance");
+MODULE_PARM_DESC(joystick, "sets address and enables joystick interface (still need separate driver)");
 
 MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
 MODULE_DESCRIPTION("ES1371 AudioPCI97 Driver");
index c15bced8806e99b1adcfd3b7d3c8b4ccb53cd975..c73e6f06b160dbc3a99eabf43e79880e765e502f 100644 (file)
@@ -3142,6 +3142,7 @@ void gus_wave_init(struct address_info *hw_config)
                        return;
                }
 
+               hw_config->slots[4] = gus_devnum;
                audio_devs[gus_devnum]->min_fragment = 9;       /* 512k */
                audio_devs[gus_devnum]->max_fragment = 11;      /* 8k (must match size of bounce_buf */
                audio_devs[gus_devnum]->mixer_dev = -1; /* Next mixer# */
index d46088b8eee6dec8bf7af5b0e66a88332b61357e..b98c02ea6d5ef33435522065f81b3e5a224fa61c 100644 (file)
  * on the miroSOUND PCM12 card. Support for miro sound cards with
  * additional ACI functions can easily be added later.
  *
+ * / NOTE / When compiling as a module, make sure to load the module 
+ * after loading the mad16 module. The initialisation code expects the
+ * MAD16 default mixer to be already available.
+ *
  * Revision history:
  *
  *   1995-11-10  Markus Kuhn <mskuhn@cip.informatik.uni-erlangen.de>
@@ -27,6 +31,8 @@
  *   1996-05-28  Markus Kuhn
  *        Initialize CS4231A mixer, make ACI first mixer,
  *        use new private mixer API for solo mode.
+ *   1998-08-04  Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
+ *       Small modification to complete modularisation.
  */
 
 /*
  */
 
 #include <linux/config.h> /* for CONFIG_ACI_MIXER */
+#include <linux/module.h> 
 #include "lowlevel.h"
 #include "../sound_config.h"
-#include "lowlevel.h"
-#ifdef CONFIG_ACI_MIXER
+
+#if defined(CONFIG_ACI_MIXER) || defined(CONFIG_ACI_MIXER_MODULE)
 
 #undef  DEBUG             /* if defined, produce a verbose report via syslog */
 
@@ -606,3 +613,17 @@ void unload_aci(void)
 }
 
 #endif
+
+#if defined(MODULE)
+
+int init_module(void) {
+       attach_aci();
+       return(0);
+}
+
+void cleanup_module(void) {
+       unload_aci();
+}
+
+#endif /* MODULE */
\ No newline at end of file
index b0a330ca454b5e1586b8e660fa3050a01a432d5a..7cc2fa6ef41d6404ec761cc5d4af2973c846d526 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: msnd.h,v 1.6 1998/07/18 00:12:15 andrewtv Exp $
+ * $Id: msnd.h,v 1.9 1998/08/06 21:06:14 andrewtv Exp $
  *
  ********************************************************************/
 #ifndef __MSND_H
 #define __MSND_H
 
-#define VERSION                        "0.7.0"
+#define VERSION                        "0.7.2"
 
 #define DEFSAMPLERATE          DSP_DEFAULT_SPEED
 #define DEFSAMPLESIZE          8
@@ -236,12 +236,14 @@ typedef struct multisound_dev {
 #define F_EXT_MIDI_INUSE               7
 #define F_INT_MIDI_INUSE               8
 #define F_WRITEFLUSH                   9
+#define F_HAVEDIGITAL                  10
 
        struct wait_queue *writeblock, *readblock;
        struct wait_queue *writeflush;
        unsigned long recsrc;
        int left_levels[16];
        int right_levels[16];
+       int mixer_mod_count;
        int calibrate_signal;
        int sample_size;
        int sample_rate;
index ac33dcab861bddfa511ac1c260d0915fbb90c845..07bba6bc6ca6df520d450dfb4fe4e32ac2ce1042 100644 (file)
@@ -29,7 +29,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: msnd_pinnacle.c,v 1.5 1998/07/18 00:12:16 andrewtv Exp $
+ * $Id: msnd_pinnacle.c,v 1.8 1998/08/06 21:06:14 andrewtv Exp $
  *
  ********************************************************************/
 
@@ -396,11 +396,13 @@ static int mixer_set(int d, int value)
 
 static unsigned long set_recsrc(unsigned long recsrc)
 {
+       if (dev.recsrc == recsrc)
+               return dev.recsrc;
 #ifdef HAVE_NORECSRC
-       if (recsrc == 0)
+       else if (recsrc == 0)
                dev.recsrc = 0;
-       else
 #endif
+       else
                dev.recsrc ^= recsrc;
 
 #ifndef MSND_CLASSIC
@@ -416,6 +418,13 @@ static unsigned long set_recsrc(unsigned long recsrc)
                        msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ);
 
        }
+       else if ((dev.recsrc & SOUND_MASK_DIGITAL1) && test_bit(F_HAVEDIGITAL, &dev.flags)) {
+
+               if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_DAT_IN) == 0) {
+                       udelay(50);
+                       msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ);
+               }
+       }
        else {
 #ifdef HAVE_NORECSRC
                /* Select no input (?) */
@@ -431,11 +440,27 @@ static unsigned long set_recsrc(unsigned long recsrc)
        return dev.recsrc;
 }
 
+#define set_mixer_info()                                                       \
+               strncpy(info.id, "MSNDMIXER", sizeof(info.id));                 \
+               strncpy(info.name, "MultiSound Mixer", sizeof(info.name));
+
 static int mixer_ioctl(unsigned int cmd, unsigned long arg)
 {
-       int val = 0;
-
-       if (((cmd >> 8) & 0xff) == 'M') {
+       if (cmd == SOUND_MIXER_INFO) {
+               mixer_info info;
+               set_mixer_info();
+               info.modify_counter = dev.mixer_mod_count;
+               return copy_to_user((void *)arg, &info, sizeof(info));
+       }
+       else if (cmd == SOUND_OLD_MIXER_INFO) {
+               _old_mixer_info info;
+               set_mixer_info();
+               return copy_to_user((void *)arg, &info, sizeof(info));
+       }
+       else if (cmd == OSS_GETVERSION)
+               return put_user(SOUND_VERSION, (int *)arg);
+       else if (((cmd >> 8) & 0xff) == 'M') {
+               int val = 0;
                
                if (_SIOC_DIR(cmd) & _SIOC_WRITE) {
 
@@ -453,6 +478,8 @@ static int mixer_ioctl(unsigned int cmd, unsigned long arg)
                                break;
                        }
 
+                       ++dev.mixer_mod_count;
+
                        return put_user(val, (int *)arg);
                }
                else {
@@ -479,6 +506,8 @@ static int mixer_ioctl(unsigned int cmd, unsigned long arg)
 #else
                                val =   SOUND_MASK_LINE |
                                        SOUND_MASK_SYNTH;
+                               if (test_bit(F_HAVEDIGITAL, &dev.flags))
+                                       val |= SOUND_MASK_DIGITAL1;
 #endif
                                break;
                                  
@@ -1309,7 +1338,14 @@ __initfunc(static int attach_multisound(void))
        printk(KERN_INFO LOGNAME ": Using DSP minor %d, mixer minor %d\n", MIXERMINOR, DSPMINOR);
 
        calibrate_adc(dev.sample_rate);
-       set_recsrc(0);
+#ifndef MSND_CLASSIC
+       printk(KERN_INFO LOGNAME ": Setting recording source to Line In\n");
+       if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_ANA_IN) != 0 ||
+           msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ) != 0) {
+               printk(KERN_DEBUG LOGNAME ": Error setting Line In as recording source\n");
+       }
+       dev.recsrc = SOUND_MASK_LINE;
+#endif
        
        return 0;
 }
@@ -1342,10 +1378,16 @@ MODULE_PARM                             (mem, "i");
 MODULE_PARM                            (major, "i");
 MODULE_PARM                            (fifosize, "i");
 MODULE_PARM                            (calibrate_signal, "i");
+#ifndef MSND_CLASSIC
+MODULE_PARM                            (digital, "i");
+#endif
 
 static int io __initdata =             -1;
 static int irq __initdata =            -1;
 static int mem __initdata =            -1;
+#ifndef MSND_CLASSIC
+static int digital __initdata;
+#endif
 static int fifosize __initdata =       DEFFIFOSIZE;
 static int calibrate_signal __initdata;
 
@@ -1355,13 +1397,24 @@ int init_module(void)
 static int io __initdata =             CONFIG_MSNDCLAS_IO;
 static int irq __initdata =            CONFIG_MSNDCLAS_IRQ;
 static int mem __initdata =            CONFIG_MSNDCLAS_MEM;
-#else
+#else /* Pinnacle/Fiji */
 static int io __initdata =             CONFIG_MSNDPIN_IO;
 static int irq __initdata =            CONFIG_MSNDPIN_IRQ;
 static int mem __initdata =            CONFIG_MSNDPIN_MEM;
+#ifndef CONFIG_MSNDPIN_DIGITAL
+#  define CONFIG_MSNDPIN_DIGITAL       0
 #endif
-static int fifosize __initdata =       DEFFIFOSIZE;
-static int calibrate_signal __initdata;
+static int digital __initdata =                CONFIG_MSNDPIN_DIGITAL;
+#endif /* MSND_CLASSIC */
+#ifndef CONFIG_MSND_FIFOSIZE
+#  define CONFIG_MSND_FIFOSIZE         DEFFIFOSIZE
+#endif /* CONFIG_MSND_FIFOSIZE */
+static int fifosize __initdata =       CONFIG_MSND_FIFOSIZE;
+#ifndef CONFIG_MSND_CALSIGNAL
+#  define CONFIG_MSND_CALSIGNAL                0
+#endif /* CONFIG_MSND_CALSIGNAL */
+static int
+calibrate_signal __initdata =          CONFIG_MSND_CALSIGNAL;
 
 #ifdef MSND_CLASSIC
 __initfunc(int msnd_classic_init(void))
@@ -1460,6 +1513,13 @@ __initfunc(int msnd_pinnacle_init(void))
        dev.inc_ref = mod_inc_ref;
        dev.dec_ref = mod_dec_ref;
 
+#ifndef MSND_CLASSIC
+       if (digital) {
+               set_bit(F_HAVEDIGITAL, &dev.flags);
+               printk(KERN_INFO LOGNAME ": Digital I/O access enabled\n");
+       }
+#endif
+
        init_waitqueue(&dev.writeblock);
        init_waitqueue(&dev.readblock);
        init_waitqueue(&dev.writeflush);
index bc6382f99ebc242e07763e5c3a0f02df4fe49092..8898c655a15f1beafc25f8009f6a9ea6ae0a0ceb 100644 (file)
@@ -169,7 +169,7 @@ int opl3_detect(int ioaddr, int *osp)
 
        if (devc == NULL)
        {
-               printk(KERN_ERR "OPL3: Can't allocate memory for the device control "
+               printk(KERN_ERR "opl3: Can't allocate memory for the device control "
                        "structure \n ");
                return 0;
        }
@@ -495,7 +495,7 @@ static int opl3_start_note (int dev, int voice, int note, int volume)
 
        if (instr->channel < 0)
        {
-               printk(KERN_WARNING "OPL3: Initializing voice %d with undefined instrument\n", voice);
+               printk(KERN_WARNING "opl3: Initializing voice %d with undefined instrument\n", voice);
                return 0;
        }
 
@@ -1091,7 +1091,7 @@ int opl3_init(int ioaddr, int *osp)
 
        if (devc == NULL)
        {
-               printk(KERN_ERR "opl3_init: Device control structure not initialized.\n");
+               printk(KERN_ERR "opl3: Device control structure not initialized.\n");
                return -1;
        }
 
@@ -1137,16 +1137,15 @@ int opl3_init(int ioaddr, int *osp)
 
        if (devc->model == 2)
        {
-               if (devc->is_opl4)
-                       conf_printf2("Yamaha OPL4/OPL3 FM", ioaddr, 0, -1, -1);
-               else
-                       conf_printf2("Yamaha OPL3 FM", ioaddr, 0, -1, -1);
+               if (devc->is_opl4) 
+                       strcpy(devc->fm_info.name, "Yamaha OPL4/OPL3 FM");
+               else 
+                       strcpy(devc->fm_info.name, "Yamaha OPL3");
 
                devc->v_alloc->max_voice = devc->nr_voice = 18;
                devc->fm_info.nr_drums = 0;
                devc->fm_info.synth_subtype = FM_TYPE_OPL3;
                devc->fm_info.capabilities |= SYNTH_CAP_OPL3;
-               strcpy(devc->fm_info.name, "Yamaha OPL-3");
 
                for (i = 0; i < 18; i++)
                {
@@ -1160,13 +1159,14 @@ int opl3_init(int ioaddr, int *osp)
        }
        else
        {
-               conf_printf2("Yamaha OPL2 FM", ioaddr, 0, -1, -1);
+               strcpy(devc->fm_info.name, "Yamaha OPL2");
                devc->v_alloc->max_voice = devc->nr_voice = 9;
                devc->fm_info.nr_drums = 0;
 
                for (i = 0; i < 18; i++)
                        pv_map[i].ioaddr = devc->left_io;
        };
+       conf_printf2(devc->fm_info.name, ioaddr, 0, -1, -1);
 
        for (i = 0; i < SBFM_MAXINSTR; i++)
                devc->i_map[i].channel = -1;
@@ -1185,14 +1185,21 @@ int me;
 
 int init_module (void)
 {
-       printk("YM3812 and OPL-3 driver Copyright (C) by Hannu Savolainen, Rob Hooft 1993-1996\n");
+       printk(KERN_INFO "YM3812 and OPL-3 driver Copyright (C) by Hannu Savolainen, Rob Hooft 1993-1996\n");
        if (io != -1)   /* User loading pure OPL3 module */
        {
+               if (check_region(io, 4))
+               {
+                       printk(KERN_WARNING "opl3: I/O port 0x%x already in use\n", io);
+                       return 0;
+               }
                if (!opl3_detect(io, NULL))
                {
                        return -ENODEV;
                }
                me = opl3_init(io, NULL);
+               request_region(io,4,devc->fm_info.name);
+
        }
        SOUND_LOCK;
        return 0;
@@ -1202,6 +1209,8 @@ void cleanup_module(void)
 {
        if (devc)
        {
+               if(devc->base)
+                       release_region(devc->base,4);
                kfree(devc);
                devc = NULL;
                sound_unload_synthdev(me);
index 8d7ffe1a716f423c0382905d49ce93ad1bec902c..19f8ee825836190c57ce9089086386f16cb538a0 100644 (file)
@@ -121,7 +121,7 @@ int sb_dsp_reset (sb_devc *devc);
 void sb_setmixer (sb_devc *devc, unsigned int port, unsigned int value);
 unsigned int sb_getmixer (sb_devc *devc, unsigned int port);
 int sb_dsp_detect (struct address_info *hw_config);
-void sb_dsp_init (struct address_info *hw_config);
+int sb_dsp_init (struct address_info *hw_config);
 void sb_dsp_unload(struct address_info *hw_config);
 int sb_mixer_init(sb_devc *devc);
 void sb_mixer_set_stereo (sb_devc *devc, int mode);
index 432501ebc5226d8650ef974cd3caf18a3c311856..2fc88cb24e08935d5dc3fa03ac84ee438a7ea87d 100644 (file)
@@ -25,7 +25,8 @@
 void attach_sb_card(struct address_info *hw_config)
 {
 #if defined(CONFIG_AUDIO) || defined(CONFIG_MIDI)
-       sb_dsp_init(hw_config);
+       if(!sb_dsp_init(hw_config))
+               hw_config->slots[0] = -1;
 #endif
 }
 
@@ -41,7 +42,8 @@ int probe_sb(struct address_info *hw_config)
 
 void unload_sb(struct address_info *hw_config)
 {
-       sb_dsp_unload(hw_config);
+       if(hw_config->slots[0]!=-1)
+               sb_dsp_unload(hw_config);
 }
 
 int sb_be_quiet=0;
@@ -92,7 +94,7 @@ int init_module(void)
        {
                if (io == -1 || dma == -1 || irq == -1)
                {
-                       printk(KERN_ERR "I/O, IRQ, and DMA are mandatory\n");
+                       printk(KERN_ERR "sb_card: I/O, IRQ, and DMA are mandatory\n");
                        return -EINVAL;
                }
                config.io_base = io;
@@ -104,6 +106,9 @@ int init_module(void)
                if (!probe_sb(&config))
                        return -ENODEV;
                attach_sb_card(&config);
+               
+               if(config.slots[0]==-1)
+                       return -ENODEV;
 #ifdef CONFIG_MIDI
                config_mpu.io_base = mpu_io;
                if (mpu_io && probe_sbmpu(&config_mpu))
index 8fe5a44f032512d3cb7363456e332730e06dd166..3ec472f4d26cdaa1e3c1c230ee1264a67032c547 100644 (file)
@@ -162,7 +162,7 @@ static void sbintr(int irq, void *dev_id, struct pt_regs *dummy)
                                break;
 
                        default:
-                               /* printk( "Sound Blaster: Unexpected interrupt\n"); */
+                               /* printk(KERN_WARN "Sound Blaster: Unexpected interrupt\n"); */
                                ;
                }
        }
@@ -242,7 +242,7 @@ static int sb16_set_dma_hw(sb_devc * devc)
 
        if (devc->dma8 != 0 && devc->dma8 != 1 && devc->dma8 != 3)
        {
-               printk(KERN_ERR "sb16: Invalid 8 bit DMA (%d)\n", devc->dma8);
+               printk(KERN_ERR "SB16: Invalid 8 bit DMA (%d)\n", devc->dma8);
                return 0;
        }
        bits = (1 << devc->dma8);
@@ -298,7 +298,7 @@ static int sb16_set_irq_hw(sb_devc * devc, int level)
                        ival = 8;
                        break;
                default:
-                       printk(KERN_ERR "SB16 IRQ%d is not possible\n", level);
+                       printk(KERN_ERR "SB16: Invalid IRQ%d\n", level);
                        return 0;
        }
        sb_setmixer(devc, IRQ_NR, ival);
@@ -694,7 +694,7 @@ int sb_dsp_detect(struct address_info *hw_config)
        return 1;
 }
 
-void sb_dsp_init(struct address_info *hw_config)
+static int sb_dsp_init(struct address_info *hw_config)
 {
        sb_devc *devc;
        char name[100];
@@ -710,7 +710,7 @@ void sb_dsp_init(struct address_info *hw_config)
        if (detected_devc == NULL)
        {
                MDB(printk("No detected device\n"));
-               return;
+               return 0;
        }
        devc = detected_devc;
        detected_devc = NULL;
@@ -718,7 +718,7 @@ void sb_dsp_init(struct address_info *hw_config)
        if (devc->base != hw_config->io_base)
        {
                DDB(printk("I/O port mismatch\n"));
-               return;
+               return 0;
        }
        /*
         * Now continue initialization of the device
@@ -731,7 +731,7 @@ void sb_dsp_init(struct address_info *hw_config)
                if (request_irq(hw_config->irq, sbintr, 0, "soundblaster", devc) < 0)
                {
                        printk(KERN_ERR "SB: Can't allocate IRQ%d\n", hw_config->irq);
-                       return;
+                       return 0;
                }
                devc->irq_ok = 0;
 
@@ -739,7 +739,7 @@ void sb_dsp_init(struct address_info *hw_config)
                        if (!sb16_set_irq_hw(devc, devc->irq))  /* Unsupported IRQ */
                        {
                                free_irq(devc->irq, devc);
-                               return;
+                               return 0;
                        }
                if ((devc->type == 0 || devc->type == MDL_ESS) &&
                        devc->major == 3 && devc->minor == 1)
@@ -853,7 +853,11 @@ void sb_dsp_init(struct address_info *hw_config)
                        else
                                devc->dma16 = hw_config->dma2;
 
-                       sb16_set_dma_hw(devc);
+                       if(!sb16_set_dma_hw(devc)) {
+                               free_irq(devc->irq, devc);
+                               return 0;
+                       }
+
                        devc->caps |= SB_NO_MIDI;
        }
 
@@ -903,7 +907,7 @@ void sb_dsp_init(struct address_info *hw_config)
        {
                if (sound_alloc_dma(devc->dma8, "SoundBlaster8"))
                {
-                       printk(KERN_WARNING "SB: Can't allocate 8 bit DMA channel %d\n", devc->dma8);
+                       printk(KERN_WARNING "Sound Blaster: Can't allocate 8 bit DMA channel %d\n", devc->dma8);
                }
                if (devc->dma16 >= 0 && devc->dma16 != devc->dma8)
                {
@@ -917,6 +921,7 @@ void sb_dsp_init(struct address_info *hw_config)
        {
                MDB(printk("Sound Blaster:  no audio devices found.\n"));
        }
+       return 1;
 }
 
 void sb_dsp_disable_midi(int io_base)
@@ -1160,7 +1165,9 @@ static int ess_midi_init(sb_devc * devc, struct address_info *hw_config)
 
        tmp = 1;                /* MPU enabled without interrupts */
 
-       switch (hw_config->irq)
+       /* May be shared: if so the value is -ve */
+       
+       switch(abs(hw_config->irq))
        {
                case 9:
                        tmp = 0x4;
index e4f962035baf1cf1b6a3f8af4005dd31762ce827..5143335122073fe767d22faf73c1a3a3ce85bce2 100644 (file)
@@ -1061,7 +1061,10 @@ int sequencer_open(int dev, struct file *file)
                setup_mode2();
        }
        if (!max_synthdev && !max_mididev)
+       {
+               sequencer_busy=0;
                return -ENXIO;
+       }
 
        synth_open_mask = 0;
 
index 4f81fcdf35904329b5a44b135e9c3a6326d4f533..066d722eb95e50403fa21bfad30a1f05496c32f6 100644 (file)
@@ -43,6 +43,9 @@
  *                     Fix hwptr out of bounds (now mpg123 works)
  *    14.05.98   0.4   Don't allow excessive interrupt rates
  *    08.06.98   0.5   First release using Alan Cox' soundcore instead of miscdevice
+ *    03.08.98   0.6   Do not include modversions.h
+ *                     Now mixer behaviour can basically be selected between
+ *                     "OSS documented" and "OSS actual" behaviour
  *
  */
 
@@ -50,7 +53,6 @@
       
 #include <linux/version.h>
 #include <linux/module.h>
-#include <linux/modversions.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
 
 /* --------------------------------------------------------------------- */
 
+#undef OSS_DOCUMENTED_MIXER_SEMANTICS
+
+/* --------------------------------------------------------------------- */
+
 #ifndef PCI_VENDOR_ID_S3
 #define PCI_VENDOR_ID_S3             0x5333
 #endif
@@ -245,6 +251,9 @@ struct sv_state {
         /* mixer stuff */
         struct {
                 unsigned int modcnt;
+#ifndef OSS_DOCUMENTED_MIXER_SEMANTICS
+               unsigned short vol[13];
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
         } mix;
 
        /* wave stuff */
@@ -471,6 +480,7 @@ static unsigned setpll(struct sv_state *s, unsigned char reg, unsigned rate)
        unsigned long flags;
        unsigned char r, m, n;
        unsigned xm, xn, xr, xd, metric = ~0U;
+       /* the warnings about m and n used uninitialized are bogus and may safely be ignored */
 
        if (rate < 625000/ADCMULT)
                rate = 625000/ADCMULT;
@@ -619,10 +629,9 @@ static void start_adc(struct sv_state *s)
 
 /* --------------------------------------------------------------------- */
 
-#define DMABUF_DEFAULTORDER 8
+#define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
 #define DMABUF_MINORDER 1
 
-
 static void dealloc_dmabuf(struct dmabuf *db)
 {
        unsigned long map, mapend;
@@ -885,6 +894,8 @@ static const struct {
        [SOUND_MIXER_PCM]    = { SV_CIMIX_PCMINL,    SV_CIMIX_PCMINR,    MT_6MUTE,     0 }
 };
 
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+
 static int return_mixval(struct sv_state *s, unsigned i, int *arg)
 {
        unsigned long flags;
@@ -928,6 +939,23 @@ static int return_mixval(struct sv_state *s, unsigned i, int *arg)
        return put_user((rr << 8) | rl, arg);
 }
 
+#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+
+static const unsigned char volidx[SOUND_MIXER_NRDEVICES] = 
+{
+       [SOUND_MIXER_RECLEV] = 1,
+       [SOUND_MIXER_LINE1]  = 2,
+       [SOUND_MIXER_CD]     = 3,
+       [SOUND_MIXER_LINE]   = 4,
+       [SOUND_MIXER_MIC]    = 5,
+       [SOUND_MIXER_SYNTH]  = 6,
+       [SOUND_MIXER_LINE2]  = 7,
+       [SOUND_MIXER_VOLUME] = 8,
+       [SOUND_MIXER_PCM]    = 9
+};
+
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+
 static unsigned mixer_recmask(struct sv_state *s)
 {
        unsigned long flags;
@@ -1022,7 +1050,13 @@ static int mixer_ioctl(struct sv_state *s, unsigned int cmd, unsigned long arg)
                        i = _IOC_NR(cmd);
                         if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type)
                                 return -EINVAL;
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
                        return return_mixval(s, i, (int *)arg);
+#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+                       if (!volidx[i])
+                               return -EINVAL;
+                       return put_user(s->mix.vol[volidx[i]-1], (int *)arg);
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
                }
        }
         if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) 
@@ -1116,7 +1150,14 @@ static int mixer_ioctl(struct sv_state *s, unsigned int cmd, unsigned long arg)
                        break;
                }
                spin_unlock_irqrestore(&s->lock, flags);
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
                 return return_mixval(s, i, (int *)arg);
+#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+               if (!volidx[i])
+                       return -EINVAL;
+               s->mix.vol[volidx[i]-1] = val;
+               return put_user(s->mix.vol[volidx[i]-1], (int *)arg);
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
        }
 }
 
@@ -2200,7 +2241,10 @@ static /*const*/ struct file_operations sv_dmfm_fops = {
 #define NR_DEVICE 5
 
 static int reverb[NR_DEVICE] = { 0, };
+
+#if 0
 static int wavetable[NR_DEVICE] = { 0, };
+#endif
 
 static unsigned dmaio = 0xac00;
 
@@ -2234,7 +2278,7 @@ __initfunc(int init_sonicvibes(void))
 
        if (!pci_present())   /* No PCI bus in this machine! */
                return -ENODEV;
-       printk(KERN_INFO "sv: version v0.5 time " __TIME__ " " __DATE__ "\n");
+       printk(KERN_INFO "sv: version v0.6 time " __TIME__ " " __DATE__ "\n");
 #if 0
        if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
                printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
@@ -2297,7 +2341,6 @@ __initfunc(int init_sonicvibes(void))
                /* hack */
                pci_write_config_dword(pcidev, 0x60, wavetable_mem >> 12);  /* wavetable base address */
 
-
                if (check_region(s->ioenh, SV_EXTENT_ENH)) {
                        printk(KERN_ERR "sv: io ports %#x-%#x in use\n", s->ioenh, s->ioenh+SV_EXTENT_ENH-1);
                        goto err_region5;
@@ -2328,8 +2371,8 @@ __initfunc(int init_sonicvibes(void))
                udelay(50);
                outb(0x00, s->ioenh + SV_CODEC_CONTROL); /* deassert reset */
                udelay(50);
-               outb(SV_CCTRL_INTADRIVE | SV_CCTRL_ENHANCED /*| SV_CCTRL_WAVETABLE | SV_CCTRL_REVERB*/,
-                    s->ioenh + SV_CODEC_CONTROL);
+               outb(SV_CCTRL_INTADRIVE | SV_CCTRL_ENHANCED /*| SV_CCTRL_WAVETABLE */
+                    | (reverb[index] ? SV_CCTRL_REVERB : 0), s->ioenh + SV_CODEC_CONTROL);
                inb(s->ioenh + SV_CODEC_STATUS); /* clear ints */
                wrindir(s, SV_CIDRIVECONTROL, 0);  /* drive current 16mA */
                wrindir(s, SV_CIENABLE, s->enable = 0);  /* disable DMAA and DMAC */
@@ -2412,9 +2455,11 @@ __initfunc(int init_sonicvibes(void))
 #ifdef MODULE
 
 MODULE_PARM(reverb, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(reverb, "if 1 enables joystick interface (still need separate driver)");
+MODULE_PARM_DESC(reverb, "if 1 enables the reverb circuitry. NOTE: your card must have the reverb RAM");
+#if 0
 MODULE_PARM(wavetable, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(wavetable, "if 1 the LINE input is converted to LINE out");
+MODULE_PARM_DESC(wavetable, "if 1 the wavetable synth is enabled");
+#endif
 
 MODULE_PARM(dmaio, "i");
 MODULE_PARM_DESC(dmaio, "if the motherboard BIOS did not allocate DDMA io, allocate them starting at this address");
index 2abd7fa2224deb2553d369d8e1bca25ef6f12af4..d679ff8bc715a5b0425942c4fa1bfad8a23df207 100644 (file)
@@ -846,12 +846,16 @@ static int      sound[20] = {
 
 #ifdef MODULE
 
+int traceinit = 0;
+MODULE_PARM(traceinit, "i");
+
 int init_module(void)
 {
        int             err;
        int             ints[21];
        int             i;
 
+       trace_init=traceinit;
        /*
         * "sound=" command line handling by Harald Milz.
         */
index 735dcd93f612a00f8cdac4b6d02060bd538dc0f6..3740dd263ce2d92ca7ee7e29ec5d4f0e1e214e18 100644 (file)
@@ -1,8 +1,8 @@
-/*
- * sound/wavefront.c
+/*  -*- linux-c -*-
  *
- * A low level driver for Turtle Beach WaveFront Series
- *    (Maui, Tropez, Tropez Plus, and perhaps the Monterey & Rio)
+ * sound/wavfront.c
+ *
+ * A Linux driver for Turtle Beach WaveFront Series (Maui, Tropez, Tropez Plus)
  *
  * This driver supports the onboard wavetable synthesizer (an ICS2115),
  * including patch, sample and program loading and unloading, conversion
  * This chip also controls the configuration of the card: the wavefront
  * synth is logical unit 4.
  *
- * NOTE: this driver has been written to support multiple WaveFront
- * cards, but without using PnP to configure the CS4232, all of them
- * would end up with the same configuration. Further, the current
- * module loading interface doesn't permit this, since it only allows
- * once instance of a module (which happens to be equivalent to a
- * single hardware configuration) to be installed at one time.In
- * addition, there is a hard limit on the available DMA channels that
- * also makes installing more than 1 card limited to purely MIDI/synth
- * activities on the second card. Still, the coding style gets rid of
- * virtually all globals, which I believe is a better way to code
- * device drivers (or anything else, for that matter).
- *
  **********************************************************************
  *
  * Copyright (C) by Paul Barton-Davis 1998
  * aspects of configuring a WaveFront soundcard, particularly the
  * effects processor.
  *
+ * $Id: wavfront.c,v 0.4 1998/07/22 02:12:11 pbd Exp $
+ *
  * This program is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info.  */
+ * for more info.
+ */
 
 #include <linux/config.h>
 #include <linux/module.h>
 #define MIDI_SYNTH_CAPS        SYNTH_CAP_INPUT
 #include "midi_synth.h"
 
-#define COPY_FROM_USER(a,b,c) copy_from_user ((a),(b),(c))
-#define COPY_TO_USER(a,b,c)   copy_to_user ((a),(b),(c))
+/* This thing is meant to work as a module */
 
-#if defined(CONFIG_SOUND_WAVEFRONT) || defined(CONFIG_SOUND_WAVEFRONT_MODULE)
+#if defined(CONFIG_SOUND_WAVEFRONT_MODULE) && defined(MODULE)
 
-/* This thing is meant to work as a module */
+/* if WF_DEBUG not defined, no run-time debugging messages will
+   be available via the debug flag setting. Given the current
+   beta state of the driver, this will remain set until a future 
+   version.
+*/
 
-#ifdef MODULE
+#define WF_DEBUG 1
 
 /* bitmasks for WaveFront status port value */
 
 #define STAT_INTR_WRITE                0x40
 #define STAT_CAN_WRITE         0x20
-#define STAT_RINTR_ENABLED     0x10
+#define STAT_WINTR_ENABLED     0x10
 #define STAT_INTR_READ         0x04
 #define STAT_CAN_READ          0x02
-#define STAT_WINTR_ENABLED     0x01
+#define STAT_RINTR_ENABLED     0x01
 
 /*** Module-accessible parameters ***************************************/
 
@@ -111,7 +105,7 @@ int fx_raw = 1; /* if this is zero, we'll leave the FX processor in
                   operation, whatever that means.
                */
 
-int wf_debug_default = 0;  /* you can set this to control debugging
+int debug_default = 0;  /* you can set this to control debugging
                              during driver loading. it takes any combination
                              of the WF_DEBUG_* flags defined in
                              wavefront.h
@@ -119,27 +113,33 @@ int wf_debug_default = 0;  /* you can set this to control debugging
 
 /* XXX this needs to be made firmware and hardware version dependent */
 
-char *wf_ospath = "/etc/sound/wavefront.os"; /* where to find a processed
-                                               version of the WaveFront OS
-                                            */
+char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed
+                                            version of the WaveFront OS
+                                         */
 
-/* These three don't need to be messed with unless you're trying to
-   tweak the driver for optimal I/O performance. Read wavefront_wait()
-   and wavefront_sleep() to see what they do. You may need or want to
-   tweak them for CPU's different than the 486/66Mhz that I run on.
-*/
+int sleep_interval = 100;     /* HZ/sleep_interval seconds per sleep */
+int sleep_tries = 50;       /* number of times we'll try to sleep */
+
+int wait_usecs = 150; /* This magic number seems to give pretty optimal
+                        throughput based on my limited experimentation.
+                        If you want to play around with it and find a better
+                        value, be my guest. Remember, the idea is to
+                        get a number that causes us to just busy wait
+                        for as many WaveFront commands as possible, without
+                        coming up with a number so large that we hog the
+                        whole CPU.
 
-int wf_short_wait_count = 5000; /* loops, CPU dependent */
-int wf_sleep_interval = 50;     /* HZ/wf_sleep_interval seconds per sleep */
-int wf_sleep_tries = 100;  /*2sec*/ /* number of times we'll try to sleep */
+                        Specifically, with this number, out of about 134,000
+                        status waits, only about 250 result in a sleep.
+                     */
 
 MODULE_PARM(wf_raw,"i");
 MODULE_PARM(fx_raw,"i");
-MODULE_PARM(wf_debug_default,"i");
-MODULE_PARM(wf_ospath,"s");
-MODULE_PARM(wf_short_wait_count,"i");
-MODULE_PARM(wf_sleep_interval,"i");
-MODULE_PARM(wf_sleep_tries,"i");
+MODULE_PARM(debug_default,"i");
+MODULE_PARM(sleep_interval,"i");
+MODULE_PARM(sleep_tries,"i");
+MODULE_PARM(wait_usecs,"i");
+MODULE_PARM(ospath,"s");
 
 /***************************************************************************/
 
@@ -150,9 +150,7 @@ static struct synth_info wavefront_info =
 static int (*midi_load_patch) (int dev, int format, const char *addr,
                               int offs, int count, int pmgr_flag) = NULL;
 
-
 typedef struct wf_config {
-       int installed;        /* well, is it ? note: doesn't mean "working" */
        int devno;            /* device number from kernel */
        int irq;              /* "you were one, one of the few ..." */
        int base;             /* low i/o port address */
@@ -185,7 +183,7 @@ typedef struct wf_config {
        volatile int irq_ok;               /* set by interrupt handler */
        int opened;                        /* flag, holds open(1) mode */
        char debug;                        /* debugging flags */
-       unsigned int freemem;              /* installed RAM, in bytes */ 
+       int freemem;                       /* installed RAM, in bytes */ 
        int synthdev;                      /* OSS minor devnum for synth */
        int mididev;                       /* OSS minor devno for internal MIDI */
        int ext_mididev;                   /* OSS minor devno for external MIDI */ 
@@ -198,9 +196,20 @@ typedef struct wf_config {
        int samples_used;                  /* how many */
        char interrupts_on;                /* h/w MPU interrupts enabled ? */
        char rom_samples_rdonly;           /* can we write on ROM samples */
+       struct wait_queue *interrupt_sleeper; 
+#ifdef  WF_STATS
+       unsigned long status_found_during_loop;
+       unsigned long status_found_during_sleep[4];
+#endif  WF_STATS
+
 } wf_config;
 
-static wf_config wfs[WAVEFRONT_MAX_DEVICES];
+/* Note: because this module doesn't export any symbols, this really isn't
+   a global variable, even if it looks like one. I was quite confused by
+   this when I started writing this as a (newer) module -- pbd.
+*/
+
+static wf_config wavefront_configuration;
 
 #define wavefront_status(hw) (inb (hw->status_port))
 
@@ -210,14 +219,6 @@ static int wffx_ioctl (struct wf_config *, wavefront_fx_info *);
 static int wffx_init (struct wf_config *hw);
 static int wavefront_delete_sample (struct wf_config *hw, int sampnum);
 
-static volatile int irq2hw[17] =
-{-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1};
-
-static volatile int dev2hw[17] =
-{-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1};
-
 typedef struct {
        int cmd;
        char *action;
@@ -304,25 +305,10 @@ static wavefront_command wavefront_commands[] = {
        { WFC_DISABLE_DRUM_PROGRAM, "disable drum program", 0, 1, NEEDS_ACK },
        { WFC_REPORT_CHANNEL_PROGRAMS, "report channel program numbers",
          32, 0, 0 },
+       { WFC_NOOP, "the no-op command", 0, 0, NEEDS_ACK },
        { 0x00 }
 };
 
-wf_config *
-hw_from_dev (int dev)
-
-{
-       int i;
-
-       if ((i = dev2hw[dev]) == -1) {
-               printk (KERN_ERR
-                       "WaveFront: no hardware associated with device %d.\n",
-                       dev);
-               return 0;
-       }
-
-       return &wfs[i];
-}
-
 static const char *
 wavefront_errorstr (int errnum)
 
@@ -370,21 +356,35 @@ wavefront_wait (wf_config *hw, int mask)
 
 {
        int             i;
+       static int      short_loop_cnt = 0;
+
+       if (short_loop_cnt == 0) {
+           short_loop_cnt = (int) (((double) wait_usecs / 1000000.0) *
+               (double) current_cpu_data.loops_per_sec);
+       }
 
-       for (i = 0; i < wf_short_wait_count; i++) {
+       for (i = 0; i < short_loop_cnt; i++) {
                if (wavefront_status(hw) & mask) {
+#ifdef WF_STATS
+                       hw->status_found_during_loop++;
+#endif WF_STATS
                        return 1;
                }
        }
 
-       for (i = 0; i < wf_sleep_tries; i++) {
+       for (i = 0; i < sleep_tries; i++) {
 
                if (wavefront_status(hw) & mask) {
+#ifdef WF_STATS
+                       if (i < 4) {
+                               hw->status_found_during_sleep[i]++;
+                       }
+#endif WF_STATS
                        return 1;
                }
 
-               if (wavefront_sleep (hw, HZ/wf_sleep_interval)) {
-                       return 0;
+               if (wavefront_sleep (hw, HZ/sleep_interval)) {
+                       return (0);
                }
        }
 
@@ -397,23 +397,30 @@ wavefront_read (wf_config *hw)
        if (wavefront_wait (hw, STAT_CAN_READ))
                return inb (hw->data_port);
 
+#ifdef WF_DEBUG
        if (hw->debug & WF_DEBUG_DATA) {
                printk (KERN_DEBUG "WaveFront: read timeout.\n");
        }
+#endif WF_DEBUG
+
        return -1;
 }
 
 static int
 wavefront_write (wf_config *hw, unsigned char data)
+
 {
        if (wavefront_wait (hw, STAT_CAN_WRITE)) {
                outb (data, hw->data_port);
                return 1;
        }
 
+#ifdef WF_DEBUG
        if (hw->debug & WF_DEBUG_DATA) {
                printk (KERN_DEBUG "WaveFront: write timeout.\n");
        }
+#endif WF_DEBUG
+
        return 0;
 }
 
@@ -444,60 +451,74 @@ wavefront_cmd (wf_config *hw, int cmd,
                rbuf = 0;
        }
 
+#ifdef WF_DEBUG
        if (hw->debug & WF_DEBUG_CMD) {
                printk (KERN_DEBUG "Wavefront: 0x%x [%s] (%d,%d,%d)\n",
                        cmd, wfcmd->action, wfcmd->read_cnt, wfcmd->write_cnt,
                        wfcmd->need_ack);
        }
+#endif WF_DEBUG
     
        if (!wavefront_write (hw, cmd)) { 
+#ifdef WF_DEBUG
                if (hw->debug & (WF_DEBUG_IO|WF_DEBUG_CMD)) {
                        printk (KERN_DEBUG "WaveFront: cannot request "
                                "0x%x [%s].\n",
                                cmd, wfcmd->action);
                }
+#endif WF_DEBUG
                return 1;
        } 
 
        if (wfcmd->write_cnt > 0) {
+#ifdef WF_DEBUG
                if (hw->debug & WF_DEBUG_DATA) {
                        printk (KERN_DEBUG "WaveFront: writing %d bytes "
                                "for 0x%x\n",
                                wfcmd->write_cnt, cmd);
                }
+#endif WF_DEBUG
 
                for (i = 0; i < wfcmd->write_cnt; i++) {
                        if (!wavefront_write (hw, wbuf[i])) {
+#ifdef WF_DEBUG
                                if (hw->debug & WF_DEBUG_IO) {
                                        printk (KERN_DEBUG
                            "WaveFront: bad write for byte %d of 0x%x [%s].\n",
                                                i, cmd, wfcmd->action);
                                }
+#endif WF_DEBUG
                                return 1;
                        }
+#ifdef WF_DEBUG
                        if (hw->debug & WF_DEBUG_DATA) {
                                printk (KERN_DEBUG
                                         "WaveFront: write[%d] = 0x%x\n",
                                        i, wbuf[i]);
+#endif WF_DEBUG
                        }
                }
        }
 
        if (wfcmd->read_cnt > 0) {
+#ifdef WF_DEBUG
                if (hw->debug & WF_DEBUG_DATA) {
                        printk (KERN_DEBUG "WaveFront: reading %d ints "
                                "for 0x%x\n",
                                wfcmd->read_cnt, cmd);
                }
+#endif WF_DEBUG
 
                for (i = 0; i < wfcmd->read_cnt; i++) {
 
                        if ((c = wavefront_read(hw)) == -1) {
+#ifdef WF_DEBUG
                                if (hw->debug & WF_DEBUG_IO) {
                                        printk (KERN_DEBUG
                                "WaveFront: bad read for byte %d of 0x%x [%s].\n",
                                                i, cmd, wfcmd->action);
                                }
+#endif WF_DEBUG
                                return 1;
                        }
 
@@ -505,12 +526,14 @@ wavefront_cmd (wf_config *hw, int cmd,
            
                        if (c == 0xff) { 
                                if ((c = wavefront_read (hw)) == -1) {
+#ifdef WF_DEBUG
                                        if (hw->debug & WF_DEBUG_IO) {
                                                printk (KERN_DEBUG
                                  "WaveFront: bad read for error byte at "
                                   "read byte %d of 0x%x [%s].\n",
                                                        i, cmd, wfcmd->action);
                                        }
+#endif WF_DEBUG
                                        return 1;
                                }
 
@@ -519,7 +542,7 @@ wavefront_cmd (wf_config *hw, int cmd,
                                if (c == 1 &&
                                    wfcmd->cmd == WFC_IDENTIFY_SAMPLE_TYPE) {
                                        rbuf[0] = WF_ST_EMPTY;
-                                       return 0;
+                                       return (0);
 
                                } else if (c == 3 &&
                                           wfcmd->cmd == WFC_UPLOAD_PATCH) {
@@ -533,6 +556,7 @@ wavefront_cmd (wf_config *hw, int cmd,
 
                                } else {
 
+#ifdef WF_DEBUG
                                        if (hw->debug & WF_DEBUG_IO) {
                                                printk (KERN_DEBUG
                                             "WaveFront: error %d (%s) during "
@@ -542,6 +566,7 @@ wavefront_cmd (wf_config *hw, int cmd,
                                                        wavefront_errorstr (c),
                                                        i, cmd, wfcmd->action);
                                        }
+#endif WF_DEBUG
                                        return 1;
 
                                }
@@ -549,20 +574,24 @@ wavefront_cmd (wf_config *hw, int cmd,
                                rbuf[i] = c;
                        }
 
+#ifdef WF_DEBUG
                        if (hw->debug & WF_DEBUG_DATA) {
                                printk (KERN_DEBUG
                                        "WaveFront: read[%d] = 0x%x\n",
                                        i, rbuf[i]);
                        }
+#endif WF_DEBUG
                }
        }
 
        if ((wfcmd->read_cnt == 0 && wfcmd->write_cnt == 0) || wfcmd->need_ack) {
 
+#ifdef WF_DEBUG
                if (hw->debug & WF_DEBUG_CMD) {
                        printk (KERN_DEBUG "WaveFront: reading ACK for 0x%x\n",
                                cmd);
                }
+#endif WF_DEBUG
 
                /* Some commands need an ACK, but return zero instead
                   of the standard value.
@@ -574,11 +603,13 @@ wavefront_cmd (wf_config *hw, int cmd,
        
                if (ack != WF_ACK) {
                        if (ack == -1) {
+#ifdef WF_DEBUG
                                if (hw->debug & WF_DEBUG_IO) {
                                        printk (KERN_DEBUG
                                "WaveFront: cannot read ack for 0x%x [%s].\n",
                                                cmd, wfcmd->action);
                                }
+#endif WF_DEBUG
                                return 1;
                
                        } else {
@@ -587,14 +618,17 @@ wavefront_cmd (wf_config *hw, int cmd,
                                if (ack == 0xff) { /* explicit error */
                    
                                        if ((err = wavefront_read (hw)) == -1) {
+#ifdef WF_DEBUG
                                                if (hw->debug & WF_DEBUG_DATA) {
                                                        printk (KERN_DEBUG
                                "WaveFront: cannot read err for 0x%x [%s].\n",
                                                             cmd, wfcmd->action);
                                                }
+#endif WF_DEBUG
                                        }
                                }
 
+#ifdef WF_DEBUG
                                if (hw->debug & WF_DEBUG_IO) {
                                        printk (KERN_DEBUG
                                                "WaveFront: 0x%x [%s] "
@@ -602,22 +636,27 @@ wavefront_cmd (wf_config *hw, int cmd,
                                                cmd, wfcmd->action, ack, err,
                                                wavefront_errorstr (err));
                                }
+#endif WF_DEBUG
                                return -err;
                        } 
                }
 
+#ifdef WF_DEBUG
                if (hw->debug & WF_DEBUG_DATA) {
                        printk (KERN_DEBUG "WaveFront: ack received "
                                "for 0x%x [%s]\n",
                                cmd, wfcmd->action);
                }
+#endif WF_DEBUG
        } else {
+#ifdef WF_DEBUG
                if (hw->debug & WF_DEBUG_CMD) {
                        printk (KERN_DEBUG 
                                "Wavefront: 0x%x [%s] does not need "
                                "ACK (%d,%d,%d)\n",
                                cmd, wfcmd->action, wfcmd->read_cnt,
                                wfcmd->write_cnt, wfcmd->need_ack);
+#endif WF_DEBUG
                }
        }
 
@@ -795,7 +834,7 @@ wavefront_get_sample_status (struct wf_config *hw, int assume_rom)
                WF_MAX_SAMPLE - hw->samples_used);
 
 
-       return 0;
+       return (0);
 
 }
 
@@ -826,6 +865,7 @@ wavefront_get_patch_status (struct wf_config *hw)
                        printk (KERN_ERR "WaveFront: upload patch "
                                "error 0x%x\n", x);
                        hw->patch_status[i] = 0;
+                       return 1;
                }
        }
 
@@ -843,7 +883,7 @@ wavefront_get_patch_status (struct wf_config *hw)
        printk (KERN_INFO
                "WaveFront: %d patch slots filled, %d in use\n", cnt, cnt2);
 
-       return 0;
+       return (0);
 }
 
 static int
@@ -889,7 +929,7 @@ wavefront_get_program_status (struct wf_config *hw)
 
        printk (KERN_INFO "WaveFront: %d programs slots in use\n", cnt);
 
-       return 0;
+       return (0);
 }
 
 static int
@@ -900,10 +940,12 @@ wavefront_send_patch (wf_config *hw,
        unsigned char buf[WF_PATCH_BYTES+2];
        unsigned char *bptr;
 
+#ifdef WF_DEBUG
        if (hw->debug & WF_DEBUG_LOAD_PATCH) {
                printk (KERN_DEBUG "WaveFront: downloading patch %d\n",
                        header->number);
        }
+#endif WF_DEBUG
 
        hw->patch_status[header->number] |= WF_SLOT_FILLED;
 
@@ -913,10 +955,10 @@ wavefront_send_patch (wf_config *hw,
     
        if (wavefront_cmd (hw, WFC_DOWNLOAD_PATCH, 0, buf)) {
                printk (KERN_ERR "WaveFront: download patch failed\n");
-               return -EIO;
+               return -(EIO);
        }
 
-       return 0;
+       return (0);
 }
 
 static int
@@ -927,10 +969,12 @@ wavefront_send_program (wf_config *hw,
        unsigned char buf[WF_PROGRAM_BYTES+1];
        int i;
 
+#ifdef WF_DEBUG
        if (hw->debug & WF_DEBUG_LOAD_PATCH) {
                printk (KERN_DEBUG
                        "WaveFront: downloading program %d\n", header->number);
        }
+#endif WF_DEBUG
 
        hw->prog_status[header->number] = WF_SLOT_USED;
 
@@ -954,10 +998,10 @@ wavefront_send_program (wf_config *hw,
     
        if (wavefront_cmd (hw, WFC_DOWNLOAD_PROGRAM, 0, buf)) {
                printk (KERN_WARNING "WaveFront: download patch failed\n");     
-               return -EIO;
+               return -(EIO);
        }
 
-       return 0;
+       return (0);
 }
 
 static int
@@ -1004,6 +1048,7 @@ wavefront_send_sample (wf_config      *hw,
        int skip = 0;
        int initial_skip = 0;
 
+#ifdef WF_DEBUG
        if (hw->debug & WF_DEBUG_LOAD_PATCH) {
                printk (KERN_DEBUG "WaveFront: sample %sdownload for slot %d, "
                        "type %d, %d bytes from 0x%x\n",
@@ -1011,6 +1056,7 @@ wavefront_send_sample (wf_config      *hw,
                        header->number, header->subkey, header->size,
                        (int) header->dataptr);
        }
+#endif WF_DEBUG
 
        if (header->size) {
 
@@ -1032,10 +1078,9 @@ wavefront_send_sample (wf_config      *hw,
                   or theoretically some other configuration) is the
                   responsibility of the user level library. 
 
-                  To try to do this in the kernel would be a little crazy:
-                  we'd need 24 * 512 bytes (12K) of kernel space just to
-                  hold copies of the original sample headers; the whole
-                  patch/program/sample header data is about 158K!!!
+                  To try to do this in the kernel would be a little
+                  crazy: we'd need 158K of kernel space just to hold
+                  a copy of the patch/program/sample header data.
                */
 
                if (hw->rom_samples_rdonly) {
@@ -1073,7 +1118,7 @@ wavefront_send_sample (wf_config      *hw,
                        printk (KERN_ERR
                                "WaveFront: channel selection only possible "
                                "on 16-bit samples");
-                       return -EINVAL;
+                       return -(EINVAL);
                }
        }
 
@@ -1108,11 +1153,13 @@ wavefront_send_sample (wf_config      *hw,
                break;
        }
 
+#ifdef WF_DEBUG
        if (hw->debug & WF_DEBUG_LOAD_PATCH) {
                printk (KERN_DEBUG "WaveFront: channel selection: %d => "
                        "initial skip = %d, skip = %d\n",
                        WF_GET_CHANNEL (&header->hdr.s), initial_skip, skip);
        }
+#endif WF_DEBUG
     
        /* Be safe, and zero the "Unused" bits ... */
 
@@ -1153,7 +1200,7 @@ wavefront_send_sample (wf_config      *hw,
        
        /* This one is truly weird.  What kind of weirdo decided that in
           a system dominated by 16- and 32-bit integers, they would use
-          a 12-bit transfer size ?
+          just 12 bits ?
        */
        
        shptr = munge_int32 (header->hdr.s.FrequencyBias, shptr, 3);
@@ -1171,7 +1218,7 @@ wavefront_send_sample (wf_config      *hw,
                           0, sample_hdr)) {
                printk (KERN_WARNING "WaveFront: sample %sdownload refused.\n",
                        header->size ? "" : "header ");
-               return -EIO;
+               return -(EIO);
        }
 
        if (header->size == 0) {
@@ -1197,7 +1244,7 @@ wavefront_send_sample (wf_config      *hw,
                if (wavefront_cmd (hw, WFC_DOWNLOAD_BLOCK, 0, 0)) {
                        printk (KERN_WARNING "WaveFront: download block "
                                "request refused.\n");
-                       return -EIO;
+                       return -(EIO);
                }
 
                for (i = 0; i < blocksize; i++) {
@@ -1207,7 +1254,7 @@ wavefront_send_sample (wf_config      *hw,
                                get_user (sample_short, dataptr);
                                dataptr += skip;
                
-                               if (data_is_unsigned) {
+                               if (data_is_unsigned) { /* GUS ? */
 
                                        if (WF_SAMPLE_IS_8BIT(&header->hdr.s)) {
                        
@@ -1255,12 +1302,12 @@ wavefront_send_sample (wf_config      *hw,
                        if (dma_ack == -1) {
                                printk (KERN_ERR "WaveFront: upload sample "
                                        "DMA ack timeout\n");
-                               return -EIO;
+                               return -(EIO);
                        } else {
                                printk (KERN_ERR "WaveFront: upload sample "
                                        "DMA ack error 0x%x\n",
                                        dma_ack);
-                               return -EIO;
+                               return -(EIO);
                        }
                }
        }
@@ -1272,7 +1319,7 @@ wavefront_send_sample (wf_config      *hw,
        */
 
  sent:
-       return 0;
+       return (0);
 }
 
 static int
@@ -1282,12 +1329,14 @@ wavefront_send_alias (struct wf_config *hw,
 {
        unsigned char alias_hdr[WF_ALIAS_BYTES];
 
+#ifdef WF_DEBUG
        if (hw->debug & WF_DEBUG_LOAD_PATCH) {
                printk (KERN_DEBUG "WaveFront: download alias, %d is "
                        "alias for %d\n",
                        header->number,
                        header->hdr.a.OriginalSample);
        }
+#endif WF_DEBUG
     
        munge_int32 (header->number, &alias_hdr[0], 2);
        munge_int32 (header->hdr.a.OriginalSample, &alias_hdr[2], 2);
@@ -1304,12 +1353,12 @@ wavefront_send_alias (struct wf_config *hw,
 
        if (wavefront_cmd (hw, WFC_DOWNLOAD_SAMPLE_ALIAS, 0, alias_hdr)) {
                printk (KERN_ERR "WaveFront: download alias failed.\n");
-               return -EIO;
+               return -(EIO);
        }
 
        hw->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_ALIAS);
 
-       return 0;
+       return (0);
 }
 
 static int
@@ -1330,17 +1379,21 @@ wavefront_send_multisample (struct wf_config *hw,
        num_samples = (1<<(header->hdr.ms.NumberOfSamples&7));
        msample_hdr[2] = (unsigned char) header->hdr.ms.NumberOfSamples;
 
+#ifdef WF_DEBUG
        if (hw->debug & WF_DEBUG_LOAD_PATCH) {
                printk (KERN_DEBUG "WaveFront: multi %d with %d=%d samples\n",
                        header->number, header->hdr.ms.NumberOfSamples, num_samples);
        }
+#endif WF_DEBUG
 
        for (i = 0; i < num_samples; i++) {
+#ifdef WF_DEBUG
                if ((hw->debug & (WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA)) ==
                    (WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA)) {
                        printk (KERN_DEBUG "WaveFront: sample[%d] = %d\n",
                                i, header->hdr.ms.SampleNumber[i]);
                }
+#endif WF_DEBUG
                munge_int32 (header->hdr.ms.SampleNumber[i],
                             &msample_hdr[3+(i*2)], 2);
        }
@@ -1354,12 +1407,12 @@ wavefront_send_multisample (struct wf_config *hw,
                           (unsigned char *) ((num_samples*2)+3),
                           msample_hdr)) {
                printk (KERN_ERR "WaveFront: download of multisample failed.\n");
-               return -EIO;
+               return -(EIO);
        }
 
        hw->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE);
 
-       return 0;
+       return (0);
 }
 
 static int
@@ -1375,13 +1428,15 @@ wavefront_fetch_multisample (struct wf_config *hw,
     
        if (wavefront_cmd (hw, WFC_UPLOAD_MULTISAMPLE, log_ns, number)) {
                printk (KERN_ERR "WaveFront: upload multisample failed.\n");
-               return -EIO;
+               return -(EIO);
        }
     
+#ifdef WF_DEBUG
        if (hw->debug & WF_DEBUG_DATA) {
                printk (KERN_DEBUG "WaveFront: msample %d has %d samples\n",
                        header->number, log_ns[0]);
        }
+#endif WF_DEBUG
 
        header->hdr.ms.NumberOfSamples = log_ns[0];
 
@@ -1395,26 +1450,28 @@ wavefront_fetch_multisample (struct wf_config *hw,
                if ((d[0] = wavefront_read (hw)) == -1) {
                        printk (KERN_ERR "WaveFront: upload multisample failed "
                                "during sample loop.\n");
-                       return -EIO;
+                       return -(EIO);
                }
 
                if ((d[1] = wavefront_read (hw)) == -1) {
                        printk (KERN_ERR "WaveFront: upload multisample failed "
                                "during sample loop.\n");
-                       return -EIO;
+                       return -(EIO);
                }
        
                header->hdr.ms.SampleNumber[i] =
                        demunge_int32 ((unsigned char *) d, 2);
        
+#ifdef WF_DEBUG
                if (hw->debug & WF_DEBUG_DATA) {
                        printk (KERN_DEBUG "WaveFront: msample "
                                "sample[%d] = %d\n",
                                i, header->hdr.ms.SampleNumber[i]);
                }
+#endif WF_DEBUG
        }
 
-       return 0;
+       return (0);
 }
 
 
@@ -1426,12 +1483,14 @@ wavefront_send_drum (struct wf_config *hw, wavefront_patch_info *header)
        wavefront_drum *drum = &header->hdr.d;
        int i;
 
+#ifdef WF_DEBUG
        if (hw->debug & WF_DEBUG_LOAD_PATCH) {
                printk (KERN_DEBUG
                        "WaveFront: downloading edrum for MIDI "
                        "note %d, patch = %d\n", 
                        header->number, drum->PatchNumber);
        }
+#endif WF_DEBUG
 
        drumbuf[0] = header->number & 0x7f;
 
@@ -1441,10 +1500,10 @@ wavefront_send_drum (struct wf_config *hw, wavefront_patch_info *header)
 
        if (wavefront_cmd (hw, WFC_DOWNLOAD_EDRUM_PROGRAM, 0, drumbuf)) {
                printk (KERN_ERR "WaveFront: download drum failed.\n");
-               return -EIO;
+               return -(EIO);
        }
 
-       return 0;
+       return (0);
 }
 
 static int 
@@ -1468,7 +1527,7 @@ wavefront_find_free_patch (struct wf_config *hw)
 {
        int i;
 
-       for (i = 0; i < WF_MAX_SAMPLE; i++) {
+       for (i = 0; i < WF_MAX_PATCH; i++) {
                if (!(hw->patch_status[i] & WF_SLOT_FILLED)) {
                        return i;
                }
@@ -1522,7 +1581,7 @@ wavefront_load_gus_patch (struct wf_config *hw,
        /* Copy in the header of the GUS patch */
 
        sizeof_patch = (long) &guspatch.data[0] - (long) &guspatch; 
-       COPY_FROM_USER (&((char *) &guspatch)[offs],
+       copy_from_user (&((char *) &guspatch)[offs],
                        &(addr)[offs], sizeof_patch - offs);
 
        if ((i = wavefront_find_free_patch (hw)) == -1) {
@@ -1656,19 +1715,15 @@ wavefront_load_patch (int dev, int format, const char *addr,
                      int offs, int count, int pmgr_flag)
 {
 
-       struct wf_config *hw;
+       struct wf_config *hw = &wavefront_configuration;
        wavefront_patch_info header;
 
-       if ((hw = hw_from_dev (dev)) == 0) {
-               return -EINVAL;
-       }
-
        if (format == SYSEX_PATCH) {    /* Handled by midi_synth.c */
                if (midi_load_patch == NULL) {
                        printk (KERN_ERR
                                "WaveFront: SYSEX not loadable: "
                                "no midi patch loader!\n");
-                       return -EINVAL;
+                       return -(EINVAL);
                }
                return midi_load_patch (dev, format, addr,
                                        offs, count, pmgr_flag);
@@ -1679,12 +1734,12 @@ wavefront_load_patch (int dev, int format, const char *addr,
 
        } else if (format != WAVEFRONT_PATCH) {
                printk (KERN_ERR "WaveFront: unknown patch format %d\n", format);
-               return -EINVAL;
+               return -(EINVAL);
        }
 
        if (count < sizeof (wavefront_patch_info)) {
                printk (KERN_ERR "WaveFront: sample header too short\n");
-               return -EINVAL;
+               return -(EINVAL);
        }
 
        /* copied in so far: `offs' bytes from `addr'. We shouldn't copy
@@ -1694,10 +1749,11 @@ wavefront_load_patch (int dev, int format, const char *addr,
           through the 'hdrptr' field.
        */
 
-       COPY_FROM_USER (&((char *) &header)[offs], &(addr)[offs],
+       copy_from_user (&((char *) &header)[offs], &(addr)[offs],
                        sizeof(wavefront_patch_info) -
                        sizeof(wavefront_any) - offs);
 
+#ifdef WF_DEBUG
        if (hw->debug & WF_DEBUG_LOAD_PATCH) {
                printk (KERN_DEBUG "WaveFront: download "
                        "Sample type: %d "
@@ -1707,11 +1763,12 @@ wavefront_load_patch (int dev, int format, const char *addr,
                        header.number,
                        header.size);
        }
+#endif WF_DEBUG
 
        switch (header.subkey) {
        case WF_ST_SAMPLE:  /* sample or sample_header, based on patch->size */
 
-               COPY_FROM_USER ((unsigned char *) &header.hdr.s,
+               copy_from_user ((unsigned char *) &header.hdr.s,
                                (unsigned char *) header.hdrptr,
                                sizeof (wavefront_sample));
 
@@ -1719,7 +1776,7 @@ wavefront_load_patch (int dev, int format, const char *addr,
 
        case WF_ST_MULTISAMPLE:
 
-               COPY_FROM_USER ((unsigned char *) &header.hdr.s,
+               copy_from_user ((unsigned char *) &header.hdr.s,
                                (unsigned char *) header.hdrptr,
                                sizeof (wavefront_multisample));
 
@@ -1728,28 +1785,28 @@ wavefront_load_patch (int dev, int format, const char *addr,
 
        case WF_ST_ALIAS:
 
-               COPY_FROM_USER ((unsigned char *) &header.hdr.a,
+               copy_from_user ((unsigned char *) &header.hdr.a,
                                (unsigned char *) header.hdrptr,
                                sizeof (wavefront_alias));
 
                return wavefront_send_alias (hw, &header);
 
        case WF_ST_DRUM:
-               COPY_FROM_USER ((unsigned char *) &header.hdr.d, 
+               copy_from_user ((unsigned char *) &header.hdr.d, 
                                (unsigned char *) header.hdrptr,
                                sizeof (wavefront_drum));
 
                return wavefront_send_drum (hw, &header);
 
        case WF_ST_PATCH:
-               COPY_FROM_USER ((unsigned char *) &header.hdr.p, 
+               copy_from_user ((unsigned char *) &header.hdr.p, 
                                (unsigned char *) header.hdrptr,
                                sizeof (wavefront_patch));
 
                return wavefront_send_patch (hw, &header);
 
        case WF_ST_PROGRAM:
-               COPY_FROM_USER ((unsigned char *) &header.hdr.pr, 
+               copy_from_user ((unsigned char *) &header.hdr.pr, 
                                (unsigned char *) header.hdrptr,
                                sizeof (wavefront_program));
 
@@ -1758,7 +1815,7 @@ wavefront_load_patch (int dev, int format, const char *addr,
        default:
                printk (KERN_ERR "WaveFront: unknown patch type %d.\n",
                        header.subkey);
-               return -EINVAL;
+               return -(EINVAL);
        }
 
        return 0;
@@ -1804,24 +1861,19 @@ static int
 wavefront_synth_control (int dev, int cmd, caddr_t arg)
 
 {
-       struct wf_config *hw;
+       struct wf_config *hw = &wavefront_configuration;
        wavefront_control wc;
        unsigned char patchnumbuf[2];
        int i;
 
-       if ((hw = hw_from_dev (dev)) == 0) {
-               printk (KERN_ERR
-                       "WaveFront: synth_control with unknown "
-                       "device number %d\n", dev);
-               return -EINVAL;
-       }
-
-       COPY_FROM_USER (&wc, arg, sizeof (wc));
+       copy_from_user (&wc, arg, sizeof (wc));
 
+#ifdef WF_DEBUG
        if (hw->debug & WF_DEBUG_CMD) {
                printk (KERN_DEBUG "WaveFront: synth control with "
                        "cmd 0x%x\n", wc.cmd);
        }
+#endif WF_DEBUG
 
        /* special case handling of or for various commands */
 
@@ -1940,7 +1992,7 @@ wavefront_synth_control (int dev, int cmd, caddr_t arg)
           is a low priority fix.
        */
 
-       COPY_TO_USER (arg, &wc, sizeof (wc));
+       copy_to_user (arg, &wc, sizeof (wc));
        return 0;
 }
 
@@ -1953,13 +2005,9 @@ WaveFront: MIDI synth interface
 static int
 wavefront_ioctl (int dev, unsigned int cmd, caddr_t arg)
 {
-       wf_config *hw;
+       wf_config *hw = &wavefront_configuration;
        unsigned char rbuf[4];
 
-       if ((hw = hw_from_dev (dev)) == 0) {
-               return -EINVAL;
-       }
-
        switch (cmd) {
        case SNDCTL_SYNTH_INFO:
                memcpy (&((char *) arg)[0], &wavefront_info,
@@ -1992,7 +2040,7 @@ wavefront_ioctl (int dev, unsigned int cmd, caddr_t arg)
                return wavefront_synth_control (dev, cmd, arg);
 
        default:
-               return -EINVAL;
+               return -(EINVAL);
        }
 }
 
@@ -2000,32 +2048,30 @@ static int
 wavefront_open (int dev, int mode)
 
 {
-       struct wf_config *hw;
-
-       if ((hw = hw_from_dev (dev)) == 0) {
-               return -EINVAL;
-       }
+       struct wf_config *hw = &wavefront_configuration;
 
        if (hw->opened) {
-               printk (KERN_ERR "WaveFront: warning: device in use\n");
+               printk (KERN_WARNING "WaveFront: warning: device in use\n");
        }
 
        hw->opened = mode;
-       return 0;
+       return (0);
 }
 
 static void
 wavefront_close (int dev)
 
 {
-       struct wf_config *hw;
+       struct wf_config *hw = &wavefront_configuration;
+       int i;
 
-       if ((hw = hw_from_dev (dev)) == 0) {
-               printk (KERN_ERR
-                       "WaveFront: close() called on non-existent dev %d", dev);
-               return;
+#ifdef WF_STATS
+       printk ("Status during loop: %ld\n", hw->status_found_during_loop);
+       for (i = 0; i < 4; i++) {
+               printk ("Status during sleep[%d]: %ld\n",
+                       i, hw->status_found_during_sleep[i]);
        }
-
+#endif WF_STATS
        hw->opened = 0;
        hw->debug = 0;
 
@@ -2035,70 +2081,65 @@ wavefront_close (int dev)
 static void
 wavefront_aftertouch (int dev, int channel, int pressure)
 {
-       struct wf_config *hw = hw_from_dev (dev);
-       if (!hw) return;
-       midi_synth_aftertouch (hw->mididev,channel,pressure);
+       midi_synth_aftertouch (wavefront_configuration.mididev,channel,pressure);
 };
 
 static void
 wavefront_bender (int dev, int chn, int value)
 {
-       struct wf_config *hw = hw_from_dev (dev);
-       if (!hw) return;
-       midi_synth_bender (hw->mididev, chn, value);
+       midi_synth_bender (wavefront_configuration.mididev, chn, value);
 };
 
 static void
 wavefront_controller (int dev, int channel, int ctrl_num, int value)
 {
-       struct wf_config *hw = hw_from_dev (dev);
-       if (!hw) return;
        if(ctrl_num==CTRL_PITCH_BENDER) wavefront_bender(0,channel,value);
-       midi_synth_controller (hw->mididev, channel,ctrl_num,value);
+       midi_synth_controller (wavefront_configuration.mididev,
+                              channel,ctrl_num,value);
 };
 
 static void
 wavefront_panning(int dev, int channel, int pressure)
 {
-       struct wf_config *hw = hw_from_dev (dev);
-       if (!hw) return;
-       midi_synth_controller(hw->mididev,channel,CTL_PAN,pressure);
+       midi_synth_controller (wavefront_configuration.mididev,
+                              channel,CTL_PAN,pressure);
 };
 
 static int
 wavefront_set_instr (int dev, int channel, int instr_no)
 {
-       struct wf_config *hw = hw_from_dev (dev);
-       if (!hw) return 1;
-       return(midi_synth_set_instr(hw->mididev,channel,instr_no));
+       return(midi_synth_set_instr (wavefront_configuration.mididev,
+                                    channel,instr_no));
 };
 
 static int
 wavefront_kill_note (int dev, int channel, int note, int volume)
 {
-       struct wf_config *hw = hw_from_dev (dev);
-       if (!hw) return 1;
        if (note==255)
-               return(midi_synth_start_note(hw->mididev, channel, 0, 0));
-       return(midi_synth_kill_note(hw->mididev, channel, note, volume));
+               return (midi_synth_start_note (wavefront_configuration.mididev,
+                                              channel, 0, 0));
+       return(midi_synth_kill_note (wavefront_configuration.mididev,
+                                    channel, note, volume));
 };
 
 static int
 wavefront_start_note (int dev, int channel, int note, int volume)
 {
-       struct wf_config *hw = hw_from_dev (dev);
-       if (!hw) return 1;
-
        if (note==255) {
-               /*midi_synth_controller(hw->mididev,channel,7,volume);*/
-               midi_synth_aftertouch(hw->mididev,channel,volume); 
+               midi_synth_aftertouch (wavefront_configuration.mididev,
+                                      channel,volume); 
                return(0);
        };
+
        if (volume==0) {
                volume=127;
-               midi_synth_aftertouch(hw->mididev,channel,0);
+               midi_synth_aftertouch
+                       (wavefront_configuration.mididev,
+                        channel,0);
        };
-       midi_synth_start_note (hw->mididev, channel, note, volume);
+
+       midi_synth_start_note (wavefront_configuration.mididev,
+                              channel, note, volume);
        return(0);
 };
 
@@ -2111,7 +2152,8 @@ static void wavefront_reset (int dev)
 
 {
        int i;
-       for(i=0;i<16;i++) {
+
+       for (i = 0; i < 16; i++) {
                midi_synth_kill_note (dev,i,0,0);
        };
 };
@@ -2149,16 +2191,18 @@ WaveFront: OSS/Free and/or Linux kernel installation interface
 void
 wavefrontintr (int irq, void *dev_id, struct pt_regs *dummy)
 {
-       int i;
+        /* We don't use this handler except during device
+          configuration. While the module is installed, the 
+          interrupt is used to signal MIDI interrupts, and is 
+          handled by the interrupt routine in wf_midi.c
+        */
+          
+       wf_config *hw = (wf_config *) dev_id;
+       hw->irq_ok = 1;
 
-       if (irq < 0 || irq > 16) {
-               printk (KERN_WARNING "WaveFront: bogus interrupt %d recv'd\n",
-                       irq);
-       } else if ((i = irq2hw[irq]) == -1) {
-               printk (KERN_ALERT
-                       "WaveFront: interrupt from unknown hw (irq=%d).\n", irq);
-       } else {
-               wfs[i].irq_ok = 1;
+       if ((wavefront_status(hw) & STAT_INTR_WRITE) ||
+           (wavefront_status(hw) & STAT_INTR_READ)) {
+               wake_up (&hw->interrupt_sleeper);
        }
 }
 
@@ -2173,106 +2217,24 @@ wavefrontintr (int irq, void *dev_id, struct pt_regs *dummy)
 6 Host Tx Interrupt Pending (1=Interrupt)
 7 Unused
 
-*/
+11111001 
+  Rx Intr enable
+  nothing to read from board
+  no rx interrupt pending
+  unused
+  tx interrupt enabled
+  space to transmit
+  tx interrupt pending
 
-/* CONTROL REGISTER
-0 Host Rx Interrupt Enable (1=Enabled)      0x1
-1 Unused                                    0x2
-2 Unused                                    0x4
-3 Unused                                    0x8
-4 Host Tx Interrupt Enable                 0x10
-5 Mute (0=Mute; 1=Play)                    0x20
-6 Master Interrupt Enable (1=Enabled)      0x40
-7 Master Reset (0=Reset; 1=Run)            0x80
 */
 
 int
-probe_wavefront (struct address_info *hw_config)
+wavefront_interrupt_bits (int irq)
 
 {
-       int             i;
-       int             tmp1, tmp2;
-       unsigned char   bits;
-       unsigned char   rbuf[32], wbuf[32];
-       wf_config       *hw;
-
-       if (hw_config->irq < 0 || hw_config->irq > 16) {
-           printk (KERN_WARNING "WaveFront: impossible IRQ suggested(%d)\n", 
-                   hw_config->irq);
-           return 0;
-       }
-  
-       /* Yeah yeah, TB docs say 8, but the FX device on the Tropez Plus
-          takes up another 8 ...
-       */
-
-       if (check_region (hw_config->io_base, 16)) {
-               printk (KERN_ERR "WaveFront: IO address range 0x%x - 0x%x "
-                       "already in use - ignored\n", hw_config->io_base,
-                       hw_config->io_base+15);
-               return 0;
-       }
-  
-       for (i = 0; i < WAVEFRONT_MAX_DEVICES; i++) {
-               if (!wfs[i].installed) {
-                       wfs[i].installed = 1;
-                       break;
-               }
-       }
-
-       if (i == WAVEFRONT_MAX_DEVICES) {
-               printk (KERN_WARNING "WaveFront: no device slots available (max = %d).\n",
-                       WAVEFRONT_MAX_DEVICES);
-               return 0;
-       }
-  
-       hw = &wfs[i];
-
-       hw->irq = hw_config->irq;
-       hw->base = hw_config->io_base;
-
-       hw->israw = 0;
-       hw->debug = wf_debug_default;
-       hw->interrupts_on = 0;
-       hw->rom_samples_rdonly = 1; /* XXX default lock on ROM sample slots */
-
-       hw_config->slots[WF_SYNTH_SLOT] = hw->synthdev = -1;
-       hw_config->slots[WF_INTERNAL_MIDI_SLOT] = hw->mididev = -1;
-       hw_config->slots[WF_EXTERNAL_MIDI_SLOT] = hw->ext_mididev = -1;
+       int bits;
 
-       irq2hw[hw_config->irq] = i;
-  
-       if (wavefront_cmd (hw, WFC_FIRMWARE_VERSION, rbuf, wbuf) == 0) {
-               hw->fw_version[0] = rbuf[0];
-               hw->fw_version[1] = rbuf[1];
-               printk (KERN_INFO "WaveFront: firmware %d.%d already loaded.\n",
-                       rbuf[0], rbuf[1]);
-      
-               if (wavefront_cmd (hw, WFC_HARDWARE_VERSION, rbuf, wbuf) == 0) {
-                       hw->hw_version[0] = rbuf[0];
-                       hw->hw_version[1] = rbuf[1];
-               } else {
-                       printk (KERN_INFO "WaveFront: not raw, but no hardware version!\n");
-                       return 0;
-               }
-               if (!wf_raw) {
-                       return 1;
-               }
-       } else {
-               hw->israw = 1;
-               printk (KERN_INFO
-                       "WaveFront: no response to firmware probe, "
-                       "assume raw.\n");
-       }
-
-       if (request_irq (hw_config->irq, wavefrontintr,
-                        0, "WaveFront", NULL) < 0) {
-               printk (KERN_WARNING "WaveFront: IRQ %d not available!\n",
-                       hw_config->irq);
-               return 0;
-       }
-
-       switch (hw_config->irq) {
+       switch (irq) {
        case 9:
                bits = 0x00;
                break;
@@ -2287,11 +2249,42 @@ probe_wavefront (struct address_info *hw_config)
                break;
        
        default:
-               printk (KERN_WARNING "WaveFront: invalid IRQ %d\n",
-                       hw_config->irq);
-               return 0;
+               printk (KERN_WARNING "WaveFront: invalid IRQ %d\n", irq);
+               bits = -1;
        }
-  
+
+       return bits;
+}
+
+void
+wavefront_should_cause_interrupt (wf_config *hw, int val, int port, int timeout)
+
+{
+       unsigned long flags;
+
+       save_flags (flags);
+       cli();
+       hw->irq_ok = 0;
+       outb (val,port);
+       current->timeout = jiffies + timeout;
+       interruptible_sleep_on (&hw->interrupt_sleeper);
+       restore_flags (flags);
+}
+
+static int
+wavefront_hw_reset (wf_config *hw)
+
+{
+       int bits;
+       int hwv[2];
+
+       if (request_irq (hw->irq, wavefrontintr,
+                        0, "WaveFront", (void *) hw) < 0) {
+               printk (KERN_WARNING "WaveFront: IRQ %d not available!\n",
+                       hw->irq);
+               return 1;
+       }
+
        /* try reset of port */
       
        outb (0x0, hw->control_port); 
@@ -2305,9 +2298,6 @@ probe_wavefront (struct address_info *hw_config)
      
           Bit 6 - MIDI Interface Select
 
-          XXX PBD: I think this documentation is backwards. I leave bit
-          6 unset, and get MIDI data from the 9 pin D connector.
-
           0 - Use the MIDI Input from the 26-pin WaveBlaster
           compatible header as the serial MIDI source
           1 - Use the MIDI Input from the 9-pin D connector as the serial MIDI 
@@ -2331,101 +2321,270 @@ probe_wavefront (struct address_info *hw_config)
      
        */
 
-       /* configure hardware: IRQ, plus external MIDI interface selected */
-  
-       outb (bits | 0x80, hw->data_port);      
-  
-       /* take us out of reset, unmute, master + TX + RX interrupts on */
-  
-       outb (0x80|0x20|0x40|0x10|0x1, hw->control_port);
-  
-       for (i = 0; i < 1000000 && !hw->irq_ok; i++);
-  
-       /* Data port is now the data port, not the h/w initialization port 
-     
-          The boot ROM will check the OSRAM, and will then
-          wait for the either the "download OS" or
-          "report h/w version" commands.
-
-          Any other command will supposedly be ignored.
+       /* configure hardware: IRQ, enable interrupts, 
+          plus external 9-pin MIDI interface selected
        */
+
+       if ((bits = wavefront_interrupt_bits (hw->irq)) < 0) {
+               return 1;
+       }
+
+       outb (0x80 | 0x40 | bits, hw->data_port);       
   
+       /* CONTROL REGISTER
+
+          0 Host Rx Interrupt Enable (1=Enabled)      0x1
+          1 Unused                                    0x2
+          2 Unused                                    0x4
+          3 Unused                                    0x8
+          4 Host Tx Interrupt Enable                 0x10
+          5 Mute (0=Mute; 1=Play)                    0x20
+          6 Master Interrupt Enable (1=Enabled)      0x40
+          7 Master Reset (0=Reset; 1=Run)            0x80
+
+          Take us out of reset, unmute, master + TX + RX interrupts on.
+          
+          We'll get an interrupt presumably to tell us that the TX
+          register is clear. However, this doesn't mean that the
+          board is ready. We actually have to send it a command, and
+          wait till it gets back to use. After a cold boot, this can
+          take some time.
+          
+          
+          I think this is because its only after a cold boot that the
+          onboard ROM does its memory check, which can take "up to 4
+          seconds" according to the WaveFront SDK. So, since sleeping
+          doesn't cost us much, we'll give it *plenty* of time. It
+          turns out that with 12MB of RAM, it can take up to 16
+          seconds or so!! See the code after "ABOUT INTERRUPTS"
+       */
+
+       wavefront_should_cause_interrupt(hw,
+                                        0x80|0x40|0x10|0x1,
+                                        hw->control_port,
+                                        (2*HZ)/100);
+
+       /* Note: data port is now the data port, not the h/w initialization
+          port.
+        */
+
        if (!hw->irq_ok) {
                printk (KERN_WARNING
                        "WaveFront: intr not received after h/w un-reset.\n");
-               free_irq (hw_config->irq, NULL);
-               return 0;
-       } else {
-               hw->irq_ok = 0;
-       }
+               goto gone_bad;
+       } 
 
        hw->interrupts_on = 1;
-
-       /* WaveFront SDK says:
-     
-          "When the Master Reset is set to zero (0), the audio board is held
-          in reset, which is the power-up condition. Setting Master Reset to one
-          (1) allows the on-board processor to run. It takes approximately two
-          to four seconds, depending on the memory configuration, for the
-          on-board processor to complete it's initialization routine before it
-          will respond to commands after a reset."
-
-          Actually, it seems that most of the time, even with 8MB of RAM,
-          its actually ready immediately.
+       
+       /* ABOUT INTERRUPTS:
+          -----------------
+          
+          When we talk about interrupts, there are two kinds
+          generated by the ICS2115. The first is to signal MPU data
+          ready to read, and the second is to signal RX or TX status
+          changes. We *always* want interrupts for MPU stuff but we 
+          generally avoid using RX/TX interrupts.
+
+          In theory, we could use the TX and RX interrupts for all
+          communication with the card. However, there are 2 good
+          reasons not to do this.
+
+          First of all, the MIDI interface is going to use the same
+          interrupt. This presents no practical problem since Linux
+          allows us to share IRQ's. However, there are times when it
+          makes sense for a user to ask the driver to disable
+          interrupts, to avoid bothering Linux with a stream of MIDI
+          interrupts that aren't going to be used because nothing
+          cares about them. If we rely on them for communication with
+          the WaveFront synth as well, this disabling would be
+          crippling. Since being able to disable them can save quite
+          a bit of overhead (consider the interrupt frequency of a
+          physical MIDI controller like a modwheel being shunted back
+          and forth - its higher than the mouse, and much of
+          the time is of absolutely no interest to the kernel or any
+          user space processes whatsoever), we don't want to do this.
+
+          Secondly, much of the time, there's no reason to go to
+          sleep on a TX or RX status: the WaveFront gets back to us
+          quickly enough that its a lot more efficient to just busy
+          wait on the relevant status. Once we go to sleep, all is
+          lost anyway, and so interrupts don't really help us much anyway.
+
+          Therefore, we don't use interrupts for communication with
+          the WaveFront synth. We just poll the relevant RX/TX status.
+
+          However, there is one broad exception to this. During module
+          loading, to deal with several situations where timing would
+          be an issue, we use TX/RX interrupts to help us avoid busy
+          waiting for indeterminate and hard to manage periods of
+          time. So, TX/RX interrupts are enabled until the end of 
+          wavefront_init(), and not used again after that.
+
+        */
+
+       /* Note: data port is now the data port, not the h/w initialization
+          port.
+
+          At this point, only "HW VERSION" or "DOWNLOAD OS" commands
+          will work. So, issue one of them, and wait for TX
+          interrupt. This can take a *long* time after a cold boot,
+          while the ISC ROM does its RAM test. The SDK says up to 4
+          seconds - with 12MB of RAM on a Tropez+, it takes a lot
+          longer than that (~16secs). Note that the card understands
+          the difference between a warm and a cold boot, so
+          subsequent ISC2115 reboots (say, caused by module
+          reloading) will get through this much faster.
+
+          Interesting question: why is no RX interrupt received first ?
        */
+       
+       wavefront_should_cause_interrupt(hw, WFC_HARDWARE_VERSION, 
+                                        hw->data_port, 20*HZ);
 
-       if (!wavefront_wait (hw, STAT_CAN_WRITE)) {
-               if (!wavefront_wait (hw, STAT_CAN_WRITE)) {
-                       if (!wavefront_wait (hw, STAT_CAN_WRITE)) {
-                               printk (KERN_WARNING
-                                       "WaveFront: OS not ready after "
-                                       "memory check.\n");
-                               free_irq (hw_config->irq, NULL);
-                               return 0;
-                       }
-               }
+       if (!hw->irq_ok) {
+               printk (KERN_WARNING
+                       "WaveFront: post-RAM-check interrupt not received.\n");
+               goto gone_bad;
+       } 
+
+       if (!(wavefront_status(hw) & STAT_CAN_READ)) {
+               printk (KERN_WARNING
+                       "WaveFront: no response to HW version cmd.\n");
+               goto gone_bad;
+       }
+       
+       if ((hwv[0] = wavefront_read (hw)) == -1) {
+               printk (KERN_WARNING
+                       "WaveFront: board not responding correctly.\n");
+               goto gone_bad;
        }
 
-       /* get H/W version, and check we get an interrupt */
-  
-       outb (WFC_HARDWARE_VERSION, hw->data_port);
-  
-       for (i = 0; i < 1000000 && !hw->irq_ok; i++);
-  
-       /* We don't need the IRQ anymore for the WaveFront code,
-          and to allow an MPU-401 driver to attach to it later, lets
-          give it back ....
+       if (hwv[0] == 0xFF) { /* NAK */
 
-          DO NOT alter irq2hw[], since we'll still use this to lookup
-          the config struct from an address_info struct.
-       */
+               /* Board's RAM test failed. Try to read error code,
+                  and tell us about it either way.
+               */
+               
+               if ((hwv[0] = wavefront_read (hw)) == -1) {
+                       printk (KERN_WARNING 
+                               "WaveFront: on-board RAM test failed "
+                               "(bad error code).\n");
+               } else {
+                       printk (KERN_WARNING 
+                               "WaveFront: on-board RAM test failed "
+                               "(error code: 0x%x).\n",
+                               hwv[0]);
+               }
+               goto gone_bad;
+       }
 
-       free_irq (hw_config->irq, NULL);
+       /* We're OK, just get the next byte of the HW version response */
 
-       if (!hw->irq_ok) {
+       if ((hwv[1] = wavefront_read (hw)) == -1) {
                printk (KERN_WARNING
-                       "WaveFront: interrupt not received after "
-                       "h/w version cmd.\n");
-               return 0;
-       } else {
-               hw->irq_ok = 0;
+                       "WaveFront: board not responding correctly(2).\n");
+               goto gone_bad;
+       }
+
+       printk (KERN_INFO "WaveFront: hardware version %d.%d\n",
+               hwv[0], hwv[1]);
+
+       return 0;
+
+
+     gone_bad:
+       free_irq (hw->irq, hw);
+       return (1);
+       }
+
+int
+probe_wavefront (struct address_info *hw_config)
+
+{
+       unsigned char   rbuf[4], wbuf[4];
+       wf_config       *hw;
+
+       if (hw_config->irq < 0 || hw_config->irq > 16) {
+           printk (KERN_WARNING "WaveFront: impossible IRQ suggested(%d)\n", 
+                   hw_config->irq);
+           return 0;
        }
   
-       if ((tmp1 = wavefront_read(hw)) == -1) {
-               printk (KERN_WARNING
-                       "WaveFront @ 0x%x not ready, ignoring\n", hw->base);
+       /* Yeah yeah, TB docs say 8, but the FX device on the Tropez Plus
+          takes up another 8 ...
+       */
+
+       if (check_region (hw_config->io_base, 16)) {
+               printk (KERN_ERR "WaveFront: IO address range 0x%x - 0x%x "
+                       "already in use - ignored\n", hw_config->io_base,
+                       hw_config->io_base+15);
                return 0;
        }
   
-       if ((tmp2 = wavefront_read(hw)) == -1) {
-               printk (KERN_WARNING
-                       "WaveFront @ 0x%x not responding correctly, ignoring\n",
-                       hw->base);
+       hw = &wavefront_configuration;
+
+       hw->irq = hw_config->irq;
+       hw->base = hw_config->io_base;
+
+       hw->israw = 0;
+       hw->debug = debug_default;
+       hw->interrupts_on = 0;
+       hw->rom_samples_rdonly = 1; /* XXX default lock on ROM sample slots */
+
+#ifdef WF_STATS
+       hw->status_found_during_sleep[0] = 0;
+       hw->status_found_during_sleep[1] = 0;
+       hw->status_found_during_sleep[2] = 0;
+       hw->status_found_during_sleep[3] = 0;
+       hw->status_found_during_loop = 0;
+#endif WF_STATS
+
+       hw_config->slots[WF_SYNTH_SLOT] = hw->synthdev = -1;
+       hw_config->slots[WF_INTERNAL_MIDI_SLOT] = hw->mididev = -1;
+       hw_config->slots[WF_EXTERNAL_MIDI_SLOT] = hw->ext_mididev = -1;
+
+       if (wavefront_cmd (hw, WFC_FIRMWARE_VERSION, rbuf, wbuf) == 0) {
+
+               hw->fw_version[0] = rbuf[0];
+               hw->fw_version[1] = rbuf[1];
+               printk (KERN_INFO
+                       "WaveFront: firmware %d.%d already loaded.\n",
+                       rbuf[0], rbuf[1]);
+
+               /* check that a command actually works */
+      
+               if (wavefront_cmd (hw, WFC_HARDWARE_VERSION,
+                                  rbuf, wbuf) == 0) {
+                       hw->hw_version[0] = rbuf[0];
+                       hw->hw_version[1] = rbuf[1];
+               } else {
+                       printk (KERN_INFO "WaveFront: not raw, but no "
+                               "hardware version!\n");
+                       return 0;
+               }
+
+               if (!wf_raw) {
+                       return 1;
+               } else {
+                       printk (KERN_INFO
+                               "WaveFront: reloading firmware anyway.\n");
+               }
+
+       } else {
+
+               hw->israw = 1;
+               printk (KERN_INFO "WaveFront: no response to firmware probe, "
+                       "assume raw.\n");
+
+       }
+
+       init_waitqueue (&hw->interrupt_sleeper);
+
+       if (wavefront_hw_reset (hw)) {
+               printk (KERN_WARNING "WaveFront: hardware reset failed\n");
                return 0;
        }
-  
-       printk (KERN_INFO "WaveFront: hardware version %d.%d\n", tmp1, tmp2);
-  
+
        return 1;
 }
 
@@ -2465,7 +2624,8 @@ wavefront_download_firmware (wf_config *hw, char *path)
        set_fs (get_ds());
 
        if ((fd = open (path, 0, 0)) < 0) {
-               printk (KERN_WARNING "WaveFront: Unable to load \"%s\".\n", path);
+               printk (KERN_WARNING "WaveFront: Unable to load \"%s\".\n",
+                       path);
                return 1;
        }
 
@@ -2512,9 +2672,13 @@ wavefront_download_firmware (wf_config *hw, char *path)
                                        section_cnt_downloaded + 1, c);
                                goto failure;
                
-                       } else if ((hw->debug & WF_DEBUG_IO) &&
+                       } else {
+#ifdef WF_DEBUG
+                           if ((hw->debug & WF_DEBUG_IO) &&
                                   !(++section_cnt_downloaded % 10)) {
                                printk (KERN_DEBUG ".");
+                           }
+#endif WF_DEBUG
                        }
 
                } else {
@@ -2526,9 +2690,11 @@ wavefront_download_firmware (wf_config *hw, char *path)
 
        close (fd);
        set_fs (fs);
+#ifdef WF_DEBUG
        if (hw->debug & WF_DEBUG_IO) {
                printk (KERN_DEBUG "\n");
        }
+#endif WF_DEBUG
        return 0;
 
  failure:
@@ -2618,81 +2784,137 @@ wavefront_config_midi (wf_config *hw, struct address_info *hw_config)
 }
 
 static int
-wavefront_init (wf_config *hw, struct address_info *hw_config)
+wavefront_do_reset (wf_config *hw, int atboot)
 
 {
-       int samples_are_from_rom = 0;
+       char voices[1];
 
-       /* XXX what state does the board need to be in before
-          I can download the firmware ? I think any state
-          after it acknowledges a hardware version command
-          post-booting.
-       */
+       if (!atboot && wavefront_hw_reset (hw)) {
+               printk (KERN_WARNING "WaveFront: hw reset failed.\n");
+               goto gone_bad;
+       }
 
        if (hw->israw || wf_raw) {
-               samples_are_from_rom = 1;
-
-               if (wavefront_download_firmware (hw, wf_ospath)) {
+               if (wavefront_download_firmware (hw, ospath)) {
+                       goto gone_bad;
                        return 1;
                }
-    
-               /* enter normal operation:
-                  bit 7: (on) reset  0x80
-                  bit 6: interrupts enabled 0x40
-                  bit 5: (on) mute (i.e. in play mode) 0x20
-                  bits 4-0: zero
+       }
+
+       if (fx_raw) {
+               wffx_init (hw);
+       }
+
+       /* If we loaded the OS, we now have to wait for it to be ready
+          to roll. We can't guarantee that interrupts are enabled,
+          because we might be reloading the module without forcing a
+          reset/reload of the firmware.
           
-                  note: tx and rx interrupts turned off
-               */
+          Rather than busy-wait, lets just turn interrupts on.
+       */
+
+       outb (0x80|0x40|0x10|0x1, hw->control_port);
+
+       wavefront_should_cause_interrupt (hw, WFC_NOOP,
+                                         hw->data_port, (10*HZ));
        
-               outb (0x80|0x40|0x20, hw->control_port);
+       if (!hw->irq_ok) {
+               printk (KERN_WARNING "WaveFront: no post-OS interrupt.\n");
+               goto gone_bad;
+       }
+
+       /* Now, do it again ! */
+
+       wavefront_should_cause_interrupt (hw, WFC_NOOP,
+                                         hw->data_port, (10*HZ));
        
-               /* Set up MPU-401 emulation mode.  For some reason, this always
-                  fails the first time, and generates no ACK, so we'll
-                  treat it as a special case by sleeping for a while, and then
-                  trying again.
-               */
+       if (!hw->irq_ok) {
+               printk (KERN_WARNING "WaveFront: no post-OS interrupt(2).\n");
+               goto gone_bad;
+       }
        
-               wavefront_write (hw, 0xf0);
-               wavefront_write (hw, 1);
-               wavefront_sleep (hw, (HZ/wf_sleep_interval) * wf_sleep_tries);
-               wavefront_write (hw, 0xf0);
-               wavefront_write (hw, 1);
-               if (wavefront_read (hw) != 0x80) {
-                       printk (KERN_ERR
-                               "WaveFront: set MPU emulation mode "
-                               "command failed.\n");
-                       return (1);
+       /* OK, no (RX/TX) interrupts any more, but leave mute
+          on. Master interrupts get enabled when we're done here.
+       */
+
+       outb (0x80, hw->control_port); 
+
+       /* No need for the IRQ anymore */
+
+       free_irq (hw->irq, hw);
+
+       /* SETUPSND.EXE asks for sample memory config here, but since i
+          have no idea how to interpret the result, we'll forget
+          about it.
+       */
+       
+       if ((hw->freemem = wavefront_freemem (hw)) < 0) {
+               goto gone_bad;
+       }
+               
+       printk (KERN_INFO "WaveFront: available DRAM %dk\n", hw->freemem / 1024);
+
+       if (!wavefront_write (hw, 0xf0) ||
+           !wavefront_write (hw, 1) ||
+           (wavefront_read (hw) < 0)) {
+               hw->debug = 0;
+               printk (KERN_WARNING "WaveFront: MPU emulation mode not set.\n");
+               goto gone_bad;
+       }
+
+       voices[0] = 32;
+
+       if (wavefront_cmd (hw, WFC_SET_NVOICES, 0, voices)) {
+               printk (KERN_WARNING
+                       "WaveFront: cannot set number of voices to 32.\n");
+       }
+
+       return 0;
+
+ gone_bad:
+       /* reset that sucker so that it doesn't bother us. */
+
+       outb (0x0, hw->control_port);
+       free_irq (hw->irq, hw);
+       return 1;
+}
+
+static int
+wavefront_init (wf_config *hw, int atboot)
+
+{
+       int samples_are_from_rom;
+
+       if (hw->israw || wf_raw) {
+               samples_are_from_rom = 1;
+       } else {
+               samples_are_from_rom = 0;
+       }
+
+       if (hw->israw || wf_raw || fx_raw) {
+               if (wavefront_do_reset (hw, atboot)) {
+                       return 1;
                }
        }
 
-       hw->freemem = wavefront_freemem (hw);
-       printk (KERN_INFO "WaveFront: available DRAM %dk\n", hw->freemem / 1024);
-    
        wavefront_get_sample_status (hw, samples_are_from_rom);
        wavefront_get_program_status (hw);
        wavefront_get_patch_status (hw);
 
-       if (fx_raw) {
-               wffx_init (hw);
-       }
-    
-       return 0;
+       /* Start normal operation: unreset, master interrupt enable
+          (for MPU interrupts) no mute
+       */
+
+       outb (0x80|0x40|0x20, hw->control_port); 
+
+       return (0);
 }
 
 void
 attach_wavefront (struct address_info *hw_config)
 {
        int i;
-       struct wf_config *hw;
-
-       if ((i = irq2hw[hw_config->irq]) == -1) {
-               printk (KERN_ERR "WaveFront: cannot attach unknown irq 0x%x.\n",
-                       hw_config->irq);
-               return;
-       }
-
-       hw = &wfs[i];
+       struct wf_config *hw = &wavefront_configuration;
 
        if ((i = sound_alloc_synthdev()) == -1) {
                printk (KERN_ERR "WaveFront: Too many synthesizers\n");
@@ -2700,15 +2922,13 @@ attach_wavefront (struct address_info *hw_config)
        } else {
                hw_config->slots[WF_SYNTH_SLOT] = i;
                hw->synthdev = i;
-               dev2hw[hw->synthdev] = i;
                synth_devs[hw->synthdev] = &wavefront_operations;
        }
 
-       if (wavefront_init (hw, hw_config)) {
+       if (wavefront_init (hw, 1)) {
                printk (KERN_WARNING "WaveFront: board could not "
                        "be initialized.\n");
                sound_unload_synthdev (i);
-               hw->installed = 0;
                return;
        }
     
@@ -2731,18 +2951,11 @@ attach_wavefront (struct address_info *hw_config)
 void
 unload_wavefront (struct address_info *hw_config)
 {
-       struct wf_config *hw;
-       int i;
-
-       if ((i = irq2hw[hw_config->irq]) == -1) {
-           printk (KERN_ERR "WaveFront: unloading unrecognized device!\n");
-           return;
-       }
-       hw = &wfs[i];
+       struct wf_config *hw = &wavefront_configuration;
 
        /* the first two are freed by the wf_mpu code */
-       release_region (hw_config->io_base+2, 6);
-       release_region (hw_config->io_base+8, 8);
+       release_region (hw->base+2, 6);
+       release_region (hw->base+8, 8);
        sound_unload_synthdev (hw->synthdev);
 #if defined(CONFIG_MIDI)
        unload_wf_mpu (hw_config);
@@ -2802,13 +3015,13 @@ wffx_memset (struct wf_config *hw, int page,
        if (page < 0 || page > 7) {
                printk (KERN_ERR "WaveFront: FX memset: "
                        "page must be >= 0 and <= 7\n");
-               return -EINVAL;
+               return -(EINVAL);
        }
 
        if (addr < 0 || addr > 0x7f) {
                printk (KERN_ERR "WaveFront: FX memset: "
                        "addr must be >= 0 and <= 7f\n");
-               return -EINVAL;
+               return -(EINVAL);
        }
 
        if (cnt == 1) {
@@ -2842,7 +3055,7 @@ wffx_memset (struct wf_config *hw, int page,
                                "WaveFront: FX memset "
                                "(0x%x, 0x%x, 0x%x, %d) incomplete\n",
                                page, addr, (int) data, cnt);
-                       return -EIO;
+                       return -(EIO);
                }
        }
 
@@ -2866,18 +3079,17 @@ wffx_ioctl (struct wf_config *hw, wavefront_fx_info *r)
                if (r->data[2] <= 0) {
                        printk (KERN_ERR "WaveFront: cannot write "
                                "<= 0 bytes to FX\n");
-                       return -EINVAL;
+                       return -(EINVAL);
                } else if (r->data[2] == 1) {
                        pd = (unsigned short *) &r->data[3];
                } else {
                        if (r->data[2] > sizeof (page_data)) {
-                               printk (KERN_ERR
-                                       "WaveFront: cannot write "
+                               printk (KERN_ERR "WaveFront: cannot write "
                                        "> 255 bytes to FX\n");
-                               return -EINVAL;
+                               return -(EINVAL);
                        }
-                       COPY_FROM_USER(page_data, (unsigned char *) r->data[3],
-                                      r->data[2]);
+                       copy_from_user (page_data, (unsigned char *) r->data[3],
+                                       r->data[2]);
                        pd = page_data;
                }
 
@@ -2891,7 +3103,7 @@ wffx_ioctl (struct wf_config *hw, wavefront_fx_info *r)
                printk (KERN_WARNING
                        "WaveFront: FX: ioctl %d not yet supported\n",
                        r->request);
-               return -EINVAL;
+               return -(EINVAL);
        }
 }
 
@@ -3364,7 +3576,7 @@ wffx_init (struct wf_config *hw)
 
        outb (0x00, hw->fx_op); /* mute off */
 
-       return 0;
+       return (0);
 }
 
 EXPORT_NO_SYMBOLS;
@@ -3388,6 +3600,7 @@ int init_module (void)
                        "options must be set.\n");
                return -EINVAL;
        }
+
        cfg.io_base = io;
        cfg.irq = irq;
 
@@ -3406,7 +3619,6 @@ void cleanup_module (void)
        SOUND_LOCK_END;
 }
 
-#endif MODULE   
-#endif CONFIG_SOUND_WAVEFRONT 
+#endif CONFIG_SOUND_WAVEFRONT_MODULE_AND_MODULE
 
 
index c525abc97a704ff181f4975588e22a0ef2b1c8ab..2333fd118d55c8e8904282a0060122ed2e9230b1 100644 (file)
@@ -454,12 +454,12 @@ wf_mpu_open (int dev, int mode,
        struct wf_mpu_config *devc;
 
        if (dev < 0 || dev >= num_midis || midi_devs[dev]==NULL)
-               return -ENXIO;
+               return -(ENXIO);
 
        devc = &dev_conf[dev];
 
        if (devc->opened) {
-               return -EBUSY;
+               return -(EBUSY);
        }
 
        devc->mode = MODE_MIDI;
@@ -678,8 +678,8 @@ static struct synth_operations wf_mpu_synth_proto =
        midi_synth_send_sysex
 };
 
-static struct synth_operations wf_mpu_synth_operations[WAVEFRONT_MAX_DEVICES*2];
-static struct midi_operations  wf_mpu_midi_operations[WAVEFRONT_MAX_DEVICES*2];
+static struct synth_operations wf_mpu_synth_operations[2];
+static struct midi_operations  wf_mpu_midi_operations[2];
 static int wfmpu_cnt = 0;
 
 static struct midi_operations wf_mpu_midi_proto =
@@ -707,9 +707,8 @@ config_wf_mpu (int dev, struct address_info *hw_config)
        struct wf_mpu_config *devc;
        int                internal;
 
-       if (wfmpu_cnt >= WAVEFRONT_MAX_DEVICES * 2) {
-               printk (KERN_ERR "WF-MPU: eh ? more MPU devices "
-                       "than cards ?!!\n");
+       if (wfmpu_cnt >= 2) {
+               printk (KERN_ERR "WF-MPU: more MPU devices than cards ?!!\n");
                return (-1);
        }
   
index 608b72d936141917c5e5d1a6daaf8f8ea1f3ef1b..a14debe633b39eff0fff9ab17253859d7d015846 100644 (file)
@@ -1193,8 +1193,9 @@ static int elf_core_dump(long signr, struct pt_regs * regs)
        notes[1].type = NT_PRPSINFO;
        notes[1].datasz = sizeof(psinfo);
        notes[1].data = &psinfo;
-       psinfo.pr_state = current->state;
-       psinfo.pr_sname = (current->state < 0 || current->state > 5) ? '.' : "RSDZTD"[current->state];
+       i = current->state ? ffz(~current->state) + 1 : 0;
+       psinfo.pr_state = i;
+       psinfo.pr_sname = (i < 0 || i > 5) ? '.' : "RSDZTD"[i];
        psinfo.pr_zomb = psinfo.pr_sname == 'Z';
        psinfo.pr_nice = current->priority-15;
        psinfo.pr_flag = current->flags;
index 4c7ea2e3b2652b203f04523ea4dfea62076920f6..6cd34bb4a6b0cbc0ac48cfd5429552efd2d38e6b 100644 (file)
@@ -643,9 +643,10 @@ int d_validate(struct dentry *dentry, struct dentry *dparent,
                 * Special case: local mount points don't live in
                 * the hashes, so we search the super blocks.
                 */
-               struct super_block *sb = super_blocks + 0;
+               struct super_block *sb = sb_entry(super_blocks.next);
 
-               for (; sb < super_blocks + NR_SUPER; sb++) {
+               for (; sb != sb_entry(&super_blocks); 
+                    sb = sb_entry(sb->s_list.next)) {
                        if (!sb->s_dev)
                                continue;
                        if (sb->s_root == dentry)
index a35db83a864942d6bffdd22921a256c525e3abc8..91920408867b6c173cb1ac23daef439338af12a0 100644 (file)
@@ -84,7 +84,7 @@ asmlinkage int sys_dup(unsigned int fildes)
 
 #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC)
 
-static int setfl(struct file * filp, unsigned long arg)
+static int setfl(int fd, struct file * filp, unsigned long arg)
 {
        struct inode * inode = filp->f_dentry->d_inode;
 
@@ -98,7 +98,7 @@ static int setfl(struct file * filp, unsigned long arg)
        /* Did FASYNC state change? */
        if ((arg ^ filp->f_flags) & FASYNC) {
                if (filp->f_op->fasync)
-                       filp->f_op->fasync(filp, (arg & FASYNC) != 0);
+                       filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0);
        }
 
        /* required for strict SunOS emulation */
@@ -137,7 +137,7 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
                        err = filp->f_flags;
                        break;
                case F_SETFL:
-                       err = setfl(filp, arg);
+                       err = setfl(fd, filp, arg);
                        break;
                case F_GETLK:
                        err = fcntl_getlk(fd, (struct flock *) arg);
@@ -166,6 +166,17 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
                        if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
                                err = sock_fcntl (filp, F_SETOWN, arg);
                        break;
+               case F_GETSIG:
+                       err = filp->f_owner.signum;
+                       break;
+               case F_SETSIG:
+                       if (arg <= 0 || arg > _NSIG) {
+                               err = -EINVAL;
+                               break;
+                       }
+                       err = 0;
+                       filp->f_owner.signum = arg;
+                       break;
                default:
                        /* sockets need a few special fcntls. */
                        if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
@@ -180,10 +191,13 @@ out:
        return err;
 }
 
-static void send_sigio(int pid, uid_t uid, uid_t euid)
+static void send_sigio(struct fown_struct *fown, struct fasync_struct *fa)
 {
        struct task_struct * p;
-
+       int   pid       = fown->pid;
+       uid_t uid       = fown->uid;
+       uid_t euid      = fown->euid;
+       
        read_lock(&tasklist_lock);
        for_each_task(p) {
                int match = p->pid;
@@ -195,9 +209,27 @@ static void send_sigio(int pid, uid_t uid, uid_t euid)
                    (euid ^ p->suid) && (euid ^ p->uid) &&
                    (uid ^ p->suid) && (uid ^ p->uid))
                        continue;
-               send_sig(SIGIO, p, 1);
-               if (p->state == TASK_INTERRUPTIBLE && signal_pending(p))
-                       wake_up_process(p);
+               switch (fown->signum) {
+                       siginfo_t si;
+               default:
+                       /* Queue a rt signal with the appropriate fd as its
+                          value.  We use SI_SIGIO as the source, not 
+                          SI_KERNEL, since kernel signals always get 
+                          delivered even if we can't queue.  Failure to
+                          queue in this case _should_ be reported; we fall
+                          back to SIGIO in that case. --sct */
+                       si.si_signo = fown->signum;
+                       si.si_errno = 0;
+                       si.si_code  = SI_SIGIO;
+                       si.si_pid   = pid;
+                       si.si_uid   = uid;
+                       si.si_fd    = fa->fa_fd;
+                       if (!send_sig_info(fown->signum, &si, p))
+                               break;
+               /* fall-through: fall back on the old plain SIGIO signal */
+               case 0:
+                       send_sig(SIGIO, p, 1);
+               }
        }
        read_unlock(&tasklist_lock);
 }
@@ -213,7 +245,7 @@ void kill_fasync(struct fasync_struct *fa, int sig)
                }
                fown = &fa->fa_file->f_owner;
                if (fown->pid)
-                       send_sigio(fown->pid, fown->uid, fown->euid);
+                       send_sigio(fown, fa);
                fa = fa->fa_next;
        }
 }
index 2b8f7a1985a90c022be7810cab67b938c75f067b..c68ea1b4c5524fb444a7a98d9e8b47303ad8c558 100644 (file)
@@ -177,14 +177,13 @@ static inline void sync_list(struct list_head *head)
  */
 void sync_inodes(kdev_t dev)
 {
-       struct super_block * sb = super_blocks + 0;
-       int i;
+       struct super_block * sb = sb_entry(super_blocks.next);
 
        /*
         * Search the super_blocks array for the device(s) to sync.
         */
        spin_lock(&inode_lock);
-       for (i = NR_SUPER ; i-- ; sb++) {
+       for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.next)) {
                if (!sb->s_dev)
                        continue;
                if (dev && sb->s_dev != dev)
index 66b33161f8985b4c32b4ab49d387f78bf420a78a..ba7a6c6e9719b19fa9d9379d5f1e49d095f695ac 100644 (file)
  *              Following Linus comments on my original hack, this version
  *              depends only on the dcache stuff and doesn't touch the inode
  *              layer (iput() and friends).
+ * 04 Aug 1998  Ion Badulescu <ionut@cs.columbia.edu>     
+ *             FIFO's need special handling in NFSv2
+ */
+
+/*
+ * Fixes:
+ *    Ion Badulescu <ionut@cs.columbia.edu>     : FIFO's need special handling in NFSv2
  */
 
 #include <linux/sched.h>
@@ -645,7 +652,10 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode)
        if (dentry->d_name.len > NFS_MAXNAMLEN)
                goto out;
 
-       sattr.mode = mode;
+       if (mode & S_IFIFO)
+               sattr.mode = (mode & ~S_IFMT) | S_IFCHR;
+       else
+               sattr.mode = mode;
        sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
        sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
 
@@ -655,6 +665,15 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode)
        nfs_invalidate_dircache(dir);
        error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
                        dentry->d_name.name, &sattr, &fhandle, &fattr);
+       /*
+        *      Retry invalid FIFO creates as the original object
+        *      to cover for NFS servers that don't cope.
+        */
+       if (error == -EINVAL && (mode & S_IFIFO)) {
+               sattr.mode = mode;
+               error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
+                                       dentry->d_name.name, &sattr, &fhandle, &fattr);
+       }
        if (!error)
                error = nfs_instantiate(dentry, &fhandle, &fattr);
        if (error)
@@ -684,7 +703,10 @@ static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rde
        if (dentry->d_name.len > NFS_MAXNAMLEN)
                return -ENAMETOOLONG;
 
-       sattr.mode = mode;
+       if (mode & S_IFIFO)
+               sattr.mode = (mode & ~S_IFMT) | S_IFCHR;
+       else
+               sattr.mode = mode;
        sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
        if (S_ISCHR(mode) || S_ISBLK(mode))
                sattr.size = rdev; /* get out your barf bag */
@@ -693,6 +715,11 @@ static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rde
        nfs_invalidate_dircache(dir);
        error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
                                dentry->d_name.name, &sattr, &fhandle, &fattr);
+       if (error == -EINVAL && (mode & S_IFIFO)) {
+               sattr.mode = mode;
+               error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
+                                       dentry->d_name.name, &sattr, &fhandle, &fattr);
+       }
        if (!error)
                error = nfs_instantiate(dentry, &fhandle, &fattr);
        if (error)
index 81da8f9968ddbd4e9528631ff6c3ba262a419bdd..3ecb9bfa630e44c713f67dd45124323a25d6be66 100644 (file)
@@ -78,6 +78,7 @@ mnt_create(char *hostname, struct sockaddr_in *srvaddr)
                clnt->cl_softrtry = 1;
                clnt->cl_chatty   = 1;
                clnt->cl_oneshot  = 1;
+               clnt->cl_intr = 1;
        }
        return clnt;
 }
index 1c6a74a71799c48734500a4b8f0aa44b7036cb1a..bab335a15f30dd86902f5c9aee30d468b19c3f2d 100644 (file)
@@ -5,6 +5,9 @@
  *
  * Copyright (C) 1992, 1993, 1994  Rick Sladkey
  * Copyright (C) 1996 Olaf Kirch
+ *
+ * 04 Aug 1998  Ion Badulescu <ionut@cs.columbia.edu>     
+ *             FIFO's need special handling in NFSv2
  */
 
 #define NFS_NEED_XDR_TYPES
@@ -114,6 +117,11 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
        fattr->mtime.useconds = ntohl(*p++);
        fattr->ctime.seconds = ntohl(*p++);
        fattr->ctime.useconds = ntohl(*p++);
+       if (fattr->type == NFCHR && fattr->rdev == NFS_FIFO_DEV) {
+               fattr->type = NFFIFO;
+               fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
+               fattr->rdev = 0;
+       }
        return p;
 }
 
index c317f330bbd34d7261025ef2a22a9984aaf11ed8..0a58b6a025a893c114fbfea83f9261ab6c74a15b 100644 (file)
@@ -468,7 +468,9 @@ wait_on_write_request(struct nfs_wreq *req)
        struct wait_queue       wait = { current, NULL };
        struct page             *page = req->wb_page;
        int                     retval;
+       sigset_t                oldmask;
 
+       rpc_clnt_sigmask(NFS_CLIENT(req->wb_inode), &oldmask);
        add_wait_queue(&page->wait, &wait);
        atomic_inc(&page->count);
        for (;;) {
@@ -477,7 +479,8 @@ wait_on_write_request(struct nfs_wreq *req)
                if (!PageLocked(page))
                        break;
                retval = -ERESTARTSYS;
-               if (IS_SOFT && signalled())
+               /* IS_SOFT is a timeout item .. */
+               if (signalled())
                        break;
                schedule();
        }
@@ -485,6 +488,7 @@ wait_on_write_request(struct nfs_wreq *req)
        current->state = TASK_RUNNING;
        /* N.B. page may have been unused, so we must use free_page() */
        free_page(page_address(page));
+       rpc_clnt_sigunmask(NFS_CLIENT(req->wb_inode), &oldmask);
        return retval;
 }
 
@@ -534,6 +538,10 @@ nfs_updatepage(struct file *file, struct page *page, const char *buffer,
        if ((req = find_write_request(inode, page)) != NULL) {
                if (update_write_request(req, offset, count)) {
                        /* N.B. check for a fault here and cancel the req */
+                       /*
+                        *      SECURITY - copy_from_user must zero the
+                        *      rest of the data after a fault!
+                        */
                        copy_from_user(page_addr + offset, buffer, count);
                        goto updated;
                }
@@ -889,6 +897,9 @@ nfs_wback_result(struct rpc_task *task)
                /* Update attributes as result of writeback. 
                 * Beware: when UDP replies arrive out of order, we
                 * may end up overwriting a previous, bigger file size.
+                *
+                * When the file size shrinks we cancel all pending
+                * writebacks. 
                 */
                if (fattr->mtime.seconds >= inode->i_mtime) {
                        if (fattr->size < inode->i_size)
index 0d4b748fcecf69a0215eb2a0dfb5c9b1a16a589c..d5a97963983c811906fa2c17698e6acac0ec60dd 100644 (file)
@@ -485,16 +485,18 @@ static unsigned long get_wchan(struct task_struct *p)
                return 0;
 #if defined(__i386__)
        {
-               unsigned long ebp, eip;
+               unsigned long ebp, esp, eip;
                unsigned long stack_page;
                int count = 0;
 
-               stack_page = 4096 + (unsigned long)p;
-               if (!stack_page)
+               stack_page = (unsigned long)p;
+               esp = p->tss.esp;
+               if (!stack_page || esp < stack_page || esp >= 8188+stack_page)
                        return 0;
-               ebp = p->tss.ebp;
+               /* include/asm-i386/system.h:switch_to() pushes ebp last. */
+               ebp = *(unsigned long *) esp;
                do {
-                       if (ebp < stack_page || ebp >= 4092+stack_page)
+                       if (ebp < stack_page || ebp >= 8188+stack_page)
                                return 0;
                        eip = *(unsigned long *) (ebp+4);
                        if (eip < first_sched || eip >= last_sched)
index 07aa03a63c98c707dd5f4ee187122591f55a4e68..924a02f8fc3183c3a1c0e1ba463ee4856790693a 100644 (file)
@@ -68,7 +68,10 @@ static int do_remount_sb(struct super_block *sb, int flags, char * data);
 /* this is initialized in init/main.c */
 kdev_t ROOT_DEV;
 
-struct super_block super_blocks[NR_SUPER];
+int nr_super_blocks = 0;
+int max_super_blocks = NR_SUPER;
+LIST_HEAD(super_blocks);
+
 static struct file_system_type *file_systems = (struct file_system_type *) NULL;
 struct vfsmount *vfsmntlist = (struct vfsmount *) NULL;
 static struct vfsmount *vfsmnttail = (struct vfsmount *) NULL,
@@ -446,7 +449,9 @@ void sync_supers(kdev_t dev)
 {
        struct super_block * sb;
 
-       for (sb = super_blocks + 0 ; sb < super_blocks + NR_SUPER ; sb++) {
+       for (sb = sb_entry(super_blocks.next);
+            sb != sb_entry(&super_blocks); 
+            sb = sb_entry(sb->s_list.next)) {
                if (!sb->s_dev)
                        continue;
                if (dev && sb->s_dev != dev)
@@ -471,15 +476,15 @@ struct super_block * get_super(kdev_t dev)
        if (!dev)
                return NULL;
 restart:
-       s = 0+super_blocks;
-       while (s < NR_SUPER+super_blocks)
+       s = sb_entry(super_blocks.next);
+       while (s != sb_entry(&super_blocks))
                if (s->s_dev == dev) {
                        wait_on_super(s);
                        if (s->s_dev == dev)
                                return s;
                        goto restart;
                } else
-                       s++;
+                       s = sb_entry(s->s_list.next);
        return NULL;
 }
 
@@ -519,16 +524,28 @@ out:
  */
 static struct super_block *get_empty_super(void)
 {
-       struct super_block *s = 0+super_blocks;
+       struct super_block *s;
 
-       for (; s < NR_SUPER+super_blocks; s++) {
+       for (s  = sb_entry(super_blocks.next);
+            s != sb_entry(&super_blocks); 
+            s  = sb_entry(s->s_list.next)) {
                if (s->s_dev)
                        continue;
                if (!s->s_lock)
                        return s;
                printk("VFS: empty superblock %p locked!\n", s);
        }
-       return NULL;
+       /* Need a new one... */
+       if (nr_super_blocks >= max_super_blocks)
+               return NULL;
+       s = kmalloc(sizeof(struct super_block),  GFP_USER);
+       nr_super_blocks++;
+       if (s) {
+               memset(s, 0, sizeof(struct super_block));
+               INIT_LIST_HEAD(&s->s_dirty);
+               list_add (&s->s_list, super_blocks.prev);
+       }
+       return s;
 }
 
 static struct super_block * read_super(kdev_t dev,const char *name,int flags,
@@ -1112,7 +1129,7 @@ clean_up:
        goto dput_and_out;
 }
 
-__initfunc(static void do_mount_root(void))
+__initfunc(void mount_root(void))
 {
        struct file_system_type * fs_type;
        struct super_block * sb;
@@ -1120,7 +1137,7 @@ __initfunc(static void do_mount_root(void))
        struct inode * d_inode = NULL;
        struct file filp;
        int retval;
-  
+
 #ifdef CONFIG_ROOT_NFS
        if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
                ROOT_DEV = 0;
@@ -1207,22 +1224,6 @@ __initfunc(static void do_mount_root(void))
 }
 
 
-__initfunc(void mount_root(void))
-{
-       struct super_block * sb = super_blocks;
-       int i;
-
-       memset(super_blocks, 0, sizeof(super_blocks));
-       /*
-        * Initialize the dirty inode list headers for the super blocks
-        */
-       for (i = NR_SUPER ; i-- ; sb++)
-               INIT_LIST_HEAD(&sb->s_dirty);
-
-       do_mount_root();
-}
-
-
 #ifdef CONFIG_BLK_DEV_INITRD
 
 extern int initmem_freed;
@@ -1242,7 +1243,7 @@ __initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old))
                return -EBUSY;
        }
        ROOT_DEV = new_root_dev;
-       do_mount_root();
+       mount_root();
        dput(old_root);
        dput(old_pwd);
 #if 1
index be37113d54728acafbbfd4eb020c044fcdb8ca56..49cc35d8d624ddf4d53851884ea622eb61ed157e 100644 (file)
@@ -1771,8 +1771,6 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
        MSDOS_I(new_inode)->i_logstart = MSDOS_I(old_inode)->i_logstart;
        MSDOS_I(new_inode)->i_attrs = MSDOS_I(old_inode)->i_attrs;
 
-       old_inode->i_nlink = 0;
-
        fat_cache_inval_inode(old_inode);
        mark_inode_dirty(new_inode);
 
@@ -1816,6 +1814,16 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
                fat_brelse(sb, dotdot_bh);
        }
 
+       /*
+        * This convinces the VFS layer to drop the old inode,
+        * but at the same time fools the VFAT layer to not
+        * actually delete any of the blocks in the old file
+        * (because they are very much used by the renamed file)
+        */
+       MSDOS_I(old_inode)->i_start = 0;
+       MSDOS_I(old_inode)->i_logstart = 0;
+       old_inode->i_nlink = 0;
+
        if (res > 0) res = 0;
 
        if (res == 0) {
index 3df5edf2bedc4033d833d379fa018fd91dac7507..7f0e967aac65747545a8c5b277ae190c9ca73939 100644 (file)
@@ -29,6 +29,8 @@
 
 #define F_SETOWN       5       /*  for sockets. */
 #define F_GETOWN       6       /*  for sockets. */
+#define F_SETSIG       10      /*  for sockets. */
+#define F_GETSIG       11      /*  for sockets. */
 
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC     1       /* actually anything with low bit set goes */
index c2304b041979eedce0c26785c6fc39f2de001120..f9f3e040ad44ee2da4ca7f942f4365cc816dbc98 100644 (file)
@@ -87,6 +87,7 @@ typedef struct siginfo {
 #define SI_TIMER       -2      /* sent by timer expiration */
 #define SI_MESGQ       -3      /* sent by real time mesq state change */
 #define SI_ASYNCIO     -4      /* sent by AIO completion */
+#define SI_SIGIO       -5      /* sent by queued SIGIO */
 
 #define SI_FROMUSER(siptr)     ((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)   ((siptr)->si_code > 0)
index af29f7f4641d76ffe19f08044f3745647d9750f1..a9e469a492ce96739108847e1969c363fb02cc68 100644 (file)
@@ -28,6 +28,8 @@
 
 #define F_SETOWN       8       /*  for sockets. */
 #define F_GETOWN       9       /*  for sockets. */
+#define F_SETSIG       10      /*  for sockets. */
+#define F_GETSIG       11      /*  for sockets. */
 
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC     1       /* actually anything with low bit set goes */
index bcec2810f28a568590583b9682b72adebcbc92af..2dec6e08079df25e30447200e8e64236be3714a1 100644 (file)
@@ -87,6 +87,7 @@ typedef struct siginfo {
 #define SI_TIMER       -2      /* sent by timer expiration */
 #define SI_MESGQ       -3      /* sent by real time mesq state change */
 #define SI_ASYNCIO     -4      /* sent by AIO completion */
+#define SI_SIGIO       -5      /* sent by queued SIGIO */
 
 #define SI_FROMUSER(siptr)     ((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)   ((siptr)->si_code > 0)
index 369ac5153b7b37d1b1d305b818b78cea68886d63..dfdd500c6ef5484eabf95561f38cfd04f3620b4d 100644 (file)
@@ -28,6 +28,8 @@
 
 #define F_SETOWN       8       /*  for sockets. */
 #define F_GETOWN       9       /*  for sockets. */
+#define F_SETSIG       10      /*  for sockets. */
+#define F_GETSIG       11      /*  for sockets. */
 
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC     1       /* actually anything with low bit set goes */
index 01ef4d08ab13f0a08433b9864d0099b4c4f0bcf4..d0cae4709254cff388bfcae34514314c154873b9 100644 (file)
@@ -87,6 +87,7 @@ typedef struct siginfo {
 #define SI_TIMER       -2      /* sent by timer expiration */
 #define SI_MESGQ       -3      /* sent by real time mesq state change */
 #define SI_ASYNCIO     -4      /* sent by AIO completion */
+#define SI_SIGIO       -5      /* sent by queued SIGIO */
 
 #define SI_FROMUSER(siptr)     ((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)   ((siptr)->si_code > 0)
index c1f6ea405a0af31181f472e8574053229a8febd9..500d495bf21b0770c2b691b72fff247a368203be 100644 (file)
@@ -28,6 +28,8 @@
 
 #define F_SETOWN       8       /*  for sockets. */
 #define F_GETOWN       9       /*  for sockets. */
+#define F_SETSIG       10      /*  for sockets. */
+#define F_GETSIG       11      /*  for sockets. */
 
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC     1       /* actually anything with low bit set goes */
index f6799d2b1e957474b8e00aaf8c66114aabc844d8..4061e6f72946dbb4b3e1fdaa58e3decc39ccb6a5 100644 (file)
@@ -87,6 +87,7 @@ typedef struct siginfo {
 #define SI_TIMER       -2      /* sent by timer expiration */
 #define SI_MESGQ       -3      /* sent by real time mesq state change */
 #define SI_ASYNCIO     -4      /* sent by AIO completion */
+#define SI_SIGIO       -5      /* sent by queued SIGIO */
 
 #define SI_FROMUSER(siptr)     ((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)   ((siptr)->si_code > 0)
index 3606b252adaeeffb96c12004200e7ce0b553b5d9..d40aac7e84540aed83f8c984860a9427f57f37bd 100644 (file)
@@ -29,6 +29,8 @@
 
 #define F_SETOWN       24      /*  for sockets. */
 #define F_GETOWN       23      /*  for sockets. */
+#define F_SETSIG       10      /*  for sockets. */
+#define F_GETSIG       11      /*  for sockets. */
 
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC     1       /* actually anything with low bit set goes */
index 2cf7fd22ebce8a0802740d353c94855a7cb1e705..83893d5af56b1af5ec62a3c843a44f6016901b15 100644 (file)
@@ -87,6 +87,7 @@ typedef struct siginfo {
 #define SI_TIMER       -2      /* sent by timer expiration */
 #define SI_MESGQ       -3      /* sent by real time mesq state change */
 #define SI_ASYNCIO     -4      /* sent by AIO completion */
+#define SI_SIGIO       -5      /* sent by queued SIGIO */
 
 #define SI_FROMUSER(siptr)     ((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)   ((siptr)->si_code > 0)
index 61d0fa703f745249b8087ee4e1e7eb04888d89c4..773e6a252435e71cb981880ebb653b36df7f632b 100644 (file)
@@ -28,6 +28,8 @@
 
 #define F_SETOWN       8       /*  for sockets. */
 #define F_GETOWN       9       /*  for sockets. */
+#define F_SETSIG       10      /*  for sockets. */
+#define F_GETSIG       11      /*  for sockets. */
 
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC     1       /* actually anything with low bit set goes */
index 0ead0b84e5752cfc6d9dabf711ed51daa0ca0c17..c3a46ceffa4819e21af84b233b0359c0df1d719c 100644 (file)
@@ -87,6 +87,7 @@ typedef struct siginfo {
 #define SI_TIMER       -2      /* sent by timer expiration */
 #define SI_MESGQ       -3      /* sent by real time mesq state change */
 #define SI_ASYNCIO     -4      /* sent by AIO completion */
+#define SI_SIGIO       -5      /* sent by queued SIGIO */
 
 #define SI_FROMUSER(siptr)     ((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)   ((siptr)->si_code > 0)
index 5e4a68af6f5a882d820b4a1c03561d2c3dbcce46..775a800d4f222f250a1dfd9d621bbbff65f31d0b 100644 (file)
@@ -28,6 +28,8 @@
 #define F_GETLK                7
 #define F_SETLK                8
 #define F_SETLKW       9
+#define F_SETSIG       10      /*  for sockets. */
+#define F_GETSIG       11      /*  for sockets. */
 
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC     1       /* actually anything with low bit set goes */
index 0509aa1b317acaf9c2590b73daeab13cb1fb9faf..0a666b4e2fb7a3e52bbe3a362c253a7c1ddb51e1 100644 (file)
@@ -91,6 +91,7 @@ typedef struct siginfo {
 #define SI_TIMER       -2      /* sent by timer expiration */
 #define SI_MESGQ       -3      /* sent by real time mesq state change */
 #define SI_ASYNCIO     -4      /* sent by AIO completion */
+#define SI_SIGIO       -5      /* sent by queued SIGIO */
 
 #define SI_FROMUSER(siptr)     ((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)   ((siptr)->si_code > 0)
index 33044df82d6e4b45520e6a713f2f2a5e5eacb14c..1db734bed188c7cc80314405d64cdca363d2e27f 100644 (file)
@@ -28,6 +28,8 @@
 #define F_GETLK                7
 #define F_SETLK                8
 #define F_SETLKW       9
+#define F_SETSIG       10      /*  for sockets. */
+#define F_GETSIG       11      /*  for sockets. */
 
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC     1       /* actually anything with low bit set goes */
index ff2534c66cf01da8657a894e2d942a32fa8b46a3..b3ccd57a9bb1324afd306e9e061875464d9807c2 100644 (file)
@@ -150,6 +150,7 @@ typedef struct siginfo32 {
 #define SI_TIMER       -2      /* sent by timer expiration */
 #define SI_MESGQ       -3      /* sent by real time mesq state change */
 #define SI_ASYNCIO     -4      /* sent by AIO completion */
+#define SI_SIGIO       -5      /* sent by queued SIGIO */
 
 #define SI_FROMUSER(siptr)     ((siptr)->si_code <= 0)
 #define SI_FROMKERNEL(siptr)   ((siptr)->si_code > 0)
index ed86feae5e45f37835d87a7460da8338dc6ff623..24b132b249cce0d86514927affe08aed84ad0284 100644 (file)
@@ -39,16 +39,17 @@ struct poll_table_struct;
 #undef NR_OPEN
 #define NR_OPEN 1024
 
-#define NR_SUPER 64
 #define BLOCK_SIZE_BITS 10
 #define BLOCK_SIZE (1<<BLOCK_SIZE_BITS)
 
 /* And dynamically-tunable limits and defaults: */
 extern int max_inodes;
 extern int max_files, nr_files, nr_free_files;
+extern int max_super_blocks, nr_super_blocks;
 
 #define NR_FILE  4096  /* this can well be larger on a larger system */
 #define NR_RESERVED_FILES 10 /* reserved for root */
+#define NR_SUPER 256
 
 #define MAY_EXEC 1
 #define MAY_WRITE 2
@@ -400,6 +401,7 @@ static inline void mark_inode_dirty(struct inode *inode)
 struct fown_struct {
        int pid;                /* pid or -pgrp where SIGIO should be sent */
        uid_t uid, euid;        /* uid/euid of process setting the owner */
+       int signum;             /* posix.1b rt signal to be delivered on IO */
 };
 
 struct file {
@@ -509,13 +511,14 @@ extern inline int locks_verify_area(int read_write, struct inode *inode,
 
 struct fasync_struct {
        int    magic;
+       int    fa_fd;
        struct fasync_struct    *fa_next; /* singly linked list */
        struct file             *fa_file;
 };
 
 #define FASYNC_MAGIC 0x4601
 
-extern int fasync_helper(struct file *, int, struct fasync_struct **);
+extern int fasync_helper(int, struct file *, int, struct fasync_struct **);
 
 #include <linux/minix_fs_sb.h>
 #include <linux/ext2_fs_sb.h>
@@ -532,7 +535,11 @@ extern int fasync_helper(struct file *, int, struct fasync_struct **);
 #include <linux/hfs_fs_sb.h>
 #include <linux/adfs_fs_sb.h>
 
+extern struct list_head super_blocks;
+
+#define sb_entry(list) list_entry((list), struct super_block, s_list)
 struct super_block {
+       struct list_head        s_list;         /* Keep this first */
        kdev_t                  s_dev;
        unsigned long           s_blocksize;
        unsigned char           s_blocksize_bits;
@@ -591,7 +598,7 @@ struct file_operations {
        int (*open) (struct inode *, struct file *);
        int (*release) (struct inode *, struct file *);
        int (*fsync) (struct file *, struct dentry *);
-       int (*fasync) (struct file *, int);
+       int (*fasync) (int, struct file *, int);
        int (*check_media_change) (kdev_t dev);
        int (*revalidate) (kdev_t dev);
        int (*lock) (struct file *, int, struct file_lock *);
@@ -704,7 +711,6 @@ extern int fs_may_remount_ro(struct super_block *);
 extern int fs_may_mount(kdev_t dev);
 
 extern struct file *inuse_filps;
-extern struct super_block super_blocks[NR_SUPER];
 
 extern void refile_buffer(struct buffer_head * buf);
 extern void set_writetime(struct buffer_head * buf, int flag);
index 8553a05c507be2aba8f1c62556835bd9b82fee25..98a25005186d70b4134a267a361f71038edfd764 100644 (file)
@@ -118,6 +118,9 @@ int         rpc_do_call(struct rpc_clnt *clnt, u32 proc,
                                void *argp, void *resp, int flags,
                                rpc_action callback, void *clntdata);
 void           rpc_restart_call(struct rpc_task *);
+void           rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset);
+void           rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
+
 #define rpc_call(clnt, proc, argp, resp, flags)        \
                rpc_do_call(clnt, proc, argp, resp, flags, NULL, NULL)
 
index 697950b2ee7ba58cb29f790bcf66eb4d37aadde5..f0f8e03845e55b43a5eef9ea419f2de5e87308e3 100644 (file)
@@ -146,6 +146,8 @@ void *              rpc_allocate(unsigned int flags, unsigned int);
 void           rpc_free(void *);
 int            rpciod_up(void);
 void           rpciod_down(void);
+void           rpciod_wake_up(void);
+void           rpciod_tcp_dispatcher(void);
 #ifdef RPC_DEBUG
 void           rpc_show_tasks(void);
 #endif
index 0037b5738d7aeb47a7d2526937cd0a7e07d98fe4..df16576d7d7eae650b34bc7aa068b8afb51539db 100644 (file)
@@ -36,7 +36,7 @@
  * Note: on machines with low memory we should probably use a smaller
  * MAXREQS value: At 32 outstanding reqs with 8 megs of RAM, fragment
  * reassembly will frequently run out of memory.
- * Come Linux 2.1, we'll handle fragments directly.
+ * Come Linux 2.3, we'll handle fragments directly.
  */
 #define RPC_MAXCONG            16
 #define RPC_MAXREQS            (RPC_MAXCONG + 1)
@@ -103,6 +103,12 @@ struct rpc_rqst {
         * For authentication (e.g. auth_des)
         */
        u32                     rq_creddata[2];
+       
+       /*
+        * Partial send handling
+        */
+       
+       u32                     rq_bytes_sent;  /* Bytes we have sent */
 
 #ifdef RPC_PROFILE
        unsigned long           rq_xtime;       /* when transmitted */
@@ -166,6 +172,8 @@ struct rpc_xprt {
         */
        struct rpc_iov          snd_buf;        /* send buffer */
        struct rpc_task *       snd_task;       /* Task blocked in send */
+       u32                     snd_sent;       /* Bytes we have sent */
+
 
        void                    (*old_data_ready)(struct sock *, int);
        void                    (*old_state_change)(struct sock *);
index 07ac5fbf9d164838ad905c7d0686c27135b28f29..aeeff7ef4e4b8a97d99074ad419682bce3664808 100644 (file)
@@ -7,6 +7,23 @@
 
 #define MAX_SWAPFILES 8
 
+union swap_header {
+       struct 
+       {
+               char reserved[PAGE_SIZE - 10];
+               char magic[10];
+       } magic;
+       struct 
+       {
+               char         bootbits[1024];    /* Space for disklabel etc. */
+               unsigned int version;
+               unsigned int last_page;
+               unsigned int nr_badpages;
+               unsigned int padding[125];
+               unsigned int badpages[1];
+       } info;
+};
+
 #ifdef __KERNEL__
 
 #undef DEBUG_SWAP
 
 #define SWAP_CLUSTER_MAX 32
 
+#define SWAP_MAP_MAX   0x7fff
+#define SWAP_MAP_BAD   0x8000
+
 struct swap_info_struct {
        unsigned int flags;
        kdev_t swap_device;
        struct dentry * swap_file;
-       unsigned char * swap_map;
+       unsigned short * swap_map;
        unsigned char * swap_lockmap;
        unsigned int lowest_bit;
        unsigned int highest_bit;
index ef9044aa184f3f1bd5b870df8cd5530ac18a0e36..c310573ee02b85099455190cd7300d4101cdb3ba 100644 (file)
@@ -2,6 +2,23 @@
  * sysctl.h: General linux system control interface
  *
  * Begun 24 March 1995, Stephen Tweedie
+ *
+ ****************************************************************
+ ****************************************************************
+ **
+ **  WARNING:  
+ **  The values in this file are exported to user space via 
+ **  the sysctl() binary interface.  Do *NOT* change the 
+ **  numbering of any existing values here, and do not change
+ **  any numbers within any one set of values.  If you have
+ **  to redefine an existing interface, use a new number for it.
+ **  The kernel will then return ENOTDIR to any application using
+ **  the old binary interface.
+ **
+ **  --sct
+ **
+ ****************************************************************
+ ****************************************************************
  */
 
 #include <linux/lists.h>
@@ -33,32 +50,32 @@ struct __sysctl_args {
 
 enum
 {
-       CTL_KERN=1,             /* General kernel info and control */
+/*1*/  CTL_KERN=1,             /* General kernel info and control */
        CTL_VM,                 /* VM management */
        CTL_NET,                /* Networking */
        CTL_PROC,               /* Process info */
        CTL_FS,                 /* Filesystems */
        CTL_DEBUG,              /* Debugging */
-       CTL_DEV,                /* Devices */
+/*7*/  CTL_DEV,                /* Devices */
 };
 
 
 /* CTL_KERN names: */
 enum
 {
-       KERN_OSTYPE=1,          /* string: system version */
+/*1*/  KERN_OSTYPE=1,          /* string: system version */
        KERN_OSRELEASE,         /* string: system release */
        KERN_OSREV,             /* int: system revision */
        KERN_VERSION,           /* string: compile time info */
        KERN_SECUREMASK,        /* struct: maximum rights mask */
        KERN_PROF,              /* table: profiling information */
        KERN_NODENAME,
-       KERN_DOMAINNAME,
-       KERN_SECURELVL,         /* int: system security level */
+/*8*/  KERN_DOMAINNAME,
+/*14*/ KERN_SECURELVL=14,      /* int: system security level */
        KERN_PANIC,             /* int: panic timeout */
-       KERN_REALROOTDEV,       /* real root device to mount after initrd */
-       KERN_JAVA_INTERPRETER,  /* path to Java(tm) interpreter */
-       KERN_JAVA_APPLETVIEWER, /* path to Java(tm) appletviewer */
+/*16*/ KERN_REALROOTDEV,       /* real root device to mount after initrd */
+/*19*/ KERN_JAVA_INTERPRETER=19,/* path to Java(tm) interpreter */
+/*20*/ KERN_JAVA_APPLETVIEWER, /* path to Java(tm) appletviewer */
        KERN_SPARC_REBOOT,      /* reboot command on Sparc */
        KERN_CTLALTDEL,         /* int: allow ctl-alt-del to reboot */
        KERN_PRINTK,            /* sturct: control printk logging parameters */
@@ -67,14 +84,14 @@ enum
        KERN_PPC_ZEROPAGED,     /* turn idle page zeroing on/off on PPC */
        KERN_PPC_POWERSAVE_NAP, /* use nap mode for power saving */
        KERN_MODPROBE,
-       KERN_SG_BIG_BUFF
+/*29*/ KERN_SG_BIG_BUFF
 };
 
 
 /* CTL_VM names: */
 enum
 {
-       VM_SWAPCTL=1,           /* struct: Set vm swapping control */
+/*1*/  VM_SWAPCTL=1,           /* struct: Set vm swapping control */
        VM_SWAPOUT,             /* int: Background pageout interval */
        VM_FREEPG,              /* struct: Set free page thresholds */
        VM_BDFLUSH,             /* struct: Control buffer cache flushing */
@@ -82,14 +99,14 @@ enum
        VM_BUFFERMEM,           /* struct: Set buffer memory thresholds */
        VM_PAGECACHE,           /* struct: Set cache memory thresholds */
        VM_PAGERDAEMON,         /* struct: Control kswapd behaviour */
-       VM_PGT_CACHE            /* struct: Set page table cache parameters */
+/*9*/  VM_PGT_CACHE            /* struct: Set page table cache parameters */
 };
 
 
 /* CTL_NET names: */
 enum
 {
-       NET_CORE=1,
+/*1*/  NET_CORE=1,
        NET_ETHER,
        NET_802,
        NET_UNIX,
@@ -98,19 +115,19 @@ enum
        NET_ATALK,
        NET_NETROM,
        NET_AX25,
-       NET_BRIDGE,
-       NET_IPV6,
+/*10*/ NET_BRIDGE,
        NET_ROSE,
+       NET_IPV6,
        NET_X25,
        NET_TR,
-       NET_DECNET
+/*15*/ NET_DECNET
 };
 
 
 /* /proc/sys/net/core */
 enum
 {
-       NET_CORE_WMEM_MAX=1,
+/*1*/  NET_CORE_WMEM_MAX=1,
        NET_CORE_RMEM_MAX,
        NET_CORE_WMEM_DEFAULT,
        NET_CORE_RMEM_DEFAULT,
@@ -119,7 +136,7 @@ enum
        NET_CORE_FASTROUTE,
        NET_CORE_MSG_COST,
        NET_CORE_MSG_BURST,
-       NET_CORE_OPTMEM_MAX,
+/*10*/ NET_CORE_OPTMEM_MAX,
 };
 
 /* /proc/sys/net/ethernet */
@@ -130,23 +147,23 @@ enum
 
 enum
 {
-       NET_UNIX_DESTROY_DELAY=1,
-       NET_UNIX_DELETE_DELAY,
+/*1*/  NET_UNIX_DESTROY_DELAY=1,
+/*2*/  NET_UNIX_DELETE_DELAY,
 };
 
 /* /proc/sys/net/ipv4 */
 enum
 {
        /* v2.0 compatibile variables */
-       NET_IPV4_FORWARD = 8,
+/*8*/  NET_IPV4_FORWARD = 8,
        NET_IPV4_DYNADDR = 9,
 
-       NET_IPV4_CONF = 16,
+/*16*/ NET_IPV4_CONF = 16,
        NET_IPV4_NEIGH = 17,
        NET_IPV4_ROUTE = 18,
        NET_IPV4_FIB_HASH = 19,
 
-       NET_IPV4_TCP_HOE_RETRANSMITS=32,
+/*32*/ NET_IPV4_TCP_HOE_RETRANSMITS=32,
        NET_IPV4_TCP_TIMESTAMPS,
        NET_IPV4_TCP_WINDOW_SCALING,
        NET_IPV4_TCP_SACK,
@@ -154,7 +171,7 @@ enum
        NET_IPV4_DEFAULT_TTL,
        NET_IPV4_AUTOCONFIG,
        NET_IPV4_NO_PMTU_DISC,
-       NET_IPV4_TCP_SYN_RETRIES,
+/*40*/ NET_IPV4_TCP_SYN_RETRIES,
        NET_IPV4_IPFRAG_HIGH_THRESH,
        NET_IPV4_IPFRAG_LOW_THRESH,
        NET_IPV4_IPFRAG_TIME,
@@ -164,7 +181,7 @@ enum
        NET_IPV4_TCP_RETRIES1,
        NET_IPV4_TCP_RETRIES2,
        NET_IPV4_TCP_FIN_TIMEOUT,
-       NET_IPV4_IP_MASQ_DEBUG,
+/*50*/ NET_IPV4_IP_MASQ_DEBUG,
        NET_TCP_SYNCOOKIES,
        NET_TCP_STDURG,
        NET_TCP_RFC1337,
@@ -174,14 +191,14 @@ enum
        NET_IPV4_ICMP_ECHO_IGNORE_ALL,
        NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS,
        NET_IPV4_ICMP_SOURCEQUENCH_RATE,
-       NET_IPV4_ICMP_DESTUNREACH_RATE,
+/*60*/ NET_IPV4_ICMP_DESTUNREACH_RATE,
        NET_IPV4_ICMP_TIMEEXCEED_RATE,
        NET_IPV4_ICMP_PARAMPROB_RATE,
-       NET_IPV4_ICMP_ECHOREPLY_RATE,
+/*63*/ NET_IPV4_ICMP_ECHOREPLY_RATE,
 };
 
 enum {
-       NET_IPV4_ROUTE_FLUSH = 1,
+/*1*/  NET_IPV4_ROUTE_FLUSH = 1,
        NET_IPV4_ROUTE_MIN_DELAY,
        NET_IPV4_ROUTE_MAX_DELAY,
        NET_IPV4_ROUTE_GC_THRESH,
@@ -190,24 +207,24 @@ enum {
        NET_IPV4_ROUTE_GC_TIMEOUT,
        NET_IPV4_ROUTE_GC_INTERVAL,
        NET_IPV4_ROUTE_REDIRECT_LOAD,
-       NET_IPV4_ROUTE_REDIRECT_NUMBER,
+/*10*/ NET_IPV4_ROUTE_REDIRECT_NUMBER,
        NET_IPV4_ROUTE_REDIRECT_SILENCE,
        NET_IPV4_ROUTE_ERROR_COST,
        NET_IPV4_ROUTE_ERROR_BURST,
-       NET_IPV4_ROUTE_GC_ELASTICITY,
+/*14*/ NET_IPV4_ROUTE_GC_ELASTICITY,
 };
 
 enum
 {
-       NET_PROTO_CONF_ALL = -2,
-       NET_PROTO_CONF_DEFAULT = -3,
+/*-2*/ NET_PROTO_CONF_ALL = -2,
+/*-3*/ NET_PROTO_CONF_DEFAULT = -3,
 
        /* And device ifindices ... */
 };
 
 enum
 {
-       NET_IPV4_CONF_FORWARDING = 1,
+/*1*/  NET_IPV4_CONF_FORWARDING = 1,
        NET_IPV4_CONF_MC_FORWARDING,
        NET_IPV4_CONF_PROXY_ARP,
        NET_IPV4_CONF_ACCEPT_REDIRECTS,
@@ -216,29 +233,29 @@ enum
        NET_IPV4_CONF_SHARED_MEDIA,
        NET_IPV4_CONF_RP_FILTER,
        NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE,
-       NET_IPV4_CONF_BOOTP_RELAY,
-       NET_IPV4_CONF_LOG_MARTIANS,
+/*10*/ NET_IPV4_CONF_BOOTP_RELAY,
+/*11*/ NET_IPV4_CONF_LOG_MARTIANS,
 };
 
 /* /proc/sys/net/ipv6 */
 enum {
-       NET_IPV6_CONF = 16,
+/*16*/ NET_IPV6_CONF = 16,
        NET_IPV6_NEIGH = 17,
-       NET_IPV6_ROUTE = 18,
+/*18*/ NET_IPV6_ROUTE = 18,
 };
 
 enum {
-       NET_IPV6_ROUTE_FLUSH = 1,
+/*1*/  NET_IPV6_ROUTE_FLUSH = 1,
        NET_IPV6_ROUTE_GC_THRESH,
        NET_IPV6_ROUTE_MAX_SIZE,
        NET_IPV6_ROUTE_GC_MIN_INTERVAL,
        NET_IPV6_ROUTE_GC_TIMEOUT,
        NET_IPV6_ROUTE_GC_INTERVAL,
-       NET_IPV6_ROUTE_GC_ELASTICITY,
+/*7*/  NET_IPV6_ROUTE_GC_ELASTICITY,
 };
 
 enum {
-       NET_IPV6_FORWARDING = 1,
+/*1*/  NET_IPV6_FORWARDING = 1,
        NET_IPV6_HOP_LIMIT,
        NET_IPV6_MTU,
        NET_IPV6_ACCEPT_RA,
@@ -247,12 +264,12 @@ enum {
        NET_IPV6_DAD_TRANSMITS,
        NET_IPV6_RTR_SOLICITS,
        NET_IPV6_RTR_SOLICIT_INTERVAL,
-       NET_IPV6_RTR_SOLICIT_DELAY,
+/*10*/ NET_IPV6_RTR_SOLICIT_DELAY,
 };
 
 /* /proc/sys/net/<protocol>/neigh/<dev> */
 enum {
-       NET_NEIGH_MCAST_SOLICIT=1,
+/*1*/  NET_NEIGH_MCAST_SOLICIT=1,
        NET_NEIGH_UCAST_SOLICIT,
        NET_NEIGH_APP_SOLICIT,
        NET_NEIGH_RETRANS_TIME,
@@ -261,13 +278,13 @@ enum {
        NET_NEIGH_GC_STALE_TIME,
        NET_NEIGH_UNRES_QLEN,
        NET_NEIGH_PROXY_QLEN,
-       NET_NEIGH_ANYCAST_DELAY,
+/*10*/ NET_NEIGH_ANYCAST_DELAY,
        NET_NEIGH_PROXY_DELAY,
        NET_NEIGH_LOCKTIME,
        NET_NEIGH_GC_INTERVAL,
        NET_NEIGH_GC_THRESH1,
        NET_NEIGH_GC_THRESH2,
-       NET_NEIGH_GC_THRESH3
+/*16*/ NET_NEIGH_GC_THRESH3
 };
 
 /* /proc/sys/net/ipx */
@@ -275,16 +292,16 @@ enum {
 
 /* /proc/sys/net/appletalk */
 enum {
-       NET_ATALK_AARP_EXPIRY_TIME = 1,
+/*1*/  NET_ATALK_AARP_EXPIRY_TIME = 1,
        NET_ATALK_AARP_TICK_TIME,
        NET_ATALK_AARP_RETRANSMIT_LIMIT,
-       NET_ATALK_AARP_RESOLVE_TIME,
+/*4*/  NET_ATALK_AARP_RESOLVE_TIME,
 };
 
 
 /* /proc/sys/net/netrom */
 enum {
-       NET_NETROM_DEFAULT_PATH_QUALITY = 1,
+/*1*/  NET_NETROM_DEFAULT_PATH_QUALITY = 1,
        NET_NETROM_OBSOLESCENCE_COUNT_INITIALISER,
        NET_NETROM_NETWORK_TTL_INITIALISER,
        NET_NETROM_TRANSPORT_TIMEOUT,
@@ -293,13 +310,13 @@ enum {
        NET_NETROM_TRANSPORT_BUSY_DELAY,
        NET_NETROM_TRANSPORT_REQUESTED_WINDOW_SIZE,
        NET_NETROM_TRANSPORT_NO_ACTIVITY_TIMEOUT,
-       NET_NETROM_ROUTING_CONTROL,
-       NET_NETROM_LINK_FAILS_COUNT
+/*10*/ NET_NETROM_ROUTING_CONTROL,
+/*11*/ NET_NETROM_LINK_FAILS_COUNT
 };
 
 /* /proc/sys/net/ax25 */
 enum {
-       NET_AX25_IP_DEFAULT_MODE = 1,
+/*1*/  NET_AX25_IP_DEFAULT_MODE = 1,
        NET_AX25_DEFAULT_MODE,
        NET_AX25_BACKOFF_TYPE,
        NET_AX25_CONNECT_MODE,
@@ -308,50 +325,50 @@ enum {
        NET_AX25_T1_TIMEOUT,
        NET_AX25_T2_TIMEOUT,
        NET_AX25_T3_TIMEOUT,
-       NET_AX25_IDLE_TIMEOUT,
+/*10*/ NET_AX25_IDLE_TIMEOUT,
        NET_AX25_N2,
        NET_AX25_PACLEN,
        NET_AX25_PROTOCOL,
-       NET_AX25_DAMA_SLAVE_TIMEOUT
+/*14*/ NET_AX25_DAMA_SLAVE_TIMEOUT
 };
 
 /* /proc/sys/net/rose */
 enum {
-       NET_ROSE_RESTART_REQUEST_TIMEOUT = 1,
+/*1*/  NET_ROSE_RESTART_REQUEST_TIMEOUT = 1,
        NET_ROSE_CALL_REQUEST_TIMEOUT,
        NET_ROSE_RESET_REQUEST_TIMEOUT,
        NET_ROSE_CLEAR_REQUEST_TIMEOUT,
-       NET_ROSE_NO_ACTIVITY_TIMEOUT,
        NET_ROSE_ACK_HOLD_BACK_TIMEOUT,
        NET_ROSE_ROUTING_CONTROL,
        NET_ROSE_LINK_FAIL_TIMEOUT,
        NET_ROSE_MAX_VCS,
-       NET_ROSE_WINDOW_SIZE
+       NET_ROSE_WINDOW_SIZE,
+/*10*/ NET_ROSE_NO_ACTIVITY_TIMEOUT,
 };
 
 /* /proc/sys/net/x25 */
 enum {
-       NET_X25_RESTART_REQUEST_TIMEOUT = 1,
+/*1*/  NET_X25_RESTART_REQUEST_TIMEOUT = 1,
        NET_X25_CALL_REQUEST_TIMEOUT,
        NET_X25_RESET_REQUEST_TIMEOUT,
        NET_X25_CLEAR_REQUEST_TIMEOUT,
-       NET_X25_ACK_HOLD_BACK_TIMEOUT
+/*5*/  NET_X25_ACK_HOLD_BACK_TIMEOUT
 };
 
 /* /proc/sys/net/token-ring */
 enum
 {
-       NET_TR_RIF_TIMEOUT=1
+/*1*/  NET_TR_RIF_TIMEOUT=1
 };
 
 /* /proc/sys/net/decnet */
 enum {
-       NET_DECNET_DEF_T3_BROADCAST = 1,
+/*1*/  NET_DECNET_DEF_T3_BROADCAST = 1,
        NET_DECNET_DEF_T3_POINTTOPOINT,
        NET_DECNET_DEF_T1,
        NET_DECNET_DEF_BCT1,
        NET_DECNET_CACHETIMEOUT,
-       NET_DECNET_DEBUG_LEVEL
+/*6*/  NET_DECNET_DEBUG_LEVEL
 };
 
 /* CTL_PROC names: */
@@ -359,7 +376,7 @@ enum {
 /* CTL_FS names: */
 enum
 {
-       FS_NRINODE=1,           /* int: current number of allocated inodes */
+/*1*/  FS_NRINODE=1,           /* int: current number of allocated inodes */
        FS_STATINODE,
        FS_MAXINODE,            /* int: maximum number of inodes that can be allocated */
        FS_NRDQUOT,             /* int: current number of allocated dquots */
@@ -367,18 +384,21 @@ enum
        FS_NRFILE,              /* int: current number of allocated filedescriptors */
        FS_MAXFILE,             /* int: maximum number of filedescriptors that can be allocated */
        FS_DENTRY,
+       FS_NRSUPER,             /* int: current number of allocated super_blocks */
+/*10*/ FS_MAXSUPER,            /* int: maximum number of super_blocks that can be allocated */
 };
 
 /* CTL_DEBUG names: */
 
 /* CTL_DEV names: */
 enum {
-       DEV_CDROM = 1,
+/*1*/  DEV_CDROM = 1,
+/*2*/  DEV_HWMON,
 };
 
 /* /proc/sys/dev/cdrom */
 enum {
-       DEV_CDROM_INFO = 1,
+/*1*/  DEV_CDROM_INFO = 1,
 };
 
 #ifdef __KERNEL__
index 701fb88706595bc74a485bc9849a945f812087e1..11943bcd71263be358bb5cd2f60f173db4a8f73d 100644 (file)
@@ -47,6 +47,7 @@ extern void video_unregister_device(struct video_device *);
 #define VID_TYPE_FRAMERAM      64      /* Uses the frame buffer memory */
 #define VID_TYPE_SCALES                128     /* Scalable */
 #define VID_TYPE_MONOCHROME    256     /* Monochrome only */
+#define VID_TYPE_SUBCAPTURE    512     /* Can capture subareas of the image */
 
 struct video_capability
 {
@@ -72,6 +73,7 @@ struct video_channel
        __u16  type;
 #define VIDEO_TYPE_TV          1
 #define VIDEO_TYPE_CAMERA      2       
+       __u16 norm;                     /* Norm set by channel */
 };
 
 struct video_tuner
@@ -84,6 +86,7 @@ struct video_tuner
 #define VIDEO_TUNER_NTSC       2
 #define VIDEO_TUNER_SECAM      4
 #define VIDEO_TUNER_LOW                8       /* Uses KHz not MHz */
+#define VIDEO_TUNER_NORM       16      /* Tuner can set norm */
 #define VIDEO_TUNER_STEREO_ON  128     /* Tuner is seeing stereo */
        __u16 mode;                     /* PAL/NTSC/SECAM/OTHER */
 #define VIDEO_MODE_PAL         0
@@ -135,6 +138,8 @@ struct video_audio
 #define VIDEO_SOUND_LANG1      3
 #define VIDEO_SOUND_LANG2      4
         __u16   mode;
+        __u16  balance;        /* Stereo balance */
+        __u16  step;           /* Step actual volume uses */
 };
 
 struct video_clip
@@ -146,8 +151,8 @@ struct video_clip
 
 struct video_window
 {
-       __u32   x,y;
-       __u32   width,height;
+       __u32   x,y;                    /* Position of window */
+       __u32   width,height;           /* Its size */
        __u32   chromakey;
        __u32   flags;
        struct  video_clip *clips;      /* Set only */
@@ -155,6 +160,16 @@ struct video_window
 #define VIDEO_WINDOW_INTERLACE 1
 };
 
+struct video_capture
+{
+       __u32   x,y;                    /* Offsets into image */
+       __u32   width, height;          /* Area to capture */
+       __u16   decimation;             /* Decimation divder */
+       __u16   flags;                  /* Flags for capture */
+#define VIDEO_CAPTURE_ODD              0       /* Temporal */
+#define VIDEO_CAPTURE_EVEN             1
+};
+
 struct video_buffer
 {
        void    *base;
@@ -165,9 +180,9 @@ struct video_buffer
 
 struct video_mmap
 {
-       unsigned int frame;             /* Frame (0 or 1) for double buffer */
-       int height,width;
-       unsigned int format;    /* should be VIDEO_PALETTE_* */
+       unsigned        int frame;              /* Frame (0 - n) for double buffer */
+       int             height,width;
+       unsigned        int format;             /* should be VIDEO_PALETTE_* */
 };
 
 struct video_key
@@ -175,7 +190,30 @@ struct video_key
        __u8    key[8];
        __u32   flags;
 };
+
+
+#define VIDEO_MAX_FRAME                32
+
+struct video_mbuf
+{
+       int     size;           /* Total memory to map */
+       int     frames;         /* Frames */
+       int     offsets[VIDEO_MAX_FRAME];
+};
        
+
+#define        VIDEO_NO_UNIT   (-1)
+
+       
+struct video_unit
+{
+       int     video;          /* Video minor */
+       int     vbi;            /* VBI minor */
+       int     radio;          /* Radio minor */
+       int     audio;          /* Audio minor */
+       int     teletext;       /* Teletext minor */
+};
+
 #define VIDIOCGCAP             _IOR('v',1,struct video_capability)     /* Get capabilities */
 #define VIDIOCGCHAN            _IOWR('v',2,struct video_channel)       /* Get channel info (sources) */
 #define VIDIOCSCHAN            _IOW('v',3,int)                         /* Set channel  */
@@ -193,9 +231,12 @@ struct video_key
 #define VIDIOCSFREQ            _IOW('v',15, unsigned long)             /* Set tuner */
 #define VIDIOCGAUDIO           _IOR('v',16, struct video_audio)        /* Get audio info */
 #define VIDIOCSAUDIO           _IOW('v',17, struct video_audio)        /* Audio source, mute etc */
-#define VIDIOCSYNC             _IO('v',18)                             /* Sync with mmap grabbing */
+#define VIDIOCSYNC             _IOW('v',18, int)                       /* Sync with mmap grabbing */
 #define VIDIOCMCAPTURE         _IOW('v',19, struct video_mmap)         /* Grab frames */
-
+#define VIDIOCGMBUF            _IOR('v', 20, struct video_mbuf)        /* Memory map buffer info */
+#define VIDIOCGUNIT            _IOR('v', 21, struct video_unit)        /* Get attached units */
+#define VIDIOCGCAPTURE         _IOR('v',22, struct video_capture)      /* Get frame buffer */
+#define VIDIOCSCAPTURE         _IOW('v',23, struct video_capture)      /* Set frame buffer - root only */
 
 #define BASE_VIDIOCPRIVATE     192             /* 192-255 are private */
 
@@ -213,6 +254,8 @@ struct video_key
 #define VID_HARDWARE_SAA7146    11
 #define VID_HARDWARE_VIDEUM    12      /* Reserved for Winnov videum */
 #define VID_HARDWARE_RTRACK2   13
+#define VID_HARDWARE_PERMEDIA2 14      /* Reserved for Permedia2 */
+#define VID_HARDWARE_RIVA128   15      /* Reserved for RIVA 128 */
 
 /*
  *     Initialiser list
index 5a577abe382e0e0ad519f32af759de7251839a97..6035d7a5009aa308291a936f5125dbfefb1d317f 100644 (file)
@@ -356,8 +356,9 @@ static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk)
        return 0;
 }
 
-/* return value is only accurate by +-sizeof(long)*8 fds */ 
-/* XXX make this architecture specific */
+/*
+ * Copy a fd_set and compute the maximum fd it contains. 
+ */
 static inline int __copy_fdset(unsigned long *d, unsigned long *src)
 {
        int i; 
@@ -411,7 +412,6 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
                new_fds = (struct file **) kmalloc(size, GFP_KERNEL);
        if (!new_fds)
                goto out_release;
-       memset((void *) new_fds, 0, size);
 
        atomic_set(&newf->count, 1);
        newf->max_fds = NR_OPEN;
@@ -421,13 +421,15 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
 
        old_fds = oldf->fd;
        for (; i != 0; i--) {
-               struct file * f = *old_fds;
-               old_fds++;
+               struct file *f = *old_fds++;
                *new_fds = f;
                if (f)
                        f->f_count++;
                new_fds++;
        }
+       /* This is long word aligned thus could use a optimized version */ 
+       memset(new_fds, 0, (char *)newf->fd + size - (char *)new_fds); 
+      
        tsk->files = newf;
        error = 0;
 out:
@@ -639,20 +641,13 @@ bad_fork_free:
        goto bad_fork;
 }
 
-static void files_ctor(void *fp, kmem_cache_t *cachep, unsigned long flags)
-{
-       struct files_struct *f = fp;
-
-       memset(f, 0, sizeof(*f));
-}
-
 __initfunc(void filescache_init(void))
 {
        files_cachep = kmem_cache_create("files_cache", 
                                         sizeof(struct files_struct),
                                         0, 
                                         SLAB_HWCACHE_ALIGN,
-                                        files_ctor, NULL);
+                                        NULL, NULL);
        if (!files_cachep) 
                panic("Cannot create files cache"); 
 }
index 1b76fee500c8ace5c36332c867dd4f27660e1912..ace9d0f130f28a7f9125f6a90c7d61895254c7db 100644 (file)
@@ -1588,11 +1588,13 @@ asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp)
 static void show_task(int nr,struct task_struct * p)
 {
        unsigned long free = 0;
+       int state;
        static const char * stat_nam[] = { "R", "S", "D", "Z", "T", "W" };
 
        printk("%-8s %3d ", p->comm, (p == current) ? -nr : nr);
-       if (((unsigned) p->state) < sizeof(stat_nam)/sizeof(char *))
-               printk(stat_nam[p->state]);
+       state = p->state ? ffz(~p->state) + 1 : 0;
+       if (((unsigned) state) < sizeof(stat_nam)/sizeof(char *))
+               printk(stat_nam[state]);
        else
                printk(" ");
 #if (BITS_PER_LONG == 32)
index cfd87da4a796e657156765fed16f1514c6eab367..b1e0a642c51804128a821975ce88b9588041f184 100644 (file)
@@ -35,6 +35,9 @@
 
 static kmem_cache_t *signal_queue_cachep;
 
+static int nr_queued_signals;
+static int max_queued_signals = 1024;
+
 void
 signals_init(void)
 {
@@ -64,6 +67,7 @@ flush_signals(struct task_struct *t)
        while (q) {
                n = q->next;
                kmem_cache_free(signal_queue_cachep, q);
+               nr_queued_signals--;
                q = n;
        }
 }
@@ -160,7 +164,8 @@ printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid,
                                        current->sigqueue_tail = pp;
                                *info = q->info;
                                kmem_cache_free(signal_queue_cachep,q);
-
+                               nr_queued_signals--;
+                               
                                /* then see if this signal is still pending. */
                                q = *pp;
                                while (q) {
@@ -300,9 +305,14 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
                   make sure at least one signal gets delivered and don't
                   pass on the info struct.  */
 
-               struct signal_queue *q = (struct signal_queue *)
-                       kmem_cache_alloc(signal_queue_cachep, GFP_KERNEL);
+               struct signal_queue *q = 0;
 
+               if (nr_queued_signals < max_queued_signals) {
+                       q = (struct signal_queue *)
+                           kmem_cache_alloc(signal_queue_cachep, GFP_KERNEL);
+                       nr_queued_signals++;
+               }
+               
                if (q) {
                        q->next = NULL;
                        *t->sigqueue_tail = q;
@@ -825,6 +835,7 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)
                                        else {
                                                *pp = q->next;
                                                kmem_cache_free(signal_queue_cachep, q);
+                                               nr_queued_signals--;
                                        }
                                        q = *pp;
                                }
index 95db1657615e629077258e0f969a0ffb650f71b2..20798b239f41bf02f97d3d2eba6ae1f2cd84b2a6 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/fs.h>
 
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
@@ -228,6 +229,10 @@ static ctl_table fs_table[] = {
         0444, NULL, &proc_dointvec},
        {FS_MAXFILE, "file-max", &max_files, sizeof(int),
         0644, NULL, &proc_dointvec},
+       {FS_NRSUPER, "super-nr", &nr_super_blocks, sizeof(int),
+        0444, NULL, &proc_dointvec},
+       {FS_MAXSUPER, "super-max", &max_super_blocks, sizeof(int),
+        0644, NULL, &proc_dointvec},
        {FS_NRDQUOT, "dquot-nr", &nr_dquots, 2*sizeof(int),
         0444, NULL, &proc_dointvec},
        {FS_MAXDQUOT, "dquot-max", &max_dquots, sizeof(int),
index 1cdfb61d94e49e75df2556bafc303355115bedcd..cea727b964671c448c3d2e1e6c5c8681a2c266b0 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * This file handles the generic file mmap semantics used by
  * most "normal" filesystems (but you don't /have/ to use this:
- * the NFS filesystem does this differently, for example)
+ * the NFS filesystem used to do this differently, for example)
  */
 #include <linux/stat.h>
 #include <linux/sched.h>
@@ -172,12 +172,10 @@ static inline int shrink_one_page(struct page *page, int gfp_mask)
                                break;
                        }
                        age_page(page);
-#if 0
                        if (page->age)
                                break;
                        if (page_cache_size * 100 < (page_cache.min_percent * num_physpages))
                                break;
-#endif
                        if (PageSwapCache(page)) {
                                delete_from_swap_cache(page);
                                return 1;
@@ -213,8 +211,8 @@ int shrink_mmap(int priority, int gfp_mask)
        struct page * page;
        int count_max, count_min;
 
-       count_max = (limit<<1) >> (priority>>1);
-       count_min = (limit<<1) >> (priority);
+       count_max = (limit<<2) >> (priority>>1);
+       count_min = (limit<<2) >> (priority);
 
        page = mem_map + clock;
        do {
index 3cedb215c8b710eb2228d42d6387e8dc5106e883..7ddd801f86609cc8feb371e06556a8c6c4322e61 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -56,12 +56,15 @@ atomic_t nr_async_pages = ATOMIC_INIT(0);
  * Constants for the page aging mechanism: the maximum age (actually,
  * the maximum "youthfulness"); the quanta by which pages rejuvenate
  * and age; and the initial age for new pages. 
+ *
+ * The "pageout_weight" is strictly a fixedpoint number with the
+ * ten low bits being the fraction (ie 8192 really means "8.0").
  */
-
 swap_control_t swap_control = {
        20, 3, 1, 3,            /* Page aging */
        32, 4,                  /* Aging cluster */
-       8192, 8192,             /* Pageout and bufferout weights */
+       8192,                   /* sc_pageout_weight aka PAGEOUT_WEIGHT */
+       8192,                   /* sc_bufferout_weight aka BUFFEROUT_WEIGHT */
 };
 
 swapstat_t swapstats = {0};
@@ -69,11 +72,11 @@ swapstat_t swapstats = {0};
 buffer_mem_t buffer_mem = {
        5,      /* minimum percent buffer */
        25,     /* borrow percent buffer */
-       50      /* maximum percent buffer */
+       60      /* maximum percent buffer */
 };
 
 buffer_mem_t page_cache = {
-       10,     /* minimum percent page cache */
+       5,      /* minimum percent page cache */
        30,     /* borrow percent page cache */
        75      /* maximum */
 };
index eb52f7b4bf3d8ab2406df1cff3129ba89188f82c..a6c45008dc02d86dc459f9b805e32a7637421545 100644 (file)
@@ -85,7 +85,7 @@ int add_to_swap_cache(struct page *page, unsigned long entry)
 }
 
 /*
- * If swap_map[] reaches 127, the entries are treated as "permanent".
+ * If swap_map[] reaches SWAP_MAP_MAX the entries are treated as "permanent".
  */
 void swap_duplicate(unsigned long entry)
 {
@@ -105,14 +105,14 @@ void swap_duplicate(unsigned long entry)
                goto bad_offset;
        if (!p->swap_map[offset])
                goto bad_unused;
-       if (p->swap_map[offset] < 126)
+       if (p->swap_map[offset] < SWAP_MAP_MAX)
                p->swap_map[offset]++;
        else {
                static int overflow = 0;
                if (overflow++ < 5)
                        printk("swap_duplicate: entry %08lx map count=%d\n",
                                entry, p->swap_map[offset]);
-               p->swap_map[offset] = 127;
+               p->swap_map[offset] = SWAP_MAP_MAX;
        }
 #ifdef DEBUG_SWAP
        printk("DebugVM: swap_duplicate(entry %08lx, count now %d)\n",
index d33a334cb61aace186f2eddd894747bd936578e7..0df60f6f0c0bbcd08b166953595fe3cbd24bc192 100644 (file)
@@ -116,10 +116,7 @@ unsigned long get_swap_page(void)
        }
 }
 
-/*
- * If the swap count overflows (swap_map[] == 127), the entry is considered
- * "permanent" and can't be reclaimed until the swap device is closed.
- */
+
 void swap_free(unsigned long entry)
 {
        struct swap_info_struct * p;
@@ -147,7 +144,7 @@ void swap_free(unsigned long entry)
                p->highest_bit = offset;
        if (!p->swap_map[offset])
                goto bad_free;
-       if (p->swap_map[offset] < 127) {
+       if (p->swap_map[offset] < SWAP_MAP_MAX) {
                if (!--p->swap_map[offset])
                        nr_swap_pages++;
        }
@@ -309,7 +306,7 @@ static int try_to_unuse(unsigned int type)
                 * Find a swap page in use and read it in.
                 */
                for (i = 1 , entry = 0; i < si->max ; i++) {
-                       if (si->swap_map[i] > 0 && si->swap_map[i] != 0x80) {
+                       if (si->swap_map[i] > 0 && si->swap_map[i] != SWAP_MAP_BAD) {
                                entry = SWP_ENTRY(type, i);
                                break;
                        }
@@ -334,7 +331,7 @@ static int try_to_unuse(unsigned int type)
                        delete_from_swap_cache(page_map);
                free_page(page);
                if (si->swap_map[i] != 0) {
-                       if (si->swap_map[i] != 127)
+                       if (si->swap_map[i] != SWAP_MAP_MAX)
                                printk("try_to_unuse: entry %08lx "
                                       "not in use\n", entry);
                        si->swap_map[i] = 0;
@@ -425,7 +422,7 @@ asmlinkage int sys_swapoff(const char * specialfile)
        p->swap_device = 0;
        vfree(p->swap_map);
        p->swap_map = NULL;
-       free_page((long) p->swap_lockmap);
+       vfree(p->swap_lockmap);
        p->swap_lockmap = NULL;
        p->flags = 0;
        err = 0;
@@ -458,7 +455,7 @@ int get_swaparea_info(char *buf)
                        usedswap = 0;
                        for (j = 0; j < ptr->max; ++j)
                                switch (ptr->swap_map[j]) {
-                                       case 128:
+                                       case SWAP_MAP_BAD:
                                        case 0:
                                                continue;
                                        default:
@@ -486,7 +483,12 @@ asmlinkage int sys_swapon(const char * specialfile, int swap_flags)
        int error = -EPERM;
        struct file filp;
        static int least_priority = 0;
-
+       union swap_header *swap_header = 0;
+       int swap_header_version;
+       int lock_map_size = PAGE_SIZE;
+       int nr_good_pages = 0;
+       char tmp_lock_map = 0;
+       
        lock_kernel();
        if (!capable(CAP_SYS_ADMIN))
                goto out;
@@ -547,54 +549,114 @@ asmlinkage int sys_swapon(const char * specialfile, int swap_flags)
                }
        } else if (!S_ISREG(swap_dentry->d_inode->i_mode))
                goto bad_swap;
-       p->swap_lockmap = (unsigned char *) get_free_page(GFP_USER);
-       if (!p->swap_lockmap) {
+       swap_header = (void *) __get_free_page(GFP_USER);
+       if (!swap_header) {
                printk("Unable to start swapping: out of memory :-)\n");
                error = -ENOMEM;
                goto bad_swap;
        }
-       rw_swap_page_nocache(READ, SWP_ENTRY(type,0), (char *) p->swap_lockmap);
-       if (memcmp("SWAP-SPACE",p->swap_lockmap+PAGE_SIZE-10,10)) {
+
+       p->swap_lockmap = &tmp_lock_map;
+       rw_swap_page_nocache(READ, SWP_ENTRY(type,0), (char *) swap_header);
+       p->swap_lockmap = 0;
+
+       if (!memcmp("SWAP-SPACE",swap_header->magic.magic,10))
+               swap_header_version = 1;
+       else if (!memcmp("SWAPSPACE2",swap_header->magic.magic,10))
+               swap_header_version = 2;
+       else {
                printk("Unable to find swap-space signature\n");
                error = -EINVAL;
                goto bad_swap;
        }
-       memset(p->swap_lockmap+PAGE_SIZE-10,0,10);
-       j = 0;
-       p->lowest_bit = 0;
-       p->highest_bit = 0;
-       for (i = 1 ; i < 8*PAGE_SIZE ; i++) {
-               if (test_bit(i,p->swap_lockmap)) {
-                       if (!p->lowest_bit)
-                               p->lowest_bit = i;
-                       p->highest_bit = i;
-                       p->max = i+1;
-                       j++;
+       
+       switch (swap_header_version) {
+       case 1:
+               memset(((char *) swap_header)+PAGE_SIZE-10,0,10);
+               j = 0;
+               p->lowest_bit = 0;
+               p->highest_bit = 0;
+               for (i = 1 ; i < 8*PAGE_SIZE ; i++) {
+                       if (test_bit(i,(char *) swap_header)) {
+                               if (!p->lowest_bit)
+                                       p->lowest_bit = i;
+                               p->highest_bit = i;
+                               p->max = i+1;
+                               j++;
+                       }
+               }
+               nr_good_pages = j;
+               p->swap_map = vmalloc(p->max * sizeof(short));
+               if (!p->swap_map) {
+                       error = -ENOMEM;                
+                       goto bad_swap;
+               }
+               for (i = 1 ; i < p->max ; i++) {
+                       if (test_bit(i,(char *) swap_header))
+                               p->swap_map[i] = 0;
+                       else
+                               p->swap_map[i] = SWAP_MAP_BAD;
+               }
+               break;
+
+       case 2:
+               /* Check the swap header's sub-version and the size of
+                   the swap file and bad block lists */
+               if (swap_header->info.version != 1) {
+                       printk(KERN_WARNING
+                              "Unable to handle swap header version %d\n",
+                              swap_header->info.version);
+                       error = -EINVAL;
+                       goto bad_swap;
+               }
+
+               p->lowest_bit  = 1;
+               p->highest_bit = swap_header->info.last_page - 1;
+               p->max         = swap_header->info.last_page;
+
+               if (p->max >= 0x7fffffffL/PAGE_SIZE ||
+                   (void *) &swap_header->info.badpages[swap_header->info.nr_badpages-1] >= (void *) swap_header->magic.magic) {
+                       error = -EINVAL;
+                       goto bad_swap;
+               }
+               
+               /* OK, set up the swap map and apply the bad block list */
+               if (!(p->swap_map = vmalloc (p->max * sizeof(short)))) {
+                       error = -ENOMEM;
+                       goto bad_swap;
                }
+
+               error = 0;
+               memset(p->swap_map, 0, p->max * sizeof(short));
+               for (i=0; i<swap_header->info.nr_badpages; i++) {
+                       int page = swap_header->info.badpages[i];
+                       if (page <= 0 || page >= swap_header->info.last_page)
+                               error = -EINVAL;
+                       else
+                               p->swap_map[page] = SWAP_MAP_BAD;
+               }
+               nr_good_pages = swap_header->info.last_page - i;
+               lock_map_size = (p->max + 7) / 8;
+               if (error) 
+                       goto bad_swap;
        }
-       if (!j) {
-               printk("Empty swap-file\n");
+       
+       if (!nr_good_pages) {
+               printk(KERN_WARNING "Empty swap-file\n");
                error = -EINVAL;
                goto bad_swap;
        }
-       p->swap_map = (unsigned char *) vmalloc(p->max);
-       if (!p->swap_map) {
+       p->swap_map[0] = SWAP_MAP_BAD;
+       if (!(p->swap_lockmap = vmalloc (lock_map_size))) {
                error = -ENOMEM;
                goto bad_swap;
        }
-       for (i = 1 ; i < p->max ; i++) {
-               if (test_bit(i,p->swap_lockmap))
-                       p->swap_map[i] = 0;
-               else
-                       p->swap_map[i] = 0x80;
-       }
-       p->swap_map[0] = 0x80;
-       memset(p->swap_lockmap,0,PAGE_SIZE);
+       memset(p->swap_lockmap,0,lock_map_size);
        p->flags = SWP_WRITEOK;
-       p->pages = j;
-       nr_swap_pages += j;
+       p->pages = nr_good_pages;
+       nr_swap_pages += nr_good_pages;
        printk(KERN_INFO "Adding Swap: %dk swap-space (priority %d)\n",
-              j<<(PAGE_SHIFT-10), p->prio);
+              nr_good_pages<<(PAGE_SHIFT-10), p->prio);
 
        /* insert swap space into swap_list: */
        prev = -1;
@@ -616,8 +678,10 @@ bad_swap:
        if(filp.f_op && filp.f_op->release)
                filp.f_op->release(filp.f_dentry->d_inode,&filp);
 bad_swap_2:
-       free_page((long) p->swap_lockmap);
-       vfree(p->swap_map);
+       if (p->swap_lockmap)
+               vfree(p->swap_lockmap);
+       if (p->swap_map)
+               vfree(p->swap_map);
        dput(p->swap_file);
        p->swap_device = 0;
        p->swap_file = NULL;
@@ -625,6 +689,8 @@ bad_swap_2:
        p->swap_lockmap = NULL;
        p->flags = 0;
 out:
+       if (swap_header)
+               free_page((long) swap_header);
        unlock_kernel();
        return error;
 }
@@ -639,7 +705,7 @@ void si_swapinfo(struct sysinfo *val)
                        continue;
                for (j = 0; j < swap_info[i].max; ++j)
                        switch (swap_info[i].swap_map[j]) {
-                               case 128:
+                               case SWAP_MAP_BAD:
                                        continue;
                                case 0:
                                        ++val->freeswap;
index b586bce72f932eed447f3543246aae9878db9349..63faf546583f1278c545c67e7b8c951c512c6206 100644 (file)
@@ -529,6 +529,20 @@ int kswapd(void *unused)
                                    namings for POSIX.4 realtime scheduling
                                    priorities.  */
 
+       /*
+        * Tell the memory management that we're a "memory allocator",
+        * and that if we need more memory we should get access to it
+        * regardless (see "try_to_free_pages()"). "kswapd" should
+        * never get caught in the normal page freeing logic.
+        *
+        * (Kswapd normally doesn't need memory anyway, but sometimes
+        * you need a small amount of memory in order to be able to
+        * page out something else, and this flag essentially protects
+        * us from recursively trying to free more memory as we're
+        * trying to free the first piece of memory in the first place).
+        */
+       current->flags |= PF_MEMALLOC;
+
        init_swap_timer();
        add_wait_queue(&kswapd_wait, &wait);
        while (1) {
@@ -592,7 +606,7 @@ int try_to_free_pages(unsigned int gfp_mask, int count)
        int retval = 1;
 
        lock_kernel();
-       if (current->flags & PF_MEMALLOC) {
+       if (!(current->flags & PF_MEMALLOC)) {
                current->flags |= PF_MEMALLOC;
                do {
                        retval = do_try_to_free_page(gfp_mask);
@@ -600,7 +614,7 @@ int try_to_free_pages(unsigned int gfp_mask, int count)
                                break;
                        count--;
                } while (count > 0);
-               current->flags &= PF_MEMALLOC;
+               current->flags &= ~PF_MEMALLOC;
        }
        unlock_kernel();
        return retval;
index 316f6d799bfb2b473d90c6ddcddb0185db084f83..eafeefac135cb6a7d7cb1a85c5dc7d2f5b1a04be 100644 (file)
@@ -751,7 +751,7 @@ static inline void handle_bridge(struct sk_buff *skb, unsigned short type)
 
                if(br_receive_frame(skb))
                        return;
-               kfree_skb(skb, FREE_READ);
+               kfree_skb(skb);
        }
        return;
 }
index 6a26240587cfead11d9e1708b14c4963f428b996..1d905854d48d4108dbc35adaabefc93b58a94630 100644 (file)
@@ -105,7 +105,7 @@ static unsigned int sock_poll(struct file *file,
                              struct poll_table_struct *wait);
 static int sock_ioctl(struct inode *inode, struct file *file,
                      unsigned int cmd, unsigned long arg);
-static int sock_fasync(struct file *filp, int on);
+static int sock_fasync(int fd, struct file *filp, int on);
 
 
 /*
@@ -483,7 +483,7 @@ int sock_close(struct inode *inode, struct file *filp)
                printk(KERN_DEBUG "sock_close: NULL inode\n");
                return 0;
        }
-       sock_fasync(filp, 0);
+       sock_fasync(-1, filp, 0);
        sock_release(socki_lookup(inode));
        return 0;
 }
@@ -492,7 +492,7 @@ int sock_close(struct inode *inode, struct file *filp)
  *     Update the socket async list
  */
 
-static int sock_fasync(struct file *filp, int on)
+static int sock_fasync(int fd, struct file *filp, int on)
 {
        struct fasync_struct *fa, *fna=NULL, **prev;
        struct socket *sock;
@@ -520,11 +520,13 @@ static int sock_fasync(struct file *filp, int on)
        {
                if(fa!=NULL)
                {
+                       fa->fa_fd=fd;
                        kfree_s(fna,sizeof(struct fasync_struct));
                        restore_flags(flags);
                        return 0;
                }
                fna->fa_file=filp;
+               fna->fa_fd=fd;
                fna->magic=FASYNC_MAGIC;
                fna->fa_next=sock->fasync_list;
                sock->fasync_list=fna;
index b1a8150ec031ae7947f7c5cad2d819f954954c38..c2690684644be43ff5a3a806d9f18b1a5ee0a3a7 100644 (file)
@@ -191,22 +191,15 @@ rpc_default_callback(struct rpc_task *task)
 }
 
 /*
- * New rpc_call implementation
+ *     Export the signal mask handling for aysnchronous code that
+ *     sleeps on RPC calls
  */
-int
-rpc_do_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp,
-                               int flags, rpc_action func, void *data)
+void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset)
 {
-       struct rpc_task my_task, *task = &my_task;
        unsigned long   sigallow = sigmask(SIGKILL);
-       sigset_t        oldset;
        unsigned long   irqflags;
-       int             async, status;
-
-       /* If this client is slain all further I/O fails */
-       if (clnt->cl_dead) 
-               return -EIO;
-               
+       
        /* Turn off various signals */
        if (clnt->cl_intr) {
                struct k_sigaction *action = current->sig->action;
@@ -216,10 +209,38 @@ rpc_do_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp,
                        sigallow |= sigmask(SIGQUIT);
        }
        spin_lock_irqsave(&current->sigmask_lock, irqflags);
-       oldset = current->blocked;
-       siginitsetinv(&current->blocked, sigallow & ~oldset.sig[0]);
+       *oldset = current->blocked;
+       siginitsetinv(&current->blocked, sigallow & ~oldset->sig[0]);
        recalc_sigpending(current);
        spin_unlock_irqrestore(&current->sigmask_lock, irqflags);
+}
+
+void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset)
+{
+       unsigned long   irqflags;
+       
+       spin_lock_irqsave(&current->sigmask_lock, irqflags);
+       current->blocked = *oldset;
+       recalc_sigpending(current);
+       spin_unlock_irqrestore(&current->sigmask_lock, irqflags);
+}
+
+/*
+ * New rpc_call implementation
+ */
+int
+rpc_do_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp,
+                               int flags, rpc_action func, void *data)
+{
+       struct rpc_task my_task, *task = &my_task;
+       sigset_t        oldset;
+       int             async, status;
+
+       /* If this client is slain all further I/O fails */
+       if (clnt->cl_dead) 
+               return -EIO;
+
+       rpc_clnt_sigmask(clnt, &oldset);                
 
        /* Create/initialize a new RPC task */
        if ((async = (flags & RPC_TASK_ASYNC)) != 0) {
@@ -248,10 +269,7 @@ rpc_do_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp,
        }
 
 out:
-       spin_lock_irqsave(&current->sigmask_lock, irqflags);
-       current->blocked = oldset;
-       recalc_sigpending(current);
-       spin_unlock_irqrestore(&current->sigmask_lock, irqflags);
+       rpc_clnt_sigunmask(clnt, &oldset);              
 
        return status;
 }
index 8caaa46e820fb91f8c4eb83d72356fab580d3247..222f905da87fa8e06a8582d2eca946e940e8b086 100644 (file)
@@ -352,6 +352,7 @@ __rpc_atrun(struct rpc_task *task)
 /*
  * This is the RPC `scheduler' (or rather, the finite state machine).
  */
+
 static int
 __rpc_execute(struct rpc_task *task)
 {
@@ -415,10 +416,16 @@ __rpc_execute(struct rpc_task *task)
                                printk("RPC: rpciod waiting on sync task!\n");
                        current->timeout = 0;
                        sleep_on(&task->tk_wait);
-
+                       
                        /* When the task received a signal, remove from
-                        * any queues etc, and make runnable again. */
-                       if (0 && signalled())
+                        * any queues etc, and make runnable again.
+                        *
+                        * The "intr" property isnt handled here. rpc_do_call
+                        * has changed the signal mask of the process for
+                        * a synchronous rpc call. If a signal gets through
+                        * this then its real.
+                        */
+                       if (signalled())
                                __rpc_wake_up(task);
 
                        dprintk("RPC: %4d sync task resuming\n",
@@ -432,7 +439,7 @@ __rpc_execute(struct rpc_task *task)
                 * clean up after sleeping on some queue, we don't
                 * break the loop here, but go around once more.
                 */
-               if (0 && !RPC_IS_ASYNC(task) && signalled()) {
+               if (!RPC_IS_ASYNC(task) && signalled()) {
                        dprintk("RPC: %4d got signal\n", task->tk_pid);
                        rpc_exit(task, -ERESTARTSYS);
                }
index 6ccf2e29f57a38041d299c644578ba9ca875aec1..e0be9527cf9a2ff6ce47825130a83d00570782e2 100644 (file)
@@ -43,6 +43,8 @@ EXPORT_SYMBOL(rpc_shutdown_client);
 EXPORT_SYMBOL(rpc_killall_tasks);
 EXPORT_SYMBOL(rpc_do_call);
 EXPORT_SYMBOL(rpc_call_setup);
+EXPORT_SYMBOL(rpc_clnt_sigmask);
+EXPORT_SYMBOL(rpc_clnt_sigunmask);
 EXPORT_SYMBOL(rpc_delay);
 EXPORT_SYMBOL(rpc_restart_call);
 
index e2af81be4f9ebdb25f91ec59fb5b6840e9befa20..518703d070facef86f1d3b984fd2eed9eb3e0657 100644 (file)
@@ -34,6 +34,7 @@
  *  Copyright (C) 1995, 1996, Olaf Kirch <okir@monad.swb.de>
  *
  *  TCP callback races fixes (C) 1998 Red Hat Software <alan@redhat.com>
+ *  TCP send fixes (C) 1998 Red Hat Software <alan@redhat.com>
  */
 
 #define __KERNEL_SYSCALLS__
@@ -135,9 +136,50 @@ xprt_from_sock(struct sock *sk)
 #endif
 }
 
+/*
+ *     Adjust the iovec to move on 'n' bytes
+ */
+extern inline void xprt_move_iov(struct msghdr *msg, int amount)
+{
+       struct iovec niv[MAX_IOVEC];
+       struct iovec *iv=msg->msg_iov;
+       
+       /*
+        *      Eat any sent iovecs
+        */
+
+       while(iv->iov_len < amount)
+       {
+               amount-=iv->iov_len;
+               iv++;
+               msg->msg_iovlen--;
+       }
+       
+       msg->msg_iov=niv;
+       
+       /*
+        *      And chew down the partial one
+        */
+
+       niv[0].iov_len = iv->iov_len-amount;
+       niv[0].iov_base =((unsigned char *)iv->iov_base)+amount;
+       iv++;
+       
+       /*
+        *      And copy any others
+        */
+        
+       for(amount=1;amount<msg->msg_iovlen; amount++)
+       {
+               niv[amount]=*iv++;
+       }
+}
 /*
  * Write data to socket.
  */
+
 static inline int
 xprt_sendmsg(struct rpc_xprt *xprt)
 {
@@ -150,7 +192,6 @@ xprt_sendmsg(struct rpc_xprt *xprt)
                                xprt->snd_buf.io_vec->iov_base,
                                xprt->snd_buf.io_vec->iov_len);
 
-#if LINUX_VERSION_CODE >= 0x020100
        msg.msg_flags   = MSG_DONTWAIT;
        msg.msg_iov     = xprt->snd_buf.io_vec;
        msg.msg_iovlen  = xprt->snd_buf.io_nr;
@@ -158,27 +199,21 @@ xprt_sendmsg(struct rpc_xprt *xprt)
        msg.msg_namelen = sizeof(xprt->addr);
        msg.msg_control = NULL;
 
+       /* Dont repeat bytes */
+       
+       if(xprt->snd_sent)
+               xprt_move_iov(&msg, xprt->snd_sent);
+               
        oldfs = get_fs(); set_fs(get_ds());
        result = sock_sendmsg(sock, &msg, xprt->snd_buf.io_len);
        set_fs(oldfs);
-#else
-       msg.msg_flags   = 0;
-       msg.msg_iov     = xprt->snd_buf.io_vec;
-       msg.msg_iovlen  = xprt->snd_buf.io_nr;
-       msg.msg_name    = (struct sockaddr *) &xprt->addr;
-       msg.msg_namelen = sizeof(xprt->addr);
-       msg.msg_control = NULL;
-
-       oldfs = get_fs(); set_fs(get_ds());
-       result = sock->ops->sendmsg(sock, &msg, xprt->snd_buf.io_len, 1, 0);
-       set_fs(oldfs);
-#endif
 
        dprintk("RPC:      xprt_sendmsg(%d) = %d\n",
                                xprt->snd_buf.io_len, result);
 
        if (result >= 0) {
                xprt->snd_buf.io_len -= result;
+               xprt->snd_sent += result;
                return result;
        }
 
@@ -188,6 +223,8 @@ xprt_sendmsg(struct rpc_xprt *xprt)
                 * prompts ECONNREFUSED.
                 */
                break;
+       case -EAGAIN:
+               return 0;
        case -ENOTCONN: case -EPIPE:
                /* connection broken */
                break;
@@ -828,9 +865,19 @@ tcp_write_space(struct sock *sk)
 
        if (!(xprt = xprt_from_sock(sk)))
                return;
-       xprt->write_space = 1;
-       if (xprt->snd_task && !RPC_IS_RUNNING(xprt->snd_task))
-               rpc_wake_up_task(xprt->snd_task);
+       if(xprt->snd_sent && xprt->snd_task)
+               printk("write space\n");
+       if(xprt->write_space == 0)
+       {
+               xprt->write_space = 1;
+               if (xprt->snd_task && !RPC_IS_RUNNING(xprt->snd_task))
+               {
+                       if(xprt->snd_sent)
+                               printk("Write wakeup snd_sent =%d\n",
+                                       xprt->snd_sent);
+                       rpc_wake_up_task(xprt->snd_task);                       
+               }
+       }
 }
 
 /*
@@ -889,6 +936,8 @@ xprt_transmit(struct rpc_task *task)
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = req->rq_xprt;
 
+       /*DEBUG*/int ac_debug=xprt->snd_sent;
+       
        dprintk("RPC: %4d xprt_transmit(%x)\n", task->tk_pid, 
                                *(u32 *)(req->rq_svec[0].iov_base));
 
@@ -935,6 +984,8 @@ xprt_transmit(struct rpc_task *task)
                }
                xprt->snd_buf  = req->rq_snd_buf;
                xprt->snd_task = task;
+               xprt->snd_sent = 0;
+               /*DEBUG*/ac_debug = 0;
        }
 
        /* For fast networks/servers we have to put the request on
@@ -954,10 +1005,12 @@ xprt_transmit(struct rpc_task *task)
                if (xprt_transmit_some(xprt, task) != -EAGAIN) {
                        dprintk("RPC: %4d xmit complete\n", task->tk_pid);
                        xprt->snd_task = NULL;
+                       if(ac_debug)
+                               printk("Partial xmit finished\n");
                        return;
                }
 
-               dprintk("RPC: %4d xmit incomplete (%d left of %d)\n",
+               /*d*/printk("RPC: %4d xmit incomplete (%d left of %d)\n",
                                task->tk_pid, xprt->snd_buf.io_len,
                                req->rq_slen);
                task->tk_status = 0;
@@ -984,10 +1037,15 @@ xprt_transmit_status(struct rpc_task *task)
        struct rpc_xprt *xprt = task->tk_client->cl_xprt;
 
        dprintk("RPC: %4d transmit_status %d\n", task->tk_pid, task->tk_status);
-       if (xprt->snd_task == task) {
+       if (xprt->snd_task == task) 
+       {
                if (task->tk_status < 0)
+               {
                        xprt->snd_task = NULL;
-               xprt_disconnect(xprt);
+                       xprt_disconnect(xprt);
+               }
+               else
+                       xprt_transmit(task);
        }
 }