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

📄 es1371.c

📁 Minix比较全的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Best viewed with tabsize 4 *//* Original: * November 2005    ES1371 driver (Laurens Bronwasser) *//* Ensoniq ES1371 driver * * aka AudioPCI '97 * * This is the main file of the ES1371 sound driver. There is no main function * over here, instead the main function is located in the generic dma driver. * All this driver does is implement the interface audio/audio_fw.h. All * functions having the prefix 'drv_' are dictated by audio/audio_fw.h. The * function prototypes you see below define a set of private helper functions. * Control over the AC97 codec is delegated AC97.c.   * * October 2007    ES1371 driver (Pieter Hijma),  * based on ES1370 driver which is based on the ES1371 driver  * by Laurens Bronwasser */#include <ibm/pci.h>#include "../framework/audio_fw.h"#include "es1371.h"#include "AC97.h"#include "sample_rate_converter.h"#include "pci_helper.h"/* reg(n) will be the device specific addresses */#define reg(n) dev.base + n/* prototypes of private functions */FORWARD _PROTOTYPE( int detect_hw, (void) );  FORWARD _PROTOTYPE( int disable_int, (int sub_dev) );FORWARD _PROTOTYPE( int set_stereo, (u32_t stereo, int sub_dev) );FORWARD _PROTOTYPE( int set_bits, (u32_t nr_of_bits, int sub_dev) );FORWARD _PROTOTYPE( int set_sample_rate, (u32_t rate, int sub_dev) );FORWARD _PROTOTYPE( int set_sign, (u32_t val, int sub_dev) );FORWARD _PROTOTYPE( int get_max_frag_size, 		(u32_t * val, int *len, int sub_dev) );FORWARD _PROTOTYPE( int set_frag_size, (u32_t fragment_size, int sub_dev) );FORWARD _PROTOTYPE( int set_int_cnt, (int sub_dev) );FORWARD _PROTOTYPE( int free_buf, (u32_t *val, int *len, int sub_dev) );FORWARD _PROTOTYPE( int get_samples_in_buf, 		(u32_t *val, int *len, int sub_dev) );FORWARD _PROTOTYPE( int get_set_volume, (struct volume_level *level, int *len, 			int sub_dev, int flag) );FORWARD _PROTOTYPE( int reset, (int sub_dev) );DEV_STRUCT dev;aud_sub_dev_conf_t aud_conf[4];PUBLIC sub_dev_t sub_dev[4];PUBLIC special_file_t special_file[4];PUBLIC drv_t drv;PUBLIC int drv_init(void) {	drv.DriverName = DRIVER_NAME;	drv.NrOfSubDevices = 4;	drv.NrOfSpecialFiles = 4;	sub_dev[DAC1_CHAN].readable = 0;	sub_dev[DAC1_CHAN].writable = 1;	sub_dev[DAC1_CHAN].DmaSize = 64 * 1024;	sub_dev[DAC1_CHAN].NrOfDmaFragments = 2;	sub_dev[DAC1_CHAN].MinFragmentSize = 1024;	sub_dev[DAC1_CHAN].NrOfExtraBuffers = 4;	sub_dev[ADC1_CHAN].readable = 1;	sub_dev[ADC1_CHAN].writable = 0;	sub_dev[ADC1_CHAN].DmaSize = 64 * 1024;	sub_dev[ADC1_CHAN].NrOfDmaFragments = 2;	sub_dev[ADC1_CHAN].MinFragmentSize = 1024;	sub_dev[ADC1_CHAN].NrOfExtraBuffers = 4;	sub_dev[MIXER].writable = 0;	sub_dev[MIXER].readable = 0;	sub_dev[DAC2_CHAN].readable = 0;	sub_dev[DAC2_CHAN].writable = 1;	sub_dev[DAC2_CHAN].DmaSize = 64 * 1024;	sub_dev[DAC2_CHAN].NrOfDmaFragments = 2;	sub_dev[DAC2_CHAN].MinFragmentSize = 1024;	sub_dev[DAC2_CHAN].NrOfExtraBuffers = 4;	special_file[0].minor_dev_nr = 0;	special_file[0].write_chan = DAC1_CHAN;	special_file[0].read_chan = NO_CHANNEL;	special_file[0].io_ctl = DAC1_CHAN;	special_file[1].minor_dev_nr = 1;	special_file[1].write_chan = NO_CHANNEL;	special_file[1].read_chan = ADC1_CHAN;	special_file[1].io_ctl = ADC1_CHAN;	special_file[2].minor_dev_nr = 2;	special_file[2].write_chan = NO_CHANNEL;	special_file[2].read_chan = NO_CHANNEL;	special_file[2].io_ctl = MIXER;	special_file[3].minor_dev_nr = 3;	special_file[3].write_chan = DAC2_CHAN;	special_file[3].read_chan = NO_CHANNEL;	special_file[3].io_ctl = DAC2_CHAN;}PUBLIC int drv_init_hw (void) {	u16_t i, j;	u16_t chip_sel_ctrl_reg;	/* First, detect the hardware */	if (detect_hw() != OK) {		return EIO;	}	/* PCI command register 	 * enable the SERR# driver, PCI bus mastering and I/O access	 */	pci_attr_w16 (dev.devind, PCI_CR, SERR_EN|PCI_MASTER|IO_ACCESS);	/* turn everything off */	pci_outl(reg(CHIP_SEL_CTRL),  0x0UL);	/* turn off legacy (legacy control is undocumented) */	pci_outl(reg(LEGACY), 0x0UL);	pci_outl(reg(LEGACY+4), 0x0UL);	/* turn off serial interface */	pci_outl(reg(SERIAL_INTERFACE_CTRL), 0x0UL);	/*pci_outl(reg(SERIAL_INTERFACE_CTRL), 0x3UL);*/	/* clear all the memory */	for (i = 0; i < 0x10; ++i) {		pci_outb(reg(MEM_PAGE), i);		for (j = 0; j < 0x10; j += 4) {			pci_outl  (reg(MEMORY) + j, 0x0UL);		}	}	/* Sample Rate Converter initialization */	if (src_init(&dev) != OK) {		return EIO;	}	if (AC97_init(&dev) != OK) {		return EIO;	}	/* initialize variables for each sub_device */	for (i = 0; i < drv.NrOfSubDevices; i++) {		if(i != MIXER) {			aud_conf[i].busy = 0;			aud_conf[i].stereo = DEFAULT_STEREO;			aud_conf[i].sample_rate = DEFAULT_RATE;			aud_conf[i].nr_of_bits = DEFAULT_NR_OF_BITS;			aud_conf[i].sign = DEFAULT_SIGNED;			aud_conf[i].fragment_size = 				sub_dev[i].DmaSize / sub_dev[i].NrOfDmaFragments;		}	}	return OK;}PRIVATE int detect_hw(void) {	u32_t device;	int devind;	u16_t v_id, d_id;	/* detect_hw tries to find device and get IRQ and base address	   with a little (much) help from the PCI library. 	   This code is quite device independent and you can copy it. 	   (just make sure to get the bugs out first)*/	pci_init();	/* get first device and then search through the list */	device = pci_first_dev(&devind, &v_id, &d_id);	while( device > 0 ) {		/* if we have a match...break */		if (v_id == VENDOR_ID && d_id == DEVICE_ID) break;		device = pci_next_dev(&devind, &v_id, &d_id);	}	/* did we find anything? */	if (v_id != VENDOR_ID || d_id != DEVICE_ID) {		return EIO;	}	pci_reserve(devind);	dev.name = pci_dev_name(v_id, d_id);	/* get base address of our device, ignore least signif. bit 	   this last bit thing could be device dependent, i don't know */	dev.base = pci_attr_r32(devind, PCI_BAR) & 0xfffffffe;	/* get IRQ */	dev.irq = pci_attr_r8(devind, PCI_ILR);  	dev.revision = pci_attr_r8(devind, PCI_REV);	dev.d_id = d_id;	dev.v_id = v_id;	dev.devind = devind; /* pci device identifier */	return OK;}PRIVATE int reset(int chan) {	drv_stop(chan);	sub_dev[chan].OutOfData = 1;	return OK;}int drv_reset() {	return OK;}int drv_start(int sub_dev, int DmaMode) {	u32_t enable_bit, result = 0;	u32_t debug;	/* Write default values to device in case user failed to configure.	   If user did configure properly, everything is written twice.	   please raise your hand if you object against to this strategy...*/	result |= set_sample_rate(aud_conf[sub_dev].sample_rate, sub_dev);	result |= set_stereo(aud_conf[sub_dev].stereo, sub_dev);	result |= set_bits(aud_conf[sub_dev].nr_of_bits, sub_dev);	result |= set_sign(aud_conf[sub_dev].sign, sub_dev);	/* set the interrupt count */	result |= set_int_cnt(sub_dev);	if (result) {		return EIO;	}	/* if device currently paused, resume */	drv_resume(sub_dev);	switch(sub_dev) {		case ADC1_CHAN: enable_bit = ADC1_EN;break;		case DAC1_CHAN: enable_bit = DAC1_EN;break;		case DAC2_CHAN: enable_bit = DAC2_EN;break;    		default: return EINVAL;	}	/* enable interrupts from 'sub device' */	drv_reenable_int(sub_dev);	/* this means play!!! */	pci_outw(reg(CHIP_SEL_CTRL), pci_inw(reg(CHIP_SEL_CTRL)) | enable_bit);	aud_conf[sub_dev].busy = 1;	return OK;}int drv_stop(int sub_dev){	u32_t enable_bit;	switch(sub_dev) {		case ADC1_CHAN: enable_bit = ADC1_EN;break;		case DAC1_CHAN: enable_bit = DAC1_EN;break;		case DAC2_CHAN: enable_bit = DAC2_EN;break;    		default: return EINVAL;	}	/* stop the specified channel */	pci_outw(reg(CHIP_SEL_CTRL),			pci_inw(reg(CHIP_SEL_CTRL)) & ~enable_bit);	aud_conf[sub_dev].busy = 0;	disable_int(sub_dev);	return OK;}/* all IO-ctl's sent to the upper driver are passed to this function */int drv_io_ctl(int request, void * val, int * len, int sub_dev) {	int status;	switch(request) {		case DSPIORATE:				status = set_sample_rate(*((u32_t *) val), sub_dev); break;		case DSPIOSTEREO:	       			status = set_stereo(*((u32_t *) val), sub_dev); break;		case DSPIOBITS:	         			status = set_bits(*((u32_t *) val), sub_dev); break;		case DSPIOSIZE:	         			status = set_frag_size(*((u32_t *) val), sub_dev); break;		case DSPIOSIGN:	         			status = set_sign(*((u32_t *) val), sub_dev); break;		case DSPIOMAX:           			status = get_max_frag_size(val, len, sub_dev); break;		case DSPIORESET:         			status = reset(sub_dev); break;		case DSPIOFREEBUF:			status = free_buf(val, len, sub_dev); break;		case DSPIOSAMPLESINBUF: 			status = get_samples_in_buf(val, len, sub_dev); break;		case DSPIOPAUSE:			status = drv_pause(sub_dev); break;		case DSPIORESUME:			status = drv_resume(sub_dev); break;		case MIXIOGETVOLUME:			status = get_set_volume(val, len, sub_dev, 0); break;		case MIXIOSETVOLUME:			status = get_set_volume(val, len, sub_dev, 1); break;		default:                 			status = EINVAL; break;	}	return OK;}

⌨️ 快捷键说明

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