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

📄 dmasound_core.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
}static int sq_fsync(struct file *filp, struct dentry *dentry){	int rc = 0;	write_sq.syncing = 1;	sq_play();	/* there may be an incomplete frame waiting */	while (write_sq.active) {		SLEEP(write_sq.sync_queue);		if (signal_pending(current)) {			/* While waiting for audio output to drain, an			 * interrupt occurred.  Stop audio output immediately			 * and clear the queue. */			sq_reset();			rc = -EINTR;			break;		}	}	write_sq.syncing = 0;	return rc;}static int sq_release(struct inode *inode, struct file *file){	int rc = 0;	lock_kernel();	if (write_sq.busy)		rc = sq_fsync(file, file->f_dentry);	dmasound.soft = dmasound.dsp;	dmasound.hard = dmasound.dsp;	sound_silence();	write_sq_release_buffers();	read_sq_release_buffers();	dmasound.mach.release();	/* There is probably a DOS atack here. They change the mode flag. */	/* XXX add check here */	read_sq_wake_up(file);	write_sq_wake_up(file);	/* Wake up a process waiting for the queue being released.	 * Note: There may be several processes waiting for a call	 * to open() returning. */	unlock_kernel();	return rc;}static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,		    u_long arg){	int val;	u_long fmt;	int data;	int size, nbufs;	audio_buf_info info;	switch (cmd) {	case SNDCTL_DSP_RESET:		sq_reset();		return 0;	case SNDCTL_DSP_POST:	case SNDCTL_DSP_SYNC:		return sq_fsync(file, file->f_dentry);		/* ++TeSche: before changing any of these it's		 * probably wise to wait until sound playing has		 * settled down. */	case SNDCTL_DSP_SPEED:		sq_fsync(file, file->f_dentry);		IOCTL_IN(arg, data);		return IOCTL_OUT(arg, sound_set_speed(data));	case SNDCTL_DSP_STEREO:		sq_fsync(file, file->f_dentry);		IOCTL_IN(arg, data);		return IOCTL_OUT(arg, sound_set_stereo(data));	case SOUND_PCM_WRITE_CHANNELS:		sq_fsync(file, file->f_dentry);		IOCTL_IN(arg, data);		return IOCTL_OUT(arg, sound_set_stereo(data-1)+1);	case SNDCTL_DSP_SETFMT:		sq_fsync(file, file->f_dentry);		IOCTL_IN(arg, data);		return IOCTL_OUT(arg, sound_set_format(data));	case SNDCTL_DSP_GETFMTS:		fmt = 0;		if (dmasound.trans_write) {			if (dmasound.trans_write->ct_ulaw)				fmt |= AFMT_MU_LAW;			if (dmasound.trans_write->ct_alaw)				fmt |= AFMT_A_LAW;			if (dmasound.trans_write->ct_s8)				fmt |= AFMT_S8;			if (dmasound.trans_write->ct_u8)				fmt |= AFMT_U8;			if (dmasound.trans_write->ct_s16be)				fmt |= AFMT_S16_BE;			if (dmasound.trans_write->ct_u16be)				fmt |= AFMT_U16_BE;			if (dmasound.trans_write->ct_s16le)				fmt |= AFMT_S16_LE;			if (dmasound.trans_write->ct_u16le)				fmt |= AFMT_U16_LE;		}		return IOCTL_OUT(arg, fmt);	case SNDCTL_DSP_GETBLKSIZE:		size = write_sq.block_size			* dmasound.soft.size * (dmasound.soft.stereo + 1)			/ (dmasound.hard.size * (dmasound.hard.stereo + 1));		return IOCTL_OUT(arg, size);	case SNDCTL_DSP_SUBDIVIDE:		break;	case SNDCTL_DSP_SETFRAGMENT:		if (write_sq.count || write_sq.active || write_sq.syncing)			return -EINVAL;		IOCTL_IN(arg, size);		nbufs = size >> 16;		if (nbufs < 2 || nbufs > write_sq.numBufs)			nbufs = write_sq.numBufs;		size &= 0xffff;		if (size >= 8 && size <= 29) {			size = 1 << size;			size *= dmasound.hard.size * (dmasound.hard.stereo + 1);			size /= dmasound.soft.size * (dmasound.soft.stereo + 1);			if (size > write_sq.bufSize)				size = write_sq.bufSize;		} else			size = write_sq.bufSize;		sq_setup(&write_sq, write_sq.numBufs, nbufs, size);		return IOCTL_OUT(arg,write_sq.bufSize | write_sq.numBufs << 16);	case SNDCTL_DSP_GETOSPACE:		info.fragments = write_sq.max_active - write_sq.count;		info.fragstotal = write_sq.max_active;		info.fragsize = write_sq.block_size;		info.bytes = info.fragments * info.fragsize;		if (copy_to_user((void *)arg, &info, sizeof(info)))			return -EFAULT;		return 0;	case SNDCTL_DSP_GETCAPS:		val = 1;        /* Revision level of this ioctl() */		return IOCTL_OUT(arg,val);	default:		return mixer_ioctl(inode, file, cmd, arg);	}	return -EINVAL;}static struct file_operations sq_fops ={	owner:		THIS_MODULE,	llseek:		sound_lseek,	write:		sq_write,	ioctl:		sq_ioctl,	open:		sq_open,	release:	sq_release,#ifdef HAS_RECORD	read:		sq_read,#endif};static void __init sq_init(void){#ifndef MODULE	int sq_unit;#endif	sq_unit = register_sound_dsp(&sq_fops, -1);	if (sq_unit < 0)		return;	write_sq_init_waitqueue();	read_sq_init_waitqueue();	/* whatever you like as startup mode for /dev/dsp,	 * (/dev/audio hasn't got a startup mode). note that	 * once changed a new open() will *not* restore these!	 */	dmasound.dsp.format = AFMT_U8;	dmasound.dsp.stereo = 0;	dmasound.dsp.size = 8;	/* set minimum rate possible without expanding */	dmasound.dsp.speed = dmasound.mach.min_dsp_speed;	/* before the first open to /dev/dsp this wouldn't be set */	dmasound.soft = dmasound.dsp;	dmasound.hard = dmasound.dsp;	sound_silence();}    /*     *  /dev/sndstat     */static struct {    int busy;    char buf[512];	/* state.buf should not overflow! */    int len, ptr;} state;static int state_open(struct inode *inode, struct file *file){	char *buffer = state.buf;	int len = 0;	if (state.busy)		return -EBUSY;	dmasound.mach.open();	state.ptr = 0;	state.busy = 1;	len += sprintf(buffer+len, "%sDMA sound driver:\n", dmasound.mach.name);	len += sprintf(buffer+len, "\tsound.format = 0x%x",		       dmasound.soft.format);	switch (dmasound.soft.format) {	    case AFMT_MU_LAW:		len += sprintf(buffer+len, " (mu-law)");		break;	    case AFMT_A_LAW:		len += sprintf(buffer+len, " (A-law)");		break;	    case AFMT_U8:		len += sprintf(buffer+len, " (unsigned 8 bit)");		break;	    case AFMT_S8:		len += sprintf(buffer+len, " (signed 8 bit)");		break;	    case AFMT_S16_BE:		len += sprintf(buffer+len, " (signed 16 bit big)");		break;	    case AFMT_U16_BE:		len += sprintf(buffer+len, " (unsigned 16 bit big)");		break;	    case AFMT_S16_LE:		len += sprintf(buffer+len, " (signed 16 bit little)");		break;	    case AFMT_U16_LE:		len += sprintf(buffer+len, " (unsigned 16 bit little)");		break;	}	len += sprintf(buffer+len, "\n");	len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n",		       dmasound.soft.speed, dmasound.hard.speed);	len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n",		       dmasound.soft.stereo,		       dmasound.soft.stereo ? "stereo" : "mono");	if (dmasound.mach.state_info)	    len += dmasound.mach.state_info(buffer);	len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d"		       " sq.max_active = %d\n",		       write_sq.block_size, write_sq.max_count,		       write_sq.max_active);	len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n",		       write_sq.count, write_sq.rear_size);	len += sprintf(buffer+len, "\tsq.active = %d sq.syncing = %d\n",		       write_sq.active, write_sq.syncing);	state.len = len;	return 0;}static int state_release(struct inode *inode, struct file *file){	lock_kernel();	state.busy = 0;	dmasound.mach.release();	unlock_kernel();	return 0;}static ssize_t state_read(struct file *file, char *buf, size_t count,			  loff_t *ppos){	int n = state.len - state.ptr;	if (n > count)		n = count;	if (n <= 0)		return 0;	if (copy_to_user(buf, &state.buf[state.ptr], n))		return -EFAULT;	state.ptr += n;	return n;}static struct file_operations state_fops = {	owner:		THIS_MODULE,	llseek:		sound_lseek,	read:		state_read,	open:		state_open,	release:	state_release,};static void __init state_init(void){#ifndef MODULE	int state_unit;#endif	state_unit = register_sound_special(&state_fops, SND_DEV_STATUS);	if (state_unit < 0)		return;	state.busy = 0;}    /*     *  Config & Setup     *     *  This function is called by _one_ chipset-specific driver     */int __init dmasound_init(void){#ifdef MODULE	if (irq_installed)		return -EBUSY;#endif	/* Set up sound queue, /dev/audio and /dev/dsp. */	/* Set default settings. */	sq_init();	/* Set up /dev/sndstat. */	state_init();	/* Set up /dev/mixer. */	mixer_init();	if (!dmasound.mach.irqinit()) {		printk(KERN_ERR "DMA sound driver: Interrupt initialization failed\n");		return -ENODEV;	}#ifdef MODULE	irq_installed = 1;#endif	printk(KERN_INFO "DMA sound driver installed, using %d buffers of %dk.\n",	       numWriteBufs, writeBufSize);	return 0;}#ifdef MODULEvoid dmasound_deinit(void){	if (irq_installed) {		sound_silence();		dmasound.mach.irqcleanup();	}	write_sq_release_buffers();	read_sq_release_buffers();	if (mixer_unit >= 0)		unregister_sound_mixer(mixer_unit);	if (state_unit >= 0)		unregister_sound_special(state_unit);	if (sq_unit >= 0)		unregister_sound_dsp(sq_unit);}#else /* !MODULE */static int __init dmasound_setup(char *str){	int ints[6];	str = get_options(str, ARRAY_SIZE(ints), ints);	/* check the bootstrap parameter for "dmasound=" */	switch (ints[0]) {	case 3:		if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS))			printk("dmasound_setup: illegal catch radius, using default = %d\n", catchRadius);		else			catchRadius = ints[3];		/* fall through */	case 2:		if (ints[1] < MIN_BUFFERS)			printk("dmasound_setup: illegal number of buffers, using default = %d\n", numWriteBufs);		else			numWriteBufs = ints[1];		if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE)			printk("dmasound_setup: illegal buffer size, using default = %dK\n", writeBufSize);		else			writeBufSize = ints[2];		break;	case 0:		break;	default:		printk("dmasound_setup: illegal number of arguments\n");		return 0;	}	return 1;}__setup("dmasound=", dmasound_setup);#endif /* !MODULE */    /*     *  Visible symbols for modules     */EXPORT_SYMBOL(dmasound);EXPORT_SYMBOL(dmasound_init);#ifdef MODULEEXPORT_SYMBOL(dmasound_deinit);#endifEXPORT_SYMBOL(dmasound_write_sq);#ifdef HAS_RECORDEXPORT_SYMBOL(dmasound_read_sq);#endifEXPORT_SYMBOL(dmasound_catchRadius);#ifdef HAS_8BIT_TABLESEXPORT_SYMBOL(dmasound_ulaw2dma8);EXPORT_SYMBOL(dmasound_alaw2dma8);#endif#ifdef HAS_16BIT_TABLESEXPORT_SYMBOL(dmasound_ulaw2dma16);EXPORT_SYMBOL(dmasound_alaw2dma16);#endif#ifdef HAS_14BIT_TABLESEXPORT_SYMBOL(dmasound_ulaw2dma14l);EXPORT_SYMBOL(dmasound_ulaw2dma14h);EXPORT_SYMBOL(dmasound_alaw2dma14l);EXPORT_SYMBOL(dmasound_alaw2dma14h);#endif

⌨️ 快捷键说明

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