⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wf_midi.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * sound/wf_midi.c * * The low level driver for the WaveFront ICS2115 MIDI interface(s) * Note that there is also an MPU-401 emulation (actually, a UART-401 * emulation) on the CS4232 on the Tropez Plus. This code has nothing * to do with that interface at all. * * The interface is essentially just a UART-401, but is has the * interesting property of supporting what Turtle Beach called * "Virtual MIDI" mode. In this mode, there are effectively *two* * MIDI buses accessible via the interface, one that is routed * solely to/from the external WaveFront synthesizer and the other * corresponding to the pin/socket connector used to link external * MIDI devices to the board. * * This driver fully supports this mode, allowing two distinct * midi devices (/dev/midiNN and /dev/midiNN+1) to be used * completely independently, giving 32 channels of MIDI routing, * 16 to the WaveFront synth and 16 to the external MIDI bus. * * Switching between the two is accomplished externally by the driver * using the two otherwise unused MIDI bytes. See the code for more details. * * NOTE: VIRTUAL MIDI MODE IS ON BY DEFAULT (see wavefront.c) * * The main reason to turn off Virtual MIDI mode is when you want to * tightly couple the WaveFront synth with an external MIDI * device. You won't be able to distinguish the source of any MIDI * data except via SysEx ID, but thats probably OK, since for the most * part, the WaveFront won't be sending any MIDI data at all. *   * The main reason to turn on Virtual MIDI Mode is to provide two * completely independent 16-channel MIDI buses, one to the * WaveFront and one to any external MIDI devices. Given the 32 * voice nature of the WaveFront, its pretty easy to find a use * for all 16 channels driving just that synth. * *//* * Copyright (C) by Paul Barton-Davis 1998 * Some portions of this file are derived from work that is: * *    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. */#include <linux/init.h>#include "sound_config.h"#include <linux/wavefront.h>#ifdef MODULEstruct wf_mpu_config {	int             base;#define	DATAPORT(d)   (d)->base#define	COMDPORT(d)   (d)->base+1#define	STATPORT(d)   (d)->base+1	int             irq;	int             opened;	int             devno;	int             synthno;	int             mode;#define MODE_MIDI	1#define MODE_SYNTH	2	void            (*inputintr) (int dev, unsigned char data);	char isvirtual;                /* do virtual I/O stuff */};static struct wf_mpu_config  devs[2];static struct wf_mpu_config *phys_dev = &devs[0];static struct wf_mpu_config *virt_dev = &devs[1];static void start_uart_mode (void);#define	OUTPUT_READY	0x40#define	INPUT_AVAIL	0x80#define	MPU_ACK		0xFE#define	UART_MODE_ON	0x3Fstatic inline int wf_mpu_status (void){	return inb (STATPORT (phys_dev));}static inline int input_avail (void){	return !(wf_mpu_status() & INPUT_AVAIL);}static inline int output_ready (void){	return !(wf_mpu_status() & OUTPUT_READY);}static inline int  read_data (void){	return inb (DATAPORT (phys_dev));}static inline void write_data (unsigned char byte){	outb (byte, DATAPORT (phys_dev));}/* * States for the input scanner (should be in dev_table.h) */#define MST_SYSMSG		100	/* System message (sysx etc). */#define MST_MTC			102	/* Midi Time Code (MTC) qframe msg */#define MST_SONGSEL		103	/* Song select */#define MST_SONGPOS		104	/* Song position pointer */#define MST_TIMED		105	/* Leading timing byte rcvd *//* buffer space check for input scanner */#define BUFTEST(mi) if (mi->m_ptr >= MI_MAX || mi->m_ptr < 0) \{printk(KERN_ERR "WF-MPU: Invalid buffer pointer %d/%d, s=%d\n", \	mi->m_ptr, mi->m_left, mi->m_state);mi->m_ptr--;}static unsigned char len_tab[] =	/* # of data bytes following a status					 */{	2,				/* 8x */	2,				/* 9x */	2,				/* Ax */	2,				/* Bx */	1,				/* Cx */	1,				/* Dx */	2,				/* Ex */	0				/* Fx */};static intwf_mpu_input_scanner (int devno, int synthdev, unsigned char midic){	struct midi_input_info *mi = &midi_devs[devno]->in_info;	switch (mi->m_state) {	case MST_INIT:		switch (midic) {		case 0xf8:			/* Timer overflow */			break;				case 0xfc:			break;				case 0xfd:			/* XXX do something useful with this. If there is			   an external MIDI timer (e.g. a hardware sequencer,			   a useful timer can be derived ...		   			   For now, no timer support.			*/			break;				case 0xfe:			return MPU_ACK;			break;				case 0xf0:		case 0xf1:		case 0xf2:		case 0xf3:		case 0xf4:		case 0xf5:		case 0xf6:		case 0xf7:			break;				case 0xf9:			break;				case 0xff:			mi->m_state = MST_SYSMSG;			break;				default:			if (midic <= 0xef) {				mi->m_state = MST_TIMED;			}			else				printk (KERN_ERR "<MPU: Unknown event %02x> ",					midic);		}		break;	  	case MST_TIMED:	{		int             msg = ((int) (midic & 0xf0) >> 4);	  		mi->m_state = MST_DATA;	  		if (msg < 8) {	/* Data byte */	      			msg = ((int) (mi->m_prev_status & 0xf0) >> 4);			msg -= 8;			mi->m_left = len_tab[msg] - 1;	      			mi->m_ptr = 2;			mi->m_buf[0] = mi->m_prev_status;			mi->m_buf[1] = midic;			if (mi->m_left <= 0) {				mi->m_state = MST_INIT;				do_midi_msg (synthdev, mi->m_buf, mi->m_ptr);				mi->m_ptr = 0;			}		} else if (msg == 0xf) {	/* MPU MARK */	      			mi->m_state = MST_INIT;			switch (midic) {			case 0xf8:				break;		    			case 0xf9:				break;		    			case 0xfc:				break;		    			default:				break;			}		} else {			mi->m_prev_status = midic;			msg -= 8;			mi->m_left = len_tab[msg];	      			mi->m_ptr = 1;			mi->m_buf[0] = midic;	      			if (mi->m_left <= 0) {				mi->m_state = MST_INIT;				do_midi_msg (synthdev, mi->m_buf, mi->m_ptr);				mi->m_ptr = 0;			}		}	}	break;	case MST_SYSMSG:		switch (midic) {		case 0xf0:			mi->m_state = MST_SYSEX;			break;	    		case 0xf1:			mi->m_state = MST_MTC;			break;		case 0xf2:			mi->m_state = MST_SONGPOS;			mi->m_ptr = 0;			break;	    		case 0xf3:			mi->m_state = MST_SONGSEL;			break;	    		case 0xf6:			mi->m_state = MST_INIT;	    			/*			 *    Real time messages			 */		case 0xf8:			/* midi clock */			mi->m_state = MST_INIT;			/* XXX need ext MIDI timer support */			break;	    		case 0xfA:			mi->m_state = MST_INIT;			/* XXX need ext MIDI timer support */			break;	    		case 0xFB:			mi->m_state = MST_INIT;			/* XXX need ext MIDI timer support */			break;	    		case 0xFC:			mi->m_state = MST_INIT;			/* XXX need ext MIDI timer support */			break;	    		case 0xFE:			/* active sensing */			mi->m_state = MST_INIT;			break;	    		case 0xff:			mi->m_state = MST_INIT;			break;		default:			printk (KERN_ERR "unknown MIDI sysmsg %0x\n", midic);			mi->m_state = MST_INIT;		}		break;	case MST_MTC:		mi->m_state = MST_INIT;		break;	case MST_SYSEX:		if (midic == 0xf7) {			mi->m_state = MST_INIT;		} else {			/* XXX fix me */		}		break;	case MST_SONGPOS:		BUFTEST (mi);		mi->m_buf[mi->m_ptr++] = midic;		if (mi->m_ptr == 2) {			mi->m_state = MST_INIT;			mi->m_ptr = 0;			/* XXX need ext MIDI timer support */		}		break;	case MST_DATA:		BUFTEST (mi);		mi->m_buf[mi->m_ptr++] = midic;		if ((--mi->m_left) <= 0) {			mi->m_state = MST_INIT;			do_midi_msg (synthdev, mi->m_buf, mi->m_ptr);			mi->m_ptr = 0;		}		break;	default:		printk (KERN_ERR "Bad state %d ", mi->m_state);		mi->m_state = MST_INIT;	}	return 1;}voidwf_mpuintr (int irq, void *dev_id, struct pt_regs *dummy){	struct wf_mpu_config *physical_dev = dev_id;	static struct wf_mpu_config *input_dev = 0;	struct midi_input_info *mi = &midi_devs[physical_dev->devno]->in_info;	int n;	if (!input_avail()) { /* not for us */		return;	}	if (mi->m_busy) return;	mi->m_busy = 1;	sti (); 	if (!input_dev) {		input_dev = physical_dev;	}	n = 50; /* XXX why ? */	do {		unsigned char c = read_data ();      		if (phys_dev->isvirtual) {			if (c == WF_EXTERNAL_SWITCH) {				input_dev = virt_dev;				continue;			} else if (c == WF_INTERNAL_SWITCH) { 				input_dev = phys_dev;				continue;			} /* else just leave it as it is */		} else {			input_dev = phys_dev;		}		if (input_dev->mode == MODE_SYNTH) {	  			wf_mpu_input_scanner (input_dev->devno,					      input_dev->synthno, c);	  		} else if (input_dev->opened & OPEN_READ) {	  			if (input_dev->inputintr) {				input_dev->inputintr (input_dev->devno, c);			} 		}	} while (input_avail() && n-- > 0);	mi->m_busy = 0;}static intwf_mpu_open (int dev, int mode,	     void            (*input) (int dev, unsigned char data),	     void            (*output) (int dev)	){	struct wf_mpu_config *devc;	if (dev < 0 || dev >= num_midis || midi_devs[dev]==NULL)		return -(ENXIO);	if (phys_dev->devno == dev) {		devc = phys_dev;	} else if (phys_dev->isvirtual && virt_dev->devno == dev) {		devc = virt_dev;	} else {		printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev);		return -(EINVAL);	}	if (devc->opened) {		return -(EBUSY);	}	devc->mode = MODE_MIDI;	devc->opened = mode;	devc->synthno = 0;	devc->inputintr = input;	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -