📄 vxpci.cpp
字号:
/****************************************************************** 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 + -