Commit c0569a66 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 1a8fca91 95716076
......@@ -110,9 +110,9 @@
</para>
<para>
One is the the trees provided as a tarball or via cvs from the
One is the trees provided as a tarball or via cvs from the
ALSA's ftp site, and another is the 2.6 (or later) Linux kernel
tree. To synchronize both, the ALSA driver tree is split to
tree. To synchronize both, the ALSA driver tree is split into
two different trees: alsa-kernel and alsa-driver. The former
contains purely the source codes for the Linux 2.6 (or later)
tree. This tree is designed only for compilation on 2.6 or
......@@ -766,7 +766,7 @@
</para>
<para>
The ALSA interfaces like PCM or control API are define in other
The ALSA interfaces like PCM or control API are defined in other
header files as <filename>&lt;sound/xxx.h&gt;</filename>.
They have to be included after
<filename>&lt;sound/core.h&gt;</filename>.
......@@ -1103,7 +1103,7 @@
/* release the irq */
if (chip->irq >= 0)
free_irq(chip->irq, (void *)chip);
/* release the i/o ports */
/* release the i/o ports & memory */
pci_release_regions(chip->pci);
/* disable the PCI entry */
pci_disable_device(chip->pci);
......@@ -1314,6 +1314,7 @@
</para>
<para>
<!-- obsolete -->
It will reserve the i/o port region of 8 bytes of the given
PCI device. The returned value, chip-&gt;res_port, is allocated
via <function>kmalloc()</function> by
......@@ -1936,6 +1937,7 @@
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
&snd_mychip_capture_ops);
/* pre-allocation of buffers */
/* NOTE: this may fail */
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(chip->pci),
64*1024, 64*1024);
......@@ -1950,7 +1952,7 @@
<section id="pcm-interface-constructor">
<title>Constructor</title>
<para>
A pcm instance is allocated <function>snd_pcm_new()</function>
A pcm instance is allocated by <function>snd_pcm_new()</function>
function. It would be better to create a constructor for pcm,
namely,
......@@ -2235,7 +2237,8 @@ struct _snd_pcm_runtime {
unsigned char *dma_area; /* DMA area */
dma_addr_t dma_addr; /* physical bus address (not accessible from main CPU) */
size_t dma_bytes; /* size of DMA area */
void *dma_private; /* private DMA data for the memory allocator */
struct snd_dma_buffer *dma_buffer_p; /* allocated buffer */
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
/* -- OSS things -- */
......@@ -2250,7 +2253,7 @@ struct _snd_pcm_runtime {
<para>
For the operators (callbacks) of each sound driver, most of
these records are supposed to be read-only. Only the PCM
middle-layer changes / updates these info. The excpetions are
middle-layer changes / updates these info. The exceptions are
the hardware description (hw), interrupt callbacks
(transfer_ack_xxx), DMA buffer information, and the private
data. Besides, if you use the standard buffer allocation
......@@ -3250,7 +3253,7 @@ struct _snd_pcm_runtime {
<para>
There are many different constraints.
Look in <filename>sound/asound.h</filename> for a complete list.
Look in <filename>sound/pcm.h</filename> for a complete list.
You can even define your own constraint rules.
For example, let's suppose my_chip can manage a substream of 1 channel
if and only if the format is S16_LE, otherwise it supports any format
......@@ -4066,7 +4069,7 @@ struct _snd_pcm_runtime {
Both <function>snd_ac97_write()</function> and
<function>snd_ac97_update()</function> functions are used to
set a value to the given register
(<constant>AC97_XXX</constant>). The different between them is
(<constant>AC97_XXX</constant>). The difference between them is
that <function>snd_ac97_update()</function> doesn't write a
value if the given value has been already set, while
<function>snd_ac97_write()</function> always rewrites the
......@@ -4152,8 +4155,8 @@ struct _snd_pcm_runtime {
<title>Proc Files</title>
<para>
The ALSA AC97 interface will create a proc file such as
<filename>/proc/asound/card0/ac97#0</filename> and
<filename>ac97#0regs</filename>. You can refer to these files to
<filename>/proc/asound/card0/codec97#0/ac97#0-0</filename> and
<filename>ac97#0-0+regs</filename>. You can refer to these files to
see the current status and registers of the codec.
</para>
</section>
......@@ -4633,7 +4636,7 @@ struct _snd_pcm_runtime {
where <parameter>size</parameter> is the byte size to be
pre-allocated and the <parameter>max</parameter> is the maximal
size to be changed via <filename>prealloc</filename> proc file.
The allocator will try to get as the large area as possible
The allocator will try to get as large area as possible
within the given size.
</para>
......@@ -4855,7 +4858,7 @@ struct _snd_pcm_runtime {
If your hardware supports the page table like emu10k1 or the
buffer descriptors like via82xx, you can use the scatter-gather
(SG) DMA. ALSA provides an interface for handling SG-buffers.
The API is provided in <filename>&lt;sound/pcm_sgbuf.h&gt;</filename>.
The API is provided in <filename>&lt;sound/pcm.h&gt;</filename>.
</para>
<para>
......@@ -5159,12 +5162,12 @@ struct _snd_pcm_runtime {
<programlisting>
<![CDATA[
#ifdef CONFIG_PM
static int snd_my_suspend(snd_card_t *card, unsigned int state)
static int snd_my_suspend(snd_card_t *card, pm_message_t state)
{
.... // do things for suspsend
return 0;
}
static int snd_my_resume(snd_card_t *card, unsigned int state)
static int snd_my_resume(snd_card_t *card)
{
.... // do things for suspsend
return 0;
......@@ -5193,7 +5196,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
static int mychip_suspend(snd_card_t *card, unsigned int state)
static int mychip_suspend(snd_card_t *card, pm_message_t state)
{
/* (1) */
mychip_t *chip = card->pm_private_data;
......
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.
This diff is collapsed.
......@@ -106,7 +106,7 @@
#define AK4117_DIF_24L (AK4117_DIF2) /* STDO: 24-bit, left justified */
#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_MPAR (1<<6) /* mask enable for PAR bit */
#define AK4117_MAUTO (1<<5) /* mask enable for AUTO bit */
......@@ -181,8 +181,8 @@ struct ak4117 {
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);
void snd_ak4117_reg_write(ak4117_t *chip, unsigned char reg, unsigned char mask, unsigned char val);
void snd_ak4117_reinit(ak4117_t *chip);
void snd_ak4117_reg_write(ak4117_t *ak4117, unsigned char reg, unsigned char mask, unsigned char val);
void snd_ak4117_reinit(ak4117_t *ak4117);
int snd_ak4117_build(ak4117_t *ak4117, snd_pcm_substream_t *capture_substream);
int snd_ak4117_external_rate(ak4117_t *ak4117);
int snd_ak4117_check_rate_and_errors(ak4117_t *ak4117, unsigned int flags);
......
......@@ -50,7 +50,8 @@ struct snd_akm4xxx {
/* template should fill the following fields */
unsigned int idx_offset; /* control index offset */
enum {
SND_AK4524, SND_AK4528, SND_AK4529, SND_AK4355, SND_AK4381
SND_AK4524, SND_AK4528, SND_AK4529,
SND_AK4355, SND_AK4358, SND_AK4381
} type;
struct snd_ak4xxx_ops ops;
};
......
......@@ -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_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_write(snd_card_t *card, snd_ctl_file_t *file, snd_ctl_elem_value_t *control);
......
......@@ -26,6 +26,7 @@
#include <asm/semaphore.h> /* struct semaphore */
#include <linux/rwsem.h> /* struct rw_semaphore */
#include <linux/workqueue.h> /* struct workqueue_struct */
#include <linux/pm.h> /* pm_message_t */
/* Typedef's */
typedef struct timespec snd_timestamp_t;
......@@ -167,13 +168,15 @@ struct _snd_card {
struct device *dev;
#ifdef CONFIG_PM
int (*pm_suspend)(snd_card_t *card, unsigned int state);
int (*pm_resume)(snd_card_t *card, unsigned int state);
struct pm_dev *pm_dev; /* for ISA */
int (*pm_suspend)(snd_card_t *card, pm_message_t state);
int (*pm_resume)(snd_card_t *card);
void *pm_private_data;
unsigned int power_state; /* power state */
struct semaphore power_lock; /* power lock */
wait_queue_head_t power_sleep;
#ifdef CONFIG_SND_GENERIC_PM
struct snd_generic_device *pm_dev; /* for ISA */
#endif
#endif
#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)
wake_up(&card->power_sleep);
}
int snd_card_set_pm_callback(snd_card_t *card,
int (*suspend)(snd_card_t *, unsigned int),
int (*resume)(snd_card_t *, unsigned int),
int (*suspend)(snd_card_t *, pm_message_t),
int (*resume)(snd_card_t *),
void *private_data);
int snd_card_set_dev_pm_callback(snd_card_t *card, int type,
int (*suspend)(snd_card_t *, unsigned int),
int (*resume)(snd_card_t *, unsigned int),
int snd_card_set_generic_pm_callback(snd_card_t *card,
int (*suspend)(snd_card_t *, pm_message_t),
int (*resume)(snd_card_t *),
void *private_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)
#ifdef CONFIG_PCI
#ifndef SND_PCI_PM_CALLBACKS
int snd_card_pci_suspend(struct pci_dev *dev, u32 state);
snd_card_set_generic_pm_callback(card, suspend, resume, data)
struct pci_dev;
int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state);
int snd_card_pci_resume(struct pci_dev *dev);
#define SND_PCI_PM_CALLBACKS \
.suspend = snd_card_pci_suspend, .resume = snd_card_pci_resume
#endif
#endif
#else
#else /* ! CONFIG_PM */
#define snd_power_lock(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; }
#define snd_power_get_state(card) SNDRV_CTL_POWER_D0
#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_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)
#ifdef CONFIG_PCI
#define SND_PCI_PM_CALLBACKS
#endif
#endif
#endif /* CONFIG_PM */
/* device.c */
......
This diff is collapsed.
......@@ -230,7 +230,7 @@ typedef struct {
int mode; /* operation mode */
int client; /* sequencer client number */
int port; /* sequencer port number */
int midi_has_voices: 1;
unsigned int midi_has_voices: 1;
} snd_gus_port_t;
typedef struct _snd_gus_voice snd_gus_voice_t;
......@@ -264,7 +264,7 @@ typedef enum {
struct _snd_gus_voice {
int number;
int use: 1,
unsigned int use: 1,
pcm: 1,
synth:1,
midi: 1;
......
......@@ -38,6 +38,7 @@ typedef struct _snd_hwdep_ops {
int (*release) (snd_hwdep_t * hw, struct file * file);
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_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 (*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);
......
......@@ -38,7 +38,7 @@ typedef int (*snd_mixer_oss_put_recsrce_t)(snd_mixer_oss_file_t *fmixer, unsigne
struct _snd_oss_mixer_slot {
int number;
int stereo: 1;
unsigned int stereo: 1;
snd_mixer_oss_get_volume_t get_volume;
snd_mixer_oss_put_volume_t put_volume;
snd_mixer_oss_get_recsrc_t get_recsrc;
......
......@@ -65,8 +65,7 @@ typedef struct _snd_rawmidi_global_ops {
} snd_rawmidi_global_ops_t;
struct _snd_rawmidi_runtime {
unsigned int trigger: 1, /* transfer is running */
drain: 1, /* drain stage */
unsigned int drain: 1, /* drain stage */
oss: 1; /* OSS compatible mode */
/* midi stream buffer */
unsigned char *buffer; /* buffer for MIDI data */
......
......@@ -38,7 +38,7 @@ typedef struct _snd_virmidi {
int seq_mode;
int client;
int port;
int trigger: 1;
unsigned int trigger: 1;
snd_midi_event_t *parser;
snd_seq_event_t event;
snd_virmidi_dev_t *rdev;
......
......@@ -290,7 +290,7 @@ typedef struct {
int mode; /* operation mode */
int client; /* sequencer client number */
int port; /* sequencer port number */
int midi_has_voices: 1;
unsigned int midi_has_voices: 1;
} snd_trident_port_t;
typedef struct snd_trident_memblk_arg {
......@@ -308,7 +308,7 @@ typedef struct {
struct _snd_trident_voice {
unsigned int number;
int use: 1,
unsigned int use: 1,
pcm: 1,
synth:1,
midi: 1;
......@@ -347,7 +347,7 @@ struct _snd_trident_voice {
trident_t *trident;
snd_pcm_substream_t *substream;
snd_trident_voice_t *extra; /* extra PCM voice (acts as interrupt generator) */
int running: 1,
unsigned int running: 1,
capture: 1,
spdif: 1,
foldback: 1,
......
......@@ -262,7 +262,7 @@ typedef enum {
struct _snd_ymfpci_voice {
ymfpci_t *chip;
int number;
int use: 1,
unsigned int use: 1,
pcm: 1,
synth: 1,
midi: 1;
......@@ -288,9 +288,9 @@ struct _snd_ymfpci_pcm {
snd_ymfpci_pcm_type_t type;
snd_pcm_substream_t *substream;
ymfpci_voice_t *voices[2]; /* playback only */
int running: 1;
int output_front: 1;
int output_rear: 1;
unsigned int running: 1;
unsigned int output_front: 1;
unsigned int output_rear: 1;
u32 period_size; /* cached from runtime->period_size */
u32 buffer_size; /* cached from runtime->buffer_size */
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 @@
* 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,
#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;
......@@ -878,7 +878,7 @@ static int snd_sa11xx_uda1341_suspend(snd_card_t *card, unsigned int state)
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;
......@@ -938,7 +938,7 @@ static int __init sa11xx_uda1341_init(void)
if ((err = snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341, 0)) < 0)
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,
sa11xx_uda1341);
......
# ALSA soundcard-configuration
config SND_TIMER
tristate
depends on SND
config SND_PCM
tristate
select SND_TIMER
depends on SND
config SND_HWDEP
tristate
depends on SND
config SND_RAWMIDI
tristate
depends on SND
config SND_SEQUENCER
tristate "Sequencer support"
......@@ -40,6 +44,7 @@ config SND_SEQ_DUMMY
config SND_OSSEMUL
bool
depends on SND
config SND_MIXER_OSS
tristate "OSS Mixer API"
......@@ -70,7 +75,7 @@ config SND_PCM_OSS
config SND_SEQUENCER_OSS
bool "OSS Sequencer API"
depends on SND_SEQUENCER
depends on SND && SND_SEQUENCER
select SND_OSSEMUL
help
Say Y here to enable OSS sequencer emulation (both
......@@ -81,20 +86,6 @@ config SND_SEQUENCER_OSS
To compile this driver as a module, choose M here: the module
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
tristate "RTC Timer support"
depends on SND && RTC
......@@ -137,3 +128,6 @@ config SND_DEBUG_DETECT
Say Y here to enable extra-verbose log messages printed when
detecting devices.
config SND_GENERIC_PM
bool
depends on SND
......@@ -31,4 +31,3 @@ obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o
obj-$(CONFIG_SND_OSSEMUL) += oss/
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
return 0;
}
static inline int _snd_hwdep_ioctl(struct inode *inode, struct file * file,
unsigned int cmd, unsigned long arg)
static long snd_hwdep_ioctl(struct file * file, unsigned int cmd, unsigned long arg)
{
snd_hwdep_t *hw = file->private_data;
void __user *argp = (void __user *)arg;
......@@ -252,17 +251,6 @@ static inline int _snd_hwdep_ioctl(struct inode *inode, struct file * file,
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)
{
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,
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 =
.open = snd_hwdep_open,
.release = snd_hwdep_release,
.poll = snd_hwdep_poll,
.ioctl = snd_hwdep_ioctl,
.unlocked_ioctl = snd_hwdep_ioctl,
.compat_ioctl = snd_hwdep_ioctl_compat,
.mmap = snd_hwdep_mmap,
};
......@@ -509,12 +504,14 @@ static int __init alsa_hwdep_init(void)
}
snd_hwdep_proc_entry = entry;
snd_ctl_register_ioctl(snd_hwdep_control_ioctl);
snd_ctl_register_ioctl_compat(snd_hwdep_control_ioctl);
return 0;
}
static void __exit alsa_hwdep_exit(void)
{
snd_ctl_unregister_ioctl(snd_hwdep_control_ioctl);
snd_ctl_unregister_ioctl_compat(snd_hwdep_control_ioctl);
if (snd_hwdep_proc_entry) {
snd_info_unregister(snd_hwdep_proc_entry);
snd_hwdep_proc_entry = NULL;
......
......@@ -18,13 +18,9 @@
*
*/
#include <sound/driver.h>
#include <linux/time.h>
#include <linux/fs.h>
#include <sound/core.h>
#include <sound/hwdep.h>
#include <asm/uaccess.h>
#include "ioctl32.h"
/* This file is included from hwdep.c */
#include <linux/compat.h>
struct sndrv_hwdep_dsp_image32 {
u32 index;
......@@ -34,40 +30,48 @@ struct sndrv_hwdep_dsp_image32 {
u32 driver_data;
} /* 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_image32 __user *data32, *src;
struct sndrv_hwdep_dsp_image *dst;
compat_caddr_t ptr;
u32 val;
data32 = compat_ptr(arg);
data = compat_alloc_user_space(sizeof(*data));
dst = compat_alloc_user_space(sizeof(*dst));
/* index and name */
if (copy_in_user(data, data32, 4 + 64))
if (copy_in_user(dst, src, 4 + 64))
return -EFAULT;
if (__get_user(ptr, &data32->image) ||
__put_user(compat_ptr(ptr), &data->image))
if (get_user(ptr, &src->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;
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 {
SNDRV_HWDEP_IOCTL_DSP_LOAD32 = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image32)
};
struct ioctl32_mapper hwdep_mappers[] = {
MAP_COMPAT(SNDRV_HWDEP_IOCTL_PVERSION),
MAP_COMPAT(SNDRV_HWDEP_IOCTL_INFO),
MAP_COMPAT(SNDRV_HWDEP_IOCTL_DSP_STATUS),
{ SNDRV_HWDEP_IOCTL_DSP_LOAD32, AP(hwdep_dsp_image) },
{ 0 },
};
static long snd_hwdep_ioctl_compat(struct file * file, unsigned int cmd, unsigned long arg)
{
snd_hwdep_t *hw = file->private_data;
void __user *argp = compat_ptr(arg);
switch (cmd) {
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 {
unsigned int snd_cards_lock = 0; /* locked for registering/using */
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)
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,
write_lock(&snd_card_rwlock);
if (idx < 0) {
int idx2;
for (idx2 = 0; idx2 < snd_ecards_limit; idx2++)
if (!(snd_cards_lock & (1 << idx2))) {
for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
if (~snd_cards_lock & idx & 1<<idx2) {
idx = idx2;
if (idx >= snd_ecards_limit)
snd_ecards_limit = idx + 1;
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) {
if (snd_cards_lock & (1 << idx))
err = -ENODEV; /* invalid */
......@@ -229,6 +226,10 @@ int snd_card_disconnect(snd_card_t * card)
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
* @card: soundcard structure
......@@ -252,9 +253,9 @@ int snd_card_free(snd_card_t * card)
#ifdef CONFIG_PM
wake_up(&card->power_sleep);
#ifdef CONFIG_ISA
#ifdef CONFIG_SND_GENERIC_PM
if (card->pm_dev) {
pm_unregister(card->pm_dev);
snd_generic_device_unregister(card->pm_dev);
card->pm_dev = NULL;
}
#endif
......@@ -374,7 +375,7 @@ static void choose_default_id(snd_card_t * card)
while (1) {
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);
return;
}
......@@ -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.
*/
int snd_card_set_pm_callback(snd_card_t *card,
int (*suspend)(snd_card_t *, unsigned int),
int (*resume)(snd_card_t *, unsigned int),
int (*suspend)(snd_card_t *, pm_message_t),
int (*resume)(snd_card_t *),
void *private_data)
{
card->pm_suspend = suspend;
......@@ -729,56 +730,132 @@ int snd_card_set_pm_callback(snd_card_t *card,
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) {
case PM_SUSPEND:
if (! generic_driver_registered) {
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)
break;
/* FIXME: the correct state value? */
card->pm_suspend(card, 0);
return 0;
card->pm_suspend(card, PMSG_SUSPEND);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
break;
case PM_RESUME:
return 0;
}
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)
break;
/* FIXME: the correct state value? */
card->pm_resume(card, 0);
return 0;
card->pm_resume(card);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
break;
}
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
* @type: PM device type (PM_XXX)
* @suspend: suspend callback function
* @resume: resume callback function
* @private_data: private data to pass to the callback functions
*
* Registers the power-management and sets the lowlevel callbacks for
* the given card with the given PM type. These callbacks are called
* from the ALSA's common PM handler and from the control API.
* the given card. These callbacks are called from the ALSA's common
* PM handler and from the control API.
*/
int snd_card_set_dev_pm_callback(snd_card_t *card, int type,
int (*suspend)(snd_card_t *, unsigned int),
int (*resume)(snd_card_t *, unsigned int),
int snd_card_set_generic_pm_callback(snd_card_t *card,
int (*suspend)(snd_card_t *, pm_message_t),
int (*resume)(snd_card_t *),
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)
return -ENOMEM;
card->pm_dev->data = card;
snd_card_set_pm_callback(card, suspend, resume, private_data);
return 0;
}
#endif /* CONFIG_SND_GENERIC_PM */
#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);
int err;
......@@ -786,8 +863,7 @@ int snd_card_pci_suspend(struct pci_dev *dev, u32 state)
return 0;
if (card->power_state == SNDRV_CTL_POWER_D3hot)
return 0;
/* FIXME: correct state value? */
err = card->pm_suspend(card, 0);
err = card->pm_suspend(card, PMSG_SUSPEND);
pci_save_state(dev);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
return err;
......@@ -802,8 +878,7 @@ int snd_card_pci_resume(struct pci_dev *dev)
return 0;
/* restore the PCI config space */
pci_restore_state(dev);
/* FIXME: correct state value? */
card->pm_resume(card, 0);
card->pm_resume(card);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
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;
static long snd_alloc_vmalloc;
static LIST_HEAD(snd_alloc_kmalloc_list);
static LIST_HEAD(snd_alloc_vmalloc_list);
static spinlock_t snd_alloc_kmalloc_lock = SPIN_LOCK_UNLOCKED;
static spinlock_t snd_alloc_vmalloc_lock = SPIN_LOCK_UNLOCKED;
static DEFINE_SPINLOCK(snd_alloc_kmalloc_lock);
static DEFINE_SPINLOCK(snd_alloc_vmalloc_lock);
#define KMALLOC_MAGIC 0x87654321
#define VMALLOC_MAGIC 0x87654320
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,
return -ENXIO;
}
/* FIXME: need to unlock BKL to allow preemption */
static int snd_mixer_oss_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int err;
/* 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;
return snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, 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
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
*/
......@@ -393,7 +393,8 @@ static struct file_operations snd_mixer_oss_f_ops =
.owner = THIS_MODULE,
.open = snd_mixer_oss_open,
.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 =
......
......@@ -636,10 +636,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char
if (in_kernel) {
mm_segment_t fs;
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);
} else {
ret = snd_pcm_lib_write(substream, ptr, frames);
ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
}
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
......@@ -679,10 +679,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, s
if (in_kernel) {
mm_segment_t fs;
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);
} else {
ret = snd_pcm_lib_read(substream, ptr, frames);
ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
}
if (ret == -EPIPE) {
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
if (in_kernel) {
mm_segment_t fs;
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);
} else {
ret = snd_pcm_lib_writev(substream, bufs, frames);
ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
}
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
......@@ -758,10 +758,10 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs
if (in_kernel) {
mm_segment_t fs;
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);
} else {
ret = snd_pcm_lib_readv(substream, bufs, frames);
ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
}
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
......@@ -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;
size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
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;
buf = runtime->oss.buffer;
}
......@@ -839,7 +839,7 @@ static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char __u
return xfer > 0 ? xfer : -EAGAIN;
}
} 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)
return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
runtime->oss.bytes += tmp;
......@@ -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_sframes_t frames, frames1;
char *final_dst = buf;
char __user *final_dst = (char __user *)buf;
if (runtime->oss.plugin_first) {
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;
......@@ -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) {
size = (runtime->frame_bits * size) / 8;
while (size > 0) {
mm_segment_t fs;
size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes;
size -= size1;
size1 *= 8;
......@@ -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,
runtime->oss.buffer,
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) {
void __user *buffers[runtime->channels];
......@@ -1913,8 +1916,7 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file)
return 0;
}
static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
snd_pcm_oss_file_t *pcm_oss_file;
int __user *p = (int __user *)arg;
......@@ -2073,16 +2075,12 @@ static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
}
/* FIXME: need to unlock BKL to allow preemption */
static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int err;
unlock_kernel();
err = _snd_pcm_oss_ioctl(inode, file, cmd, arg);
lock_kernel();
return err;
}
#ifdef CONFIG_COMPAT
/* all compatible */
#define snd_pcm_oss_ioctl_compat snd_pcm_oss_ioctl
#else
#define snd_pcm_oss_ioctl_compat NULL
#endif
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 =
.open = snd_pcm_oss_open,
.release = snd_pcm_oss_release,
.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,
};
......
......@@ -1004,6 +1004,7 @@ static int __init alsa_pcm_init(void)
snd_info_entry_t *entry;
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) {
snd_info_set_text_ops(entry, NULL, SNDRV_CARDS * SNDRV_PCM_DEVICES * 128, snd_pcm_proc_read);
if (snd_info_register(entry) < 0) {
......@@ -1018,6 +1019,7 @@ static int __init alsa_pcm_init(void)
static void __exit alsa_pcm_exit(void)
{
snd_ctl_unregister_ioctl(snd_pcm_control_ioctl);
snd_ctl_unregister_ioctl_compat(snd_pcm_control_ioctl);
if (snd_pcm_proc_entry) {
snd_info_unregister(snd_pcm_proc_entry);
snd_pcm_proc_entry = NULL;
......
......@@ -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
* @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().
*
* 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
*
*/
rwlock_t snd_pcm_link_rwlock = RW_LOCK_UNLOCKED;
DEFINE_RWLOCK(snd_pcm_link_rwlock);
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
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;
int res;
unsigned int channel;
snd_assert(substream != NULL, return -ENXIO);
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
channel = info.channel;
channel = info->channel;
runtime = substream->runtime;
snd_pcm_stream_lock_irq(substream);
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
snd_pcm_stream_unlock_irq(substream);
if (channel >= runtime->channels)
return -EINVAL;
memset(&info, 0, sizeof(info));
info.channel = channel;
res = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, &info);
memset(info, 0, sizeof(*info));
info->channel = channel;
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)
return res;
if (copy_to_user(_info, &info, sizeof(info)))
......@@ -2440,7 +2446,7 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream,
case SNDRV_PCM_IOCTL_STATUS:
return snd_pcm_status_user(substream, arg);
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:
return snd_pcm_prepare(substream);
case SNDRV_PCM_IOCTL_RESET:
......@@ -2640,40 +2646,28 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_common_ioctl1(substream, cmd, arg);
}
static int snd_pcm_playback_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
snd_pcm_file_t *pcm_file;
int err;
pcm_file = file->private_data;
if (((cmd >> 8) & 0xff) != 'A')
return -ENOTTY;
/* FIXME: need to unlock BKL to allow preemption */
unlock_kernel();
err = snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
lock_kernel();
return err;
return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
}
static int snd_pcm_capture_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
snd_pcm_file_t *pcm_file;
int err;
pcm_file = file->private_data;
if (((cmd >> 8) & 0xff) != 'A')
return -ENOTTY;
/* FIXME: need to unlock BKL to allow preemption */
unlock_kernel();
err = snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
lock_kernel();
return err;
return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
}
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;
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);
return result;
}
......@@ -2695,7 +2689,7 @@ int snd_pcm_kernel_capture_ioctl(snd_pcm_substream_t *substream,
int result;
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);
return result;
}
......@@ -3197,6 +3191,15 @@ static int snd_pcm_fasync(int fd, struct file * file, int on)
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
*/
......@@ -3318,7 +3321,8 @@ static struct file_operations snd_pcm_f_ops_playback = {
.open = snd_pcm_open,
.release = snd_pcm_release,
.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,
.fasync = snd_pcm_fasync,
};
......@@ -3330,7 +3334,8 @@ static struct file_operations snd_pcm_f_ops_capture = {
.open = snd_pcm_open,
.release = snd_pcm_release,
.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,
.fasync = snd_pcm_fasync,
};
......
......@@ -29,6 +29,8 @@
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <sound/rawmidi.h>
#include <sound/info.h>
#include <sound/control.h>
......@@ -115,7 +117,6 @@ int snd_rawmidi_drop_output(snd_rawmidi_substream_t * substream)
snd_rawmidi_runtime_t *runtime = substream->runtime;
substream->ops->trigger(substream, 0);
runtime->trigger = 0;
runtime->drain = 0;
/* interrupts are not enabled at this moment,
so spinlock is not required */
......@@ -132,27 +133,22 @@ int snd_rawmidi_drain_output(snd_rawmidi_substream_t * substream)
err = 0;
runtime->drain = 1;
while (runtime->avail < runtime->buffer_size) {
timeout = interruptible_sleep_on_timeout(&runtime->sleep, 10 * HZ);
if (signal_pending(current)) {
timeout = wait_event_interruptible_timeout(runtime->sleep,
(runtime->avail >= runtime->buffer_size),
10*HZ);
if (signal_pending(current))
err = -ERESTARTSYS;
break;
}
if (runtime->avail < runtime->buffer_size && !timeout) {
snd_printk(KERN_WARNING "rawmidi drain error (avail = %li, buffer_size = %li)\n", (long)runtime->avail, (long)runtime->buffer_size);
err = -EIO;
break;
}
}
runtime->drain = 0;
if (err != -ERESTARTSYS) {
/* we need wait a while to make sure that Tx FIFOs are empty */
if (substream->ops->drain)
substream->ops->drain(substream);
else {
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ / 20);
}
else
msleep(50);
snd_rawmidi_drop_output(substream);
}
return err;
......@@ -163,7 +159,6 @@ int snd_rawmidi_drain_input(snd_rawmidi_substream_t * substream)
snd_rawmidi_runtime_t *runtime = substream->runtime;
substream->ops->trigger(substream, 0);
runtime->trigger = 0;
runtime->drain = 0;
/* interrupts aren't enabled at this moment, so spinlock isn't needed */
runtime->appl_ptr = runtime->hw_ptr = 0;
......@@ -465,7 +460,6 @@ int snd_rawmidi_kernel_release(snd_rawmidi_file_t * rfile)
substream = rfile->input;
rfile->input = NULL;
runtime = substream->runtime;
runtime->trigger = 0;
substream->ops->trigger(substream, 0);
substream->ops->close(substream);
snd_rawmidi_done_buffer(runtime);
......@@ -673,8 +667,7 @@ static int snd_rawmidi_input_status(snd_rawmidi_substream_t * substream,
return 0;
}
static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
snd_rawmidi_file_t *rfile;
void __user *argp = (void __user *)arg;
......@@ -784,17 +777,6 @@ static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file,
return -ENOTTY;
}
/* FIXME: need to unlock BKL to allow preemption */
static int snd_rawmidi_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int err;
unlock_kernel();
err = _snd_rawmidi_ioctl(inode, file, cmd, arg);
lock_kernel();
return err;
}
static int snd_rawmidi_control_ioctl(snd_card_t * card,
snd_ctl_file_t * control,
unsigned int cmd,
......@@ -887,7 +869,7 @@ int snd_rawmidi_receive(snd_rawmidi_substream_t * substream, const unsigned char
count1 = count;
if (count1 > (int)(runtime->buffer_size - runtime->avail)) {
count1 = runtime->buffer_size - runtime->avail;
runtime->xruns = count - count1;
runtime->xruns += count - count1;
}
if (count1 > 0) {
memcpy(runtime->buffer, buffer, count1);
......@@ -925,7 +907,8 @@ static long snd_rawmidi_kernel_read1(snd_rawmidi_substream_t *substream,
memcpy(buf + result, runtime->buffer + runtime->appl_ptr, count1);
} else {
spin_unlock_irqrestore(&runtime->lock, flags);
if (copy_to_user(buf + result, runtime->buffer + runtime->appl_ptr, count1)) {
if (copy_to_user((char __user *)buf + result,
runtime->buffer + runtime->appl_ptr, count1)) {
return result > 0 ? result : -EFAULT;
}
spin_lock_irqsave(&runtime->lock, flags);
......@@ -942,7 +925,6 @@ static long snd_rawmidi_kernel_read1(snd_rawmidi_substream_t *substream,
long snd_rawmidi_kernel_read(snd_rawmidi_substream_t *substream, unsigned char *buf, long count)
{
substream->runtime->trigger = 1;
substream->ops->trigger(substream, 1);
return snd_rawmidi_kernel_read1(substream, buf, count, 1);
}
......@@ -960,7 +942,6 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
if (substream == NULL)
return -EIO;
runtime = substream->runtime;
runtime->trigger = 1;
substream->ops->trigger(substream, 1);
result = 0;
while (count > 0) {
......@@ -984,7 +965,7 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
spin_lock_irq(&runtime->lock);
}
spin_unlock_irq(&runtime->lock);
count1 = snd_rawmidi_kernel_read1(substream, buf, count, 0);
count1 = snd_rawmidi_kernel_read1(substream, (unsigned char *)buf, count, 0);
if (count1 < 0)
return result > 0 ? result : count1;
result += count1;
......@@ -1012,8 +993,6 @@ int snd_rawmidi_transmit_empty(snd_rawmidi_substream_t * substream)
}
spin_lock_irqsave(&runtime->lock, flags);
result = runtime->avail >= runtime->buffer_size;
if (result)
runtime->trigger = 1;
spin_unlock_irqrestore(&runtime->lock, flags);
return result;
}
......@@ -1046,7 +1025,6 @@ int snd_rawmidi_transmit_peek(snd_rawmidi_substream_t * substream, unsigned char
spin_lock_irqsave(&runtime->lock, flags);
if (runtime->avail >= runtime->buffer_size) {
/* warning: lowlevel layer MUST trigger down the hardware */
runtime->trigger = 0;
goto __skip;
}
if (count == 1) { /* special case, faster code */
......@@ -1061,8 +1039,12 @@ int snd_rawmidi_transmit_peek(snd_rawmidi_substream_t * substream, unsigned char
memcpy(buffer, runtime->buffer + runtime->hw_ptr, count1);
count -= count1;
result += count1;
if (count > 0)
if (count > 0) {
if (count > (int)(runtime->buffer_size - runtime->avail - count1))
count = runtime->buffer_size - runtime->avail - count1;
memcpy(buffer + count1, runtime->buffer, count);
result += count;
}
}
__skip:
spin_unlock_irqrestore(&runtime->lock, flags);
......@@ -1152,7 +1134,8 @@ static long snd_rawmidi_kernel_write1(snd_rawmidi_substream_t * substream, const
memcpy(runtime->buffer + runtime->appl_ptr, buf, count1);
} else {
spin_unlock_irqrestore(&runtime->lock, flags);
if (copy_from_user(runtime->buffer + runtime->appl_ptr, buf, count1)) {
if (copy_from_user(runtime->buffer + runtime->appl_ptr,
(char __user *)buf, count1)) {
spin_lock_irqsave(&runtime->lock, flags);
result = result > 0 ? result : -EFAULT;
goto __end;
......@@ -1167,8 +1150,6 @@ static long snd_rawmidi_kernel_write1(snd_rawmidi_substream_t * substream, const
count -= count1;
}
__end:
if (result > 0)
runtime->trigger = 1;
count1 = runtime->avail < runtime->buffer_size;
spin_unlock_irqrestore(&runtime->lock, flags);
if (count1)
......@@ -1217,7 +1198,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, size
spin_lock_irq(&runtime->lock);
}
spin_unlock_irq(&runtime->lock);
count1 = snd_rawmidi_kernel_write1(substream, buf, count, 0);
count1 = snd_rawmidi_kernel_write1(substream, (unsigned char *)buf, count, 0);
if (count1 < 0)
return result > 0 ? result : count1;
result += count1;
......@@ -1257,7 +1238,6 @@ static unsigned int snd_rawmidi_poll(struct file *file, poll_table * wait)
rfile = file->private_data;
if (rfile->input != NULL) {
runtime = rfile->input->runtime;
runtime->trigger = 1;
rfile->input->ops->trigger(rfile->input, 1);
poll_wait(file, &runtime->sleep, wait);
}
......@@ -1277,6 +1257,14 @@ static unsigned int snd_rawmidi_poll(struct file *file, poll_table * wait)
return mask;
}
/*
*/
#ifdef CONFIG_COMPAT
#include "rawmidi_compat.c"
#else
#define snd_rawmidi_ioctl_compat NULL
#endif
/*
*/
......@@ -1347,7 +1335,8 @@ static struct file_operations snd_rawmidi_f_ops =
.open = snd_rawmidi_open,
.release = snd_rawmidi_release,
.poll = snd_rawmidi_poll,
.ioctl = snd_rawmidi_ioctl,
.unlocked_ioctl = snd_rawmidi_ioctl,
.compat_ioctl = snd_rawmidi_ioctl_compat,
};
static snd_minor_t snd_rawmidi_reg =
......@@ -1628,6 +1617,7 @@ static int __init alsa_rawmidi_init(void)
{
snd_ctl_register_ioctl(snd_rawmidi_control_ioctl);
snd_ctl_register_ioctl_compat(snd_rawmidi_control_ioctl);
#ifdef CONFIG_SND_OSSEMUL
{ int i;
/* check device map table */
......@@ -1649,6 +1639,7 @@ static int __init alsa_rawmidi_init(void)
static void __exit alsa_rawmidi_exit(void)
{
snd_ctl_unregister_ioctl(snd_rawmidi_control_ioctl);
snd_ctl_unregister_ioctl_compat(snd_rawmidi_control_ioctl);
}
module_init(alsa_rawmidi_init)
......
......@@ -18,14 +18,9 @@
*
*/
#include <sound/driver.h>
#include <linux/time.h>
#include <linux/fs.h>
/* This file included from rawmidi.c */
#include <linux/compat.h>
#include <sound/core.h>
#include <sound/rawmidi.h>
#include <asm/uaccess.h>
#include "ioctl32.h"
struct sndrv_rawmidi_params32 {
s32 stream;
......@@ -35,14 +30,27 @@ struct sndrv_rawmidi_params32 {
unsigned char reserved[16];
} __attribute__((packed));
#define CVT_sndrv_rawmidi_params()\
{\
COPY(stream);\
COPY_CVT(buffer_size);\
COPY_CVT(avail_min);\
if (copy_in_user(((size_t __user *)&dst->avail_min + 1),\
((size_t __user *)&src->avail_min + 1), 4)) \
return -EFAULT;\
static int snd_rawmidi_ioctl_params_compat(snd_rawmidi_file_t *rfile,
struct sndrv_rawmidi_params32 __user *src)
{
snd_rawmidi_params_t params;
unsigned int val;
if (rfile->output == NULL)
return -EINVAL;
if (get_user(params.stream, &src->stream) ||
get_user(params.buffer_size, &src->buffer_size) ||
get_user(params.avail_min, &src->avail_min) ||
get_user(val, &src->no_active_sensing))
return -EFAULT;
params.no_active_sensing = val;
switch (params.stream) {
case SNDRV_RAWMIDI_STREAM_OUTPUT:
return snd_rawmidi_output_params(rfile->output, &params);
case SNDRV_RAWMIDI_STREAM_INPUT:
return snd_rawmidi_input_params(rfile->input, &params);
}
return -EINVAL;
}
struct sndrv_rawmidi_status32 {
......@@ -53,39 +61,60 @@ struct sndrv_rawmidi_status32 {
unsigned char reserved[16];
} __attribute__((packed));
#define CVT_sndrv_rawmidi_status()\
{\
COPY(stream);\
COPY_CVT(tstamp.tv_sec);\
COPY_CVT(tstamp.tv_nsec);\
COPY_CVT(avail);\
COPY_CVT(xruns);\
}
static int snd_rawmidi_ioctl_status_compat(snd_rawmidi_file_t *rfile,
struct sndrv_rawmidi_status32 __user *src)
{
int err;
snd_rawmidi_status_t status;
if (rfile->output == NULL)
return -EINVAL;
if (get_user(status.stream, &src->stream))
return -EFAULT;
DEFINE_ALSA_IOCTL(rawmidi_params);
DEFINE_ALSA_IOCTL(rawmidi_status);
switch (status.stream) {
case SNDRV_RAWMIDI_STREAM_OUTPUT:
err = snd_rawmidi_output_status(rfile->output, &status);
break;
case SNDRV_RAWMIDI_STREAM_INPUT:
err = snd_rawmidi_input_status(rfile->input, &status);
break;
default:
return -EINVAL;
}
if (err < 0)
return err;
DEFINE_ALSA_IOCTL_ENTRY(rawmidi_params, rawmidi_params, SNDRV_RAWMIDI_IOCTL_PARAMS);
DEFINE_ALSA_IOCTL_ENTRY(rawmidi_status, rawmidi_status, SNDRV_RAWMIDI_IOCTL_STATUS);
if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) ||
put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) ||
put_user(status.avail, &src->avail) ||
put_user(status.xruns, &src->xruns))
return -EFAULT;
#define AP(x) snd_ioctl32_##x
return 0;
}
enum {
SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct sndrv_rawmidi_params32),
SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct sndrv_rawmidi_status32),
};
struct ioctl32_mapper rawmidi_mappers[] = {
MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_PVERSION),
MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_INFO),
{ SNDRV_RAWMIDI_IOCTL_PARAMS32, AP(rawmidi_params) },
{ SNDRV_RAWMIDI_IOCTL_STATUS32, AP(rawmidi_status) },
MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_DROP),
MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_DRAIN),
MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE),
MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_INFO),
MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE),
static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
{
snd_rawmidi_file_t *rfile;
void __user *argp = compat_ptr(arg);
{ 0 },
};
rfile = file->private_data;
switch (cmd) {
case SNDRV_RAWMIDI_IOCTL_PVERSION:
case SNDRV_RAWMIDI_IOCTL_INFO:
case SNDRV_RAWMIDI_IOCTL_DROP:
case SNDRV_RAWMIDI_IOCTL_DRAIN:
return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp);
case SNDRV_RAWMIDI_IOCTL_PARAMS32:
return snd_rawmidi_ioctl_params_compat(rfile, argp);
case SNDRV_RAWMIDI_IOCTL_STATUS32:
return snd_rawmidi_ioctl_status_compat(rfile, argp);
}
return -ENOIOCTLCMD;
}
......@@ -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 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 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);
#ifdef CONFIG_PROC_FS
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
return snd_seq_oss_write(dp, buf, count, file);
}
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)
{
seq_oss_devinfo_t *dp;
int err;
dp = file->private_data;
snd_assert(dp != NULL, return -EIO);
/* FIXME: need to unlock BKL to allow preemption */
unlock_kernel();
err = snd_seq_oss_ioctl(dp, cmd, arg);
lock_kernel();
return err;
return snd_seq_oss_ioctl(dp, cmd, arg);
}
#ifdef CONFIG_COMPAT
#define odev_ioctl_compat odev_ioctl
#else
#define odev_ioctl_compat NULL
#endif
static unsigned int
odev_poll(struct file *file, poll_table * wait)
......@@ -213,7 +213,8 @@ static struct file_operations seq_oss_f_ops =
.open = odev_open,
.release = odev_release,
.poll = odev_poll,
.ioctl = odev_ioctl,
.unlocked_ioctl = odev_ioctl,
.compat_ioctl = odev_ioctl_compat,
};
static snd_minor_t seq_oss_reg = {
......
......@@ -56,7 +56,7 @@ struct seq_oss_midi_t {
static int max_midi_devs;
static seq_oss_midi_t *midi_devs[SNDRV_SEQ_OSS_MAX_MIDI_DEVS];
static spinlock_t register_lock = SPIN_LOCK_UNLOCKED;
static DEFINE_SPINLOCK(register_lock);
/*
* prototypes
......
......@@ -24,6 +24,7 @@
#include "seq_oss_event.h"
#include <sound/seq_oss_legacy.h>
#include "../seq_lock.h"
#include <linux/wait.h>
/*
* constants
......@@ -165,7 +166,9 @@ snd_seq_oss_readq_pick(seq_oss_readq_t *q, evrec_t *rec)
void
snd_seq_oss_readq_wait(seq_oss_readq_t *q)
{
interruptible_sleep_on_timeout(&q->midi_sleep, q->pre_event_timeout);
wait_event_interruptible_timeout(q->midi_sleep,
(q->qlen > 0 || q->head == q->tail),
q->pre_event_timeout);
}
/*
......
......@@ -75,7 +75,7 @@ static seq_oss_synth_t midi_synth_dev = {
"MIDI", /* name */
};
static spinlock_t register_lock = SPIN_LOCK_UNLOCKED;
static DEFINE_SPINLOCK(register_lock);
/*
* prototypes
......
......@@ -26,6 +26,7 @@
#include <sound/seq_oss_legacy.h>
#include "../seq_lock.h"
#include "../seq_clientmgr.h"
#include <linux/wait.h>
/*
......@@ -91,7 +92,6 @@ snd_seq_oss_writeq_sync(seq_oss_writeq_t *q)
{
seq_oss_devinfo_t *dp = q->dp;
abstime_t time;
unsigned long flags;
time = snd_seq_oss_timer_cur_tick(dp->timer);
if (q->sync_time >= time)
......@@ -115,26 +115,12 @@ snd_seq_oss_writeq_sync(seq_oss_writeq_t *q)
snd_seq_kernel_client_enqueue_blocking(dp->cseq, &ev, NULL, 0, 0);
}
spin_lock_irqsave(&q->sync_lock, flags);
if (! q->sync_event_put) { /* echoback event has been received */
spin_unlock_irqrestore(&q->sync_lock, flags);
return 0;
}
/* wait for echo event */
spin_unlock(&q->sync_lock);
interruptible_sleep_on_timeout(&q->sync_sleep, HZ);
spin_lock(&q->sync_lock);
if (signal_pending(current)) {
wait_event_interruptible_timeout(q->sync_sleep, ! q->sync_event_put, HZ);
if (signal_pending(current))
/* interrupted - return 0 to finish sync */
q->sync_event_put = 0;
spin_unlock_irqrestore(&q->sync_lock, flags);
return 0;
}
spin_unlock_irqrestore(&q->sync_lock, flags);
if (q->sync_time >= time)
if (! q->sync_event_put || q->sync_time >= time)
return 0;
else
return 1;
}
......
This diff is collapsed.
......@@ -430,7 +430,7 @@ static int instr_put(snd_seq_kinstr_ops_t *ops,
if (ev->data.ext.len < sizeof(snd_seq_instr_header_t))
goto __return;
if (copy_from_user(&put, ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) {
if (copy_from_user(&put, (void __user *)ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) {
result = -EFAULT;
goto __return;
}
......@@ -466,7 +466,7 @@ static int instr_put(snd_seq_kinstr_ops_t *ops,
if (instr->type == SNDRV_SEQ_INSTR_ATYPE_DATA) {
result = ops->put(ops->private_data,
instr,
ev->data.ext.ptr + sizeof(snd_seq_instr_header_t),
(void __user *)ev->data.ext.ptr + sizeof(snd_seq_instr_header_t),
ev->data.ext.len - sizeof(snd_seq_instr_header_t),
atomic,
put.cmd);
......@@ -513,7 +513,7 @@ static int instr_free(snd_seq_kinstr_ops_t *ops,
if (ev->data.ext.len < sizeof(snd_seq_instr_header_t))
goto __return;
if (copy_from_user(&ifree, ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) {
if (copy_from_user(&ifree, (void __user *)ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) {
result = -EFAULT;
goto __return;
}
......
......@@ -90,7 +90,7 @@ int snd_seq_dump_var_event(const snd_seq_event_t *event, snd_seq_dump_func_t fun
if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
char buf[32];
char __user *curptr = event->data.ext.ptr;
char __user *curptr = (char __user *)event->data.ext.ptr;
while (len > 0) {
int size = sizeof(buf);
if (len < size)
......@@ -134,7 +134,7 @@ static int seq_copy_in_kernel(char **bufptr, const void *src, int size)
return 0;
}
static int seq_copy_in_user(char **bufptr, const void *src, int size)
static int seq_copy_in_user(char __user **bufptr, const void *src, int size)
{
if (copy_to_user(*bufptr, src, size))
return -EFAULT;
......@@ -158,7 +158,7 @@ int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf,
if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
if (! in_kernel)
return -EINVAL;
if (copy_from_user(buf, event->data.ext.ptr, len))
if (copy_from_user(buf, (void __user *)event->data.ext.ptr, len))
return -EFAULT;
return newlen;
}
......@@ -336,7 +336,7 @@ int snd_seq_event_dup(pool_t *pool, snd_seq_event_t *event, snd_seq_event_cell_t
tmp->event = src->event;
src = src->next;
} else if (is_usrptr) {
if (copy_from_user(&tmp->event, buf, size)) {
if (copy_from_user(&tmp->event, (char __user *)buf, size)) {
err = -EFAULT;
goto __error;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -111,7 +111,7 @@ int snd_seq_queue_use(int queueid, int client, int use);
int snd_seq_queue_is_used(int queueid, int client);
int snd_seq_control_queue(snd_seq_event_t *ev, int atomic, int hop);
void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int from_timer_port, int atomic, int hop);
void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop);
/*
* 64bit division - for sync stuff..
......
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