Updating upstream ioctl32 patch.
authorJeremy Huddleston <eradicator@gentoo.org>
Fri, 26 Nov 2004 20:23:51 +0000 (20:23 +0000)
committerJeremy Huddleston <eradicator@gentoo.org>
Fri, 26 Nov 2004 20:23:51 +0000 (20:23 +0000)
media-sound/alsa-driver/ChangeLog
media-sound/alsa-driver/files/alsa-driver-1.0.7-ioctl32.patch-r1

index 27beba5aa698af9ad60619ef3fbd3ec20c852170..1416e3d9885bbb11feb4f57f789a06f7a329d3b7 100644 (file)
@@ -1,6 +1,10 @@
 # ChangeLog for media-sound/alsa-driver
 # Copyright 2002-2004 Gentoo Foundation; Distributed under the GPL v2
-# $Header: /var/cvsroot/gentoo-x86/media-sound/alsa-driver/ChangeLog,v 1.109 2004/11/26 06:53:30 eradicator Exp $
+# $Header: /var/cvsroot/gentoo-x86/media-sound/alsa-driver/ChangeLog,v 1.110 2004/11/26 20:23:51 eradicator Exp $
+
+  26 Nov 2004; Jeremy Huddleston <eradicator@gentoo.org>
+  files/alsa-driver-1.0.7-ioctl32.patch-r1:
+  Updating upstream ioctl32 patch.
 
   25 Nov 2004; Jeremy Huddleston <eradicator@gentoo.org>
   +files/alsa-driver-1.0.7-audigy71.patch,
