/* * sound/oss/v_midi.c * * The low level driver for the Sound Blaster DS chips. * * * Copyright (C) by Hannu Savolainen 1993-1996 * * USS/Lite 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. * ?? * * Changes * Alan Cox Modularisation, changed memory allocations * Christoph Hellwig Adapted to module_init/module_exit * * Status * Untested */ #include #include #include #include #include "sound_config.h" #include "v_midi.h" static vmidi_devc *v_devc[2] = { NULL, NULL}; static int midi1,midi2; static void *midi_mem = NULL; /* * 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 v_midi_open (int dev, int mode, void (*input) (int dev, unsigned char data), void (*output) (int dev) ) { vmidi_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->intr_active = 1; if (mode & OPEN_READ) { devc->input_opened = 1; devc->midi_input_intr = input; } return 0; } static void v_midi_close (int dev) { vmidi_devc *devc = midi_devs[dev]->devc; unsigned long flags; if (devc == NULL) return; spin_lock_irqsave(&devc->lock,flags); devc->intr_active = 0; devc->input_opened = 0; devc->opened = 0; spin_unlock_irqrestore(&devc->lock,flags); } static int v_midi_out (int dev, unsigned char midi_byte) { vmidi_devc *devc = midi_devs[dev]->devc; vmidi_devc *pdevc; if (devc == NULL) return -ENXIO; pdevc = midi_devs[devc->pair_mididev]->devc; if (pdevc->input_opened > 0){ if (MIDIbuf_avail(pdevc->my_mididev) > 500) return 0; pdevc->midi_input_intr (pdevc->my_mididev, midi_byte); } return 1; } static inline int v_midi_start_read (int dev) { return 0; } static int v_midi_end_read (int dev) { vmidi_devc *devc = midi_devs[dev]->devc; if (devc == NULL) return -ENXIO; devc->intr_active = 0; return 0; } /* why -EPERM and not -EINVAL?? */ static inline int v_midi_ioctl (int dev, unsigned cmd, void __user *arg) { return -EPERM; } #define MIDI_SYNTH_NAME "Loopback MIDI" #define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT #include "midi_synth.h" static struct midi_operations v_midi_operations = { .owner = THIS_MODULE, .info = {"Loopback MIDI Port 1", 0, 0, SNDCARD_VMIDI}, .converter = &std_midi_synth, .in_info = {0}, .open = v_midi_open, .close = v_midi_close, .ioctl = v_midi_ioctl, .outputc = v_midi_out, .start_read = v_midi_start_read, .end_read = v_midi_end_read, }; static struct midi_operations v_midi_operations2 = { .owner = THIS_MODULE, .info = {"Loopback MIDI Port 2", 0, 0, SNDCARD_VMIDI}, .converter = &std_midi_synth, .in_info = {0}, .open = v_midi_open, .close = v_midi_close, .ioctl = v_midi_ioctl, .outputc = v_midi_out, .start_read = v_midi_start_read, .end_read = v_midi_end_read, }; /* * We kmalloc just one of these - it makes life simpler and the code * cleaner and the memory handling far more efficient */ struct vmidi_memory { /* Must be first */ struct midi_operations m_ops[2]; struct synth_operations s_ops[2]; struct vmidi_devc v_ops[2]; }; static void __init attach_v_midi (struct address_info *hw_config) { struct vmidi_memory *m; /* printk("Attaching v_midi device.....\n"); */ midi1 = sound_alloc_mididev(); if (midi1 == -1) { printk(KERN_ERR "v_midi: Too many midi devices detected\n"); return; } m = kmalloc(sizeof(struct vmidi_memory), GFP_KERNEL); if (m == NULL) { printk(KERN_WARNING "Loopback MIDI: Failed to allocate memory\n"); sound_unload_mididev(midi1); return; } midi_mem = m; midi_devs[midi1] = &m->m_ops[0]; midi2 = sound_alloc_mididev(); if (midi2 == -1) { printk (KERN_ERR "v_midi: Too many midi devices detected\n"); kfree(m); sound_unload_mididev(midi1); return; } midi_devs[midi2] = &m->m_ops[1]; /* printk("VMIDI1: %d VMIDI2: %d\n",midi1,midi2); */ /* for MIDI-1 */ v_devc[0] = &m->v_ops[0]; memcpy ((char *) midi_devs[midi1], (char *) &v_midi_operations, sizeof (struct midi_operations)); v_devc[0]->my_mididev = midi1; v_devc[0]->pair_mididev = midi2; v_devc[0]->opened = v_devc[0]->input_opened = 0; v_devc[0]->intr_active = 0; v_devc[0]->midi_input_intr = NULL; spin_lock_init(&v_devc[0]->lock); midi_devs[midi1]->devc = v_devc[0]; midi_devs[midi1]->converter = &m->s_ops[0]; std_midi_synth.midi_dev = midi1; memcpy ((char *) midi_devs[midi1]->converter, (char *) &std_midi_synth, sizeof (struct synth_operations)); midi_devs[midi1]->converter->id = "V_MIDI 1"; /* for MIDI-2 */ v_devc[1] = &m->v_ops[1]; memcpy ((char *) midi_devs[midi2], (char *) &v_midi_operations2, sizeof (struct midi_operations)); v_devc[1]->my_mididev = midi2; v_devc[1]->pair_mididev = midi1; v_devc[1]->opened = v_devc[1]->input_opened = 0; v_devc[1]->intr_active = 0; v_devc[1]->midi_input_intr = NULL; spin_lock_init(&v_devc[1]->lock); midi_devs[midi2]->devc = v_devc[1]; midi_devs[midi2]->converter = &m->s_ops[1]; std_midi_synth.midi_dev = midi2; memcpy ((char *) midi_devs[midi2]->converter, (char *) &std_midi_synth, sizeof (struct synth_operations)); midi_devs[midi2]->converter->id = "V_MIDI 2"; sequencer_init(); /* printk("Attached v_midi device\n"); */ } static inline int __init probe_v_midi(struct address_info *hw_config) { return(1); /* always OK */ } static void __exit unload_v_midi(struct address_info *hw_config) { sound_unload_mididev(midi1); sound_unload_mididev(midi2); kfree(midi_mem); } static struct address_info cfg; /* dummy */ static int __init init_vmidi(void) { printk("MIDI Loopback device driver\n"); if (!probe_v_midi(&cfg)) return -ENODEV; attach_v_midi(&cfg); return 0; } static void __exit cleanup_vmidi(void) { unload_v_midi(&cfg); } module_init(init_vmidi); module_exit(cleanup_vmidi); MODULE_LICENSE("GPL"); on hardware handling of unaligned accesses, manipulating the FDT with the MMU off may result in alignment faults. So fix the situation by moving the update_fdt_memmap() call into the callback function invoked by efi_exit_boot_services() right before it calls the ExitBootServices() UEFI service (which is arguably a better place for it anyway) Note that disabling the MMU in ExitBootServices() is not compliant with the UEFI spec, and carries great risk due to the fact that switching from cached to uncached memory accesses halfway through compiler generated code (i.e., involving a stack) can never be done in a way that is architecturally safe. Fixes: abfb7b686a3e ("efi/libstub/arm*: Pass latest memory map to the kernel") Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Tested-by: Riku Voipio <riku.voipio@linaro.org> Cc: <stable@vger.kernel.org> Cc: mark.rutland@arm.com Cc: linux-efi@vger.kernel.org Cc: matt@codeblueprint.co.uk Cc: leif.lindholm@linaro.org Cc: linux-arm-kernel@lists.infradead.org Link: http://lkml.kernel.org/r/1485971102-23330-2-git-send-email-ard.biesheuvel@linaro.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'net/ipv6/udp_impl.h')