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

📄 soundcard.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	strncpy(info.name, mixer_devs[dev]->name, sizeof(info.name));	info.name[sizeof(info.name)-1] = 0;	info.modify_counter = mixer_devs[dev]->modify_counter;	if (__copy_to_user(arg, &info,  sizeof(info)))		return -EFAULT;	return 0;}static int get_old_mixer_info(int dev, caddr_t arg){	_old_mixer_info info; 	strncpy(info.id, mixer_devs[dev]->id, sizeof(info.id)); 	strncpy(info.name, mixer_devs[dev]->name, sizeof(info.name)); 	info.name[sizeof(info.name)-1] = 0;	 	if (copy_to_user(arg, &info,  sizeof(info)))		return -EFAULT;	return 0;}static int sound_mixer_ioctl(int mixdev, unsigned int cmd, caddr_t arg){ 	if (mixdev < 0 || mixdev >= MAX_MIXER_DEV) 		return -ENXIO; 	/* Try to load the mixer... */ 	if (mixer_devs[mixdev] == NULL) { 		char modname[20]; 		sprintf(modname, "mixer%d", mixdev); 		request_module(modname); 	} 	if (mixdev >= num_mixers || !mixer_devs[mixdev]) 		return -ENXIO;	if (cmd == SOUND_MIXER_INFO)		return get_mixer_info(mixdev, arg);	if (cmd == SOUND_OLD_MIXER_INFO)		return get_old_mixer_info(mixdev, arg);	if (_SIOC_DIR(cmd) & _SIOC_WRITE)		mixer_devs[mixdev]->modify_counter++;	if (!mixer_devs[mixdev]->ioctl)		return -EINVAL;	return mixer_devs[mixdev]->ioctl(mixdev, cmd, arg);}static int sound_ioctl(struct inode *inode, struct file *file,		       unsigned int cmd, unsigned long arg){	int err, len = 0, dtype;	int dev = MINOR(inode->i_rdev);	if (_SIOC_DIR(cmd) != _SIOC_NONE && _SIOC_DIR(cmd) != 0) {		/*		 * Have to validate the address given by the process.		 */		len = _SIOC_SIZE(cmd);		if (len < 1 || len > 65536 || arg == 0)			return -EFAULT;		if (_SIOC_DIR(cmd) & _SIOC_WRITE)			if ((err = verify_area(VERIFY_READ, (void *)arg, len)) < 0)				return err;		if (_SIOC_DIR(cmd) & _SIOC_READ)			if ((err = verify_area(VERIFY_WRITE, (void *)arg, len)) < 0)				return err;	}	DEB(printk("sound_ioctl(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));	if (cmd == OSS_GETVERSION)		return __put_user(SOUND_VERSION, (int *)arg);		if (_IOC_TYPE(cmd) == 'M' && num_mixers > 0 &&   /* Mixer ioctl */	    (dev & 0x0f) != SND_DEV_CTL) {              		dtype = dev & 0x0f;		switch (dtype) {#ifdef CONFIG_AUDIO		case SND_DEV_DSP:		case SND_DEV_DSP16:		case SND_DEV_AUDIO:			return sound_mixer_ioctl(audio_devs[dev >> 4]->mixer_dev,						 cmd, (caddr_t)arg);#endif					default:			return sound_mixer_ioctl(dev >> 4, cmd, (caddr_t)arg);		}	}	switch (dev & 0x0f) {	case SND_DEV_CTL:		if (cmd == SOUND_MIXER_GETLEVELS)			return get_mixer_levels((caddr_t)arg);		if (cmd == SOUND_MIXER_SETLEVELS)			return set_mixer_levels((caddr_t)arg);		return sound_mixer_ioctl(dev >> 4, cmd, (caddr_t)arg);#ifdef CONFIG_SEQUENCER	case SND_DEV_SEQ:	case SND_DEV_SEQ2:		return sequencer_ioctl(dev, file, cmd, (caddr_t)arg);#endif#ifdef CONFIG_AUDIO	case SND_DEV_DSP:	case SND_DEV_DSP16:	case SND_DEV_AUDIO:		return audio_ioctl(dev, file, cmd, (caddr_t)arg);		break;#endif#ifdef CONFIG_MIDI	case SND_DEV_MIDIN:		return MIDIbuf_ioctl(dev, file, cmd, (caddr_t)arg);		break;#endif	}	return -EINVAL;}#ifdef OSKITstatic unsigned int sound_poll(struct file *file, poll_table * wait){	printk("Sound: poll() not supported\n");	return 0;}static int sound_mmap(struct file *file, struct vm_area_struct *vma){	printk("Sound: mmap() not supported\n");	return -EINVAL;}#elsestatic unsigned int sound_poll(struct file *file, poll_table * wait){	struct inode *inode = file->f_dentry->d_inode;	int dev = MINOR(inode->i_rdev);	DEB(printk("sound_poll(dev=%d)\n", dev));	switch (dev & 0x0f) {#ifdef CONFIG_SEQUENCER	case SND_DEV_SEQ:	case SND_DEV_SEQ2:		return sequencer_poll(dev, file, wait);#endif#ifdef CONFIG_MIDI	case SND_DEV_MIDIN:		return MIDIbuf_poll(dev, file, wait);#endif#ifdef CONFIG_AUDIO	case SND_DEV_DSP:	case SND_DEV_DSP16:	case SND_DEV_AUDIO:		return DMAbuf_poll(file, dev >> 4, wait);#endif	}	return 0;}static int sound_mmap(struct file *file, struct vm_area_struct *vma){	int dev_class;	unsigned long size;	struct dma_buffparms *dmap = NULL;	int dev = MINOR(file->f_dentry->d_inode->i_rdev);	dev_class = dev & 0x0f;	dev >>= 4;	if (dev_class != SND_DEV_DSP && dev_class != SND_DEV_DSP16 && dev_class != SND_DEV_AUDIO)	{/*		printk("Sound: mmap() not supported for other than audio devices\n");*/		return -EINVAL;	}	if (vma->vm_flags & VM_WRITE)	/* Map write and read/write to the output buf */		dmap = audio_devs[dev]->dmap_out;	else if (vma->vm_flags & VM_READ)		dmap = audio_devs[dev]->dmap_in;	else	{/*		printk("Sound: Undefined mmap() access\n");*/		return -EINVAL;	}	if (dmap == NULL)	{/*		printk("Sound: mmap() error. dmap == NULL\n");*/		return -EIO;	}	if (dmap->raw_buf == NULL)	{/*		printk("Sound: mmap() called when raw_buf == NULL\n");*/		return -EIO;	}	if (dmap->mapping_flags)	{/*		printk("Sound: mmap() called twice for the same DMA buffer\n");*/		return -EIO;	}	if (vma->vm_offset != 0)	{/*		printk("Sound: mmap() offset must be 0.\n");*/		return -EINVAL;	}	size = vma->vm_end - vma->vm_start;	if (size != dmap->bytes_in_use)	{		printk(KERN_WARNING "Sound: mmap() size = %ld. Should be %d\n", size, dmap->bytes_in_use);	}	if (remap_page_range(vma->vm_start, virt_to_phys(dmap->raw_buf),		vma->vm_end - vma->vm_start,		vma->vm_page_prot))		return -EAGAIN;	dmap->mapping_flags |= DMA_MAP_MAPPED;	if( audio_devs[dev]->d->mmap)		audio_devs[dev]->d->mmap(dev);	memset(dmap->raw_buf,	       dmap->neutral_byte,	       dmap->bytes_in_use);	return 0;}#endifstruct file_operations oss_sound_fops ={	sound_lseek,	sound_read,	sound_write,	NULL,			/* sound_readdir */	sound_poll,	sound_ioctl,	sound_mmap,	sound_open,	NULL,			/* flush */	sound_release};/* *	Create the required special subdevices */ static int create_special_devices(void){	int seq1,seq2;	int sndstat=register_sound_special(&oss_sound_fops, 6);	if(sndstat==-1)		goto bad1;	seq1=register_sound_special(&oss_sound_fops, 1);	if(seq1==-1)		goto bad2;	seq2=register_sound_special(&oss_sound_fops, 8);	if(seq2!=-1)		return 0;	unregister_sound_special(1);bad2:	unregister_sound_special(6);		bad1:		return -1;}#ifdef MODULEstatic void#elsevoid#endifsoundcard_init(void){	/* drag in sound_syms.o */	{		extern char sound_syms_symbol;		sound_syms_symbol = 0;	}#ifndef MODULE	create_special_devices();	chrdev_registered = 1;#endif	soundcard_configured = 1;	sndtable_init();	/* Initialize call tables and detect cards */#ifdef FIXME	if (sndtable_get_cardcount() == 0)		return;		/* No cards detected */#endif#ifdef CONFIG_AUDIO	if (num_audiodevs || modular)	/* Audio devices present */	{		audio_init_devices();	}#endif#ifdef CONFIG_PROC_FS	if (proc_register(&proc_root, &proc_root_sound))		printk(KERN_ERR "sound: registering /proc/sound failed\n");#endif		}#ifdef MODULEstatic void destroy_special_devices(void){	unregister_sound_special(6);	unregister_sound_special(1);	unregister_sound_special(8);}static int      sound[20] = {	0};int traceinit = 0;static int dmabuf = 0;MODULE_PARM(traceinit, "i");MODULE_PARM(dmabuf, "i");int init_module(void){	int             err;	int             ints[21];	int             i;	trace_init=traceinit;	/*	 * "sound=" command line handling by Harald Milz.	 */	i = 0;	while (i < 20 && sound[i])		ints[i + 1] = sound[i++];	ints[0] = i;	if (i)		sound_setup("sound=", ints);	err = create_special_devices();	if (err)	{		printk(KERN_ERR "sound: driver already loaded/included in kernel\n");		return err;	}	/* Protecting the innocent */	sound_dmap_flag = (dmabuf > 0 ? 1 : 0);	chrdev_registered = 1;	soundcard_init();	if (sound_nblocks >= 1024)		printk(KERN_ERR "Sound warning: Deallocation table was too small.\n");		return 0;}void cleanup_module(void){	int i;	if (MOD_IN_USE)	{		return;	}#ifdef CONFIG_PROC_FS	        if (proc_unregister(&proc_root, PROC_SOUND))		printk(KERN_ERR "sound: unregistering /proc/sound failed\n");#endif			if (chrdev_registered)		destroy_special_devices();#ifdef CONFIG_SEQUENCER	sound_stop_timer();#endif#ifdef CONFIG_LOWLEVEL_SOUND	{		extern void     sound_unload_lowlevel_drivers(void);		sound_unload_lowlevel_drivers();	}#endif	sound_unload_drivers();	sequencer_unload();	for (i = 0; i < MAX_DMA_CHANNELS; i++)	{		if (dma_alloc_map[i] != DMA_MAP_UNAVAIL)		{			printk(KERN_ERR "Sound: Hmm, DMA%d was left allocated - fixed\n", i);			sound_free_dma(i);		}	}	for (i = 0; i < sound_nblocks; i++)	{		vfree(sound_mem_blocks[i]);	}}#endifint sound_alloc_dma(int chn, char *deviceID){	int err;	if ((err = request_dma(chn, deviceID)) != 0)		return err;	dma_alloc_map[chn] = DMA_MAP_FREE;	return 0;}int sound_open_dma(int chn, char *deviceID){	unsigned long   flags;	if (!valid_dma(chn))	{		printk(KERN_ERR "sound_open_dma: Invalid DMA channel %d\n", chn);		return 1;	}	save_flags(flags);	cli();	if (dma_alloc_map[chn] != DMA_MAP_FREE)	{		printk("sound_open_dma: DMA channel %d busy or not allocated (%d)\n", chn, dma_alloc_map[chn]);		restore_flags(flags);		return 1;	}	dma_alloc_map[chn] = DMA_MAP_BUSY;	restore_flags(flags);	return 0;}void sound_free_dma(int chn){	if (dma_alloc_map[chn] == DMA_MAP_UNAVAIL)	{		/* printk( "sound_free_dma: Bad access to DMA channel %d\n",  chn); */		return;	}	free_dma(chn);	dma_alloc_map[chn] = DMA_MAP_UNAVAIL;}void sound_close_dma(int chn){	unsigned long   flags;	save_flags(flags);	cli();	if (dma_alloc_map[chn] != DMA_MAP_BUSY)	{		printk(KERN_ERR "sound_close_dma: Bad access to DMA channel %d\n", chn);		restore_flags(flags);		return;	}	dma_alloc_map[chn] = DMA_MAP_FREE;	restore_flags(flags);}#ifdef CONFIG_SEQUENCERstatic void do_sequencer_timer(unsigned long dummy){	sequencer_timer(0);}static struct timer_list seq_timer ={NULL, NULL, 0, 0, do_sequencer_timer};void request_sound_timer(int count){	extern unsigned long seq_time;	if (count < 0)	{		seq_timer.expires = (-count) + jiffies;		add_timer(&seq_timer);		return;	}	count += seq_time;	count -= jiffies;	if (count < 1)		count = 1;	seq_timer.expires = (count) + jiffies;	add_timer(&seq_timer);}void sound_stop_timer(void){	del_timer(&seq_timer);;}#endifvoid conf_printf(char *name, struct address_info *hw_config){	if (!trace_init)		return;	printk("<%s> at 0x%03x", name, hw_config->io_base);	if (hw_config->irq)		printk(" irq %d", (hw_config->irq > 0) ? hw_config->irq : -hw_config->irq);	if (hw_config->dma != -1 || hw_config->dma2 != -1)	{		printk(" dma %d", hw_config->dma);		if (hw_config->dma2 != -1)			printk(",%d", hw_config->dma2);	}	printk("\n");}void conf_printf2(char *name, int base, int irq, int dma, int dma2){	if (!trace_init)		return;	printk("<%s> at 0x%03x", name, base);	if (irq)		printk(" irq %d", (irq > 0) ? irq : -irq);	if (dma != -1 || dma2 != -1)	{		  printk(" dma %d", dma);		  if (dma2 != -1)			  printk(",%d", dma2);	}	printk("\n");}/* *	Module and lock management */ /* *	When a sound module is registered we need to bring it to the current *	lock level... */ void sound_notifier_chain_register(struct notifier_block *bl){	int ct=0;		notifier_chain_register(&sound_locker, bl);	/*	 *	Normalise the lock count by calling the entry directly. We	 *	have to call the module as it owns its own use counter	 */	while(ct<lock_depth)	{		bl->notifier_call(bl, 1, 0);		ct++;	}}

⌨️ 快捷键说明

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