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

📄 sb_audio.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
static short sbpro_audio_set_channels(int dev, short channels){	sb_devc *devc = audio_devs[dev]->devc;	if (channels == 1 || channels == 2)	{		if (channels != devc->channels)		{			devc->channels = channels;			if (devc->model == MDL_SBPRO && devc->channels == 2)				sbpro_audio_set_speed(dev, devc->speed);		}	}	return devc->channels;}static int jazz16_audio_set_speed(int dev, int speed){	sb_devc *devc = audio_devs[dev]->devc;	if (speed > 0)	{		int tmp;		int s = speed * devc->channels;		if (speed < 5000)			speed = 5000;		if (speed > 44100)			speed = 44100;		devc->tconst = (256 - ((1000000 + s / 2) / s)) & 0xff;		tmp = 256 - devc->tconst;		speed = ((1000000 + tmp / 2) / tmp) / devc->channels;		devc->speed = speed;	}	return devc->speed;}/* * SB16 specific routines */static int sb16_audio_set_speed(int dev, int speed){	sb_devc *devc = audio_devs[dev]->devc;	int	max_speed = devc->submodel == SUBMDL_ALS100 ? 48000 : 44100;	if (speed > 0)	{		if (speed < 5000)	/* which of these */			speed = 4000;	/* is correct ??? */		if (speed > max_speed)			speed = max_speed;		devc->speed = speed;	}	return devc->speed;}static unsigned int sb16_audio_set_bits(int dev, unsigned int bits){	sb_devc *devc = audio_devs[dev]->devc;	if (bits != 0)	{		if (bits == AFMT_U8 || bits == AFMT_S16_LE)			devc->bits = bits;		else			devc->bits = AFMT_U8;	}	return devc->bits;}static int sb16_audio_prepare_for_input(int dev, int bsize, int bcount){	sb_devc *devc = audio_devs[dev]->devc;	if (!devc->fullduplex)	{		audio_devs[dev]->dmap_out->dma =			audio_devs[dev]->dmap_in->dma =				devc->bits == AFMT_S16_LE ?					devc->dma16 : devc->dma8;	}	else if (devc->bits == AFMT_S16_LE)	{		audio_devs[dev]->dmap_out->dma = devc->dma8;		audio_devs[dev]->dmap_in->dma = devc->dma16;	}	else	{		audio_devs[dev]->dmap_out->dma = devc->dma16;		audio_devs[dev]->dmap_in->dma = devc->dma8;	}	devc->trigger_bits = 0;	return 0;}static int sb16_audio_prepare_for_output(int dev, int bsize, int bcount){	sb_devc *devc = audio_devs[dev]->devc;	if (!devc->fullduplex)	{		audio_devs[dev]->dmap_out->dma =			audio_devs[dev]->dmap_in->dma =				devc->bits == AFMT_S16_LE ?					devc->dma16 : devc->dma8;	}	else if (devc->bits == AFMT_S16_LE)	{		audio_devs[dev]->dmap_out->dma = devc->dma8;		audio_devs[dev]->dmap_in->dma = devc->dma16;	}	else	{		audio_devs[dev]->dmap_out->dma = devc->dma16;		audio_devs[dev]->dmap_in->dma = devc->dma8;	}	devc->trigger_bits = 0;	return 0;}static void sb16_audio_output_block(int dev, unsigned long buf, int count,			int intrflag){	unsigned long   flags, cnt;	sb_devc        *devc = audio_devs[dev]->devc;	unsigned long   bits;	if (!devc->fullduplex || devc->bits == AFMT_S16_LE)	{		devc->irq_mode = IMODE_OUTPUT;		devc->intr_active = 1;	}	else	{		devc->irq_mode_16 = IMODE_OUTPUT;		devc->intr_active_16 = 1;	}	/* save value */	save_flags (flags);	cli ();	bits = devc->bits;	if (devc->fullduplex)		devc->bits = (devc->bits == AFMT_S16_LE) ?			AFMT_U8 : AFMT_S16_LE;	restore_flags (flags);	cnt = count;	if (devc->bits == AFMT_S16_LE)		cnt >>= 1;	cnt--;	save_flags(flags);	cli();	/* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */	sb_dsp_command(devc, 0x41);	sb_dsp_command(devc, (unsigned char) ((devc->speed >> 8) & 0xff));	sb_dsp_command(devc, (unsigned char) (devc->speed & 0xff));	sb_dsp_command(devc, (devc->bits == AFMT_S16_LE ? 0xb6 : 0xc6));	sb_dsp_command(devc, ((devc->channels == 2 ? 0x20 : 0) +			      (devc->bits == AFMT_S16_LE ? 0x10 : 0)));	sb_dsp_command(devc, (unsigned char) (cnt & 0xff));	sb_dsp_command(devc, (unsigned char) (cnt >> 8));	/* restore real value after all programming */	devc->bits = bits;	restore_flags(flags);}static void sb16_audio_start_input(int dev, unsigned long buf, int count, int intrflag){	unsigned long   flags, cnt;	sb_devc        *devc = audio_devs[dev]->devc;	if (!devc->fullduplex || devc->bits != AFMT_S16_LE)	{		devc->irq_mode = IMODE_INPUT;		devc->intr_active = 1;	}	else	{		devc->irq_mode_16 = IMODE_INPUT;		devc->intr_active_16 = 1;	}	cnt = count;	if (devc->bits == AFMT_S16_LE)		cnt >>= 1;	cnt--;	save_flags(flags);	cli();	/* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */	sb_dsp_command(devc, 0x42);	sb_dsp_command(devc, (unsigned char) ((devc->speed >> 8) & 0xff));	sb_dsp_command(devc, (unsigned char) (devc->speed & 0xff));	sb_dsp_command(devc, (devc->bits == AFMT_S16_LE ? 0xbe : 0xce));	sb_dsp_command(devc, ((devc->channels == 2 ? 0x20 : 0) +			      (devc->bits == AFMT_S16_LE ? 0x10 : 0)));	sb_dsp_command(devc, (unsigned char) (cnt & 0xff));	sb_dsp_command(devc, (unsigned char) (cnt >> 8));	restore_flags(flags);}static void sb16_audio_trigger(int dev, int bits){	sb_devc *devc = audio_devs[dev]->devc;	int bits_16 = bits & devc->irq_mode_16;	bits &= devc->irq_mode;	if (!bits && !bits_16)		sb_dsp_command(devc, 0xd0);	/* Halt DMA */	else	{		if (bits)		{			switch (devc->irq_mode)			{				case IMODE_INPUT:					sb16_audio_start_input(dev,							devc->trg_buf,							devc->trg_bytes,							devc->trg_intrflag);					break;				case IMODE_OUTPUT:					sb16_audio_output_block(dev,							devc->trg_buf,							devc->trg_bytes,							devc->trg_intrflag);					break;			}		}		if (bits_16)		{			switch (devc->irq_mode_16)			{				case IMODE_INPUT:					sb16_audio_start_input(dev,							devc->trg_buf_16,							devc->trg_bytes_16,							devc->trg_intrflag_16);					break;				case IMODE_OUTPUT:					sb16_audio_output_block(dev,							devc->trg_buf_16,							devc->trg_bytes_16,							devc->trg_intrflag_16);					break;			}		}	}	devc->trigger_bits = bits | bits_16;}static unsigned char lbuf8[2048];static signed short *lbuf16 = (signed short *)lbuf8;#define LBUFCOPYSIZE 1024static voidsb16_copy_from_user(int dev,		char *localbuf, int localoffs,		const char *userbuf, int useroffs,		int max_in, int max_out,		int *used, int *returned,		int len){	sb_devc       *devc = audio_devs[dev]->devc;	int           i, c, p, locallen;	unsigned char *buf8;	signed short  *buf16;	/* if not duplex no conversion */	if (!devc->fullduplex)	{		copy_from_user (localbuf + localoffs, userbuf + useroffs, len);		*used = len;		*returned = len;	}	else if (devc->bits == AFMT_S16_LE)	{		/* 16 -> 8 */		/* max_in >> 1, max number of samples in ( 16 bits ) */		/* max_out, max number of samples out ( 8 bits ) */		/* len, number of samples that will be taken ( 16 bits )*/		/* c, count of samples remaining in buffer ( 16 bits )*/		/* p, count of samples already processed ( 16 bits )*/		len = ( (max_in >> 1) > max_out) ? max_out : (max_in >> 1);		c = len;		p = 0;		buf8 = (unsigned char *)(localbuf + localoffs);		while (c)		{			locallen = (c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c);			/* << 1 in order to get 16 bit samples */			copy_from_user (lbuf16,					userbuf+useroffs + (p << 1),					locallen << 1);			for (i = 0; i < locallen; i++)			{				buf8[p+i] = ~((lbuf16[i] >> 8) & 0xff) ^ 0x80;			}			c -= locallen; p += locallen;		}		/* used = ( samples * 16 bits size ) */		*used = len << 1;		/* returned = ( samples * 8 bits size ) */		*returned = len;	}	else	{		/* 8 -> 16 */		/* max_in, max number of samples in ( 8 bits ) */		/* max_out >> 1, max number of samples out ( 16 bits ) */		/* len, number of samples that will be taken ( 8 bits )*/		/* c, count of samples remaining in buffer ( 8 bits )*/		/* p, count of samples already processed ( 8 bits )*/		len = max_in > (max_out >> 1) ? (max_out >> 1) : max_in;		c = len;		p = 0;		buf16 = (signed short *)(localbuf + localoffs);		while (c)		{			locallen = (c >= LBUFCOPYSIZE ? LBUFCOPYSIZE : c);			copy_from_user (lbuf8,					userbuf+useroffs + p,					locallen);			for (i = 0; i < locallen; i++)			{				buf16[p+i] = (~lbuf8[i] ^ 0x80) << 8;			}	      		c -= locallen; p += locallen;		}		/* used = ( samples * 8 bits size ) */		*used = len;		/* returned = ( samples * 16 bits size ) */		*returned = len << 1;	}}static voidsb16_audio_mmap(int dev){	sb_devc       *devc = audio_devs[dev]->devc;	devc->fullduplex = 0;}static struct audio_driver sb1_audio_driver =	/* SB1.x */{	sb_audio_open,	sb_audio_close,	sb_set_output_parms,	sb_set_input_parms,	NULL, /* ioctl */	sb1_audio_prepare_for_input,	sb1_audio_prepare_for_output,	sb1_audio_halt_xfer,	NULL,			/* local_qlen */	NULL,			/* copy_from_user */	NULL,	NULL,	sb1_audio_trigger,	sb1_audio_set_speed,	sb1_audio_set_bits,	sb1_audio_set_channels};static struct audio_driver sb20_audio_driver =	/* SB2.0 */{	sb_audio_open,	sb_audio_close,	sb_set_output_parms,	sb_set_input_parms,	NULL,	sb1_audio_prepare_for_input,	sb1_audio_prepare_for_output,	sb1_audio_halt_xfer,	NULL,			/* local_qlen */	NULL,			/* copy_from_user */	NULL,	NULL,	sb20_audio_trigger,	sb1_audio_set_speed,	sb1_audio_set_bits,	sb1_audio_set_channels};static struct audio_driver sb201_audio_driver =		/* SB2.01 */{	sb_audio_open,	sb_audio_close,	sb_set_output_parms,	sb_set_input_parms,	NULL,	sb1_audio_prepare_for_input,	sb1_audio_prepare_for_output,	sb1_audio_halt_xfer,	NULL,			/* local_qlen */	NULL,			/* copy_from_user */	NULL,	NULL,	sb20_audio_trigger,	sb201_audio_set_speed,	sb1_audio_set_bits,	sb1_audio_set_channels};static struct audio_driver sbpro_audio_driver =		/* SB Pro */{	sb_audio_open,	sb_audio_close,	sb_set_output_parms,	sb_set_input_parms,	NULL,	sbpro_audio_prepare_for_input,	sbpro_audio_prepare_for_output,	sb1_audio_halt_xfer,	NULL,			/* local_qlen */	NULL,			/* copy_from_user */	NULL,	NULL,	sb20_audio_trigger,	sbpro_audio_set_speed,	sb1_audio_set_bits,	sbpro_audio_set_channels};static struct audio_driver jazz16_audio_driver =	/* Jazz16 and SM Wave */{	sb_audio_open,	sb_audio_close,	sb_set_output_parms,	sb_set_input_parms,	NULL,	sbpro_audio_prepare_for_input,	sbpro_audio_prepare_for_output,	sb1_audio_halt_xfer,	NULL,			/* local_qlen */	NULL,			/* copy_from_user */	NULL,	NULL,	sb20_audio_trigger,	jazz16_audio_set_speed,	sb16_audio_set_bits,	sbpro_audio_set_channels};static struct audio_driver sb16_audio_driver =	/* SB16 */{	sb_audio_open,	sb_audio_close,	sb_set_output_parms,	sb_set_input_parms,	NULL,	sb16_audio_prepare_for_input,	sb16_audio_prepare_for_output,	sb1_audio_halt_xfer,	NULL,			/* local_qlen */	sb16_copy_from_user,	/* copy_from_user */	NULL,	NULL,	sb16_audio_trigger,	sb16_audio_set_speed,	sb16_audio_set_bits,	sbpro_audio_set_channels,	NULL,	NULL,	sb16_audio_mmap};void sb_audio_init(sb_devc * devc, char *name){	int audio_flags = 0;	int format_mask = AFMT_U8;	struct audio_driver *driver = &sb1_audio_driver;	switch (devc->model)	{		case MDL_SB1:	/* SB1.0 or SB 1.5 */			DDB(printk("Will use standard SB1.x driver\n"));			audio_flags = DMA_HARDSTOP;			break;		case MDL_SB2:			DDB(printk("Will use SB2.0 driver\n"));			audio_flags = DMA_AUTOMODE;			driver = &sb20_audio_driver;			break;		case MDL_SB201:			DDB(printk("Will use SB2.01 (high speed) driver\n"));			audio_flags = DMA_AUTOMODE;			driver = &sb201_audio_driver;			break;		case MDL_JAZZ:		case MDL_SMW:			DDB(printk("Will use Jazz16 driver\n"));			audio_flags = DMA_AUTOMODE;			format_mask |= AFMT_S16_LE;			driver = &jazz16_audio_driver;			break;		case MDL_ESS:			DDB(printk("Will use ESS ES688/1688 driver\n"));			driver = ess_audio_init (devc, &audio_flags, &format_mask);			break;		case MDL_SB16:			DDB(printk("Will use SB16 driver\n"));			audio_flags = DMA_AUTOMODE;			format_mask |= AFMT_S16_LE;			if (devc->dma8 != devc->dma16 && devc->dma16 != -1)			{				audio_flags |= DMA_DUPLEX;				devc->duplex = 1;			}			driver = &sb16_audio_driver;			break;		default:			DDB(printk("Will use SB Pro driver\n"));			audio_flags = DMA_AUTOMODE;			driver = &sbpro_audio_driver;	}	if ((devc->dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION,				name,driver, sizeof(struct audio_driver),				audio_flags, format_mask, devc,				devc->dma8,				devc->duplex ? devc->dma16 : devc->dma8)) < 0)	{		  printk(KERN_ERR "Sound Blaster:  unable to install audio.\n");		  return;	}	audio_devs[devc->dev]->mixer_dev = devc->my_mixerdev;	audio_devs[devc->dev]->min_fragment = 5;}#endif

⌨️ 快捷键说明

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