OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [sound/] [v_midi.c] - Rev 1765

Compare with Previous | Blame | View Log

/*
 * sound/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 <linux/init.h>
#include <linux/module.h>
 
#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.
 */
 
 
void            (*midi_input_intr) (int dev, unsigned char data);
 
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);
 
	save_flags (flags);
	cli();
	if (devc->opened)
	{
		restore_flags (flags);
		return -(EBUSY);
	}
	devc->opened = 1;
	restore_flags (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;
 
	save_flags (flags);
	cli ();
	devc->intr_active = 0;
	devc->input_opened = 0;
	devc->opened = 0;
	restore_flags (flags);
}
 
static int v_midi_out (int dev, unsigned char midi_byte)
{
	vmidi_devc *devc = midi_devs[dev]->devc;
	vmidi_devc *pdevc = midi_devs[devc->pair_mididev]->devc;
 
	if (devc == NULL)
		return -(ENXIO);
 
	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, caddr_t 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=(struct vmidi_memory *)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;
 
	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;
 
	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");
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.