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

📄 vxpci.cpp

📁 devloped under vxwork, support ess sound card. driver library, include datasheet.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/****************************************************************** MODULE:		VxPCI.cpp** DESCRIPTION:	Functions used to install PCI linux-compatable drivers on a VxWorks 
*				system
*				
* ORIGINAL AUTHOR: 	Dan Walkes - with several structure/data definitions
*						and code referenced from linux source tree
*					* UPDATED BY:		* * CREATED:		Oct, 2005* MODIFIED:		
* * NOTES:*
*	Many assumptions were made in this file as of the first release to simplify
*	the code, the most important of which are listed below:
*
*		1) Interrupt routing and memory access for North/Soutbridge is initialized
*			by the BIOS (or some other utility)
*		2) PCI_SYSTEM_START_MEM_ALLOC_SPACE and  PCI_SYSTEM_START_IO_ALLOC_SPACE are
*			set to ranges of free PCI memory and IO spaces with sizes large enough for
*			all possible installed drivers.
** CODE USAGE:*	Below is a basic overview of how to use this module.  For more information please
*	see the documents listed in the "Reference" section.
*
*	Starting/Stopping Drivers:
*		vx_pci_start - Starts drivers for all installed PCI cards.  Make sure that a pointer to
*						your pci_driver	table is included in the pci_DrvTable structure
*
*		vx_pci_stop - Stops and un-installs all currently installed PCI cards and frees
*						all resources. 
**
*	Debug Functions:
*		d_vxpci_display - Displays information about all found devices
*
*		d_vxpci_get - returns a register value for a specific PCI device
*
*		d_vxpci_set - sets a register value for a specific PCI device
*
*
* REVISION HISTORY AND NOTES:** Date			Update* ---------------------------------------------------------------------* Oct 1, 2005	Created.** REFERENCES:** 1) "vxWALSA Sound Driver" document included with this release.
*****************************************************************/

/* Vxworks -linux includes */
#include "VxTypes.h"
#include "VxPCI.h"
#include "VxSound.h"
#include "es1938.h"




/* pcPentium BSP includes */
#include "sysLib.h"

/*--------------------------------------------------------------
	#defines
----------------------------------------------------------------*/

/* set this to the start of your MMIO space */
#define 	PCI_SYSTEM_START_MEM_ALLOC_SPACE	 0x04000000
#define 	PCI_SYSTEM_START_IO_ALLOC_SPACE		 0xE000


/*--------------------------------------------------------------
	Global Variables
----------------------------------------------------------------*/

unsigned long  	pci_memAllocRegionStart = PCI_SYSTEM_START_MEM_ALLOC_SPACE;
unsigned long 	pci_IOAllocRegionStart = PCI_SYSTEM_START_IO_ALLOC_SPACE;

/* null terminated table including all pci drivers 
	Place a pointer to your pci_driver table in the null-terminated
	list to include your driver.
*/
static const pci_driver *pci_DrvTable[] =
{
	&ES1938_driver,
	NULL,
};

/* currently only bus 0 is supported.. this is the default structure */
static const pci_bus pci_Bus0Struct ={
/*	.number = 0;
	.bus_id = "Bus ID 0";  */
	0,
	{ "Bus ID 0" }
};
	
/* this global holds a pointer to the pci dev linked list */
static pci_dev	*pci_pListHeadDev = 0;

/*--------------------------------------------------------------
	Function Prototypes
----------------------------------------------------------------*/
static int pci_baseAddressRegisterSizeOfDecodeSpace(int returnval);
static int vx_pci_probe_devices( const pci_driver *pPCIDrvTable[], pci_dev *pci );
int d_vxpci_get( int req_device, int reg,  unsigned char numbytes );