index 97a066faab04ee56ddf5c1478e098c930d001b88..c8fbb767e216897009372a3354479df4d9ff389f 100644 (file)
@@ -1,3 +1,176 @@
+Index: alsa-kernel/core/control.c
+===================================================================
+RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/control.c,v
+retrieving revision 1.42
+diff -u -r1.42 control.c
+--- alsa-kernel/core/control.c 16 Jul 2004 16:50:36 -0000      1.42
++++ alsa-kernel/core/control.c 26 Nov 2004 14:05:44 -0000
+@@ -635,19 +635,13 @@
+       return result;
+ }
+ 
+-static int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t __user *_control)
++int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *control)
+ {
+-      snd_ctl_elem_value_t *control;
+       snd_kcontrol_t *kctl;
+       snd_kcontrol_volatile_t *vd;
+       unsigned int index_offset;
+       int result, indirect;
+-      
+-      control = kmalloc(sizeof(*control), GFP_KERNEL);
+-      if (control == NULL)
+-              return -ENOMEM; 
+-      if (copy_from_user(control, _control, sizeof(*control)))
+-              return -EFAULT;
++
+       down_read(&card->controls_rwsem);
+       kctl = snd_ctl_find_id(card, &control->id);
+       if (kctl == NULL) {
+@@ -668,27 +662,37 @@
+               }
+       }
+       up_read(&card->controls_rwsem);
++      return result;
++}
++
++static int snd_ctl_elem_read_user(snd_card_t *card, snd_ctl_elem_value_t __user *_control)
++{
++      snd_ctl_elem_value_t *control;
++      int result;
++      
++      control = kmalloc(sizeof(*control), GFP_KERNEL);
++      if (control == NULL)
++              return -ENOMEM; 
++      if (copy_from_user(control, _control, sizeof(*control))) {
++              kfree(control);
++              return -EFAULT;
++      }
++      result = snd_ctl_elem_read(card, control);
+       if (result >= 0)
+               if (copy_to_user(_control, control, sizeof(*control)))
+-                      return -EFAULT;
++                      result = -EFAULT;
+       kfree(control);
+       return result;
+ }
+ 
+-static int snd_ctl_elem_write(snd_ctl_file_t *file, snd_ctl_elem_value_t __user *_control)
++int snd_ctl_elem_write(snd_ctl_file_t *file, snd_ctl_elem_value_t *control)
+ {
+       snd_card_t *card = file->card;
+-      snd_ctl_elem_value_t *control;
+       snd_kcontrol_t *kctl;
+       snd_kcontrol_volatile_t *vd;
+       unsigned int index_offset;
+       int result, indirect;
+ 
+-      control = kmalloc(sizeof(*control), GFP_KERNEL);
+-      if (control == NULL)
+-              return -ENOMEM; 
+-      if (copy_from_user(control, _control, sizeof(*control)))
+-              return -EFAULT;
+       down_read(&card->controls_rwsem);
+       kctl = snd_ctl_find_id(card, &control->id);
+       if (kctl == NULL) {
+@@ -711,16 +715,30 @@
+                       if (result > 0) {
+                               up_read(&card->controls_rwsem);
+                               snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &control->id);
+-                              result = 0;
+-                              goto __unlocked;
++                              return 0;
+                       }
+               }
+       }
+       up_read(&card->controls_rwsem);
+-      __unlocked:
++      return result;
++}
++
++static int snd_ctl_elem_write_user(snd_ctl_file_t *file, snd_ctl_elem_value_t __user *_control)
++{
++      snd_ctl_elem_value_t *control;
++      int result;
++
++      control = kmalloc(sizeof(*control), GFP_KERNEL);
++      if (control == NULL)
++              return -ENOMEM; 
++      if (copy_from_user(control, _control, sizeof(*control))) {
++              kfree(control);
++              return -EFAULT;
++      }
++      result = snd_ctl_elem_write(file, control);
+       if (result >= 0)
+               if (copy_to_user(_control, control, sizeof(*control)))
+-                      return -EFAULT;
++                      result = -EFAULT;
+       kfree(control);
+       return result;
+ }
+@@ -1045,9 +1063,9 @@
+       case SNDRV_CTL_IOCTL_ELEM_INFO:
+               return snd_ctl_elem_info(ctl, argp);
+       case SNDRV_CTL_IOCTL_ELEM_READ:
+-              return snd_ctl_elem_read(ctl->card, argp);
++              return snd_ctl_elem_read_user(ctl->card, argp);
+       case SNDRV_CTL_IOCTL_ELEM_WRITE:
+-              return snd_ctl_elem_write(ctl, argp);
++              return snd_ctl_elem_write_user(ctl, argp);
+       case SNDRV_CTL_IOCTL_ELEM_LOCK:
+               return snd_ctl_elem_lock(ctl, argp);
+       case SNDRV_CTL_IOCTL_ELEM_UNLOCK:
+Index: alsa-kernel/core/pcm_lib.c
+===================================================================
+RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/pcm_lib.c,v
+retrieving revision 1.57
+diff -u -r1.57 pcm_lib.c
+--- alsa-kernel/core/pcm_lib.c 24 Sep 2004 13:55:54 -0000      1.57
++++ alsa-kernel/core/pcm_lib.c 26 Nov 2004 13:42:21 -0000
+@@ -2660,6 +2660,7 @@
+ EXPORT_SYMBOL(snd_pcm_hw_param_near);
+ EXPORT_SYMBOL(snd_pcm_hw_param_set);
+ EXPORT_SYMBOL(snd_pcm_hw_refine);
++EXPORT_SYMBOL(snd_pcm_hw_params);
+ EXPORT_SYMBOL(snd_pcm_hw_constraints_init);
+ EXPORT_SYMBOL(snd_pcm_hw_constraints_complete);
+ EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
+Index: alsa-kernel/core/pcm_native.c
+===================================================================
+RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/pcm_native.c,v
+retrieving revision 1.85
+diff -u -r1.85 pcm_native.c
+--- alsa-kernel/core/pcm_native.c      16 Nov 2004 15:17:15 -0000      1.85
++++ alsa-kernel/core/pcm_native.c      26 Nov 2004 13:34:12 -0000
+@@ -329,8 +329,8 @@
+       return err;
+ }
+ 
+-static int snd_pcm_hw_params(snd_pcm_substream_t *substream,
+-                           snd_pcm_hw_params_t *params)
++int snd_pcm_hw_params(snd_pcm_substream_t *substream,
++                    snd_pcm_hw_params_t *params)
+ {
+       snd_pcm_runtime_t *runtime;
+       int err;
+Index: alsa-kernel/core/sound.c
+===================================================================
+RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/sound.c,v
+retrieving revision 1.62
+diff -u -r1.62 sound.c
+--- alsa-kernel/core/sound.c   8 Nov 2004 11:37:34 -0000       1.62
++++ alsa-kernel/core/sound.c   26 Nov 2004 14:06:50 -0000
+@@ -475,6 +475,10 @@
+ EXPORT_SYMBOL(snd_ctl_notify);
+ EXPORT_SYMBOL(snd_ctl_register_ioctl);
+ EXPORT_SYMBOL(snd_ctl_unregister_ioctl);
++#ifdef CONFIG_COMPAT
++EXPORT_SYMBOL(snd_ctl_elem_read);
++EXPORT_SYMBOL(snd_ctl_elem_write);
++#endif
+   /* misc.c */
+ EXPORT_SYMBOL(snd_task_name);
+ #ifdef CONFIG_SND_VERBOSE_PRINTK
 Index: alsa-kernel/core/ioctl32/hwdep32.c
 ===================================================================
 RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/ioctl32/hwdep32.c,v
@@ -52,7 +225,7 @@ RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/ioctl32/ioctl32.c,v
 retrieving revision 1.27
 diff -u -r1.27 ioctl32.c
 --- alsa-kernel/core/ioctl32/ioctl32.c 18 Oct 2004 14:31:33 -0000      1.27
-+++ alsa-kernel/core/ioctl32/ioctl32.c 24 Nov 2004 13:48:10 -0000
++++ alsa-kernel/core/ioctl32/ioctl32.c 26 Nov 2004 14:11:08 -0000
 @@ -30,6 +30,23 @@
  #include <asm/uaccess.h>
  #include "ioctl32.h"
@@ -105,7 +278,7 @@ diff -u -r1.27 ioctl32.c
 +      data = compat_alloc_user_space(sizeof(*data));
 +
 +      /* offset, space, used, count */
-+      if (copy_in_user(data, data32, 4 * 4))
++      if (copy_in_user(data, data32, 4 * sizeof(u32)))
                return -EFAULT;
 -      memset(&data, 0, sizeof(data));
 -      data.offset = data32.offset;
@@ -131,11 +304,11 @@ diff -u -r1.27 ioctl32.c
 -      data32.count = data.count;
 -      //data.pids = data.pids;
 -      if (copy_to_user((void __user *)arg, &data32, sizeof(data32)))
-+      if (copy_in_user(data32, data, 4 * 4))
++      if (copy_in_user(data32, data, 4 * sizeof(u32)))
                return -EFAULT;
        return 0;
  }
