#include <linux/ac97_codec.h>
#include <linux/gameport.h>
#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/mutex.h>
+#include <linux/mm.h>
#include <asm/io.h>
#include <asm/page.h>
#include <asm/uaccess.h>
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+#define SUPPORT_JOYSTICK
+#endif
+
/* --------------------------------------------------------------------- */
#undef OSS_DOCUMENTED_MIXER_SEMANTICS
unsigned dac1rate, dac2rate, adcrate;
spinlock_t lock;
- struct semaphore open_sem;
+ struct mutex open_mutex;
mode_t open_mode;
wait_queue_head_t open_wait;
unsigned char obuf[MIDIOUTBUF];
} midi;
- struct gameport gameport;
- struct semaphore sem;
+#ifdef SUPPORT_JOYSTICK
+ struct gameport *gameport;
+#endif
+
+ struct mutex sem;
};
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
-static void __init src_init(struct es1371_state *s)
+static void __devinit src_init(struct es1371_state *s)
{
unsigned int i;
if (!db->rawbuf)
return -ENOMEM;
db->buforder = order;
- /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
+ /* now mark the pages as reserved; otherwise remap_pfn_range doesn't do what we want */
pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
for (page = virt_to_page(db->rawbuf); page <= pend; page++)
SetPageReserved(page);
outb((s->midi.ocnt > 0) ? UCTRL_RXINTEN | UCTRL_ENA_TXINT : UCTRL_RXINTEN, s->io+ES1371_REG_UART_CONTROL);
}
-static irqreturn_t es1371_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t es1371_interrupt(int irq, void *dev_id)
{
- struct es1371_state *s = (struct es1371_state *)dev_id;
+ struct es1371_state *s = dev_id;
unsigned int intsrc, sctl;
/* fastpath out, to ease interrupt sharing */
return 0;
case SOUND_MIXER_WRITE_PCM: /* use SRC for PCM volume */
- if (get_user(val, (int *)arg))
+ if (get_user(val, (int __user *)arg))
return -EFAULT;
right = ((val >> 8) & 0xff);
left = (val & 0xff);
return 0;
case SOUND_MIXER_READ_PCM:
- return put_user(s->spdif_volume, (int *)arg);
+ return put_user(s->spdif_volume, (int __user *)arg);
}
return codec->mixer_ioctl(codec, cmd, arg);
}
}
VALIDATE_STATE(s);
file->private_data = s;
- return 0;
+ return nonseekable_open(inode, file);
}
static int es1371_release_mixdev(struct inode *inode, struct file *file)
/* --------------------------------------------------------------------- */
-static ssize_t es1371_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+static ssize_t es1371_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
struct es1371_state *s = (struct es1371_state *)file->private_data;
DECLARE_WAITQUEUE(wait, current);
int cnt;
VALIDATE_STATE(s);
- if (ppos != &file->f_pos)
- return -ESPIPE;
if (s->dma_adc.mapped)
return -ENXIO;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
- down(&s->sem);
+ mutex_lock(&s->sem);
if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
goto out2;
ret = -EAGAIN;
goto out;
}
- up(&s->sem);
+ mutex_unlock(&s->sem);
schedule();
if (signal_pending(current)) {
if (!ret)
ret = -ERESTARTSYS;
goto out2;
}
- down(&s->sem);
+ mutex_lock(&s->sem);
if (s->dma_adc.mapped)
{
ret = -ENXIO;
start_adc(s);
}
out:
- up(&s->sem);
+ mutex_unlock(&s->sem);
out2:
remove_wait_queue(&s->dma_adc.wait, &wait);
set_current_state(TASK_RUNNING);
return ret;
}
-static ssize_t es1371_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+static ssize_t es1371_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
struct es1371_state *s = (struct es1371_state *)file->private_data;
DECLARE_WAITQUEUE(wait, current);
int cnt;
VALIDATE_STATE(s);
- if (ppos != &file->f_pos)
- return -ESPIPE;
if (s->dma_dac2.mapped)
return -ENXIO;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
- down(&s->sem);
+ mutex_lock(&s->sem);
if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s)))
goto out3;
ret = 0;
ret = -EAGAIN;
goto out;
}
- up(&s->sem);
+ mutex_unlock(&s->sem);
schedule();
if (signal_pending(current)) {
if (!ret)
ret = -ERESTARTSYS;
goto out2;
}
- down(&s->sem);
+ mutex_lock(&s->sem);
if (s->dma_dac2.mapped)
{
ret = -ENXIO;
start_dac2(s);
}
out:
- up(&s->sem);
+ mutex_unlock(&s->sem);
out2:
remove_wait_queue(&s->dma_dac2.wait, &wait);
out3:
VALIDATE_STATE(s);
lock_kernel();
- down(&s->sem);
+ mutex_lock(&s->sem);
if (vma->vm_flags & VM_WRITE) {
if ((ret = prog_dmabuf_dac2(s)) != 0) {
ret = -EINVAL;
goto out;
}
- if (remap_page_range(vma, vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) {
+ if (remap_pfn_range(vma, vma->vm_start,
+ virt_to_phys(db->rawbuf) >> PAGE_SHIFT,
+ size, vma->vm_page_prot)) {
ret = -EAGAIN;
goto out;
}
db->mapped = 1;
out:
- up(&s->sem);
+ mutex_unlock(&s->sem);
unlock_kernel();
return ret;
}
count_info cinfo;
int count;
int val, mapped, ret;
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
VALIDATE_STATE(s);
mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac2.mapped) ||
((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
switch (cmd) {
case OSS_GETVERSION:
- return put_user(SOUND_VERSION, (int *)arg);
+ return put_user(SOUND_VERSION, p);
case SNDCTL_DSP_SYNC:
if (file->f_mode & FMODE_WRITE)
return 0;
case SNDCTL_DSP_GETCAPS:
- return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg);
+ return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, p);
case SNDCTL_DSP_RESET:
if (file->f_mode & FMODE_WRITE) {
return 0;
case SNDCTL_DSP_SPEED:
- if (get_user(val, (int *)arg))
+ if (get_user(val, p))
return -EFAULT;
if (val >= 0) {
if (file->f_mode & FMODE_READ) {
set_dac2_rate(s, val);
}
}
- return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, (int *)arg);
+ return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, p);
case SNDCTL_DSP_STEREO:
- if (get_user(val, (int *)arg))
+ if (get_user(val, p))
return -EFAULT;
if (file->f_mode & FMODE_READ) {
stop_adc(s);
return 0;
case SNDCTL_DSP_CHANNELS:
- if (get_user(val, (int *)arg))
+ if (get_user(val, p))
return -EFAULT;
if (val != 0) {
if (file->f_mode & FMODE_READ) {
spin_unlock_irqrestore(&s->lock, flags);
}
}
- return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ? 2 : 1, (int *)arg);
+ return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ? 2 : 1, p);
case SNDCTL_DSP_GETFMTS: /* Returns a mask */
- return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
+ return put_user(AFMT_S16_LE|AFMT_U8, p);
case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
- if (get_user(val, (int *)arg))
+ if (get_user(val, p))
return -EFAULT;
if (val != AFMT_QUERY) {
if (file->f_mode & FMODE_READ) {
}
}
return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SEB : SCTRL_P2SEB)) ?
- AFMT_S16_LE : AFMT_U8, (int *)arg);
+ AFMT_S16_LE : AFMT_U8, p);
case SNDCTL_DSP_POST:
return 0;
val |= PCM_ENABLE_INPUT;
if (file->f_mode & FMODE_WRITE && s->ctrl & CTRL_DAC2_EN)
val |= PCM_ENABLE_OUTPUT;
- return put_user(val, (int *)arg);
+ return put_user(val, p);
case SNDCTL_DSP_SETTRIGGER:
- if (get_user(val, (int *)arg))
+ if (get_user(val, p))
return -EFAULT;
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
abinfo.fragstotal = s->dma_dac2.numfrag;
abinfo.fragments = abinfo.bytes >> s->dma_dac2.fragshift;
spin_unlock_irqrestore(&s->lock, flags);
- return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+ return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
case SNDCTL_DSP_GETISPACE:
if (!(file->f_mode & FMODE_READ))
abinfo.fragstotal = s->dma_adc.numfrag;
abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;
spin_unlock_irqrestore(&s->lock, flags);
- return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+ return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
case SNDCTL_DSP_NONBLOCK:
file->f_flags |= O_NONBLOCK;
spin_unlock_irqrestore(&s->lock, flags);
if (count < 0)
count = 0;
- return put_user(count, (int *)arg);
+ return put_user(count, p);
case SNDCTL_DSP_GETIPTR:
if (!(file->f_mode & FMODE_READ))
if (s->dma_adc.mapped)
s->dma_adc.count &= s->dma_adc.fragsize-1;
spin_unlock_irqrestore(&s->lock, flags);
- if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+ if (copy_to_user(argp, &cinfo, sizeof(cinfo)))
return -EFAULT;
return 0;
if (s->dma_dac2.mapped)
s->dma_dac2.count &= s->dma_dac2.fragsize-1;
spin_unlock_irqrestore(&s->lock, flags);
- if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+ if (copy_to_user(argp, &cinfo, sizeof(cinfo)))
return -EFAULT;
return 0;
if (file->f_mode & FMODE_WRITE) {
if ((val = prog_dmabuf_dac2(s)))
return val;
- return put_user(s->dma_dac2.fragsize, (int *)arg);
+ return put_user(s->dma_dac2.fragsize, p);
}
if ((val = prog_dmabuf_adc(s)))
return val;
- return put_user(s->dma_adc.fragsize, (int *)arg);
+ return put_user(s->dma_adc.fragsize, p);
case SNDCTL_DSP_SETFRAGMENT:
- if (get_user(val, (int *)arg))
+ if (get_user(val, p))
return -EFAULT;
if (file->f_mode & FMODE_READ) {
s->dma_adc.ossfragshift = val & 0xffff;
if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
(file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision))
return -EINVAL;
- if (get_user(val, (int *)arg))
+ if (get_user(val, p))
return -EFAULT;
if (val != 1 && val != 2 && val != 4)
return -EINVAL;
return 0;
case SOUND_PCM_READ_RATE:
- return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, (int *)arg);
+ return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, p);
case SOUND_PCM_READ_CHANNELS:
- return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ? 2 : 1, (int *)arg);
+ return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ? 2 : 1, p);
case SOUND_PCM_READ_BITS:
- return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SEB : SCTRL_P2SEB)) ? 16 : 8, (int *)arg);
+ return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SEB : SCTRL_P2SEB)) ? 16 : 8, p);
case SOUND_PCM_WRITE_FILTER:
case SNDCTL_DSP_SETSYNCRO:
VALIDATE_STATE(s);
file->private_data = s;
/* wait for device to become free */
- down(&s->open_sem);
+ mutex_lock(&s->open_mutex);
while (s->open_mode & file->f_mode) {
if (file->f_flags & O_NONBLOCK) {
- up(&s->open_sem);
+ mutex_unlock(&s->open_mutex);
return -EBUSY;
}
add_wait_queue(&s->open_wait, &wait);
__set_current_state(TASK_INTERRUPTIBLE);
- up(&s->open_sem);
+ mutex_unlock(&s->open_mutex);
schedule();
remove_wait_queue(&s->open_wait, &wait);
set_current_state(TASK_RUNNING);
if (signal_pending(current))
return -ERESTARTSYS;
- down(&s->open_sem);
+ mutex_lock(&s->open_mutex);
}
if (file->f_mode & FMODE_READ) {
s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0;
outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
spin_unlock_irqrestore(&s->lock, flags);
s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
- up(&s->open_sem);
- init_MUTEX(&s->sem);
- return 0;
+ mutex_unlock(&s->open_mutex);
+ mutex_init(&s->sem);
+ return nonseekable_open(inode, file);
}
static int es1371_release(struct inode *inode, struct file *file)
lock_kernel();
if (file->f_mode & FMODE_WRITE)
drain_dac2(s, file->f_flags & O_NONBLOCK);
- down(&s->open_sem);
+ mutex_lock(&s->open_mutex);
if (file->f_mode & FMODE_WRITE) {
stop_dac2(s);
dealloc_dmabuf(s, &s->dma_dac2);
dealloc_dmabuf(s, &s->dma_adc);
}
s->open_mode &= ~(file->f_mode & (FMODE_READ|FMODE_WRITE));
- up(&s->open_sem);
+ mutex_unlock(&s->open_mutex);
wake_up(&s->open_wait);
unlock_kernel();
return 0;
/* --------------------------------------------------------------------- */
-static ssize_t es1371_write_dac(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+static ssize_t es1371_write_dac(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
struct es1371_state *s = (struct es1371_state *)file->private_data;
DECLARE_WAITQUEUE(wait, current);
int cnt;
VALIDATE_STATE(s);
- if (ppos != &file->f_pos)
- return -ESPIPE;
if (s->dma_dac1.mapped)
return -ENXIO;
if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s)))
if (size > (PAGE_SIZE << s->dma_dac1.buforder))
goto out;
ret = -EAGAIN;
- if (remap_page_range(vma, vma->vm_start, virt_to_phys(s->dma_dac1.rawbuf), size, vma->vm_page_prot))
+ if (remap_pfn_range(vma, vma->vm_start,
+ virt_to_phys(s->dma_dac1.rawbuf) >> PAGE_SHIFT,
+ size, vma->vm_page_prot))
goto out;
s->dma_dac1.mapped = 1;
ret = 0;
count_info cinfo;
int count;
int val, ret;
+ int __user *p = (int __user *)arg;
VALIDATE_STATE(s);
switch (cmd) {
case OSS_GETVERSION:
- return put_user(SOUND_VERSION, (int *)arg);
+ return put_user(SOUND_VERSION, p);
case SNDCTL_DSP_SYNC:
return drain_dac1(s, 0/*file->f_flags & O_NONBLOCK*/);
return -EINVAL;
case SNDCTL_DSP_GETCAPS:
- return put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg);
+ return put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, p);
case SNDCTL_DSP_RESET:
stop_dac1(s);
return 0;
case SNDCTL_DSP_SPEED:
- if (get_user(val, (int *)arg))
+ if (get_user(val, p))
return -EFAULT;
if (val >= 0) {
stop_dac1(s);
s->dma_dac1.ready = 0;
set_dac1_rate(s, val);
}
- return put_user(s->dac1rate, (int *)arg);
+ return put_user(s->dac1rate, p);
case SNDCTL_DSP_STEREO:
- if (get_user(val, (int *)arg))
+ if (get_user(val, p))
return -EFAULT;
stop_dac1(s);
s->dma_dac1.ready = 0;
return 0;
case SNDCTL_DSP_CHANNELS:
- if (get_user(val, (int *)arg))
+ if (get_user(val, p))
return -EFAULT;
if (val != 0) {
stop_dac1(s);
outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
spin_unlock_irqrestore(&s->lock, flags);
}
- return put_user((s->sctrl & SCTRL_P1SMB) ? 2 : 1, (int *)arg);
+ return put_user((s->sctrl & SCTRL_P1SMB) ? 2 : 1, p);
case SNDCTL_DSP_GETFMTS: /* Returns a mask */
- return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
+ return put_user(AFMT_S16_LE|AFMT_U8, p);
case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
- if (get_user(val, (int *)arg))
+ if (get_user(val, p))
return -EFAULT;
if (val != AFMT_QUERY) {
stop_dac1(s);
outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
spin_unlock_irqrestore(&s->lock, flags);
}
- return put_user((s->sctrl & SCTRL_P1SEB) ? AFMT_S16_LE : AFMT_U8, (int *)arg);
+ return put_user((s->sctrl & SCTRL_P1SEB) ? AFMT_S16_LE : AFMT_U8, p);
case SNDCTL_DSP_POST:
return 0;
case SNDCTL_DSP_GETTRIGGER:
- return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, (int *)arg);
+ return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, p);
case SNDCTL_DSP_SETTRIGGER:
- if (get_user(val, (int *)arg))
+ if (get_user(val, p))
return -EFAULT;
if (val & PCM_ENABLE_OUTPUT) {
if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s)))
abinfo.fragstotal = s->dma_dac1.numfrag;
abinfo.fragments = abinfo.bytes >> s->dma_dac1.fragshift;
spin_unlock_irqrestore(&s->lock, flags);
- return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+ return copy_to_user((void __user *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
case SNDCTL_DSP_NONBLOCK:
file->f_flags |= O_NONBLOCK;
spin_unlock_irqrestore(&s->lock, flags);
if (count < 0)
count = 0;
- return put_user(count, (int *)arg);
+ return put_user(count, p);
case SNDCTL_DSP_GETOPTR:
if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
if (s->dma_dac1.mapped)
s->dma_dac1.count &= s->dma_dac1.fragsize-1;
spin_unlock_irqrestore(&s->lock, flags);
- if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo)))
+ if (copy_to_user((void __user *)arg, &cinfo, sizeof(cinfo)))
return -EFAULT;
return 0;
case SNDCTL_DSP_GETBLKSIZE:
if ((val = prog_dmabuf_dac1(s)))
return val;
- return put_user(s->dma_dac1.fragsize, (int *)arg);
+ return put_user(s->dma_dac1.fragsize, p);
case SNDCTL_DSP_SETFRAGMENT:
- if (get_user(val, (int *)arg))
+ if (get_user(val, p))
return -EFAULT;
s->dma_dac1.ossfragshift = val & 0xffff;
s->dma_dac1.ossmaxfrags = (val >> 16) & 0xffff;
case SNDCTL_DSP_SUBDIVIDE:
if (s->dma_dac1.subdivision)
return -EINVAL;
- if (get_user(val, (int *)arg))
+ if (get_user(val, p))
return -EFAULT;
if (val != 1 && val != 2 && val != 4)
return -EINVAL;
return 0;
case SOUND_PCM_READ_RATE:
- return put_user(s->dac1rate, (int *)arg);
+ return put_user(s->dac1rate, p);
case SOUND_PCM_READ_CHANNELS:
- return put_user((s->sctrl & SCTRL_P1SMB) ? 2 : 1, (int *)arg);
+ return put_user((s->sctrl & SCTRL_P1SMB) ? 2 : 1, p);
case SOUND_PCM_READ_BITS:
- return put_user((s->sctrl & SCTRL_P1SEB) ? 16 : 8, (int *)arg);
+ return put_user((s->sctrl & SCTRL_P1SEB) ? 16 : 8, p);
case SOUND_PCM_WRITE_FILTER:
case SNDCTL_DSP_SETSYNCRO:
return -EINVAL;
file->private_data = s;
/* wait for device to become free */
- down(&s->open_sem);
+ mutex_lock(&s->open_mutex);
while (s->open_mode & FMODE_DAC) {
if (file->f_flags & O_NONBLOCK) {
- up(&s->open_sem);
+ mutex_unlock(&s->open_mutex);
return -EBUSY;
}
add_wait_queue(&s->open_wait, &wait);
__set_current_state(TASK_INTERRUPTIBLE);
- up(&s->open_sem);
+ mutex_unlock(&s->open_mutex);
schedule();
remove_wait_queue(&s->open_wait, &wait);
set_current_state(TASK_RUNNING);
if (signal_pending(current))
return -ERESTARTSYS;
- down(&s->open_sem);
+ mutex_lock(&s->open_mutex);
}
s->dma_dac1.ossfragshift = s->dma_dac1.ossmaxfrags = s->dma_dac1.subdivision = 0;
s->dma_dac1.enabled = 1;
outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
spin_unlock_irqrestore(&s->lock, flags);
s->open_mode |= FMODE_DAC;
- up(&s->open_sem);
- return 0;
+ mutex_unlock(&s->open_mutex);
+ return nonseekable_open(inode, file);
}
static int es1371_release_dac(struct inode *inode, struct file *file)
VALIDATE_STATE(s);
lock_kernel();
drain_dac1(s, file->f_flags & O_NONBLOCK);
- down(&s->open_sem);
+ mutex_lock(&s->open_mutex);
stop_dac1(s);
dealloc_dmabuf(s, &s->dma_dac1);
s->open_mode &= ~FMODE_DAC;
- up(&s->open_sem);
+ mutex_unlock(&s->open_mutex);
wake_up(&s->open_wait);
unlock_kernel();
return 0;
/* --------------------------------------------------------------------- */
-static ssize_t es1371_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+static ssize_t es1371_midi_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
struct es1371_state *s = (struct es1371_state *)file->private_data;
DECLARE_WAITQUEUE(wait, current);
int cnt;
VALIDATE_STATE(s);
- if (ppos != &file->f_pos)
- return -ESPIPE;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
if (count == 0)
return ret;
}
-static ssize_t es1371_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+static ssize_t es1371_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
struct es1371_state *s = (struct es1371_state *)file->private_data;
DECLARE_WAITQUEUE(wait, current);
int cnt;
VALIDATE_STATE(s);
- if (ppos != &file->f_pos)
- return -ESPIPE;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
if (count == 0)
VALIDATE_STATE(s);
file->private_data = s;
/* wait for device to become free */
- down(&s->open_sem);
+ mutex_lock(&s->open_mutex);
while (s->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) {
if (file->f_flags & O_NONBLOCK) {
- up(&s->open_sem);
+ mutex_unlock(&s->open_mutex);
return -EBUSY;
}
add_wait_queue(&s->open_wait, &wait);
__set_current_state(TASK_INTERRUPTIBLE);
- up(&s->open_sem);
+ mutex_unlock(&s->open_mutex);
schedule();
remove_wait_queue(&s->open_wait, &wait);
set_current_state(TASK_RUNNING);
if (signal_pending(current))
return -ERESTARTSYS;
- down(&s->open_sem);
+ mutex_lock(&s->open_mutex);
}
spin_lock_irqsave(&s->lock, flags);
if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
es1371_handle_midi(s);
spin_unlock_irqrestore(&s->lock, flags);
s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE);
- up(&s->open_sem);
- return 0;
+ mutex_unlock(&s->open_mutex);
+ return nonseekable_open(inode, file);
}
static int es1371_midi_release(struct inode *inode, struct file *file)
remove_wait_queue(&s->midi.owait, &wait);
set_current_state(TASK_RUNNING);
}
- down(&s->open_sem);
+ mutex_lock(&s->open_mutex);
s->open_mode &= ~((file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE));
spin_lock_irqsave(&s->lock, flags);
if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
outl(s->ctrl, s->io+ES1371_REG_CONTROL);
}
spin_unlock_irqrestore(&s->lock, flags);
- up(&s->open_sem);
+ mutex_unlock(&s->open_mutex);
wake_up(&s->open_wait);
unlock_kernel();
return 0;
static unsigned int devindex;
-MODULE_PARM(spdif, "1-" __MODULE_STRING(NR_DEVICE) "i");
+module_param_array(spdif, bool, NULL, 0);
MODULE_PARM_DESC(spdif, "if 1 the output is in S/PDIF digital mode");
-MODULE_PARM(nomix, "1-" __MODULE_STRING(NR_DEVICE) "i");
+module_param_array(nomix, bool, NULL, 0);
MODULE_PARM_DESC(nomix, "if 1 no analog audio is mixed to the digital output");
-MODULE_PARM(amplifier, "1-" __MODULE_STRING(NR_DEVICE) "i");
+module_param_array(amplifier, bool, NULL, 0);
MODULE_PARM_DESC(amplifier, "Set to 1 if the machine needs the amp control enabling (many laptops)");
MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
static struct initvol {
int mixch;
int vol;
-} initvol[] __initdata = {
+} initvol[] __devinitdata = {
{ SOUND_MIXER_WRITE_LINE, 0x4040 },
{ SOUND_MIXER_WRITE_CD, 0x4040 },
{ MIXER_WRITE(SOUND_MIXER_VIDEO), 0x4040 },
{ PCI_ANY_ID, PCI_ANY_ID }
};
+#ifdef SUPPORT_JOYSTICK
+
+static int __devinit es1371_register_gameport(struct es1371_state *s)
+{
+ struct gameport *gp;
+ int gpio;
+
+ for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08)
+ if (request_region(gpio, JOY_EXTENT, "es1371"))
+ break;
+
+ if (gpio < 0x200) {
+ printk(KERN_ERR PFX "no free joystick address found\n");
+ return -EBUSY;
+ }
+
+ s->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR PFX "can not allocate memory for gameport\n");
+ release_region(gpio, JOY_EXTENT);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "ESS1371 Gameport");
+ gameport_set_phys(gp, "isa%04x/gameport0", gpio);
+ gp->dev.parent = &s->dev->dev;
+ gp->io = gpio;
+
+ s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
+ outl(s->ctrl, s->io + ES1371_REG_CONTROL);
+
+ gameport_register_port(gp);
+
+ return 0;
+}
+
+static inline void es1371_unregister_gameport(struct es1371_state *s)
+{
+ if (s->gameport) {
+ int gpio = s->gameport->io;
+ gameport_unregister_port(s->gameport);
+ release_region(gpio, JOY_EXTENT);
+
+ }
+}
+
+#else
+static inline int es1371_register_gameport(struct es1371_state *s) { return -ENOSYS; }
+static inline void es1371_unregister_gameport(struct es1371_state *s) { }
+#endif /* SUPPORT_JOYSTICK */
+
static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
{
return -ENODEV;
if (pcidev->irq == 0)
return -ENODEV;
- i = pci_set_dma_mask(pcidev, 0xffffffff);
+ i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK);
if (i) {
printk(KERN_WARNING "es1371: architecture does not support 32bit PCI busmaster DMA\n");
return i;
init_waitqueue_head(&s->open_wait);
init_waitqueue_head(&s->midi.iwait);
init_waitqueue_head(&s->midi.owait);
- init_MUTEX(&s->open_sem);
+ mutex_init(&s->open_mutex);
spin_lock_init(&s->lock);
s->magic = ES1371_MAGIC;
s->dev = pcidev;
res = -EBUSY;
goto err_region;
}
- if ((res=request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371",s))) {
+ if ((res=request_irq(s->irq, es1371_interrupt, IRQF_SHARED, "es1371",s))) {
printk(KERN_ERR PFX "irq %u in use\n", s->irq);
goto err_irq;
}
- printk(KERN_INFO PFX "found es1371 rev %d at io %#lx irq %u joystick %#x\n",
- s->rev, s->io, s->irq, s->gameport.io);
+ printk(KERN_INFO PFX "found es1371 rev %d at io %#lx irq %u\n",
+ s->rev, s->io, s->irq);
/* register devices */
if ((res=(s->dev_audio = register_sound_dsp(&es1371_audio_fops,-1)))<0)
goto err_dev1;
printk(KERN_INFO PFX "Enabling internal amplifier.\n");
}
}
- s->gameport.io = 0;
- for (i = 0x218; i >= 0x200; i -= 0x08) {
- if (request_region(i, JOY_EXTENT, "es1371")) {
- s->ctrl |= CTRL_JYSTK_EN | (((i >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
- s->gameport.io = i;
- break;
- }
- }
- if (!s->gameport.io)
- printk(KERN_ERR PFX "no free joystick address found\n");
s->sctrl = 0;
cssr = 0;
set_fs(fs);
/* turn on S/PDIF output driver if requested */
outl(cssr, s->io+ES1371_REG_STATUS);
- /* register gameport */
- if (s->gameport.io)
- gameport_register_port(&s->gameport);
+
+ es1371_register_gameport(s);
+
/* store it in the driver field */
pci_set_drvdata(pcidev, s);
/* put it into driver list */
/* increment devindex */
if (devindex < NR_DEVICE-1)
devindex++;
- return 0;
+ return 0;
err_gp:
- if (s->gameport.io)
- release_region(s->gameport.io, JOY_EXTENT);
#ifdef ES1371_DEBUG
if (s->ps)
remove_proc_entry("es1371", NULL);
outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */
synchronize_irq(s->irq);
free_irq(s->irq, s);
- if (s->gameport.io) {
- gameport_unregister_port(&s->gameport);
- release_region(s->gameport.io, JOY_EXTENT);
- }
+ es1371_unregister_gameport(s);
release_region(s->io, ES1371_EXTENT);
unregister_sound_dsp(s->dev_audio);
unregister_sound_mixer(s->codec->dev_mixer);
static int __init init_es1371(void)
{
printk(KERN_INFO PFX "version v0.32 time " __TIME__ " " __DATE__ "\n");
- return pci_module_init(&es1371_driver);
+ return pci_register_driver(&es1371_driver);
}
static void __exit cleanup_es1371(void)