/*--------------------------------------------------------------
	Function Description:
		Sets up the passed resource structure based on the value
		read back from the Base Address Register.  Allocates memory
		or I/O space based on global #defines and variables
	
	Arguments:
		resource *pres - a pointer to the resource to initialize
		unsigned int barReadback - the value read from the Base Address Register
	
	Returns:
		0 (success)		
---------------------------------------------------------------*/
static int vx_pci_set_resource(resource *pres, unsigned int barReadback )
{

	if( !BAR_IS_IMPLEMENTED( barReadback ) )
	{
		pres->start = 0;
		pres->end = 0;
		pres->flags = IORESOURCE_DISABLED;
	}
	else 
	{
		if(BAR_IS_MEM_ADDRESS_DECODER( barReadback ) )
		{
			pres->flags = IORESOURCE_MEM;
			pres->start = pci_memAllocRegionStart;
			pres->end = pres->start + pci_baseAddressRegisterSizeOfDecodeSpace( barReadback )-1;
			pci_memAllocRegionStart =  pres->end +1;
			PCI_DEBUG_PRINT("Mem Resource Start %x End %x\n",pres->start,pres->end );
		}
		if( BAR_IS_IO_ADDRESS_DECODER( barReadback ) )
		{
		 	pres->flags = IORESOURCE_IO;
			pres->start = pci_IOAllocRegionStart;
			pres->end = pres->start + pci_baseAddressRegisterSizeOfDecodeSpace( barReadback )-1;
			pci_IOAllocRegionStart =  pres->end +1;
			PCI_DEBUG_PRINT("I/O Resource Start %x End %x\n",pres->start,pres->end );
		}
	}
			
	return SUCCESS_vx;
}

/* -------------------------------------------------------

	Function : 	 pci_enable_device_bars_vx

	Arguments:	
		struct pci_dev *pci - a pointer to the pci device structure

	Returns:
		SUCCESS_vx on success
		negative value representing error type on failure

	Note:
		Source for this function was influenced by btvid_controller_config
*/
int pci_enable_device_bars_vx(pci_dev *pci)
{
	int pciBusNo = pci->bus->number;
	int pciDevNo = PCI_SLOT(pci->devfn);
	int pciFuncNo = PCI_FUNC(pci->devfn);
	int ix,barreg=0, err;
	unsigned int testval;

	pci->irq = 0;

	/* Get the programmed interrupt value */
 	pciConfigInByte(pciBusNo, pciDevNo, pciFuncNo,
		    PCI_CFG_DEV_INT_LINE, (uint8*)&pci->irq);

	/* Disable the device */
//	pciConfigOutWord (pciBusNo, pciDevNo, pciFuncNo, PCI_CFG_COMMAND, 0);


	for (ix = PCI_CFG_BASE_ADDRESS_0; ix <= PCI_CFG_BASE_ADDRESS_5; ix+=4, barreg++)
	{
		pciConfigInLong(pciBusNo, pciDevNo, pciFuncNo, ix, &testval);

		PCI_DEBUG_PRINT("BAR %d testval=0x%x before writing 0xffffffff's \n", barreg, testval);

		/* Write all f's and read back value */

		pciConfigOutLong(pciBusNo, pciDevNo, pciFuncNo, ix, 0xffffffff);
		pciConfigInLong(pciBusNo, pciDevNo, pciFuncNo, ix, &testval);

		/* setup resources for this register */
		if( ( err = vx_pci_set_resource(&pci->resource[barreg],testval) ) < 0 )
		{

			return err;
		}
	
		/* write the starting address into the BAR */
		pci_write_config_dword( pci, ix, pci->resource[barreg].start );	

		if(!BAR_IS_IMPLEMENTED(testval)) {
			PCI_DEBUG_PRINT("BAR %d not implemented\n", ((ix/4)-4));
		} else {
		if(BAR_IS_MEM_ADDRESS_DECODER(testval)) {
			PCI_DEBUG_PRINT("BAR %d is a Memory Address Decoder\n", ((ix/4)-4));
			
			if(BAR_IS_32_BIT_DECODER(testval))
				PCI_DEBUG_PRINT( "BAR %d is a 32-Bit Decoder \n", ((ix/4)-4) );
			else if(BAR_IS_64_BIT_DECODER(testval))	
				PCI_DEBUG_PRINT( "BAR %d is a 64-Bit Decoder \n", ((ix/4)-4) );
			else
				PCI_DEBUG_PRINT( "BAR %d memory width is undefined \n", ((ix/4)-4) );

			if(BAR_IS_PREFETCHABLE(testval))
				PCI_DEBUG_PRINT( "BAR %d address space is prefetachable \n", ((ix/4)-4));
			
		} else if(BAR_IS_IO_ADDRESS_DECODER(testval)) {
			PCI_DEBUG_PRINT("BAR %d is an IO Address Decoder \n", ((ix/4)-4));
		} else {
			PCI_DEBUG_PRINT("BAR %d is niether an IO Address Decoder or an Memory Address Decoder (error probably) \n", ((ix/4)-4));	
		}
		
	printf("BAR %d decodes a space %i bytes big\n", ((ix/4)-4), 
		pci_baseAddressRegisterSizeOfDecodeSpace(testval));
	}

	PCI_DEBUG_PRINT("\n\n");
	}


}