-@@ -170,54 +172,57 @@
+@@ -170,54 +172,59 @@
  
  static inline int _snd_ioctl32_ctl_elem_info(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
  {
@@ -165,7 +338,8 @@ diff -u -r1.27 ioctl32.c
 -      err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
 -      set_fs(oldseg);
 +      if (copy_in_user(&data->value.enumerated.item,
-+                       &data32->value.enumerated.item, 4))
++                       &data32->value.enumerated.item,
++                       sizeof(data->value.enumerated.item)))
 +              return -EFAULT;
 +      err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
        if (err < 0)
@@ -177,12 +351,13 @@ diff -u -r1.27 ioctl32.c
 -      data32.count = data.count;
 -      data32.owner = data.owner;
 -      switch (data.type) {
-+      /* id, type, access, count */
-+      if (copy_in_user(data32, data, 4 * 4))
-+              return -EFAULT;
 +      /* for COPY_CVT macro */
 +      src = data;
 +      dst = data32;
++      /* id, type, access, count */
++      if (copy_in_user(&data32->id, &data->id, sizeof(data->id)) ||
++          copy_in_user(&data32->type, &data->type, 3 * sizeof(u32)))
++              return -EFAULT;
 +      COPY_CVT(owner);
 +      __get_user(type, &data->type);
 +      switch (type) {
@@ -222,18 +397,50 @@ diff -u -r1.27 ioctl32.c
        return 0;
  }
  
-@@ -277,60 +282,85 @@
+@@ -250,24 +257,21 @@
+ 
+ 
+ /* hmm, it's so hard to retrieve the value type from the control id.. */
+-static int get_ctl_type(struct file *file, snd_ctl_elem_id_t *id)
++static int get_ctl_type(snd_card_t *card, snd_ctl_elem_id_t *id)
+ {
+-      snd_ctl_file_t *ctl;
+       snd_kcontrol_t *kctl;
+       snd_ctl_elem_info_t info;
+       int err;
+ 
+-      ctl = file->private_data;
+-
+-      down_read(&ctl->card->controls_rwsem);
+-      kctl = snd_ctl_find_id(ctl->card, id);
++      down_read(&card->controls_rwsem);
++      kctl = snd_ctl_find_id(card, id);
+       if (! kctl) {
+-              up_read(&ctl->card->controls_rwsem);
++              up_read(&card->controls_rwsem);
+               return -ENXIO;
+       }
+       info.id = *id;
+       err = kctl->info(kctl, &info);
+-      up_read(&ctl->card->controls_rwsem);
++      up_read(&card->controls_rwsem);
+       if (err >= 0)
+               err = info.type;
+       return err;
+@@ -277,101 +281,142 @@
  static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
  {
        struct sndrv_ctl_elem_value *data;
 -      struct sndrv_ctl_elem_value32 *data32;
 +      struct sndrv_ctl_elem_value32 __user *data32;
-+      mm_segment_t oldseg;
++      snd_ctl_file_t *ctl = ctl = file->private_data;
        int err, i;
        int type;
 -      mm_segment_t oldseg;
  
-       /* FIXME: check the sane ioctl.. */
+-      /* FIXME: check the sane ioctl.. */
++      if (ctl == NULL)
++              return -ENXIO;
  
 +      data32 = compat_ptr(arg);
        data = kmalloc(sizeof(*data), GFP_KERNEL);
@@ -243,7 +450,7 @@ diff -u -r1.27 ioctl32.c
 +      if (data == NULL)
 +              return -ENOMEM;
 +
-+      if (copy_from_user(&data->id, &data32->id, 4)) {
++      if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) {
 +              err = -EFAULT;
                goto __end;
        }
@@ -258,12 +465,13 @@ diff -u -r1.27 ioctl32.c
 -      data->indirect = data32->indirect;
 -      if (data->indirect) /* FIXME: this is not correct for long arrays */
 -              data->value.integer.value_ptr = compat_ptr(data32->value.integer.value_ptr);
+-      type = get_ctl_type(file, &data->id);
 +      /* FIXME: indirect access is not supported */
 +      if (data->indirect) {
 +              err = -EINVAL;
 +              goto __end;
 +      }
-       type = get_ctl_type(file, &data->id);
++      type = get_ctl_type(ctl->card, &data->id);
        if (type < 0) {
                err = type;
                goto __end;
@@ -320,7 +528,7 @@ diff -u -r1.27 ioctl32.c
 +                                   sizeof(data32->value.enumerated.item))) {
 +                      err = -EFAULT;
 +                      goto __end;
-               }
++              }
 +              break;
 +      case SNDRV_CTL_ELEM_TYPE_BYTES:
 +              if (__copy_from_user(data->value.bytes.data,
@@ -336,7 +544,7 @@ diff -u -r1.27 ioctl32.c
 +                                   sizeof(data32->value.iec958))) {
 +                      err = -EFAULT;
 +                      goto __end;
-+              }
+               }
 +              break;
 +      default:
 +              printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
