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

📄 sb16_dsp.c

📁 minix操作系统最新版本(3.1.1)的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* This file contains the driver for a DSP (Digital Sound Processor) on * a SoundBlaster 16 soundcard. * * The driver supports the following operations (using message format m2): * *    m_type      DEVICE    PROC_NR     COUNT    POSITION  ADRRESS * ---------------------------------------------------------------- * |  DEV_OPEN  | device  | proc nr |         |         |         | * |------------+---------+---------+---------+---------+---------| * |  DEV_CLOSE | device  | proc nr |         |         |         | * |------------+---------+---------+---------+---------+---------| * |  DEV_READ  | device  | proc nr |  bytes  |         | buf ptr | * |------------+---------+---------+---------+---------+---------| * |  DEV_WRITE | device  | proc nr |  bytes  |         | buf ptr | * |------------+---------+---------+---------+---------+---------| * |  DEV_IOCTL | device  | proc nr |func code|         | buf ptr | * ---------------------------------------------------------------- * * The file contains one entry point: * *   main:	main entry when driver is brought up *	 *  August 24 2005		Ported driver to user space (only audio playback) (Peter Boonstoppel) *  May 20 1995			Author: Michel R. Prevenier  */#include "sb16.h"_PROTOTYPE(void main, (void));FORWARD _PROTOTYPE( int dsp_open, (void) );FORWARD _PROTOTYPE( int dsp_close, (void) );FORWARD _PROTOTYPE( int dsp_ioctl, (message *m_ptr) );FORWARD _PROTOTYPE( void dsp_write, (message *m_ptr) );FORWARD _PROTOTYPE( void dsp_hardware_msg, (void) );FORWARD _PROTOTYPE( void dsp_status, (message *m_ptr) );FORWARD _PROTOTYPE( void reply, (int code, int replyee, int process, int status) );FORWARD _PROTOTYPE( void init_buffer, (void) );FORWARD _PROTOTYPE( int dsp_init, (void) );FORWARD _PROTOTYPE( int dsp_reset, (void) );FORWARD _PROTOTYPE( int dsp_command, (int value) );FORWARD _PROTOTYPE( int dsp_set_size, (unsigned int size) );FORWARD _PROTOTYPE( int dsp_set_speed, (unsigned int speed) );FORWARD _PROTOTYPE( int dsp_set_stereo, (unsigned int stereo) );FORWARD _PROTOTYPE( int dsp_set_bits, (unsigned int bits) );FORWARD _PROTOTYPE( int dsp_set_sign, (unsigned int sign) );FORWARD _PROTOTYPE( void dsp_dma_setup, (phys_bytes address, int count) );FORWARD _PROTOTYPE( void dsp_setup, (void) );PRIVATE int irq_hook_id;	/* id of irq hook at the kernel */PRIVATE char DmaBuffer[DMA_SIZE + 64 * 1024];PRIVATE char* DmaPtr;PRIVATE phys_bytes DmaPhys;PRIVATE char Buffer[DSP_MAX_FRAGMENT_SIZE * DSP_NR_OF_BUFFERS];PRIVATE int DspVersion[2]; PRIVATE unsigned int DspStereo = DEFAULT_STEREO;PRIVATE unsigned int DspSpeed = DEFAULT_SPEED; PRIVATE unsigned int DspBits = DEFAULT_BITS;PRIVATE unsigned int DspSign = DEFAULT_SIGN;PRIVATE unsigned int DspFragmentSize = DSP_MAX_FRAGMENT_SIZE;PRIVATE int DspAvail = 0;PRIVATE int DspBusy = 0;PRIVATE int DmaMode = 0;PRIVATE int DmaBusy = -1;PRIVATE int DmaFillNext = 0;PRIVATE int BufReadNext = -1;PRIVATE int BufFillNext = 0;PRIVATE int revivePending = 0;PRIVATE int reviveStatus;PRIVATE int reviveProcNr;#define dprint (void)/*===========================================================================* *				main *===========================================================================*/PUBLIC void main() {		int r, caller, proc_nr, s;	message mess;	dprint("sb16_dsp.c: main()\n");	/* Get a DMA buffer. */	init_buffer();	while(TRUE) {		/* Wait for an incoming message */		receive(ANY, &mess);		caller = mess.m_source;		proc_nr = mess.PROC_NR;		/* Now carry out the work. */		switch(mess.m_type) {			case DEV_OPEN:		r = dsp_open();	break;			case DEV_CLOSE:		r = dsp_close(); break;			case DEV_IOCTL:		r = dsp_ioctl(&mess); break;			case DEV_READ:		r = EINVAL; break; /* Not yet implemented */			case DEV_WRITE:		dsp_write(&mess); continue; /* don't reply */						case DEV_STATUS:	dsp_status(&mess); continue; /* don't reply */			case HARD_INT:		dsp_hardware_msg(); continue; /* don't reply */			case SYS_SIG:		continue; /* don't reply */			default:			r = EINVAL;		}		/* Finally, prepare and send the reply message. */		reply(TASK_REPLY, caller, proc_nr, r);	}}/*===========================================================================* *				dsp_open *===========================================================================*/PRIVATE int dsp_open(){	dprint("sb16_dsp.c: dsp_open()\n");		/* try to detect SoundBlaster card */	if(!DspAvail && dsp_init() != OK) return EIO;	/* Only one open at a time with soundcards */	if(DspBusy) return EBUSY;	/* Start with a clean DSP */	if(dsp_reset() != OK) return EIO;	/* Setup default values */	DspStereo = DEFAULT_STEREO;	DspSpeed = DEFAULT_SPEED;	DspBits = DEFAULT_BITS;	DspSign = DEFAULT_SIGN;	DspFragmentSize = DMA_SIZE / 2;	DspBusy = 1;	return OK;}/*===========================================================================* *				dsp_close *===========================================================================*/PRIVATE int dsp_close(){	dprint("sb16_dsp.c: dsp_close()\n");	DspBusy = 0;                  /* soundcard available again */	return OK;}/*===========================================================================* *				dsp_ioctl *===========================================================================*/PRIVATE int dsp_ioctl(m_ptr)message *m_ptr;{	int status;	phys_bytes user_phys;	unsigned int val;	dprint("sb16_dsp.c: dsp_ioctl()\n");	/* Cannot change parameters during play or recording */	if(DmaBusy >= 0) return EBUSY;	/* Get user data */	if(m_ptr->REQUEST != DSPIORESET) {		sys_vircopy(m_ptr->PROC_NR, D, (vir_bytes)m_ptr->ADDRESS, SELF, D, (vir_bytes)&val, sizeof(val));	}	dprint("dsp_ioctl: got ioctl %d, argument: %d\n", m_ptr->REQUEST, val);	switch(m_ptr->REQUEST) {		case DSPIORATE:		status = dsp_set_speed(val); break;		case DSPIOSTEREO:	status = dsp_set_stereo(val); break;		case DSPIOBITS:		status = dsp_set_bits(val); break;		case DSPIOSIZE:		status = dsp_set_size(val); break;		case DSPIOSIGN:		status = dsp_set_sign(val); break;		case DSPIOMAX: 			val = DSP_MAX_FRAGMENT_SIZE;			sys_vircopy(SELF, D, (vir_bytes)&val, m_ptr->PROC_NR, D, (vir_bytes)m_ptr->ADDRESS, sizeof(val));			status = OK;			break;		case DSPIORESET:    status = dsp_reset(); break;		default:            status = ENOTTY; break;	}	return status;}/*===========================================================================* *				dsp_write *===========================================================================*/PRIVATE void dsp_write(m_ptr)message *m_ptr;{	int s;	message mess;		dprint("sb16_dsp.c: dsp_write()\n");	if(m_ptr->COUNT != DspFragmentSize) {		reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EINVAL);		return;	}	if(m_ptr->m_type != DmaMode && DmaBusy >= 0) {		reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EBUSY);		return;	}		reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, SUSPEND);	if(DmaBusy < 0) { /* Dma tranfer not yet started */		DmaMode = DEV_WRITE;           /* Dma mode is writing */		sys_datacopy(m_ptr->PROC_NR, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)DmaPtr, (phys_bytes)DspFragmentSize);		dsp_dma_setup(DmaPhys, DspFragmentSize * DMA_NR_OF_BUFFERS);		dsp_setup();		DmaBusy = 0;         /* Dma is busy */		dprint(" filled dma[0]\n");		DmaFillNext = 1;	} else if(DmaBusy != DmaFillNext) { /* Dma transfer started, but Dma buffer not yet full */		sys_datacopy(m_ptr->PROC_NR, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)DmaPtr + DmaFillNext * DspFragmentSize, (phys_bytes)DspFragmentSize);		dprint(" filled dma[%d]\n", DmaFillNext);		DmaFillNext = (DmaFillNext + 1) % DMA_NR_OF_BUFFERS;	} else if(BufReadNext < 0) { /* Dma buffer full, fill first element of second buffer */ 		sys_datacopy(m_ptr->PROC_NR, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)Buffer, (phys_bytes)DspFragmentSize);		dprint(" filled buf[0]\n");		BufReadNext = 0;		BufFillNext = 1;	} else { /* Dma buffer is full, filling second buffer */ 		while(BufReadNext == BufFillNext) { /* Second buffer also full, wait for space to become available */ 			receive(HARDWARE, &mess);			dsp_hardware_msg();		}		sys_datacopy(m_ptr->PROC_NR, (vir_bytes)m_ptr->ADDRESS, SELF, (vir_bytes)Buffer + BufFillNext * DspFragmentSize, (phys_bytes)DspFragmentSize);		dprint(" filled buf[%d]\n", BufFillNext);		BufFillNext = (BufFillNext + 1) % DSP_NR_OF_BUFFERS;	} 		revivePending = 1;	reviveStatus = DspFragmentSize;	reviveProcNr = m_ptr->PROC_NR;	notify(m_ptr->m_source);}/*===========================================================================* *				dsp_hardware_msg *===========================================================================*/PRIVATE void dsp_hardware_msg(){		dprint("Interrupt: ");	if(DmaBusy >= 0) { /* Dma transfer was actually busy */		dprint("Finished playing dma[%d]; ", DmaBusy);		DmaBusy = (DmaBusy + 1) % DMA_NR_OF_BUFFERS;		if(DmaBusy == DmaFillNext) { /* Dma buffer empty, stop Dma transfer */			dsp_command((DspBits == 8 ? DSP_CMD_DMA8HALT : DSP_CMD_DMA16HALT));			dprint("No more work...!\n");			DmaBusy = -1;		} else if(BufReadNext >= 0) { /* Data in second buffer, copy one fragment to Dma buffer */						/* Acknowledge the interrupt on the DSP */			sb16_inb((DspBits == 8 ? DSP_DATA_AVL : DSP_DATA16_AVL));			memcpy(DmaPtr + DmaFillNext * DspFragmentSize, Buffer + BufReadNext * DspFragmentSize, DspFragmentSize);			dprint("copy buf[%d] -> dma[%d]; ", BufReadNext, DmaFillNext);			BufReadNext = (BufReadNext + 1) % DSP_NR_OF_BUFFERS;			DmaFillNext = (DmaFillNext + 1) % DMA_NR_OF_BUFFERS;			if(BufReadNext == BufFillNext) {				BufReadNext = -1;			} 			dprint("Starting dma[%d]\n", DmaBusy);						return;		} else { /* Second buffer empty, still data in Dma buffer, continue playback */			dprint("Starting dma[%d]\n", DmaBusy);		}	}	/* Acknowledge the interrupt on the DSP */	sb16_inb((DspBits == 8 ? DSP_DATA_AVL : DSP_DATA16_AVL));}/*===========================================================================* *				dsp_status				     * *===========================================================================*/PRIVATE void dsp_status(m_ptr)message *m_ptr;	/* pointer to the newly arrived message */{	if(revivePending) {		m_ptr->m_type = DEV_REVIVE;			/* build message */		m_ptr->REP_PROC_NR = reviveProcNr;		m_ptr->REP_STATUS = reviveStatus;		revivePending = 0;					/* unmark event */	} else {		m_ptr->m_type = DEV_NO_STATUS;	}	send(m_ptr->m_source, m_ptr);			/* send the message */}

⌨️ 快捷键说明

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