/* -------------------------------------------------------
	Function : 	 pci_baseAddressRegisterSizeOfDecodeSpace

	Note:
	This function takes the entire 32 bit readback register value including bits 
	[3:0] and returns the position starting from 0 of the first bit not 0

	Taken from btvid.c function with the same name
*/

static int pci_baseAddressRegisterSizeOfDecodeSpace(int returnval) 
{

	int tmp = 0;
	int bitpos = 0;
	int i = 0;
	
	tmp = returnval;
       	tmp &= 0xFFFFFFF0;
	
	for(i = 0; i < 32; i++) {
		if(tmp & 0x1) {
			return (int)pow(2,bitpos);
		} else {
		
			bitpos++;
			tmp >>= 1;	
		}
	}
		
}

/* -------------------------------------------------------
	Not yet implemented

*/

int pci_disable_device_vx( struct pci_dev *pci )
{
	return SUCCESS_vx;
}


/* -------------------------------------------------------
	Function : 	 pci_set_master

*/

void pci_set_master(struct pci_dev *dev)
{
	u16 cmd;

	pci_read_config_word(dev, PCI_COMMAND_OFFS, &cmd);
	if (! (cmd & PCI_COMMAND_MASTER)) {
/*		pr_debug("PCI: Enabling bus mastering for device %s\n", pci_name(dev)); */
		cmd |= PCI_COMMAND_MASTER;
		pci_write_config_word(dev, PCI_COMMAND_OFFS, cmd);
	}
	dev->is_busmaster = 1;
	pcibios_set_master(dev);
}



/* -------------------------------------------------------
	Function : 	 vx_pci_alloc_new_pci_dev

	Allocates a new pci dev for the specified bus (currently only bus 0 is supported)

	Returns a pointer to the allocated structure
*/

static pci_dev *vx_pci_alloc_new_pci_dev( int busNo )
{
	/* for now, do nothing with bus number */
	pci_dev *pDev;
	pci_dev *pDevPrev=0;

	pDev = pci_pListHeadDev;

	while( pDev )
	{
		pDevPrev = pDev;
		pDev = (pci_dev *)pDev->global_list.next;
	}

	pDev = (pci_dev *) malloc( sizeof(pci_dev) );	/* malloc a new pci device structure */

	if( pDev == NULL )
	{
		return pDev;
	}

	memset(pDev,0,sizeof(pci_dev));

	if( pDevPrev )
	{
		pDev->global_list.prev = (list_head *)pDevPrev;
		pDevPrev->global_list.next = (list_head *)pDev;
	}
	else
	{
		pci_pListHeadDev = pDev;
	}

	return pDev;
}

/* --------------------------------------------------
	Removes a pci_dev structure from the linked list.
	Note: does not currently handle PCI device memory resource de-allocation.. 
*/	
void vx_pci_remove_pci_dev( pci_dev *pDev )
{

	if( pDev->global_list.prev )
	{
		((pci_dev *)pDev->global_list.prev)->global_list.next = pDev->global_list.next;
	}
	else
	{
		pci_pListHeadDev = (pci_dev *)pDev->global_list.next;
		((pci_dev *)pDev->global_list.next)->global_list.prev = 0;
	}
	 
	if(	pDev->private_free )
	{
		(*pDev->private_free)(	pDev->private_data );
	}

	free( pDev );	/* de-allocate memory */
}

/* -------------------------------------------------------
	Function : 	 vx_pci_find_pci_dev

	Finds the pci_dev structure for a device with the given
	bus number, device number and function number

	Returns a pointer to the found structure
*/	
static pci_dev *vx_pci_find_pci_dev( int busNo, int DevNo, int FuncNo )
{
	pci_dev *pDev;
	 
	pDev = pci_pListHeadDev;

	while( pDev )
	{
		if( pDev->bus->number == busNo &&
			PCI_FUNC(pDev->devfn) == FuncNo &&
			PCI_SLOT(pDev->devfn) == DevNo )
		{
			return pDev;
		}

		pDev = (pci_dev *)pDev->global_list.next;
	}

	return NULL;	/* didn't find this device */

}	

/* -------------------------------------------------------
	Function : 	 vx_pci_probe_all_recognized_devices

	Looks for devices on the bus and attempts to match them
	with devices in the PCI driver table
*/	
static int vx_pci_probe_all_recognized_devices ( void )
{

	pci_dev *pDev;
	 
	pDev = pci_pListHeadDev;

	while( pDev )

⌨️ 快捷键说明

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