@@ -344,8 +552,14 @@ diff -u -r1.27 ioctl32.c
 +              goto __end;
        }
  
-       oldseg = get_fs();
-@@ -340,38 +370,53 @@
+-      oldseg = get_fs();
+-      set_fs(KERNEL_DS);
+-      err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+-      set_fs(oldseg);
++      if (native_ctl == SNDRV_CTL_IOCTL_ELEM_READ)
++              err = snd_ctl_elem_read(ctl->card, data);
++      else
++              err = snd_ctl_elem_write(ctl, data);
        if (err < 0)
                goto __end;
        /* restore info to 32bit */
@@ -391,7 +605,7 @@ diff -u -r1.27 ioctl32.c
 +                                 sizeof(data32->value.integer64.value))) {
 +                      err = -EFAULT;
 +                      goto __end;
-               }
++              }
 +              break;
 +      case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
 +              if (__copy_to_user(data32->value.enumerated.item,
@@ -407,7 +621,7 @@ diff -u -r1.27 ioctl32.c
 +                                 sizeof(data32->value.bytes.data))) {
 +                      err = -EFAULT;
 +                      goto __end;
-+              }
+               }
 +              break;
 +      case SNDRV_CTL_ELEM_TYPE_IEC958:
 +              if (__copy_to_user(&data32->value.iec958,
@@ -433,7 +647,7 @@ RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/ioctl32/ioctl32.h,v
 retrieving revision 1.14
 diff -u -r1.14 ioctl32.h
 --- alsa-kernel/core/ioctl32/ioctl32.h 18 Oct 2004 14:31:33 -0000      1.14
-+++ alsa-kernel/core/ioctl32/ioctl32.h 24 Nov 2004 13:49:00 -0000
++++ alsa-kernel/core/ioctl32/ioctl32.h 25 Nov 2004 10:53:58 -0000
 @@ -28,20 +28,37 @@
  
  #include <linux/compat.h>
@@ -569,8 +783,8 @@ RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/ioctl32/pcm32.c,v
 retrieving revision 1.25
 diff -u -r1.25 pcm32.c
 --- alsa-kernel/core/ioctl32/pcm32.c   18 Oct 2004 14:36:00 -0000      1.25
-+++ alsa-kernel/core/ioctl32/pcm32.c   23 Nov 2004 14:15:56 -0000
-@@ -41,16 +41,13 @@
++++ alsa-kernel/core/ioctl32/pcm32.c   26 Nov 2004 13:47:57 -0000
+@@ -41,23 +41,15 @@
        u32 val;
  };
  
@@ -580,20 +794,31 @@ diff -u -r1.25 pcm32.c
 +#define CVT_sndrv_pcm_uframes_str() { COPY_CVT(val); }
  
  
- struct sndrv_interval32 {
-       u32 min, max;
+-struct sndrv_interval32 {
+-      u32 min, max;
 -      unsigned int openmin:1,
 -                   openmax:1,
 -                   integer:1,
 -                   empty:1;
-+      u32 flags; /* bit fields */
- };
- 
+-};
+-
  struct sndrv_pcm_hw_params32 {
-@@ -73,25 +70,9 @@
+       u32 flags;
+       struct sndrv_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */
+       struct sndrv_mask mres[5];      /* reserved masks */
+-      struct sndrv_interval32 intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
++      struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
+       struct sndrv_interval ires[9];  /* reserved intervals */
+       u32 rmask;
+       u32 cmask;
+@@ -69,31 +61,6 @@
+       unsigned char reserved[64];
+ } __attribute__((packed));
  
- #define CVT_sndrv_pcm_hw_params()\
- {\
+-#define numberof(array) ARRAY_SIZE(array)
+-
+-#define CVT_sndrv_pcm_hw_params()\
+-{\
 -      unsigned int i;\
 -      COPY(flags);\
 -      for (i = 0; i < numberof(dst->masks); i++)\
@@ -613,13 +838,12 @@ diff -u -r1.25 pcm32.c
 -      COPY(rate_num);\
 -      COPY(rate_den);\
 -      COPY(fifo_size);\
-+      if (copy_in_user(dst, src, sizeof(snd_pcm_hw_params_t) - sizeof(sndrv_pcm_uframes_t) - 64)) \
-+              return -EFAULT;\
-+      COPY_CVT(fifo_size);\
- }
- 
+-}
+-
  struct sndrv_pcm_sw_params32 {
-@@ -113,13 +94,13 @@
+       s32 tstamp_mode;
+       u32 period_step;
+@@ -113,13 +80,13 @@
        COPY(tstamp_mode);\
        COPY(period_step);\
        COPY(sleep_min);\
@@ -640,7 +864,7 @@ diff -u -r1.25 pcm32.c
  }
  
  struct sndrv_pcm_channel_info32 {
-@@ -132,7 +113,7 @@
+@@ -132,7 +99,7 @@
  #define CVT_sndrv_pcm_channel_info()\
  {\
        COPY(channel);\
@@ -649,7 +873,7 @@ diff -u -r1.25 pcm32.c
        COPY(first);\
        COPY(step);\
  }
-@@ -154,16 +135,16 @@
+@@ -154,16 +121,16 @@
  #define CVT_sndrv_pcm_status()\
  {\
        COPY(state);\
@@ -676,42 +900,87 @@ diff -u -r1.25 pcm32.c
        COPY(suspended_state);\
  }
  
-@@ -194,41 +175,19 @@
+@@ -173,61 +140,60 @@
+ DEFINE_ALSA_IOCTL(pcm_channel_info);
+ DEFINE_ALSA_IOCTL(pcm_status);
  
++int snd_pcm_hw_refine(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
++int snd_pcm_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
++
+ /* recalcuate the boundary within 32bit */
+-static void recalculate_boundary(struct file *file)
++static void recalculate_boundary(snd_pcm_runtime_t *runtime)
+ {
+-      snd_pcm_file_t *pcm_file;
+-      snd_pcm_substream_t *substream;
+-      snd_pcm_runtime_t *runtime;
+-
+-      /* FIXME: need to check whether fop->ioctl is sane */
+-      if (! (pcm_file = file->private_data))
+-              return;
+-      if (! (substream = pcm_file->substream))
+-              return;
+-      if (! (runtime = substream->runtime))
++      if (! runtime->buffer_size)
+               return;
+       runtime->boundary = runtime->buffer_size;
+       while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
+               runtime->boundary *= 2;
+ }
+ 
++/* both for HW_PARAMS and HW_REFINE */
  static inline int _snd_ioctl32_pcm_hw_params(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
  {
 -      struct sndrv_pcm_hw_params32 *data32;
--      struct sndrv_pcm_hw_params *data;
--      mm_segment_t oldseg;
 +      struct sndrv_pcm_hw_params32 __user *data32;
-+      struct sndrv_pcm_hw_params __user *data;
+       struct sndrv_pcm_hw_params *data;
+-      mm_segment_t oldseg;
++      snd_pcm_file_t *pcm_file;
++      snd_pcm_substream_t *substream;
++      snd_pcm_runtime_t *runtime;
        int err;
  
 -      data32 = kmalloc(sizeof(*data32), GFP_KERNEL);
--      data = kmalloc(sizeof(*data), GFP_KERNEL);
++      if (! (pcm_file = file->private_data))
++              return -ENXIO;
++      if (! (substream = pcm_file->substream))
++              return -ENXIO;
++      if (! (runtime = substream->runtime))
++              return -ENXIO;
++
++      data32 = compat_ptr(arg);
+       data = kmalloc(sizeof(*data), GFP_KERNEL);
 -      if (data32 == NULL || data == NULL) {
 -              err = -ENOMEM;
 -              goto __end;
 -      }
 -      if (copy_from_user(data32, (void __user *)arg, sizeof(*data32))) {
--              err = -EFAULT;
++      if (data == NULL)
++              return -ENOMEM;
++      if (copy_from_user(data, data32, sizeof(*data32))) {
+               err = -EFAULT;
 -              goto __end;
--      }
++              goto error;
+       }
 -      memset(data, 0, sizeof(*data));
-+      data32 = compat_ptr(arg);
-+      data = compat_alloc_user_space(sizeof(*data));
-       convert_from_32(pcm_hw_params, data, data32);
+-      convert_from_32(pcm_hw_params, data, data32);
 -      oldseg = get_fs();
 -      set_fs(KERNEL_DS);
-       err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+-      err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
 -      set_fs(oldseg);
++      if (native_ctl == SNDRV_PCM_IOCTL_HW_REFINE)
++              err = snd_pcm_hw_refine(substream, data);
++      else
++              err = snd_pcm_hw_params(substream, data);
        if (err < 0)
 -              goto __end;
 -      err = 0;
-+              return err;
-       convert_to_32(pcm_hw_params, data32, data);
+-      convert_to_32(pcm_hw_params, data32, data);
 -      if (copy_to_user((void __user *)arg, data32, sizeof(*data32)))
--              err = -EFAULT;
++              goto error;
++      if (copy_to_user(data32, data, sizeof(*data32)) ||
++          __put_user((u32)data->fifo_size, &data32->fifo_size)) {
+               err = -EFAULT;
 -      else
 -              recalculate_boundary(file);
 -      __end:
@@ -719,13 +988,17 @@ diff -u -r1.25 pcm32.c
 -                      kfree(data);
 -              if (data32)
 -                      kfree(data32);
--      return err;
-+      recalculate_boundary(file);
-+      return 0;
++              goto error;
++      }
++
++      if (native_ctl == SNDRV_PCM_IOCTL_HW_PARAMS)
++              recalculate_boundary(runtime);
++ error:
++      kfree(data);
+       return err;
  }
  
- 
-@@ -243,24 +202,24 @@
+@@ -243,24 +209,24 @@
  static inline int _snd_ioctl32_xferi(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
  {
        struct sndrv_xferi32 data32;
@@ -761,7 +1034,7 @@ diff -u -r1.25 pcm32.c
        if (copy_to_user((void __user *)arg, &data32, sizeof(data32)))
                return -EFAULT;
        return 0;
-@@ -284,12 +243,11 @@
+@@ -284,12 +250,11 @@
  {
        snd_pcm_file_t *pcm_file;
        snd_pcm_substream_t *substream;
@@ -776,7 +1049,7 @@ diff -u -r1.25 pcm32.c
  
        /* FIXME: need to check whether fop->ioctl is sane */
  
-@@ -312,22 +270,21 @@
+@@ -312,22 +277,21 @@
        }
        if ((ch = substream->runtime->channels) > 128)
                return -EINVAL;
@@ -804,7 +1077,7 @@ diff -u -r1.25 pcm32.c
        switch (native_ctl) {
        case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
                err = snd_pcm_lib_writev(substream, bufs, data32.frames);
-@@ -336,109 +293,15 @@
+@@ -336,109 +300,15 @@
                err = snd_pcm_lib_readv(substream, bufs, data32.frames);
                break;
        }
@@ -915,7 +1188,7 @@ diff -u -r1.25 pcm32.c
  struct sndrv_pcm_mmap_status32 {
        s32 state;
        s32 pad1;
-@@ -469,15 +332,15 @@
+@@ -469,15 +339,15 @@
        COPY(flags);\
        COPY(s.status.state);\
        COPY(s.status.pad1);\
@@ -937,7 +1210,7 @@ diff -u -r1.25 pcm32.c
  
  /*
   */
-@@ -485,8 +348,6 @@
+@@ -485,8 +355,6 @@
  DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_refine, pcm_hw_params, SNDRV_PCM_IOCTL_HW_REFINE);
  DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_params, pcm_hw_params, SNDRV_PCM_IOCTL_HW_PARAMS);
  DEFINE_ALSA_IOCTL_ENTRY(pcm_sw_params, pcm_sw_params, SNDRV_PCM_IOCTL_SW_PARAMS);
@@ -946,7 +1219,7 @@ diff -u -r1.25 pcm32.c
  DEFINE_ALSA_IOCTL_ENTRY(pcm_status, pcm_status, SNDRV_PCM_IOCTL_STATUS);
  DEFINE_ALSA_IOCTL_ENTRY(pcm_delay, pcm_sframes_str, SNDRV_PCM_IOCTL_DELAY);
  DEFINE_ALSA_IOCTL_ENTRY(pcm_channel_info, pcm_channel_info, SNDRV_PCM_IOCTL_CHANNEL_INFO);
-@@ -538,8 +399,6 @@
+@@ -538,8 +406,6 @@
        SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct sndrv_xferi32),
        SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct sndrv_xfern32),
        SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct sndrv_xfern32),
@@ -955,7 +1228,7 @@ diff -u -r1.25 pcm32.c
        SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr32),
  
  };
