/* * sound/oss/sb_midi.c * * The low level driver for the Sound Blaster DS chips. * * * Copyright (C) by Hannu Savolainen 1993-1997 * * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. */ #include #include #include "sound_config.h" #include "sb.h" #undef SB_TEST_IRQ /* * The DSP channel can be used either for input or output. Variable * 'sb_irq_mode' will be set when the program calls read or write first time * after open. Current version doesn't support mode changes without closing * and reopening the device. Support for this feature may be implemented in a * future version of this driver. */ static int sb_midi_open(int dev, int mode, void (*input) (int dev, unsigned char data), void (*output) (int dev) ) { sb_devc *devc = midi_devs[dev]->devc; unsigned long flags; if (devc == NULL) return -ENXIO; spin_lock_irqsave(&devc->lock, flags); if (devc->opened) { spin_unlock_irqrestore(&devc->lock, flags); return -EBUSY; } devc->opened = 1; spin_unlock_irqrestore(&devc->lock, flags); devc->irq_mode = IMODE_MIDI; devc->midi_broken = 0; sb_dsp_reset(devc); if (!sb_dsp_command(devc, 0x35)) /* Start MIDI UART mode */ { devc->opened = 0; return -EIO; } devc->intr_active = 1; if (mode & OPEN_READ) { devc->input_opened = 1; devc->midi_input_intr = input; } return 0; } static void sb_midi_close(int dev) { sb_devc *devc = midi_devs[dev]->devc; unsigned long flags; if (devc == NULL) return; spin_lock_irqsave(&devc->lock, flags); sb_dsp_reset(devc); devc->intr_active = 0; devc->input_opened = 0; devc->opened = 0; spin_unlock_irqrestore(&devc->lock, flags); } static int sb_midi_out(int dev, unsigned char midi_byte) { sb_devc *devc = midi_devs[dev]->devc; if (devc == NULL) return 1; if (devc->midi_broken) return 1; if (!sb_dsp_command(devc, midi_byte)) { devc->midi_broken = 1; return 1; } return 1; } static int sb_midi_start_read(int dev) { return 0; } static int sb_midi_end_read(int dev) { sb_devc *devc = midi_devs[dev]->devc; if (devc == NULL) return -ENXIO; sb_dsp_reset(devc); devc->intr_active = 0; return 0; } static int sb_midi_ioctl(int dev, unsigned cmd, void __user *arg) { return -EINVAL; } void sb_midi_interrupt(sb_devc * devc) { unsigned long flags; unsigned char data; if (devc == NULL) return; spin_lock_irqsave(&devc->lock, flags); data = inb(DSP_READ); if (devc->input_opened) devc->midi_input_intr(devc->my_mididev, data); spin_unlock_irqrestore(&devc->lock, flags); } #define MIDI_SYNTH_NAME "Sound Blaster Midi" #define MIDI_SYNTH_CAPS 0 #include "midi_synth.h" static struct midi_operations sb_midi_operations = { .owner = THIS_MODULE, .info = {"Sound Blaster", 0, 0, SNDCARD_SB}, .converter = &std_midi_synth, .in_info = {0}, .open = sb_midi_open, .close = sb_midi_close, .ioctl = sb_midi_ioctl, .outputc = sb_midi_out, .start_read = sb_midi_start_read, .end_read = sb_midi_end_read, }; void sb_dsp_midi_init(sb_devc * devc, struct module *owner) { int dev; if (devc->model < 2) /* No MIDI support for SB 1.x */ return; dev = sound_alloc_mididev(); if (dev == -1) { printk(KERN_ERR "sb_midi: too many MIDI devices detected\n"); return; } std_midi_synth.midi_dev = devc->my_mididev = dev; midi_devs[dev] = kmalloc(sizeof(struct midi_operations), GFP_KERNEL); if (midi_devs[dev] == NULL) { printk(KERN_WARNING "Sound Blaster: failed to allocate MIDI memory.\n"); sound_unload_mididev(dev); return; } memcpy((char *) midi_devs[dev], (char *) &sb_midi_operations, sizeof(struct midi_operations)); if (owner) midi_devs[dev]->owner = owner; midi_devs[dev]->devc = devc; midi_devs[dev]->converter = kmalloc(sizeof(struct synth_operations), GFP_KERNEL); if (midi_devs[dev]->converter == NULL) { printk(KERN_WARNING "Sound Blaster: failed to allocate MIDI memory.\n"); kfree(midi_devs[dev]); sound_unload_mididev(dev); return; } memcpy((char *) midi_devs[dev]->converter, (char *) &std_midi_synth, sizeof(struct synth_operations)); midi_devs[dev]->converter->id = "SBMIDI"; sequencer_init(); }
authorLinus Torvalds <torvalds@linux-foundation.org>2017-01-01 12:27:05 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2017-01-01 12:27:05 -0800
commit4759d386d55fef452d692bf101167914437e848e (patch)
treee7109c192ec589fcea2a98f9702aa3c0e4009581 /net/sctp/transport.c
parent238d1d0f79f619d75c2cc741d6770fb0986aef24 (diff)
parent1db175428ee374489448361213e9c3b749d14900 (diff)
Merge branch 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull DAX updates from Dan Williams: "The completion of Jan's DAX work for 4.10. As I mentioned in the libnvdimm-for-4.10 pull request, these are some final fixes for the DAX dirty-cacheline-tracking invalidation work that was merged through the -mm, ext4, and xfs trees in -rc1. These patches were prepared prior to the merge window, but we waited for 4.10-rc1 to have a stable merge base after all the prerequisites were merged. Quoting Jan on the overall changes in these patches: "So I'd like all these 6 patches to go for rc2. The first three patches fix invalidation of exceptional DAX entries (a bug which is there for a long time) - without these patches data loss can occur on power failure even though user called fsync(2). The other three patches change locking of DAX faults so that ->iomap_begin() is called in a more relaxed locking context and we are safe to start a transaction there for ext4" These have received a build success notification from the kbuild robot, and pass the latest libnvdimm unit tests. There have not been any -next releases since -rc1, so they have not appeared there" * 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: ext4: Simplify DAX fault path dax: Call ->iomap_begin without entry lock during dax fault dax: Finish fault completely when loading holes dax: Avoid page invalidation races and unnecessary radix tree traversals mm: Invalidate DAX radix tree entries only if appropriate ext2: Return BH_New buffers for zeroed blocks
Diffstat (limited to 'net/sctp/transport.c')