// PciCardDriver.cpp: implementation of the PciCardDriver class.
//
//////////////////////////////////////////////////////////////////////
#include "PciCardDriver.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//板卡基类
PciCardDriver::PciCardDriver()
{
init();
}
PciCardDriver::PciCardDriver(
UINT uiCardID,
const DWORD SVID,
const DWORD DID,
const DWORD VID,
const DWORD PADDR,
const DWORD PRANGE,
const DWORD MRANGE,
char *iniPath
)
{
init(DID,VID,SVID,PADDR,PRANGE,MRANGE);
}
PciCardDriver::~PciCardDriver()
{
if(bHasRegistered)
{
UnRegister() ;
}
}
/*
* 函数介绍:驱动程序注册
* 输入参数:无
* 输出参数:无
* 返回值:TRUE-----注册成功
* FALSE----注册失败
*/
BOOL PciCardDriver::Register()
{
//
// Search for the device using vendor and device IDs
//
busNumber = DeviceSearch( m_VID, m_DID, &slotNumber, pciData );
//
// If the device is found
//
if( busNumber != DEVICE_NOT_FOUND )
if( !DeviceInit( busNumber, &slotNumber, pciData ) )
DeviceCleanup();
else
bHasRegistered=TRUE;
return bHasRegistered;
}
/*
* 函数介绍:驱动程序卸载
* 输入参数:无
* 输出参数:无
* 返回值:无
*/
void PciCardDriver::UnRegister()
{
bHasRegistered=FALSE;
DeviceCleanup();
}
/*
* 函数介绍:接收的数据类型转换 WORD->double
* 输入参数:wData WORD型数据
* 输出参数:无
* 返回值:double型数据
*/
double PciCardDriver::WordToDouble(WORD wData)
{
if (0x8000 > wData)
{
return (wData * 10.0 / 0x8000);
}
else if (0x8000 == wData)
{
return -10.0;
}
else
{
return((wData-0x8000) * 10.0 / 0x8000 -10.0);
}
}
/*
* 函数介绍:数据转换,double->WORD
* 输入参数:dbData---double 型数据
* 输出参数:无
* 返回值:WORD型数据
*/
WORD PciCardDriver::DoubleToWord(double dbData)
{
WORD wData = 0;
double dbTemp;
if (dbData > 0)
{
dbTemp = dbData * 0x8000/10.0;
wData = (WORD)dbTemp;
if (0x8000 == wData)
{
wData--;
}
}
else if (dbData < 0)
{
dbTemp = dbData / 10.0 * 0x8000 + 0x10000 ;
wData= (WORD)dbTemp;
}
return wData;
}
/*
* 函数介绍:返回打开卡的状态
* 输入参数:无
* 输出参数:无
* 返回值:BOOL型数据
*/
BOOL PciCardDriver::IsOpen()
{
return bHasRegistered;
}
//
// Search devices
//
int PciCardDriver::DeviceSearch (
int vendorID,
int deviceID,
PCI_SLOT_NUMBER *pSlotNumber,
PPCI_COMMON_CONFIG PciData
)
{
ULONG bus; // bus number
ULONG deviceNumber; // logical slot number for the PCI adapter
ULONG functionNumber; // function number on the specified adapter
ULONG bytesWritten; // return value from RtGetBusDataByOffset
BOOLEAN bFlag = TRUE;
int CardIndex = 0;
pSlotNumber->u.bits.Reserved = 0;
//
// All PCI cards have been searched when we are out of PCI busses. (bFlag = FALSE)
//
for ( bus=0; bFlag; bus++ )
{
for ( deviceNumber=0; deviceNumber < PCI_MAX_DEVICES && bFlag; deviceNumber++ )
{
pSlotNumber->u.bits.DeviceNumber = deviceNumber;
for ( functionNumber=0; functionNumber < PCI_MAX_FUNCTION; functionNumber++ )
{
pSlotNumber->u.bits.FunctionNumber = functionNumber;
bytesWritten = RtGetBusDataByOffset (
PCIConfiguration, // type of bus data to be retrieved
bus, // zero-based number of the bus
pSlotNumber->u.AsULONG, // logical slot number
PciData, // pointer to a buffer for configuration information
0, // byte offset into buffer
PCI_COMMON_HDR_LENGTH // length of buffer
);
if ( bytesWritten == 0 )
{
// out of PCI buses done
bFlag = FALSE;
break;
}
if ( bytesWritten == VENDOR_ID_SIZE && PciData->VendorID == PCI_INVALID_VENDORID )
{
// no device at this slot number, skip to next slot
break;
}
//
// If device is found return, otherwise continue
// until all buses have been searched.
// Base Class and sub Class can also be used to find your
// specific device.
//
if ( ( PciData->VendorID == vendorID ) && ( PciData->DeviceID == deviceID ) &&(PciData->u.type0.SubVendorID==m_SVID) )
return bus;
} // functionNumber loop
} // deviceNumber loop
} // bus loop
return DEVICE_NOT_FOUND;
}
//
// Initialize device
//
BOOLEAN PciCardDriver::DeviceInit (
int busNumber,
PCI_SLOT_NUMBER *pSlotNumber,
PPCI_COMMON_CONFIG PciData
)
{
LARGE_INTEGER memAddr; // a base port address
LARGE_INTEGER tranMemAddr; // translated base addresses returned by RtMapMemory
ULONG AddressSpace = 0; // indicates memory space
ULONG bytesWritten = 0;
int i=0;
int addressRange = m_maddressrange;
//
// Enable Port IO.
// It is not necessary to call RtEnablePortIo in an RTX application
//
if( !RtEnablePortIo ( ( unsigned char * ) IoAddress, sizeof ( DeviceIORegs ) ) )
return FALSE;
//
// Get the virtual bus addresses for each address register
// if call fails set to NULL and continue
//
for( i=0; i< NUM_REGISTERS; i++ )
{
memAddr.QuadPart = PciData->u.type0.BaseAddresses[i];
//
// Translate the base port addresses to system mapped addresses.
//
if (!RtTranslateBusAddress (
PCIBus, // bus interface type
busNumber, // bus number (zero based)
memAddr, // bus-relative address
&AddressSpace, // specifies port number or a memory address
&tranMemAddr // pointer to the translated address
) )
{
vMemAddr[i] = NULL;
continue;
}
//
// Map the addresses to virtual addresses the software can use
//
vMemAddr[i] = (char *)RtMapMemory (
tranMemAddr, // base of the physical address range to map
addressRange, // the length of address range in bytes
0 // whether or not to use cache
);
}
//
// Set the command parameter so we can access the PCI device's control registers.
//
PciData->Command = ( PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE |
PCI_ENABLE_BUS_MASTER | PCI_ENABLE_WRITE_AND_INVALIDATE );
bytesWritten = RtSetBusDataByOffset (
PCIConfiguration, // type of bus data to be set
busNumber, // bus number (zero based)
pSlotNumber->u.AsULONG, // logical slot number
PciData, // pointer buffer containing configuration information
0, // byte offset in the buffer
PCI_COMMON_HDR_LENGTH // number of bytes in the buffer
);
if( bytesWritten == 0 )
return FALSE;
//
//TO DO:
// Setup _baseAddress if you plan to use defines setup in the header file
// Do any other initialization that is necessary for this device.
//
return TRUE;
}
//
// Cleanup
//
void PciCardDriver::DeviceCleanup ()
{
for(int i=0; i< NUM_REGISTERS; i++ )
{
if( vMemAddr[i] != NULL )
{
RtUnmapMemory ( vMemAddr[i] );
vMemAddr[i] = NULL;
}
}
RtDisablePortIo ( ( unsigned char * ) IoAddress, sizeof ( DeviceIORegs ) );
}
//
// Print message and exit
//
void PciCardDriver::MsgAndExit(
char *msg
)
{
RtPrintf ( "Error: %s (0x%X)\n", msg, RtGetLastError ( ) );
RtExitProcess ( 1 );
}
void PciCardDriver::MsgPrint(
char *msg
)
{
RtPrintf( "Error: %s (0x%X)\n",msg,RtGetLastEr