/*
* Sound driver for Silicon Graphics 320 and 540 Visual Workstations'
- * onboard audio. See notes in ../../Documentation/sound/oss/vwsnd .
+ * onboard audio. See notes in Documentation/sound/oss/vwsnd .
*
* Copyright 1999 Silicon Graphics, Inc. All rights reserved.
*
* Open will block until the previous client has closed the
* device, unless O_NONBLOCK is specified.
*
- * The semaphore devc->io_sema serializes PCM I/O syscalls. This
+ * The semaphore devc->io_mutex serializes PCM I/O syscalls. This
* is unnecessary in Linux 2.2, because the kernel lock
* serializes read, write, and ioctl globally, but it's there,
* ready for the brave, new post-kernel-lock world.
* area it owns and update its pointers. See pcm_output() and
* pcm_input() for most of the gory stuff.
*
- * devc->mix_sema serializes all mixer ioctls. This is also
+ * devc->mix_mutex serializes all mixer ioctls. This is also
* redundant because of the kernel lock.
*
* The lowest level lock is lith->lithium_lock. It is a
#include <linux/smp_lock.h>
#include <linux/wait.h>
#include <linux/interrupt.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
+
#include <asm/mach-visws/cobalt.h>
#include "sound_config.h"
/* low-level lithium data */
typedef struct lithium {
- caddr_t page0; /* virtual addresses */
- caddr_t page1;
- caddr_t page2;
+ void * page0; /* virtual addresses */
+ void * page1;
+ void * page2;
spinlock_t lock; /* protects codec and UST/MSC access */
} lithium_t;
-/*
- * li_create initializes the lithium_t structure and sets up vm mappings
- * to access the registers.
- * Returns 0 on success, -errno on failure.
- */
-
-static int __init li_create(lithium_t *lith, unsigned long baseaddr)
-{
- static void li_destroy(lithium_t *);
-
- lith->lock = SPIN_LOCK_UNLOCKED;
- lith->page0 = ioremap_nocache(baseaddr + LI_PAGE0_OFFSET, PAGE_SIZE);
- lith->page1 = ioremap_nocache(baseaddr + LI_PAGE1_OFFSET, PAGE_SIZE);
- lith->page2 = ioremap_nocache(baseaddr + LI_PAGE2_OFFSET, PAGE_SIZE);
- if (!lith->page0 || !lith->page1 || !lith->page2) {
- li_destroy(lith);
- return -ENOMEM;
- }
- return 0;
-}
-
/*
* li_destroy destroys the lithium_t structure and vm mappings.
*/
}
}
+/*
+ * li_create initializes the lithium_t structure and sets up vm mappings
+ * to access the registers.
+ * Returns 0 on success, -errno on failure.
+ */
+
+static int __init li_create(lithium_t *lith, unsigned long baseaddr)
+{
+ spin_lock_init(&lith->lock);
+ lith->page0 = ioremap_nocache(baseaddr + LI_PAGE0_OFFSET, PAGE_SIZE);
+ lith->page1 = ioremap_nocache(baseaddr + LI_PAGE1_OFFSET, PAGE_SIZE);
+ lith->page2 = ioremap_nocache(baseaddr + LI_PAGE2_OFFSET, PAGE_SIZE);
+ if (!lith->page0 || !lith->page1 || !lith->page2) {
+ li_destroy(lith);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
/*
* basic register accessors - read/write long/byte
*/
static void li_shutdown_dma(dma_chan_t *chan)
{
lithium_t *lith = chan->lith;
- caddr_t lith1 = lith->page1;
+ void * lith1 = lith->page1;
DBGEV("(chan=0x%p)\n", chan);
static void li_deactivate_dma(dma_chan_t *chan)
{
lithium_t *lith = chan->lith;
- caddr_t lith2 = lith->page2;
+ void * lith2 = lith->page2;
chan->ctlval &= ~(LI_CCTL_DMA_ENABLE | LI_CCTL_RPTR | LI_CCTL_WPTR);
DBGPV("ctlval = 0x%lx\n", chan->ctlval);
*
* port->lock protects: hwstate, flags, swb_[iu]_avail.
*
- * devc->io_sema protects: swstate, sw_*, swb_[iu]_idx.
+ * devc->io_mutex protects: swstate, sw_*, swb_[iu]_idx.
*
* everything else is only written by open/release or
* pcm_{setup,shutdown}(), which are serialized by a
- * combination of devc->open_sema and devc->io_sema.
+ * combination of devc->open_mutex and devc->io_mutex.
*/
typedef struct vwsnd_port {
int hwbuf_size;
unsigned long hwbuf_paddr;
unsigned long hwbuf_vaddr;
- caddr_t hwbuf; /* hwbuf == hwbuf_vaddr */
+ void * hwbuf; /* hwbuf == hwbuf_vaddr */
int hwbuf_max; /* max bytes to preload */
- caddr_t swbuf;
+ void * swbuf;
unsigned int swbuf_size; /* size in bytes */
unsigned int swb_u_idx; /* index of next user byte */
unsigned int swb_i_idx; /* index of next intr byte */
int audio_minor; /* minor number of audio device */
int mixer_minor; /* minor number of mixer device */
- struct semaphore open_sema;
- struct semaphore io_sema;
- struct semaphore mix_sema;
+ struct mutex open_mutex;
+ struct mutex io_mutex;
+ struct mutex mix_mutex;
mode_t open_mode;
wait_queue_head_t open_wait;
* mode-setting ioctls have been done, but before the first I/O is
* done.
*
- * Locking: called with devc->io_sema held.
+ * Locking: called with devc->io_mutex held.
*
* Returns 0 on success, -errno on failure.
*/
pcm_output(devc, underflown, 0);
}
-static irqreturn_t vwsnd_audio_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t vwsnd_audio_intr(int irq, void *dev_id)
{
- vwsnd_dev_t *devc = (vwsnd_dev_t *) dev_id;
+ vwsnd_dev_t *devc = dev_id;
unsigned int status;
- DBGEV("(irq=%d, dev_id=0x%p, regs=0x%p)\n", irq, dev_id, regs);
+ DBGEV("(irq=%d, dev_id=0x%p)\n", irq, dev_id);
status = li_get_clear_intr_status(&devc->lith);
vwsnd_audio_read_intr(devc, status);
vwsnd_dev_t *devc = file->private_data;
ssize_t ret;
- down(&devc->io_sema);
+ mutex_lock(&devc->io_mutex);
ret = vwsnd_audio_do_read(file, buffer, count, ppos);
- up(&devc->io_sema);
+ mutex_unlock(&devc->io_mutex);
return ret;
}
vwsnd_dev_t *devc = file->private_data;
ssize_t ret;
- down(&devc->io_sema);
+ mutex_lock(&devc->io_mutex);
ret = vwsnd_audio_do_write(file, buffer, count, ppos);
- up(&devc->io_sema);
+ mutex_unlock(&devc->io_mutex);
return ret;
}
vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
int ret;
- down(&devc->io_sema);
+ mutex_lock(&devc->io_mutex);
ret = vwsnd_audio_do_ioctl(inode, file, cmd, arg);
- up(&devc->io_sema);
+ mutex_unlock(&devc->io_mutex);
return ret;
}
return -ENODEV;
}
- down(&devc->open_sema);
+ mutex_lock(&devc->open_mutex);
while (devc->open_mode & file->f_mode) {
- up(&devc->open_sema);
+ mutex_unlock(&devc->open_mutex);
if (file->f_flags & O_NONBLOCK) {
DEC_USE_COUNT;
return -EBUSY;
DEC_USE_COUNT;
return -ERESTARTSYS;
}
- down(&devc->open_sema);
+ mutex_lock(&devc->open_mutex);
}
devc->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
- up(&devc->open_sema);
+ mutex_unlock(&devc->open_mutex);
/* get default sample format from minor number. */
/* Initialize vwsnd_ports. */
- down(&devc->io_sema);
+ mutex_lock(&devc->io_mutex);
{
if (file->f_mode & FMODE_READ) {
devc->rport.swstate = SW_INITIAL;
devc->wport.frag_count = 0;
}
}
- up(&devc->io_sema);
+ mutex_unlock(&devc->io_mutex);
file->private_data = devc;
DBGRV();
int err = 0;
lock_kernel();
- down(&devc->io_sema);
+ mutex_lock(&devc->io_mutex);
{
DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
if (wport)
wport->swstate = SW_OFF;
}
- up(&devc->io_sema);
+ mutex_unlock(&devc->io_mutex);
- down(&devc->open_sema);
+ mutex_lock(&devc->open_mutex);
{
devc->open_mode &= ~file->f_mode;
}
- up(&devc->open_sema);
+ mutex_unlock(&devc->open_mutex);
wake_up(&devc->open_wait);
DEC_USE_COUNT;
DBGR();
/* mixer_read_ioctl handles all read ioctls on the mixer device. */
-static int mixer_read_ioctl(vwsnd_dev_t *devc, unsigned int nr, caddr_t arg)
+static int mixer_read_ioctl(vwsnd_dev_t *devc, unsigned int nr, void __user *arg)
{
int val = -1;
default:
return -EINVAL;
}
- return put_user(val, (int *) arg);
+ return put_user(val, (int __user *) arg);
}
/* mixer_write_ioctl handles all write ioctls on the mixer device. */
-static int mixer_write_ioctl(vwsnd_dev_t *devc, unsigned int nr, caddr_t arg)
+static int mixer_write_ioctl(vwsnd_dev_t *devc, unsigned int nr, void __user *arg)
{
int val;
int err;
DBGEV("(devc=0x%p, nr=0x%x, arg=0x%p)\n", devc, nr, arg);
- err = get_user(val, (int *) arg);
+ err = get_user(val, (int __user *) arg);
if (err)
return -EFAULT;
switch (nr) {
}
if (val < 0)
return val;
- return put_user(val, (int *) arg);
+ return put_user(val, (int __user *) arg);
}
/* This is the ioctl entry to the mixer driver. */
DBGEV("(devc=0x%p, cmd=0x%x, arg=0x%lx)\n", devc, cmd, arg);
- down(&devc->mix_sema);
+ mutex_lock(&devc->mix_mutex);
{
if ((cmd & ~nrmask) == MIXER_READ(0))
- retval = mixer_read_ioctl(devc, nr, (caddr_t) arg);
+ retval = mixer_read_ioctl(devc, nr, (void __user *) arg);
else if ((cmd & ~nrmask) == MIXER_WRITE(0))
- retval = mixer_write_ioctl(devc, nr, (caddr_t) arg);
+ retval = mixer_write_ioctl(devc, nr, (void __user *) arg);
else
retval = -EINVAL;
}
- up(&devc->mix_sema);
+ mutex_unlock(&devc->mix_mutex);
return retval;
}
devc->rport.hwbuf_vaddr = __get_free_pages(GFP_KERNEL, HWBUF_ORDER);
if (!devc->rport.hwbuf_vaddr)
goto fail2;
- devc->rport.hwbuf = (caddr_t) devc->rport.hwbuf_vaddr;
+ devc->rport.hwbuf = (void *) devc->rport.hwbuf_vaddr;
devc->rport.hwbuf_paddr = virt_to_phys(devc->rport.hwbuf);
/*
devc->wport.hwbuf_vaddr = __get_free_pages(GFP_KERNEL, HWBUF_ORDER);
if (!devc->wport.hwbuf_vaddr)
goto fail3;
- devc->wport.hwbuf = (caddr_t) devc->wport.hwbuf_vaddr;
+ devc->wport.hwbuf = (void *) devc->wport.hwbuf_vaddr;
devc->wport.hwbuf_paddr = virt_to_phys(devc->wport.hwbuf);
DBGP("wport hwbuf = 0x%p\n", devc->wport.hwbuf);
/* Initialize as much of *devc as possible */
- init_MUTEX(&devc->open_sema);
- init_MUTEX(&devc->io_sema);
- init_MUTEX(&devc->mix_sema);
+ mutex_init(&devc->open_mutex);
+ mutex_init(&devc->io_mutex);
+ mutex_init(&devc->mix_mutex);
devc->open_mode = 0;
- devc->rport.lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&devc->rport.lock);
init_waitqueue_head(&devc->rport.queue);
devc->rport.swstate = SW_OFF;
devc->rport.hwstate = HW_STOPPED;
devc->rport.flags = 0;
devc->rport.swbuf = NULL;
- devc->wport.lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&devc->wport.lock);
init_waitqueue_head(&devc->wport.queue);
devc->wport.swstate = SW_OFF;
devc->wport.hwstate = HW_STOPPED;