-@@ -551,8 +410,6 @@
+@@ -551,8 +417,6 @@
        MAP_COMPAT(SNDRV_PCM_IOCTL_TSTAMP),
        { SNDRV_PCM_IOCTL_HW_REFINE32, AP(pcm_hw_refine) },
        { SNDRV_PCM_IOCTL_HW_PARAMS32, AP(pcm_hw_params) },
@@ -1064,3 +1337,36 @@ diff -u -r1.8 timer32.c
        COPY(resolution);\
        COPY(lost);\
        COPY(overrun);\
+Index: alsa-kernel/include/control.h
+===================================================================
+RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/include/control.h,v
+retrieving revision 1.9
+diff -u -r1.9 control.h
+--- alsa-kernel/include/control.h      29 Jun 2004 16:01:15 -0000      1.9
++++ alsa-kernel/include/control.h      26 Nov 2004 14:06:21 -0000
+@@ -122,6 +122,10 @@
+ int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
+ int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn);
+ 
++/* for ioctl32 */
++int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *control);
++int snd_ctl_elem_write(snd_ctl_file_t *file, snd_ctl_elem_value_t *control);
++
+ static inline unsigned int snd_ctl_get_ioffnum(snd_kcontrol_t *kctl, snd_ctl_elem_id_t *id)
+ {
+       return id->numid - kctl->id.numid;
+Index: alsa-kernel/include/pcm.h
+===================================================================
+RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/include/pcm.h,v
+retrieving revision 1.51
+diff -u -r1.51 pcm.h
+--- alsa-kernel/include/pcm.h  8 Nov 2004 11:39:35 -0000       1.51
++++ alsa-kernel/include/pcm.h  26 Nov 2004 13:41:20 -0000
+@@ -810,6 +810,7 @@
+ int snd_pcm_hw_params_choose(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
+ 
+ int snd_pcm_hw_refine(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
++int snd_pcm_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
+ 
+ int snd_pcm_hw_constraints_init(snd_pcm_substream_t *substream);
+ int snd_pcm_hw_constraints_complete(snd_pcm_substream_t *substream);