Commit ece8df79 authored by Jaroslav Kysela's avatar Jaroslav Kysela

Merge suse.cz:/home/perex/bk/linux-sound/linux-2.5

into suse.cz:/home/perex/bk/linux-sound/linux-sound
parents 771a7305 72815e1f
VIA82xx mixer
=============
On many VIA82xx boards, the 'Input Source Select' mixer control does not work.
Setting it to 'Input2' on such boards will cause recording to hang, or fail
with EIO (input/output error) via OSS emulation. This control should be left
at 'Input1' for such cards.
This diff is collapsed.
...@@ -23,12 +23,12 @@ send the F5 NN command sequence at all; perhaps it ought to. ...@@ -23,12 +23,12 @@ send the F5 NN command sequence at all; perhaps it ought to.
Usage example for simple serial converter: Usage example for simple serial converter:
/sbin/setserial /dev/ttyS0 none /sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 speed=115200 /sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 speed=115200
Usage example for Roland SoundCanvas with 4 MIDI ports: Usage example for Roland SoundCanvas with 4 MIDI ports:
/sbin/setserial /dev/ttyS0 none /sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 outs=4 /sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 outs=4
In MS-124T mode, one raw MIDI substream is supported (midiCnD0); the outs In MS-124T mode, one raw MIDI substream is supported (midiCnD0); the outs
...@@ -38,7 +38,7 @@ parameter to match (A=19200, B=9600). ...@@ -38,7 +38,7 @@ parameter to match (A=19200, B=9600).
Usage example for MS-124T, with A-B switch in A position: Usage example for MS-124T, with A-B switch in A position:
/sbin/setserial /dev/ttyS0 none /sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=1 \ /sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=1 \
speed=19200 speed=19200
...@@ -48,7 +48,7 @@ the same data to all four MIDI Out connectors at full MIDI speed. ...@@ -48,7 +48,7 @@ the same data to all four MIDI Out connectors at full MIDI speed.
Usage example for S/A mode: Usage example for S/A mode:
/sbin/setserial /dev/ttyS0 none /sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=2 /sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=2
In MS-124W M/B mode, the driver supports 16 ALSA raw MIDI substreams; In MS-124W M/B mode, the driver supports 16 ALSA raw MIDI substreams;
...@@ -64,7 +64,7 @@ one byte every 320 us per port. ...@@ -64,7 +64,7 @@ one byte every 320 us per port.
Usage example for M/B mode: Usage example for M/B mode:
/sbin/setserial /dev/ttyS0 none /sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=3 /sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=3
The MS-124W hardware's M/A mode is currently not supported. This mode allows The MS-124W hardware's M/A mode is currently not supported. This mode allows
......
This diff is collapsed.
...@@ -106,7 +106,7 @@ ...@@ -106,7 +106,7 @@
#define AK4117_DIF_24L (AK4117_DIF2) /* STDO: 24-bit, left justified */ #define AK4117_DIF_24L (AK4117_DIF2) /* STDO: 24-bit, left justified */
#define AK4117_DIF_24I2S (AK4117_DIF2|AK4117_DIF0) /* STDO: I2S */ #define AK4117_DIF_24I2S (AK4117_DIF2|AK4117_DIF0) /* STDO: I2S */
/* AK4117_REG_INT0_MASK & AK4117_INT1_MASK */ /* AK4117_REG_INT0_MASK & AK4117_REG_INT1_MASK */
#define AK4117_MULK (1<<7) /* mask enable for UNLOCK bit */ #define AK4117_MULK (1<<7) /* mask enable for UNLOCK bit */
#define AK4117_MPAR (1<<6) /* mask enable for PAR bit */ #define AK4117_MPAR (1<<6) /* mask enable for PAR bit */
#define AK4117_MAUTO (1<<5) /* mask enable for AUTO bit */ #define AK4117_MAUTO (1<<5) /* mask enable for AUTO bit */
...@@ -181,8 +181,8 @@ struct ak4117 { ...@@ -181,8 +181,8 @@ struct ak4117 {
int snd_ak4117_create(snd_card_t *card, ak4117_read_t *read, ak4117_write_t *write, int snd_ak4117_create(snd_card_t *card, ak4117_read_t *read, ak4117_write_t *write,
unsigned char pgm[5], void *private_data, ak4117_t **r_ak4117); unsigned char pgm[5], void *private_data, ak4117_t **r_ak4117);
void snd_ak4117_reg_write(ak4117_t *chip, unsigned char reg, unsigned char mask, unsigned char val); void snd_ak4117_reg_write(ak4117_t *ak4117, unsigned char reg, unsigned char mask, unsigned char val);
void snd_ak4117_reinit(ak4117_t *chip); void snd_ak4117_reinit(ak4117_t *ak4117);
int snd_ak4117_build(ak4117_t *ak4117, snd_pcm_substream_t *capture_substream); int snd_ak4117_build(ak4117_t *ak4117, snd_pcm_substream_t *capture_substream);
int snd_ak4117_external_rate(ak4117_t *ak4117); int snd_ak4117_external_rate(ak4117_t *ak4117);
int snd_ak4117_check_rate_and_errors(ak4117_t *ak4117, unsigned int flags); int snd_ak4117_check_rate_and_errors(ak4117_t *ak4117, unsigned int flags);
......
...@@ -50,7 +50,8 @@ struct snd_akm4xxx { ...@@ -50,7 +50,8 @@ struct snd_akm4xxx {
/* template should fill the following fields */ /* template should fill the following fields */
unsigned int idx_offset; /* control index offset */ unsigned int idx_offset; /* control index offset */
enum { enum {
SND_AK4524, SND_AK4528, SND_AK4529, SND_AK4355, SND_AK4381 SND_AK4524, SND_AK4528, SND_AK4529,
SND_AK4355, SND_AK4358, SND_AK4381
} type; } type;
struct snd_ak4xxx_ops ops; struct snd_ak4xxx_ops ops;
}; };
......
...@@ -119,6 +119,13 @@ int snd_ctl_create(snd_card_t *card); ...@@ -119,6 +119,13 @@ int snd_ctl_create(snd_card_t *card);
int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn); int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn); int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn);
#ifdef CONFIG_COMPAT
int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn);
int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn);
#else
#define snd_ctl_register_ioctl_compat(fcn)
#define snd_ctl_unregister_ioctl_compat(fcn)
#endif
int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *control); int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *control);
int snd_ctl_elem_write(snd_card_t *card, snd_ctl_file_t *file, snd_ctl_elem_value_t *control); int snd_ctl_elem_write(snd_card_t *card, snd_ctl_file_t *file, snd_ctl_elem_value_t *control);
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <asm/semaphore.h> /* struct semaphore */ #include <asm/semaphore.h> /* struct semaphore */
#include <linux/rwsem.h> /* struct rw_semaphore */ #include <linux/rwsem.h> /* struct rw_semaphore */
#include <linux/workqueue.h> /* struct workqueue_struct */ #include <linux/workqueue.h> /* struct workqueue_struct */
#include <linux/pm.h> /* pm_message_t */
/* Typedef's */ /* Typedef's */
typedef struct timespec snd_timestamp_t; typedef struct timespec snd_timestamp_t;
...@@ -167,13 +168,15 @@ struct _snd_card { ...@@ -167,13 +168,15 @@ struct _snd_card {
struct device *dev; struct device *dev;
#ifdef CONFIG_PM #ifdef CONFIG_PM
int (*pm_suspend)(snd_card_t *card, unsigned int state); int (*pm_suspend)(snd_card_t *card, pm_message_t state);
int (*pm_resume)(snd_card_t *card, unsigned int state); int (*pm_resume)(snd_card_t *card);
struct pm_dev *pm_dev; /* for ISA */
void *pm_private_data; void *pm_private_data;
unsigned int power_state; /* power state */ unsigned int power_state; /* power state */
struct semaphore power_lock; /* power lock */ struct semaphore power_lock; /* power lock */
wait_queue_head_t power_sleep; wait_queue_head_t power_sleep;
#ifdef CONFIG_SND_GENERIC_PM
struct snd_generic_device *pm_dev; /* for ISA */
#endif
#endif #endif
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
...@@ -206,36 +209,34 @@ static inline void snd_power_change_state(snd_card_t *card, unsigned int state) ...@@ -206,36 +209,34 @@ static inline void snd_power_change_state(snd_card_t *card, unsigned int state)
wake_up(&card->power_sleep); wake_up(&card->power_sleep);
} }
int snd_card_set_pm_callback(snd_card_t *card, int snd_card_set_pm_callback(snd_card_t *card,
int (*suspend)(snd_card_t *, unsigned int), int (*suspend)(snd_card_t *, pm_message_t),
int (*resume)(snd_card_t *, unsigned int), int (*resume)(snd_card_t *),
void *private_data); void *private_data);
int snd_card_set_dev_pm_callback(snd_card_t *card, int type, int snd_card_set_generic_pm_callback(snd_card_t *card,
int (*suspend)(snd_card_t *, unsigned int), int (*suspend)(snd_card_t *, pm_message_t),
int (*resume)(snd_card_t *, unsigned int), int (*resume)(snd_card_t *),
void *private_data); void *private_data);
#define snd_card_set_isa_pm_callback(card,suspend,resume,data) \ #define snd_card_set_isa_pm_callback(card,suspend,resume,data) \
snd_card_set_dev_pm_callback(card, PM_ISA_DEV, suspend, resume, data) snd_card_set_generic_pm_callback(card, suspend, resume, data)
#ifdef CONFIG_PCI struct pci_dev;
#ifndef SND_PCI_PM_CALLBACKS int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state);
int snd_card_pci_suspend(struct pci_dev *dev, u32 state);
int snd_card_pci_resume(struct pci_dev *dev); int snd_card_pci_resume(struct pci_dev *dev);
#define SND_PCI_PM_CALLBACKS \ #define SND_PCI_PM_CALLBACKS \
.suspend = snd_card_pci_suspend, .resume = snd_card_pci_resume .suspend = snd_card_pci_suspend, .resume = snd_card_pci_resume
#endif
#endif #else /* ! CONFIG_PM */
#else
#define snd_power_lock(card) do { (void)(card); } while (0) #define snd_power_lock(card) do { (void)(card); } while (0)
#define snd_power_unlock(card) do { (void)(card); } while (0) #define snd_power_unlock(card) do { (void)(card); } while (0)
static inline int snd_power_wait(snd_card_t *card, unsigned int state, struct file *file) { return 0; } static inline int snd_power_wait(snd_card_t *card, unsigned int state, struct file *file) { return 0; }
#define snd_power_get_state(card) SNDRV_CTL_POWER_D0 #define snd_power_get_state(card) SNDRV_CTL_POWER_D0
#define snd_power_change_state(card, state) do { (void)(card); } while (0) #define snd_power_change_state(card, state) do { (void)(card); } while (0)
#define snd_card_set_pm_callback(card,suspend,resume,data) #define snd_card_set_pm_callback(card,suspend,resume,data)
#define snd_card_set_dev_pm_callback(card,suspend,resume,data) #define snd_card_set_generic_pm_callback(card,suspend,resume,data)
#define snd_card_set_isa_pm_callback(card,suspend,resume,data) #define snd_card_set_isa_pm_callback(card,suspend,resume,data)
#ifdef CONFIG_PCI
#define SND_PCI_PM_CALLBACKS #define SND_PCI_PM_CALLBACKS
#endif
#endif #endif /* CONFIG_PM */
/* device.c */ /* device.c */
......
This diff is collapsed.
...@@ -230,7 +230,7 @@ typedef struct { ...@@ -230,7 +230,7 @@ typedef struct {
int mode; /* operation mode */ int mode; /* operation mode */
int client; /* sequencer client number */ int client; /* sequencer client number */
int port; /* sequencer port number */ int port; /* sequencer port number */
int midi_has_voices: 1; unsigned int midi_has_voices: 1;
} snd_gus_port_t; } snd_gus_port_t;
typedef struct _snd_gus_voice snd_gus_voice_t; typedef struct _snd_gus_voice snd_gus_voice_t;
...@@ -264,7 +264,7 @@ typedef enum { ...@@ -264,7 +264,7 @@ typedef enum {
struct _snd_gus_voice { struct _snd_gus_voice {
int number; int number;
int use: 1, unsigned int use: 1,
pcm: 1, pcm: 1,
synth:1, synth:1,
midi: 1; midi: 1;
......
...@@ -38,6 +38,7 @@ typedef struct _snd_hwdep_ops { ...@@ -38,6 +38,7 @@ typedef struct _snd_hwdep_ops {
int (*release) (snd_hwdep_t * hw, struct file * file); int (*release) (snd_hwdep_t * hw, struct file * file);
unsigned int (*poll) (snd_hwdep_t * hw, struct file * file, poll_table * wait); unsigned int (*poll) (snd_hwdep_t * hw, struct file * file, poll_table * wait);
int (*ioctl) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg); int (*ioctl) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg);
int (*ioctl_compat) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg);
int (*mmap) (snd_hwdep_t * hw, struct file * file, struct vm_area_struct * vma); int (*mmap) (snd_hwdep_t * hw, struct file * file, struct vm_area_struct * vma);
int (*dsp_status) (snd_hwdep_t * hw, snd_hwdep_dsp_status_t * status); int (*dsp_status) (snd_hwdep_t * hw, snd_hwdep_dsp_status_t * status);
int (*dsp_load) (snd_hwdep_t * hw, snd_hwdep_dsp_image_t * image); int (*dsp_load) (snd_hwdep_t * hw, snd_hwdep_dsp_image_t * image);
......
...@@ -38,7 +38,7 @@ typedef int (*snd_mixer_oss_put_recsrce_t)(snd_mixer_oss_file_t *fmixer, unsigne ...@@ -38,7 +38,7 @@ typedef int (*snd_mixer_oss_put_recsrce_t)(snd_mixer_oss_file_t *fmixer, unsigne
struct _snd_oss_mixer_slot { struct _snd_oss_mixer_slot {
int number; int number;
int stereo: 1; unsigned int stereo: 1;
snd_mixer_oss_get_volume_t get_volume; snd_mixer_oss_get_volume_t get_volume;
snd_mixer_oss_put_volume_t put_volume; snd_mixer_oss_put_volume_t put_volume;
snd_mixer_oss_get_recsrc_t get_recsrc; snd_mixer_oss_get_recsrc_t get_recsrc;
......
...@@ -86,9 +86,6 @@ struct _snd_mpu401 { ...@@ -86,9 +86,6 @@ struct _snd_mpu401 {
spinlock_t output_lock; spinlock_t output_lock;
spinlock_t timer_lock; spinlock_t timer_lock;
atomic_t rx_loop;
atomic_t tx_loop;
struct timer_list timer; struct timer_list timer;
void (*write) (mpu401_t * mpu, unsigned char data, unsigned long addr); void (*write) (mpu401_t * mpu, unsigned char data, unsigned long addr);
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
*/ */
#include <sound/asound.h> #include <sound/asound.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
...@@ -65,8 +66,7 @@ typedef struct _snd_rawmidi_global_ops { ...@@ -65,8 +66,7 @@ typedef struct _snd_rawmidi_global_ops {
} snd_rawmidi_global_ops_t; } snd_rawmidi_global_ops_t;
struct _snd_rawmidi_runtime { struct _snd_rawmidi_runtime {
unsigned int trigger: 1, /* transfer is running */ unsigned int drain: 1, /* drain stage */
drain: 1, /* drain stage */
oss: 1; /* OSS compatible mode */ oss: 1; /* OSS compatible mode */
/* midi stream buffer */ /* midi stream buffer */
unsigned char *buffer; /* buffer for MIDI data */ unsigned char *buffer; /* buffer for MIDI data */
...@@ -80,6 +80,7 @@ struct _snd_rawmidi_runtime { ...@@ -80,6 +80,7 @@ struct _snd_rawmidi_runtime {
spinlock_t lock; spinlock_t lock;
wait_queue_head_t sleep; wait_queue_head_t sleep;
/* event handler (room [output] or new bytes [input]) */ /* event handler (room [output] or new bytes [input]) */
struct tasklet_struct event_tasklet;
void (*event)(snd_rawmidi_substream_t *substream); void (*event)(snd_rawmidi_substream_t *substream);
/* private data */ /* private data */
void *private_data; void *private_data;
......
...@@ -38,7 +38,7 @@ typedef struct _snd_virmidi { ...@@ -38,7 +38,7 @@ typedef struct _snd_virmidi {
int seq_mode; int seq_mode;
int client; int client;
int port; int port;
int trigger: 1; unsigned int trigger: 1;
snd_midi_event_t *parser; snd_midi_event_t *parser;
snd_seq_event_t event; snd_seq_event_t event;
snd_virmidi_dev_t *rdev; snd_virmidi_dev_t *rdev;
......
...@@ -290,7 +290,7 @@ typedef struct { ...@@ -290,7 +290,7 @@ typedef struct {
int mode; /* operation mode */ int mode; /* operation mode */
int client; /* sequencer client number */ int client; /* sequencer client number */
int port; /* sequencer port number */ int port; /* sequencer port number */
int midi_has_voices: 1; unsigned int midi_has_voices: 1;
} snd_trident_port_t; } snd_trident_port_t;
typedef struct snd_trident_memblk_arg { typedef struct snd_trident_memblk_arg {
...@@ -308,7 +308,7 @@ typedef struct { ...@@ -308,7 +308,7 @@ typedef struct {
struct _snd_trident_voice { struct _snd_trident_voice {
unsigned int number; unsigned int number;
int use: 1, unsigned int use: 1,
pcm: 1, pcm: 1,
synth:1, synth:1,
midi: 1; midi: 1;
...@@ -347,7 +347,7 @@ struct _snd_trident_voice { ...@@ -347,7 +347,7 @@ struct _snd_trident_voice {
trident_t *trident; trident_t *trident;
snd_pcm_substream_t *substream; snd_pcm_substream_t *substream;
snd_trident_voice_t *extra; /* extra PCM voice (acts as interrupt generator) */ snd_trident_voice_t *extra; /* extra PCM voice (acts as interrupt generator) */
int running: 1, unsigned int running: 1,
capture: 1, capture: 1,
spdif: 1, spdif: 1,
foldback: 1, foldback: 1,
......
...@@ -266,7 +266,7 @@ typedef enum { ...@@ -266,7 +266,7 @@ typedef enum {
struct _snd_ymfpci_voice { struct _snd_ymfpci_voice {
ymfpci_t *chip; ymfpci_t *chip;
int number; int number;
int use: 1, unsigned int use: 1,
pcm: 1, pcm: 1,
synth: 1, synth: 1,
midi: 1; midi: 1;
...@@ -292,9 +292,9 @@ struct _snd_ymfpci_pcm { ...@@ -292,9 +292,9 @@ struct _snd_ymfpci_pcm {
snd_ymfpci_pcm_type_t type; snd_ymfpci_pcm_type_t type;
snd_pcm_substream_t *substream; snd_pcm_substream_t *substream;
ymfpci_voice_t *voices[2]; /* playback only */ ymfpci_voice_t *voices[2]; /* playback only */
int running: 1; unsigned int running: 1;
int output_front: 1; unsigned int output_front: 1;
int output_rear: 1; unsigned int output_rear: 1;
u32 period_size; /* cached from runtime->period_size */ u32 period_size; /* cached from runtime->period_size */
u32 buffer_size; /* cached from runtime->buffer_size */ u32 buffer_size; /* cached from runtime->buffer_size */
u32 period_pos; u32 period_pos;
......
#ifndef __SOUND_YSS225_H
#define __SOUND_YSS225_H
extern unsigned char page_zero[256];
extern unsigned char page_one[256];
extern unsigned char page_two[128];
extern unsigned char page_three[128];
extern unsigned char page_four[128];
extern unsigned char page_six[192];
extern unsigned char page_seven[256];
extern unsigned char page_zero_v2[96];
extern unsigned char page_one_v2[96];
extern unsigned char page_two_v2[48];
extern unsigned char page_three_v2[48];
extern unsigned char page_four_v2[48];
extern unsigned char page_seven_v2[96];
extern unsigned char mod_v2[304];
extern unsigned char coefficients[364];
extern unsigned char coefficients2[56];
extern unsigned char coefficients3[404];
#endif /* __SOUND_YSS225_H */
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
* merged HAL layer (patches from Brian) * merged HAL layer (patches from Brian)
*/ */
/* $Id: sa11xx-uda1341.c,v 1.19 2004/12/15 15:26:10 tiwai Exp $ */ /* $Id: sa11xx-uda1341.c,v 1.21 2005/01/28 19:34:04 tiwai Exp $ */
/*************************************************************************************************** /***************************************************************************************************
* *
...@@ -862,7 +862,7 @@ static int __init snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341_t *sa11xx_uda1341, ...@@ -862,7 +862,7 @@ static int __init snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341_t *sa11xx_uda1341,
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int snd_sa11xx_uda1341_suspend(snd_card_t *card, unsigned int state) static int snd_sa11xx_uda1341_suspend(snd_card_t *card, pm_message_t state)
{ {
sa11xx_uda1341_t *chip = card->pm_private_data; sa11xx_uda1341_t *chip = card->pm_private_data;
...@@ -878,7 +878,7 @@ static int snd_sa11xx_uda1341_suspend(snd_card_t *card, unsigned int state) ...@@ -878,7 +878,7 @@ static int snd_sa11xx_uda1341_suspend(snd_card_t *card, unsigned int state)
return 0; return 0;
} }
static int snd_sa11xx_uda1341_resume(snd_card_t *card, unsigned int state) static int snd_sa11xx_uda1341_resume(snd_card_t *card)
{ {
sa11xx_uda1341_t *chip = card->pm_private_data; sa11xx_uda1341_t *chip = card->pm_private_data;
...@@ -938,7 +938,7 @@ static int __init sa11xx_uda1341_init(void) ...@@ -938,7 +938,7 @@ static int __init sa11xx_uda1341_init(void)
if ((err = snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341, 0)) < 0) if ((err = snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341, 0)) < 0)
goto nodev; goto nodev;
snd_card_set_dev_pm_callback(card, PM_SYS_DEV, snd_card_set_generic_pm_callback(card,
snd_sa11xx_uda1341_suspend, snd_sa11_uda1341_resume, snd_sa11xx_uda1341_suspend, snd_sa11_uda1341_resume,
sa11xx_uda1341); sa11xx_uda1341);
......
# ALSA soundcard-configuration # ALSA soundcard-configuration
config SND_TIMER config SND_TIMER
tristate tristate
depends on SND
config SND_PCM config SND_PCM
tristate tristate
select SND_TIMER select SND_TIMER
depends on SND
config SND_HWDEP config SND_HWDEP
tristate tristate
depends on SND
config SND_RAWMIDI config SND_RAWMIDI
tristate tristate
depends on SND
config SND_SEQUENCER config SND_SEQUENCER
tristate "Sequencer support" tristate "Sequencer support"
...@@ -40,6 +44,7 @@ config SND_SEQ_DUMMY ...@@ -40,6 +44,7 @@ config SND_SEQ_DUMMY
config SND_OSSEMUL config SND_OSSEMUL
bool bool
depends on SND
config SND_MIXER_OSS config SND_MIXER_OSS
tristate "OSS Mixer API" tristate "OSS Mixer API"
...@@ -70,7 +75,7 @@ config SND_PCM_OSS ...@@ -70,7 +75,7 @@ config SND_PCM_OSS
config SND_SEQUENCER_OSS config SND_SEQUENCER_OSS
bool "OSS Sequencer API" bool "OSS Sequencer API"
depends on SND_SEQUENCER depends on SND && SND_SEQUENCER
select SND_OSSEMUL select SND_OSSEMUL
help help
Say Y here to enable OSS sequencer emulation (both Say Y here to enable OSS sequencer emulation (both
...@@ -81,20 +86,6 @@ config SND_SEQUENCER_OSS ...@@ -81,20 +86,6 @@ config SND_SEQUENCER_OSS
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called snd-seq-oss. will be called snd-seq-oss.
config SND_BIT32_EMUL
tristate "Emulation for 32-bit applications"
depends on SND && COMPAT
select SND_PCM
select SND_RAWMIDI
select SND_TIMER
select SND_HWDEP
help
Say Y here to enable the emulation for 32-bit ALSA-native
applications.
To compile this driver as a module, choose M here: the module
will be called snd-ioctl32.
config SND_RTCTIMER config SND_RTCTIMER
tristate "RTC Timer support" tristate "RTC Timer support"
depends on SND && RTC depends on SND && RTC
...@@ -137,3 +128,6 @@ config SND_DEBUG_DETECT ...@@ -137,3 +128,6 @@ config SND_DEBUG_DETECT
Say Y here to enable extra-verbose log messages printed when Say Y here to enable extra-verbose log messages printed when
detecting devices. detecting devices.
config SND_GENERIC_PM
bool
depends on SND
...@@ -31,4 +31,3 @@ obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o ...@@ -31,4 +31,3 @@ obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o
obj-$(CONFIG_SND_OSSEMUL) += oss/ obj-$(CONFIG_SND_OSSEMUL) += oss/
obj-$(CONFIG_SND_SEQUENCER) += seq/ obj-$(CONFIG_SND_SEQUENCER) += seq/
obj-$(CONFIG_SND_BIT32_EMUL) += ioctl32/
This diff is collapsed.
...@@ -232,8 +232,7 @@ static int snd_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t __user *_in ...@@ -232,8 +232,7 @@ static int snd_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t __user *_in
return 0; return 0;
} }
static inline int _snd_hwdep_ioctl(struct inode *inode, struct file * file, static long snd_hwdep_ioctl(struct file * file, unsigned int cmd, unsigned long arg)
unsigned int cmd, unsigned long arg)
{ {
snd_hwdep_t *hw = file->private_data; snd_hwdep_t *hw = file->private_data;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
...@@ -252,17 +251,6 @@ static inline int _snd_hwdep_ioctl(struct inode *inode, struct file * file, ...@@ -252,17 +251,6 @@ static inline int _snd_hwdep_ioctl(struct inode *inode, struct file * file,
return -ENOTTY; return -ENOTTY;
} }
/* FIXME: need to unlock BKL to allow preemption */
static int snd_hwdep_ioctl(struct inode *inode, struct file * file,
unsigned int cmd, unsigned long arg)
{
int err;
unlock_kernel();
err = _snd_hwdep_ioctl(inode, file, cmd, arg);
lock_kernel();
return err;
}
static int snd_hwdep_mmap(struct file * file, struct vm_area_struct * vma) static int snd_hwdep_mmap(struct file * file, struct vm_area_struct * vma)
{ {
snd_hwdep_t *hw = file->private_data; snd_hwdep_t *hw = file->private_data;
...@@ -315,6 +303,12 @@ static int snd_hwdep_control_ioctl(snd_card_t * card, snd_ctl_file_t * control, ...@@ -315,6 +303,12 @@ static int snd_hwdep_control_ioctl(snd_card_t * card, snd_ctl_file_t * control,
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
#ifdef CONFIG_COMPAT
#include "hwdep_compat.c"
#else
#define snd_hwdep_ioctl_compat NULL
#endif
/* /*
*/ */
...@@ -328,7 +322,8 @@ static struct file_operations snd_hwdep_f_ops = ...@@ -328,7 +322,8 @@ static struct file_operations snd_hwdep_f_ops =
.open = snd_hwdep_open, .open = snd_hwdep_open,
.release = snd_hwdep_release, .release = snd_hwdep_release,
.poll = snd_hwdep_poll, .poll = snd_hwdep_poll,
.ioctl = snd_hwdep_ioctl, .unlocked_ioctl = snd_hwdep_ioctl,
.compat_ioctl = snd_hwdep_ioctl_compat,
.mmap = snd_hwdep_mmap, .mmap = snd_hwdep_mmap,
}; };
...@@ -509,12 +504,14 @@ static int __init alsa_hwdep_init(void) ...@@ -509,12 +504,14 @@ static int __init alsa_hwdep_init(void)
} }
snd_hwdep_proc_entry = entry; snd_hwdep_proc_entry = entry;
snd_ctl_register_ioctl(snd_hwdep_control_ioctl); snd_ctl_register_ioctl(snd_hwdep_control_ioctl);
snd_ctl_register_ioctl_compat(snd_hwdep_control_ioctl);
return 0; return 0;
} }
static void __exit alsa_hwdep_exit(void) static void __exit alsa_hwdep_exit(void)
{ {
snd_ctl_unregister_ioctl(snd_hwdep_control_ioctl); snd_ctl_unregister_ioctl(snd_hwdep_control_ioctl);
snd_ctl_unregister_ioctl_compat(snd_hwdep_control_ioctl);
if (snd_hwdep_proc_entry) { if (snd_hwdep_proc_entry) {
snd_info_unregister(snd_hwdep_proc_entry); snd_info_unregister(snd_hwdep_proc_entry);
snd_hwdep_proc_entry = NULL; snd_hwdep_proc_entry = NULL;
......
...@@ -18,13 +18,9 @@ ...@@ -18,13 +18,9 @@
* *
*/ */
#include <sound/driver.h> /* This file is included from hwdep.c */
#include <linux/time.h>
#include <linux/fs.h> #include <linux/compat.h>
#include <sound/core.h>
#include <sound/hwdep.h>
#include <asm/uaccess.h>
#include "ioctl32.h"
struct sndrv_hwdep_dsp_image32 { struct sndrv_hwdep_dsp_image32 {
u32 index; u32 index;
...@@ -34,40 +30,48 @@ struct sndrv_hwdep_dsp_image32 { ...@@ -34,40 +30,48 @@ struct sndrv_hwdep_dsp_image32 {
u32 driver_data; u32 driver_data;
} /* don't set packed attribute here */; } /* don't set packed attribute here */;
static inline int _snd_ioctl32_hwdep_dsp_image(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl) static int snd_hwdep_dsp_load_compat(snd_hwdep_t *hw,
struct sndrv_hwdep_dsp_image32 __user *src)
{ {
struct sndrv_hwdep_dsp_image __user *data, *dst; struct sndrv_hwdep_dsp_image *dst;
struct sndrv_hwdep_dsp_image32 __user *data32, *src;
compat_caddr_t ptr; compat_caddr_t ptr;
u32 val;
data32 = compat_ptr(arg); dst = compat_alloc_user_space(sizeof(*dst));
data = compat_alloc_user_space(sizeof(*data));
/* index and name */ /* index and name */
if (copy_in_user(data, data32, 4 + 64)) if (copy_in_user(dst, src, 4 + 64))
return -EFAULT; return -EFAULT;
if (__get_user(ptr, &data32->image) || if (get_user(ptr, &src->image) ||
__put_user(compat_ptr(ptr), &data->image)) put_user(compat_ptr(ptr), &dst->image))
return -EFAULT;
if (get_user(val, &src->length) ||
put_user(val, &dst->length))
return -EFAULT;
if (get_user(val, &src->driver_data) ||
put_user(val, &dst->driver_data))
return -EFAULT; return -EFAULT;
src = data32;
dst = data;
COPY_CVT(length);
COPY_CVT(driver_data);
return file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
}
DEFINE_ALSA_IOCTL_ENTRY(hwdep_dsp_image, hwdep_dsp_image, SNDRV_HWDEP_IOCTL_DSP_LOAD);
#define AP(x) snd_ioctl32_##x return snd_hwdep_dsp_load(hw, dst);
}
enum { enum {
SNDRV_HWDEP_IOCTL_DSP_LOAD32 = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image32) SNDRV_HWDEP_IOCTL_DSP_LOAD32 = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image32)
}; };
struct ioctl32_mapper hwdep_mappers[] = { static long snd_hwdep_ioctl_compat(struct file * file, unsigned int cmd, unsigned long arg)
MAP_COMPAT(SNDRV_HWDEP_IOCTL_PVERSION), {
MAP_COMPAT(SNDRV_HWDEP_IOCTL_INFO), snd_hwdep_t *hw = file->private_data;
MAP_COMPAT(SNDRV_HWDEP_IOCTL_DSP_STATUS), void __user *argp = compat_ptr(arg);
{ SNDRV_HWDEP_IOCTL_DSP_LOAD32, AP(hwdep_dsp_image) }, switch (cmd) {
{ 0 }, case SNDRV_HWDEP_IOCTL_PVERSION:
}; case SNDRV_HWDEP_IOCTL_INFO:
case SNDRV_HWDEP_IOCTL_DSP_STATUS:
return snd_hwdep_ioctl(file, cmd, (unsigned long)argp);
case SNDRV_HWDEP_IOCTL_DSP_LOAD32:
return snd_hwdep_dsp_load_compat(hw, argp);
}
if (hw->ops.ioctl_compat)
return hw->ops.ioctl_compat(hw, file, cmd, arg);
return -ENOIOCTLCMD;
}
...@@ -39,7 +39,7 @@ struct snd_shutdown_f_ops { ...@@ -39,7 +39,7 @@ struct snd_shutdown_f_ops {
unsigned int snd_cards_lock = 0; /* locked for registering/using */ unsigned int snd_cards_lock = 0; /* locked for registering/using */
snd_card_t *snd_cards[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = NULL}; snd_card_t *snd_cards[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = NULL};
rwlock_t snd_card_rwlock = RW_LOCK_UNLOCKED; DEFINE_RWLOCK(snd_card_rwlock);
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
int (*snd_mixer_oss_notify_callback)(snd_card_t *card, int free_flag); int (*snd_mixer_oss_notify_callback)(snd_card_t *card, int free_flag);
...@@ -84,16 +84,13 @@ snd_card_t *snd_card_new(int idx, const char *xid, ...@@ -84,16 +84,13 @@ snd_card_t *snd_card_new(int idx, const char *xid,
write_lock(&snd_card_rwlock); write_lock(&snd_card_rwlock);
if (idx < 0) { if (idx < 0) {
int idx2; int idx2;
for (idx2 = 0; idx2 < snd_ecards_limit; idx2++) for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
if (!(snd_cards_lock & (1 << idx2))) { if (~snd_cards_lock & idx & 1<<idx2) {
idx = idx2; idx = idx2;
if (idx >= snd_ecards_limit)
snd_ecards_limit = idx + 1;
break; break;
} }
if (idx < 0 && snd_ecards_limit < SNDRV_CARDS)
/* for dynamically additional devices like hotplug:
* increment the limit if still free slot exists.
*/
idx = snd_ecards_limit++;
} else if (idx < snd_ecards_limit) { } else if (idx < snd_ecards_limit) {
if (snd_cards_lock & (1 << idx)) if (snd_cards_lock & (1 << idx))
err = -ENODEV; /* invalid */ err = -ENODEV; /* invalid */
...@@ -229,6 +226,10 @@ int snd_card_disconnect(snd_card_t * card) ...@@ -229,6 +226,10 @@ int snd_card_disconnect(snd_card_t * card)
return 0; return 0;
} }
#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM)
static void snd_generic_device_unregister(struct snd_generic_device *dev);
#endif
/** /**
* snd_card_free - frees given soundcard structure * snd_card_free - frees given soundcard structure
* @card: soundcard structure * @card: soundcard structure
...@@ -252,9 +253,9 @@ int snd_card_free(snd_card_t * card) ...@@ -252,9 +253,9 @@ int snd_card_free(snd_card_t * card)
#ifdef CONFIG_PM #ifdef CONFIG_PM
wake_up(&card->power_sleep); wake_up(&card->power_sleep);
#ifdef CONFIG_ISA #ifdef CONFIG_SND_GENERIC_PM
if (card->pm_dev) { if (card->pm_dev) {
pm_unregister(card->pm_dev); snd_generic_device_unregister(card->pm_dev);
card->pm_dev = NULL; card->pm_dev = NULL;
} }
#endif #endif
...@@ -374,7 +375,7 @@ static void choose_default_id(snd_card_t * card) ...@@ -374,7 +375,7 @@ static void choose_default_id(snd_card_t * card)
while (1) { while (1) {
if (loops-- == 0) { if (loops-- == 0) {
snd_printk(KERN_ERR "unable to choose default card id (%s)", id); snd_printk(KERN_ERR "unable to choose default card id (%s)\n", id);
strcpy(card->id, card->proc_root->name); strcpy(card->id, card->proc_root->name);
return; return;
} }
...@@ -719,8 +720,8 @@ int snd_power_wait(snd_card_t *card, unsigned int power_state, struct file *file ...@@ -719,8 +720,8 @@ int snd_power_wait(snd_card_t *card, unsigned int power_state, struct file *file
* handler and from the control API. * handler and from the control API.
*/ */
int snd_card_set_pm_callback(snd_card_t *card, int snd_card_set_pm_callback(snd_card_t *card,
int (*suspend)(snd_card_t *, unsigned int), int (*suspend)(snd_card_t *, pm_message_t),
int (*resume)(snd_card_t *, unsigned int), int (*resume)(snd_card_t *),
void *private_data) void *private_data)
{ {
card->pm_suspend = suspend; card->pm_suspend = suspend;
...@@ -729,56 +730,132 @@ int snd_card_set_pm_callback(snd_card_t *card, ...@@ -729,56 +730,132 @@ int snd_card_set_pm_callback(snd_card_t *card,
return 0; return 0;
} }
static int snd_generic_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) #ifdef CONFIG_SND_GENERIC_PM
/*
* use platform_device for generic power-management without a proper bus
* (e.g. ISA)
*/
struct snd_generic_device {
struct platform_device pdev;
snd_card_t *card;
};
#define get_snd_generic_card(dev) container_of(to_platform_device(dev), struct snd_generic_device, pdev)->card
#define SND_GENERIC_NAME "snd_generic_pm"
static int snd_generic_suspend(struct device *dev, u32 state, u32 level);
static int snd_generic_resume(struct device *dev, u32 level);
static struct device_driver snd_generic_driver = {
.name = SND_GENERIC_NAME,
.bus = &platform_bus_type,
.suspend = snd_generic_suspend,
.resume = snd_generic_resume,
};
static int generic_driver_registered;
static void generic_driver_unregister(void)
{
if (generic_driver_registered) {
generic_driver_registered--;
if (! generic_driver_registered)
driver_unregister(&snd_generic_driver);
}
}
static struct snd_generic_device *snd_generic_device_register(snd_card_t *card)
{ {
snd_card_t *card = dev->data; struct snd_generic_device *dev;
switch (rqst) { if (! generic_driver_registered) {
case PM_SUSPEND: if (driver_register(&snd_generic_driver) < 0)
return NULL;
}
generic_driver_registered++;
dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
if (! dev) {
generic_driver_unregister();
return NULL;
}
dev->pdev.name = SND_GENERIC_NAME;
dev->pdev.id = card->number;
dev->card = card;
if (platform_device_register(&dev->pdev) < 0) {
kfree(dev);
generic_driver_unregister();
return NULL;
}
return dev;
}
static void snd_generic_device_unregister(struct snd_generic_device *dev)
{
platform_device_unregister(&dev->pdev);
kfree(dev);
generic_driver_unregister();
}
/* suspend/resume callbacks for snd_generic platform device */
static int snd_generic_suspend(struct device *dev, u32 state, u32 level)
{
snd_card_t *card;
if (level != SUSPEND_DISABLE)
return 0;
card = get_snd_generic_card(dev);
if (card->power_state == SNDRV_CTL_POWER_D3hot) if (card->power_state == SNDRV_CTL_POWER_D3hot)
break; return 0;
/* FIXME: the correct state value? */ card->pm_suspend(card, PMSG_SUSPEND);
card->pm_suspend(card, 0);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
break; return 0;
case PM_RESUME: }
static int snd_generic_resume(struct device *dev, u32 level)
{
snd_card_t *card;
if (level != RESUME_ENABLE)
return 0;
card = get_snd_generic_card(dev);
if (card->power_state == SNDRV_CTL_POWER_D0) if (card->power_state == SNDRV_CTL_POWER_D0)
break; return 0;
/* FIXME: the correct state value? */ card->pm_resume(card);
card->pm_resume(card, 0);
snd_power_change_state(card, SNDRV_CTL_POWER_D0); snd_power_change_state(card, SNDRV_CTL_POWER_D0);
break;
}
return 0; return 0;
} }
/** /**
* snd_card_set_dev_pm_callback - set the generic power-management callbacks * snd_card_set_generic_pm_callback - set the generic power-management callbacks
* @card: soundcard structure * @card: soundcard structure
* @type: PM device type (PM_XXX)
* @suspend: suspend callback function * @suspend: suspend callback function
* @resume: resume callback function * @resume: resume callback function
* @private_data: private data to pass to the callback functions * @private_data: private data to pass to the callback functions
* *
* Registers the power-management and sets the lowlevel callbacks for * Registers the power-management and sets the lowlevel callbacks for
* the given card with the given PM type. These callbacks are called * the given card. These callbacks are called from the ALSA's common
* from the ALSA's common PM handler and from the control API. * PM handler and from the control API.
*/ */
int snd_card_set_dev_pm_callback(snd_card_t *card, int type, int snd_card_set_generic_pm_callback(snd_card_t *card,
int (*suspend)(snd_card_t *, unsigned int), int (*suspend)(snd_card_t *, pm_message_t),
int (*resume)(snd_card_t *, unsigned int), int (*resume)(snd_card_t *),
void *private_data) void *private_data)
{ {
card->pm_dev = pm_register(type, 0, snd_generic_pm_callback); card->pm_dev = snd_generic_device_register(card);
if (! card->pm_dev) if (! card->pm_dev)
return -ENOMEM; return -ENOMEM;
card->pm_dev->data = card;
snd_card_set_pm_callback(card, suspend, resume, private_data); snd_card_set_pm_callback(card, suspend, resume, private_data);
return 0; return 0;
} }
#endif /* CONFIG_SND_GENERIC_PM */
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
int snd_card_pci_suspend(struct pci_dev *dev, u32 state) int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state)
{ {
snd_card_t *card = pci_get_drvdata(dev); snd_card_t *card = pci_get_drvdata(dev);
int err; int err;
...@@ -786,8 +863,7 @@ int snd_card_pci_suspend(struct pci_dev *dev, u32 state) ...@@ -786,8 +863,7 @@ int snd_card_pci_suspend(struct pci_dev *dev, u32 state)
return 0; return 0;
if (card->power_state == SNDRV_CTL_POWER_D3hot) if (card->power_state == SNDRV_CTL_POWER_D3hot)
return 0; return 0;
/* FIXME: correct state value? */ err = card->pm_suspend(card, PMSG_SUSPEND);
err = card->pm_suspend(card, 0);
pci_save_state(dev); pci_save_state(dev);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
return err; return err;
...@@ -802,8 +878,7 @@ int snd_card_pci_resume(struct pci_dev *dev) ...@@ -802,8 +878,7 @@ int snd_card_pci_resume(struct pci_dev *dev)
return 0; return 0;
/* restore the PCI config space */ /* restore the PCI config space */
pci_restore_state(dev); pci_restore_state(dev);
/* FIXME: correct state value? */ card->pm_resume(card);
card->pm_resume(card, 0);
snd_power_change_state(card, SNDRV_CTL_POWER_D0); snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0; return 0;
} }
......
#
# Makefile for ALSA
# Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
#
snd-ioctl32-objs := ioctl32.o pcm32.o rawmidi32.o timer32.o hwdep32.o
ifneq ($(CONFIG_SND_SEQUENCER),n)
snd-ioctl32-objs += seq32.o
endif
obj-$(CONFIG_SND_BIT32_EMUL) += snd-ioctl32.o
/*
* 32bit -> 64bit ioctl helpers
* Copyright (c) by Takashi Iwai <tiwai@suse.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* This file registers the converters from 32-bit ioctls to 64-bit ones.
* The converter assumes that a 32-bit user-pointer can be casted by compat_ptr(x)
* macro to a valid 64-bit pointer which is accessible via copy_from/to_user.
*
*/
#ifndef __ALSA_IOCTL32_H
#define __ALSA_IOCTL32_H
#include <linux/compat.h>
#define COPY(x) \
do { \
if (copy_in_user(&dst->x, &src->x, sizeof(dst->x))) \
return -EFAULT; \
} while (0)
#define COPY_ARRAY(x) \
do { \
if (copy_in_user(dst->x, src->x, sizeof(dst->x))) \
return -EFAULT; \
} while (0)
#define COPY_CVT(x) \
do { \
__typeof__(src->x) __val_tmp; \
if (get_user(__val_tmp, &src->x) || \
put_user(__val_tmp, &dst->x))\
return -EFAULT; \
} while (0)
#define convert_from_32(type, dstp, srcp)\
{\
struct sndrv_##type __user *dst = dstp;\
struct sndrv_##type##32 __user *src = srcp;\
CVT_##sndrv_##type();\
}
#define convert_to_32(type, dstp, srcp)\
{\
struct sndrv_##type __user *src = srcp;\
struct sndrv_##type##32 __user *dst = dstp;\
CVT_##sndrv_##type();\
}
#define DEFINE_ALSA_IOCTL(type) \
static inline int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\
{\
struct sndrv_##type##32 __user *data32;\
struct sndrv_##type __user *data;\
int err;\
data32 = compat_ptr(arg);\
data = compat_alloc_user_space(sizeof(*data));\
convert_from_32(type, data, data32);\
err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);\
if (err < 0) \
return err;\
if (native_ctl & (_IOC_READ << _IOC_DIRSHIFT)) {\
convert_to_32(type, data32, data);\
}\
return 0;\
}
#define DEFINE_ALSA_IOCTL_ENTRY(name,type,native_ctl) \
static int snd_ioctl32_##name(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) {\
return _snd_ioctl32_##type(fd, cmd, arg, file, native_ctl);\
}
#define MAP_COMPAT(ctl) { ctl, snd_ioctl32_compat }
struct ioctl32_mapper {
unsigned int cmd;
int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
int registered;
};
int snd_ioctl32_compat(unsigned int, unsigned int, unsigned long, struct file *);
int snd_ioctl32_register(struct ioctl32_mapper *mappers);
void snd_ioctl32_unregister(struct ioctl32_mapper *mappers);
#endif /* __ALSA_IOCTL32_H */
...@@ -50,8 +50,8 @@ static long snd_alloc_kmalloc; ...@@ -50,8 +50,8 @@ static long snd_alloc_kmalloc;
static long snd_alloc_vmalloc; static long snd_alloc_vmalloc;
static LIST_HEAD(snd_alloc_kmalloc_list); static LIST_HEAD(snd_alloc_kmalloc_list);
static LIST_HEAD(snd_alloc_vmalloc_list); static LIST_HEAD(snd_alloc_vmalloc_list);
static spinlock_t snd_alloc_kmalloc_lock = SPIN_LOCK_UNLOCKED; static DEFINE_SPINLOCK(snd_alloc_kmalloc_lock);
static spinlock_t snd_alloc_vmalloc_lock = SPIN_LOCK_UNLOCKED; static DEFINE_SPINLOCK(snd_alloc_vmalloc_lock);
#define KMALLOC_MAGIC 0x87654321 #define KMALLOC_MAGIC 0x87654321
#define VMALLOC_MAGIC 0x87654320 #define VMALLOC_MAGIC 0x87654320
static snd_info_entry_t *snd_memory_info_entry; static snd_info_entry_t *snd_memory_info_entry;
......
...@@ -359,16 +359,9 @@ static int snd_mixer_oss_ioctl1(snd_mixer_oss_file_t *fmixer, unsigned int cmd, ...@@ -359,16 +359,9 @@ static int snd_mixer_oss_ioctl1(snd_mixer_oss_file_t *fmixer, unsigned int cmd,
return -ENXIO; return -ENXIO;
} }
/* FIXME: need to unlock BKL to allow preemption */ static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static int snd_mixer_oss_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{ {
int err; return snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
/* FIXME: need to unlock BKL to allow preemption */
unlock_kernel();
err = snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
lock_kernel();
return err;
} }
int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg) int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg)
...@@ -384,6 +377,13 @@ int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long a ...@@ -384,6 +377,13 @@ int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long a
return snd_mixer_oss_ioctl1(&fmixer, cmd, arg); return snd_mixer_oss_ioctl1(&fmixer, cmd, arg);
} }
#ifdef CONFIG_COMPAT
/* all compatible */
#define snd_mixer_oss_ioctl_compat snd_mixer_oss_ioctl
#else
#define snd_mixer_oss_ioctl_compat NULL
#endif
/* /*
* REGISTRATION PART * REGISTRATION PART
*/ */
...@@ -393,7 +393,8 @@ static struct file_operations snd_mixer_oss_f_ops = ...@@ -393,7 +393,8 @@ static struct file_operations snd_mixer_oss_f_ops =
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = snd_mixer_oss_open, .open = snd_mixer_oss_open,
.release = snd_mixer_oss_release, .release = snd_mixer_oss_release,
.ioctl = snd_mixer_oss_ioctl, .unlocked_ioctl = snd_mixer_oss_ioctl,
.compat_ioctl = snd_mixer_oss_ioctl_compat,
}; };
static snd_minor_t snd_mixer_oss_reg = static snd_minor_t snd_mixer_oss_reg =
...@@ -521,7 +522,7 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer, ...@@ -521,7 +522,7 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer,
goto __unalloc; goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc); snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
snd_runtime_check(!kctl->get(kctl, uctl), goto __unalloc); snd_runtime_check(!kctl->get(kctl, uctl), goto __unalloc);
snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, return); snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, goto __unalloc);
*left = snd_mixer_oss_conv1(uctl->value.integer.value[0], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[0]); *left = snd_mixer_oss_conv1(uctl->value.integer.value[0], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[0]);
if (uinfo->count > 1) if (uinfo->count > 1)
*right = snd_mixer_oss_conv1(uctl->value.integer.value[1], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[1]); *right = snd_mixer_oss_conv1(uctl->value.integer.value[1], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[1]);
...@@ -615,7 +616,7 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer, ...@@ -615,7 +616,7 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer,
if (uinfo == NULL || uctl == NULL) if (uinfo == NULL || uctl == NULL)
goto __unalloc; goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc); snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, return); snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, goto __unalloc);
uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max); uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max);
if (uinfo->count > 1) if (uinfo->count > 1)
uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max); uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max);
......
...@@ -636,10 +636,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char ...@@ -636,10 +636,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char
if (in_kernel) { if (in_kernel) {
mm_segment_t fs; mm_segment_t fs;
fs = snd_enter_user(); fs = snd_enter_user();
ret = snd_pcm_lib_write(substream, ptr, frames); ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
snd_leave_user(fs); snd_leave_user(fs);
} else { } else {
ret = snd_pcm_lib_write(substream, ptr, frames); ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
} }
if (ret != -EPIPE && ret != -ESTRPIPE) if (ret != -EPIPE && ret != -ESTRPIPE)
break; break;
...@@ -679,10 +679,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, s ...@@ -679,10 +679,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, s
if (in_kernel) { if (in_kernel) {
mm_segment_t fs; mm_segment_t fs;
fs = snd_enter_user(); fs = snd_enter_user();
ret = snd_pcm_lib_read(substream, ptr, frames); ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
snd_leave_user(fs); snd_leave_user(fs);
} else { } else {
ret = snd_pcm_lib_read(substream, ptr, frames); ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
} }
if (ret == -EPIPE) { if (ret == -EPIPE) {
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
...@@ -718,10 +718,10 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **buf ...@@ -718,10 +718,10 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **buf
if (in_kernel) { if (in_kernel) {
mm_segment_t fs; mm_segment_t fs;
fs = snd_enter_user(); fs = snd_enter_user();
ret = snd_pcm_lib_writev(substream, bufs, frames); ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
snd_leave_user(fs); snd_leave_user(fs);
} else { } else {
ret = snd_pcm_lib_writev(substream, bufs, frames); ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
} }
if (ret != -EPIPE && ret != -ESTRPIPE) if (ret != -EPIPE && ret != -ESTRPIPE)
break; break;
...@@ -758,10 +758,10 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs ...@@ -758,10 +758,10 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs
if (in_kernel) { if (in_kernel) {
mm_segment_t fs; mm_segment_t fs;
fs = snd_enter_user(); fs = snd_enter_user();
ret = snd_pcm_lib_readv(substream, bufs, frames); ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
snd_leave_user(fs); snd_leave_user(fs);
} else { } else {
ret = snd_pcm_lib_readv(substream, bufs, frames); ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
} }
if (ret != -EPIPE && ret != -ESTRPIPE) if (ret != -EPIPE && ret != -ESTRPIPE)
break; break;
...@@ -777,7 +777,7 @@ static ssize_t snd_pcm_oss_write2(snd_pcm_substream_t *substream, const char *bu ...@@ -777,7 +777,7 @@ static ssize_t snd_pcm_oss_write2(snd_pcm_substream_t *substream, const char *bu
snd_pcm_plugin_channel_t *channels; snd_pcm_plugin_channel_t *channels;
size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8; size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
if (!in_kernel) { if (!in_kernel) {
if (copy_from_user(runtime->oss.buffer, buf, bytes)) if (copy_from_user(runtime->oss.buffer, (const char __user *)buf, bytes))
return -EFAULT; return -EFAULT;
buf = runtime->oss.buffer; buf = runtime->oss.buffer;
} }
...@@ -839,7 +839,7 @@ static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char __u ...@@ -839,7 +839,7 @@ static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char __u
return xfer > 0 ? xfer : -EAGAIN; return xfer > 0 ? xfer : -EAGAIN;
} }
} else { } else {
tmp = snd_pcm_oss_write2(substream, (char *)buf, runtime->oss.period_bytes, 0); tmp = snd_pcm_oss_write2(substream, (const char *)buf, runtime->oss.period_bytes, 0);
if (tmp <= 0) if (tmp <= 0)
return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
runtime->oss.bytes += tmp; runtime->oss.bytes += tmp;
...@@ -858,7 +858,7 @@ static ssize_t snd_pcm_oss_read2(snd_pcm_substream_t *substream, char *buf, size ...@@ -858,7 +858,7 @@ static ssize_t snd_pcm_oss_read2(snd_pcm_substream_t *substream, char *buf, size
{ {
snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_runtime_t *runtime = substream->runtime;
snd_pcm_sframes_t frames, frames1; snd_pcm_sframes_t frames, frames1;
char *final_dst = buf; char __user *final_dst = (char __user *)buf;
if (runtime->oss.plugin_first) { if (runtime->oss.plugin_first) {
snd_pcm_plugin_channel_t *channels; snd_pcm_plugin_channel_t *channels;
size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8; size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8;
...@@ -1058,6 +1058,7 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file) ...@@ -1058,6 +1058,7 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file)
if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
size = (runtime->frame_bits * size) / 8; size = (runtime->frame_bits * size) / 8;
while (size > 0) { while (size > 0) {
mm_segment_t fs;
size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes; size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes;
size -= size1; size -= size1;
size1 *= 8; size1 *= 8;
...@@ -1065,7 +1066,9 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file) ...@@ -1065,7 +1066,9 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file)
snd_pcm_format_set_silence(runtime->format, snd_pcm_format_set_silence(runtime->format,
runtime->oss.buffer, runtime->oss.buffer,
size1); size1);
snd_pcm_lib_write(substream, runtime->oss.buffer, size1); fs = snd_enter_user();
snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1);
snd_leave_user(fs);
} }
} else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) { } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
void __user *buffers[runtime->channels]; void __user *buffers[runtime->channels];
...@@ -1913,8 +1916,7 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file) ...@@ -1913,8 +1916,7 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file)
return 0; return 0;
} }
static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file, static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
unsigned int cmd, unsigned long arg)
{ {
snd_pcm_oss_file_t *pcm_oss_file; snd_pcm_oss_file_t *pcm_oss_file;
int __user *p = (int __user *)arg; int __user *p = (int __user *)arg;
...@@ -2073,16 +2075,12 @@ static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file, ...@@ -2073,16 +2075,12 @@ static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
return -EINVAL; return -EINVAL;
} }
/* FIXME: need to unlock BKL to allow preemption */ #ifdef CONFIG_COMPAT
static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file, /* all compatible */
unsigned int cmd, unsigned long arg) #define snd_pcm_oss_ioctl_compat snd_pcm_oss_ioctl
{ #else
int err; #define snd_pcm_oss_ioctl_compat NULL
unlock_kernel(); #endif
err = _snd_pcm_oss_ioctl(inode, file, cmd, arg);
lock_kernel();
return err;
}
static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset) static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{ {
...@@ -2410,7 +2408,8 @@ static struct file_operations snd_pcm_oss_f_reg = ...@@ -2410,7 +2408,8 @@ static struct file_operations snd_pcm_oss_f_reg =
.open = snd_pcm_oss_open, .open = snd_pcm_oss_open,
.release = snd_pcm_oss_release, .release = snd_pcm_oss_release,
.poll = snd_pcm_oss_poll, .poll = snd_pcm_oss_poll,
.ioctl = snd_pcm_oss_ioctl, .unlocked_ioctl = snd_pcm_oss_ioctl,
.compat_ioctl = snd_pcm_oss_ioctl_compat,
.mmap = snd_pcm_oss_mmap, .mmap = snd_pcm_oss_mmap,
}; };
......
...@@ -1004,6 +1004,7 @@ static int __init alsa_pcm_init(void) ...@@ -1004,6 +1004,7 @@ static int __init alsa_pcm_init(void)
snd_info_entry_t *entry; snd_info_entry_t *entry;
snd_ctl_register_ioctl(snd_pcm_control_ioctl); snd_ctl_register_ioctl(snd_pcm_control_ioctl);
snd_ctl_register_ioctl_compat(snd_pcm_control_ioctl);
if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) { if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) {
snd_info_set_text_ops(entry, NULL, SNDRV_CARDS * SNDRV_PCM_DEVICES * 128, snd_pcm_proc_read); snd_info_set_text_ops(entry, NULL, SNDRV_CARDS * SNDRV_PCM_DEVICES * 128, snd_pcm_proc_read);
if (snd_info_register(entry) < 0) { if (snd_info_register(entry) < 0) {
...@@ -1018,6 +1019,7 @@ static int __init alsa_pcm_init(void) ...@@ -1018,6 +1019,7 @@ static int __init alsa_pcm_init(void)
static void __exit alsa_pcm_exit(void) static void __exit alsa_pcm_exit(void)
{ {
snd_ctl_unregister_ioctl(snd_pcm_control_ioctl); snd_ctl_unregister_ioctl(snd_pcm_control_ioctl);
snd_ctl_unregister_ioctl_compat(snd_pcm_control_ioctl);
if (snd_pcm_proc_entry) { if (snd_pcm_proc_entry) {
snd_info_unregister(snd_pcm_proc_entry); snd_info_unregister(snd_pcm_proc_entry);
snd_pcm_proc_entry = NULL; snd_pcm_proc_entry = NULL;
......
...@@ -1863,9 +1863,8 @@ static void snd_pcm_system_tick_set(snd_pcm_substream_t *substream, ...@@ -1863,9 +1863,8 @@ static void snd_pcm_system_tick_set(snd_pcm_substream_t *substream,
if (ticks == 0) if (ticks == 0)
del_timer(&runtime->tick_timer); del_timer(&runtime->tick_timer);
else { else {
ticks += (1000000 / HZ) - 1;
ticks /= (1000000 / HZ); ticks /= (1000000 / HZ);
if (ticks % (1000000 / HZ))
ticks++;
mod_timer(&runtime->tick_timer, jiffies + ticks); mod_timer(&runtime->tick_timer, jiffies + ticks);
} }
} }
...@@ -2142,11 +2141,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream, ...@@ -2142,11 +2141,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
break; break;
} }
appl_ptr += frames; appl_ptr += frames;
if (appl_ptr >= runtime->boundary) { if (appl_ptr >= runtime->boundary)
runtime->control->appl_ptr = 0; appl_ptr -= runtime->boundary;
} else {
runtime->control->appl_ptr = appl_ptr; runtime->control->appl_ptr = appl_ptr;
}
if (substream->ops->ack) if (substream->ops->ack)
substream->ops->ack(substream); substream->ops->ack(substream);
...@@ -2441,11 +2438,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, ...@@ -2441,11 +2438,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream,
break; break;
} }
appl_ptr += frames; appl_ptr += frames;
if (appl_ptr >= runtime->boundary) { if (appl_ptr >= runtime->boundary)
runtime->control->appl_ptr = 0; appl_ptr -= runtime->boundary;
} else {
runtime->control->appl_ptr = appl_ptr; runtime->control->appl_ptr = appl_ptr;
}
if (substream->ops->ack) if (substream->ops->ack)
substream->ops->ack(substream); substream->ops->ack(substream);
......
...@@ -291,7 +291,7 @@ struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned lon ...@@ -291,7 +291,7 @@ struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned lon
* @substream: the substream to allocate the DMA buffer to * @substream: the substream to allocate the DMA buffer to
* @size: the requested buffer size in bytes * @size: the requested buffer size in bytes
* *
* Allocates the DMA buffer on the BUS type given by * Allocates the DMA buffer on the BUS type given earlier to
* snd_pcm_lib_preallocate_xxx_pages(). * snd_pcm_lib_preallocate_xxx_pages().
* *
* Returns 1 if the buffer is changed, 0 if not changed, or a negative * Returns 1 if the buffer is changed, 0 if not changed, or a negative
......
...@@ -65,7 +65,7 @@ static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sn ...@@ -65,7 +65,7 @@ static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sn
* *
*/ */
rwlock_t snd_pcm_link_rwlock = RW_LOCK_UNLOCKED; DEFINE_RWLOCK(snd_pcm_link_rwlock);
static DECLARE_RWSEM(snd_pcm_link_rwsem); static DECLARE_RWSEM(snd_pcm_link_rwsem);
...@@ -602,17 +602,13 @@ static int snd_pcm_status_user(snd_pcm_substream_t * substream, snd_pcm_status_t ...@@ -602,17 +602,13 @@ static int snd_pcm_status_user(snd_pcm_substream_t * substream, snd_pcm_status_t
return 0; return 0;
} }
static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t __user * _info) static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t * info)
{ {
snd_pcm_channel_info_t info;
snd_pcm_runtime_t *runtime; snd_pcm_runtime_t *runtime;
int res;
unsigned int channel; unsigned int channel;
snd_assert(substream != NULL, return -ENXIO); snd_assert(substream != NULL, return -ENXIO);
if (copy_from_user(&info, _info, sizeof(info))) channel = info->channel;
return -EFAULT;
channel = info.channel;
runtime = substream->runtime; runtime = substream->runtime;
snd_pcm_stream_lock_irq(substream); snd_pcm_stream_lock_irq(substream);
if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
...@@ -622,9 +618,19 @@ static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel ...@@ -622,9 +618,19 @@ static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel
snd_pcm_stream_unlock_irq(substream); snd_pcm_stream_unlock_irq(substream);
if (channel >= runtime->channels) if (channel >= runtime->channels)
return -EINVAL; return -EINVAL;
memset(&info, 0, sizeof(info)); memset(info, 0, sizeof(*info));
info.channel = channel; info->channel = channel;
res = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, &info); return substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, info);
}
static int snd_pcm_channel_info_user(snd_pcm_substream_t * substream, snd_pcm_channel_info_t __user * _info)
{
snd_pcm_channel_info_t info;
int res;
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
res = snd_pcm_channel_info(substream, &info);
if (res < 0) if (res < 0)
return res; return res;
if (copy_to_user(_info, &info, sizeof(info))) if (copy_to_user(_info, &info, sizeof(info)))
...@@ -2440,7 +2446,7 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream, ...@@ -2440,7 +2446,7 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream,
case SNDRV_PCM_IOCTL_STATUS: case SNDRV_PCM_IOCTL_STATUS:
return snd_pcm_status_user(substream, arg); return snd_pcm_status_user(substream, arg);
case SNDRV_PCM_IOCTL_CHANNEL_INFO: case SNDRV_PCM_IOCTL_CHANNEL_INFO:
return snd_pcm_channel_info(substream, arg); return snd_pcm_channel_info_user(substream, arg);
case SNDRV_PCM_IOCTL_PREPARE: case SNDRV_PCM_IOCTL_PREPARE:
return snd_pcm_prepare(substream); return snd_pcm_prepare(substream);
case SNDRV_PCM_IOCTL_RESET: case SNDRV_PCM_IOCTL_RESET:
...@@ -2640,40 +2646,28 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream, ...@@ -2640,40 +2646,28 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_common_ioctl1(substream, cmd, arg); return snd_pcm_common_ioctl1(substream, cmd, arg);
} }
static int snd_pcm_playback_ioctl(struct inode *inode, struct file *file, static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
unsigned int cmd, unsigned long arg)
{ {
snd_pcm_file_t *pcm_file; snd_pcm_file_t *pcm_file;
int err;
pcm_file = file->private_data; pcm_file = file->private_data;
if (((cmd >> 8) & 0xff) != 'A') if (((cmd >> 8) & 0xff) != 'A')
return -ENOTTY; return -ENOTTY;
/* FIXME: need to unlock BKL to allow preemption */ return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
unlock_kernel();
err = snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
lock_kernel();
return err;
} }
static int snd_pcm_capture_ioctl(struct inode *inode, struct file *file, static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
unsigned int cmd, unsigned long arg)
{ {
snd_pcm_file_t *pcm_file; snd_pcm_file_t *pcm_file;
int err;
pcm_file = file->private_data; pcm_file = file->private_data;
if (((cmd >> 8) & 0xff) != 'A') if (((cmd >> 8) & 0xff) != 'A')
return -ENOTTY; return -ENOTTY;
/* FIXME: need to unlock BKL to allow preemption */ return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
unlock_kernel();
err = snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
lock_kernel();
return err;
} }
int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream, int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream,
...@@ -2683,7 +2677,7 @@ int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream, ...@@ -2683,7 +2677,7 @@ int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream,
int result; int result;
fs = snd_enter_user(); fs = snd_enter_user();
result = snd_pcm_playback_ioctl1(substream, cmd, arg); result = snd_pcm_playback_ioctl1(substream, cmd, (void __user *)arg);
snd_leave_user(fs); snd_leave_user(fs);
return result; return result;
} }
...@@ -2695,7 +2689,7 @@ int snd_pcm_kernel_capture_ioctl(snd_pcm_substream_t *substream, ...@@ -2695,7 +2689,7 @@ int snd_pcm_kernel_capture_ioctl(snd_pcm_substream_t *substream,
int result; int result;
fs = snd_enter_user(); fs = snd_enter_user();
result = snd_pcm_capture_ioctl1(substream, cmd, arg); result = snd_pcm_capture_ioctl1(substream, cmd, (void __user *)arg);
snd_leave_user(fs); snd_leave_user(fs);
return result; return result;
} }
...@@ -3197,6 +3191,15 @@ static int snd_pcm_fasync(int fd, struct file * file, int on) ...@@ -3197,6 +3191,15 @@ static int snd_pcm_fasync(int fd, struct file * file, int on)
return 0; return 0;
} }
/*
* ioctl32 compat
*/
#ifdef CONFIG_COMPAT
#include "pcm_compat.c"
#else
#define snd_pcm_ioctl_compat NULL
#endif
/* /*
* To be removed helpers to keep binary compatibility * To be removed helpers to keep binary compatibility
*/ */
...@@ -3318,7 +3321,8 @@ static struct file_operations snd_pcm_f_ops_playback = { ...@@ -3318,7 +3321,8 @@ static struct file_operations snd_pcm_f_ops_playback = {
.open = snd_pcm_open, .open = snd_pcm_open,
.release = snd_pcm_release, .release = snd_pcm_release,
.poll = snd_pcm_playback_poll, .poll = snd_pcm_playback_poll,
.ioctl = snd_pcm_playback_ioctl, .unlocked_ioctl = snd_pcm_playback_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap, .mmap = snd_pcm_mmap,
.fasync = snd_pcm_fasync, .fasync = snd_pcm_fasync,
}; };
...@@ -3330,7 +3334,8 @@ static struct file_operations snd_pcm_f_ops_capture = { ...@@ -3330,7 +3334,8 @@ static struct file_operations snd_pcm_f_ops_capture = {
.open = snd_pcm_open, .open = snd_pcm_open,
.release = snd_pcm_release, .release = snd_pcm_release,
.poll = snd_pcm_capture_poll, .poll = snd_pcm_capture_poll,
.ioctl = snd_pcm_capture_ioctl, .unlocked_ioctl = snd_pcm_capture_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap, .mmap = snd_pcm_mmap,
.fasync = snd_pcm_fasync, .fasync = snd_pcm_fasync,
}; };
......
This diff is collapsed.
...@@ -183,4 +183,6 @@ MODULE_PARM_DESC(rtctimer_freq, "timer frequency in Hz"); ...@@ -183,4 +183,6 @@ MODULE_PARM_DESC(rtctimer_freq, "timer frequency in Hz");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_RTC));
#endif /* CONFIG_RTC || CONFIG_RTC_MODULE */ #endif /* CONFIG_RTC || CONFIG_RTC_MODULE */
...@@ -59,7 +59,7 @@ static int odev_open(struct inode *inode, struct file *file); ...@@ -59,7 +59,7 @@ static int odev_open(struct inode *inode, struct file *file);
static int odev_release(struct inode *inode, struct file *file); static int odev_release(struct inode *inode, struct file *file);
static ssize_t odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset); static ssize_t odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset);
static ssize_t odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset); static ssize_t odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset);
static int odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); static long odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
static unsigned int odev_poll(struct file *file, poll_table * wait); static unsigned int odev_poll(struct file *file, poll_table * wait);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static void info_read(snd_info_entry_t *entry, snd_info_buffer_t *buf); static void info_read(snd_info_entry_t *entry, snd_info_buffer_t *buf);
...@@ -177,20 +177,20 @@ odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offs ...@@ -177,20 +177,20 @@ odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offs
return snd_seq_oss_write(dp, buf, count, file); return snd_seq_oss_write(dp, buf, count, file);
} }
static int static long
odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{ {
seq_oss_devinfo_t *dp; seq_oss_devinfo_t *dp;
int err;
dp = file->private_data; dp = file->private_data;
snd_assert(dp != NULL, return -EIO); snd_assert(dp != NULL, return -EIO);
/* FIXME: need to unlock BKL to allow preemption */ return snd_seq_oss_ioctl(dp, cmd, arg);
unlock_kernel();
err = snd_seq_oss_ioctl(dp, cmd, arg);
lock_kernel();
return err;
} }
#ifdef CONFIG_COMPAT
#define odev_ioctl_compat odev_ioctl
#else
#define odev_ioctl_compat NULL
#endif
static unsigned int static unsigned int
odev_poll(struct file *file, poll_table * wait) odev_poll(struct file *file, poll_table * wait)
...@@ -213,7 +213,8 @@ static struct file_operations seq_oss_f_ops = ...@@ -213,7 +213,8 @@ static struct file_operations seq_oss_f_ops =
.open = odev_open, .open = odev_open,
.release = odev_release, .release = odev_release,
.poll = odev_poll, .poll = odev_poll,
.ioctl = odev_ioctl, .unlocked_ioctl = odev_ioctl,
.compat_ioctl = odev_ioctl_compat,
}; };
static snd_minor_t seq_oss_reg = { static snd_minor_t seq_oss_reg = {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment