#include <linux/spinlock.h>
#include <linux/gameport.h>
#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/mutex.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 sctrl;
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 mutex;
};
/* --------------------------------------------------------------------- */
return -ENXIO;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
- down(&s->sem);
+ mutex_lock(&s->mutex);
if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
goto out;
ret = -EAGAIN;
goto out;
}
- up(&s->sem);
+ mutex_unlock(&s->mutex);
schedule();
if (signal_pending(current)) {
if (!ret)
ret = -ERESTARTSYS;
goto out;
}
- down(&s->sem);
+ mutex_lock(&s->mutex);
if (s->dma_adc.mapped)
{
ret = -ENXIO;
start_adc(s);
}
out:
- up(&s->sem);
+ mutex_unlock(&s->mutex);
remove_wait_queue(&s->dma_adc.wait, &wait);
set_current_state(TASK_RUNNING);
return ret;
return -ENXIO;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
- down(&s->sem);
+ mutex_lock(&s->mutex);
if (!s->dma_dac2.ready && (ret = prog_dmabuf_dac2(s)))
goto out;
ret = 0;
ret = -EAGAIN;
goto out;
}
- up(&s->sem);
+ mutex_unlock(&s->mutex);
schedule();
if (signal_pending(current)) {
if (!ret)
ret = -ERESTARTSYS;
goto out;
}
- down(&s->sem);
+ mutex_lock(&s->mutex);
if (s->dma_dac2.mapped)
{
ret = -ENXIO;
start_dac2(s);
}
out:
- up(&s->sem);
+ mutex_unlock(&s->mutex);
remove_wait_queue(&s->dma_dac2.wait, &wait);
set_current_state(TASK_RUNNING);
return ret;
VALIDATE_STATE(s);
lock_kernel();
- down(&s->sem);
+ mutex_lock(&s->mutex);
if (vma->vm_flags & VM_WRITE) {
if ((ret = prog_dmabuf_dac2(s)) != 0) {
goto out;
}
db->mapped = 1;
out:
- up(&s->sem);
+ mutex_unlock(&s->mutex);
unlock_kernel();
return ret;
}
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);
}
spin_lock_irqsave(&s->lock, flags);
if (!(s->open_mode & (FMODE_READ|FMODE_WRITE)))
outl(s->ctrl, s->io+ES1370_REG_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);
+ mutex_unlock(&s->open_mutex);
+ mutex_init(&s->mutex);
return nonseekable_open(inode, 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);
synchronize_irq(s->irq);
}
s->open_mode &= ~(file->f_mode & (FMODE_READ|FMODE_WRITE));
wake_up(&s->open_wait);
- up(&s->open_sem);
+ mutex_unlock(&s->open_mutex);
unlock_kernel();
return 0;
}
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->ctrl, s->io+ES1370_REG_CONTROL);
spin_unlock_irqrestore(&s->lock, flags);
s->open_mode |= FMODE_DAC;
- up(&s->open_sem);
+ mutex_unlock(&s->open_mutex);
return nonseekable_open(inode, 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;
wake_up(&s->open_wait);
- up(&s->open_sem);
+ mutex_unlock(&s->open_mutex);
unlock_kernel();
return 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))) {
es1370_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);
+ mutex_unlock(&s->open_mutex);
return nonseekable_open(inode, 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))) {
}
spin_unlock_irqrestore(&s->lock, flags);
wake_up(&s->open_wait);
- up(&s->open_sem);
+ mutex_unlock(&s->open_mutex);
unlock_kernel();
return 0;
}
static struct initvol {
int mixch;
int vol;
-} initvol[] __initdata = {
+} initvol[] __devinitdata = {
{ SOUND_MIXER_WRITE_VOLUME, 0x4040 },
{ SOUND_MIXER_WRITE_PCM, 0x4040 },
{ SOUND_MIXER_WRITE_SYNTH, 0x4040 },
{ SOUND_MIXER_WRITE_OGAIN, 0x4040 }
};
+#ifdef SUPPORT_JOYSTICK
+
+static int __devinit es1370_register_gameport(struct es1370_state *s)
+{
+ struct gameport *gp;
+
+ if (!request_region(0x200, JOY_EXTENT, "es1370")) {
+ printk(KERN_ERR "es1370: joystick io port 0x200 in use\n");
+ return -EBUSY;
+ }
+
+ s->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "es1370: can not allocate memory for gameport\n");
+ release_region(0x200, JOY_EXTENT);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "ESS1370");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev));
+ gp->dev.parent = &s->dev->dev;
+ gp->io = 0x200;
+
+ s->ctrl |= CTRL_JYSTK_EN;
+ outl(s->ctrl, s->io + ES1370_REG_CONTROL);
+
+ gameport_register_port(gp);
+
+ return 0;
+}
+
+static inline void es1370_unregister_gameport(struct es1370_state *s)
+{
+ if (s->gameport) {
+ int gpio = s->gameport->io;
+ gameport_unregister_port(s->gameport);
+ release_region(gpio, JOY_EXTENT);
+
+ }
+}
+
+#else
+static inline int es1370_register_gameport(struct es1370_state *s) { return -ENOSYS; }
+static inline void es1370_unregister_gameport(struct es1370_state *s) { }
+#endif /* SUPPORT_JOYSTICK */
+
static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
{
struct es1370_state *s;
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 "es1370: 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 = ES1370_MAGIC;
s->dev = pcidev;
/* note: setting CTRL_SERR_DIS is reported to break
* mic bias setting (by Kim.Berts@fisub.mail.abb.com) */
s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL);
- s->gameport.io = 0;
- if (!request_region(0x200, JOY_EXTENT, "es1370"))
- printk(KERN_ERR "es1370: joystick io port 0x200 in use\n");
- else {
- s->ctrl |= CTRL_JYSTK_EN;
- s->gameport.io = 0x200;
- }
if (lineout[devindex])
s->ctrl |= CTRL_XCTL0;
if (micbias[devindex])
s->ctrl |= CTRL_XCTL1;
s->sctrl = 0;
- printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n"
- KERN_INFO "es1370: features: joystick %s, line %s, mic impedance %s\n",
- s->io, s->irq, (s->ctrl & CTRL_JYSTK_EN) ? "on" : "off",
- (s->ctrl & CTRL_XCTL0) ? "out" : "in",
- (s->ctrl & CTRL_XCTL1) ? "1" : "0");
+ printk(KERN_INFO "es1370: adapter at io %#lx irq %u, line %s, mic impedance %s\n",
+ s->io, s->irq, (s->ctrl & CTRL_XCTL0) ? "out" : "in",
+ (s->ctrl & CTRL_XCTL1) ? "1" : "0");
/* register devices */
if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0) {
ret = s->dev_audio;
mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
}
set_fs(fs);
- /* register gameport */
- if (s->gameport.io)
- gameport_register_port(&s->gameport);
+
+ es1370_register_gameport(s);
/* store it in the driver field */
pci_set_drvdata(pcidev, s);
err_dev1:
printk(KERN_ERR "es1370: cannot register misc device\n");
free_irq(s->irq, s);
- if (s->gameport.io)
- release_region(s->gameport.io, JOY_EXTENT);
err_irq:
release_region(s->io, ES1370_EXTENT);
err_region:
outl(0, s->io+ES1370_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);
- }
+ es1370_unregister_gameport(s);
release_region(s->io, ES1370_EXTENT);
unregister_sound_dsp(s->dev_audio);
unregister_sound_mixer(s->dev_mixer);
static int __init init_es1370(void)
{
printk(KERN_INFO "es1370: version v0.38 time " __TIME__ " " __DATE__ "\n");
- return pci_module_init(&es1370_driver);
+ return pci_register_driver(&es1370_driver);
}
static void __exit cleanup_es1370(void)