Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

825 lines
21 KiB

// $Header: G:/SwDev/WDM/Video/bt848/rcs/Device.cpp 1.18 1998/05/13 14:44:33 tomz Exp $
#include "device.h"
#include "capmain.h"
const I2C_Offset = 0x110;
const GPIO_Cntl_Offset = 0x10D;
const GPIO_OutputOffset = 0x118;
const GPIO_DataOffset = 0x200;
// Global functions/data exposing public class info to the "C" modules
PsDevice *gpPsDevice = NULL;
BYTE *gpjBaseAddr = NULL;
VOID *gpHwDeviceExtension = NULL;
DWORD GetSizeHwDeviceExtension( )
{
return ( sizeof( HW_DEVICE_EXTENSION ) + sizeof( PsDevice ));
}
DWORD GetSizeStreamEx( )
{
// return the size of the largest possible channel object
DWORD dwMax = sizeof( VBIChannel );
dwMax = max( dwMax, sizeof( AlterVideoChannel<VBIChannel> ));
dwMax = max( dwMax, sizeof( InterVideoChannel ));
DWORD dwReq = 2 * dwMax; // paired stuff has two of them together
dwReq += sizeof( STREAMEX );
return ( dwReq );
}
/* Function: GetDeviceExt
* Purpose: Used in creation of risc programs to obtain physical addresses
*/
PsDevice *GetCurrentDevice()
{
// This is only used for I2C stuff. Remove this ASAP.
return gpPsDevice;
}
/* Function: SetCurrentDevice
* Purpose: Remembers the currently active device
* Input: PsDevice *
* Output: None
*/
void SetCurrentDevice( PsDevice *dev )
{
// This is only used for I2C stuff. Remove this ASAP.
gpPsDevice = dev;
}
/* Function: GetBase
* Purpose: Returns the base address of the currently active device
* Input: None
* Output: LPBYTE
*/
BYTE *GetBase()
{
return gpjBaseAddr;
}
/* Function: SetBase
* Purpose: Remembers the base address of the currently active device
* Input: None
* Output: LPBYTE
*/
void SetBase(BYTE *base)
{
gpjBaseAddr = base;
}
PsDevice::PsDevice( DWORD dwBase ) :
BaseAddress_( (LPBYTE)dwBase ),
LastFreq_( 0 ),
dwCurCookie_( 0 ),
I2CAddr_( 0 ),
xBar( PinTypes_ ),
CaptureContrll_( xtals_ )
{
SetCurrentDevice ( this );
for ( int i = 0; i < (sizeof(videochannels)/sizeof(videochannels[0])); i++ ) {
videochannels [i] = 0;
}
I2CIsInitOK();
#ifdef HARDWAREI2C
I2CInitHWMode( 100000 ); // assume frequency = 100Khz
#else
I2CInitSWMode( 100000 ); // assume frequency = 100Khz
I2CSWStart();
I2CSWStop();
#endif
GPIOIsInitOK();
DebugOut((0, "*** Base Address = %x\n", BaseAddress_));
}
PsDevice::~PsDevice()
{
for ( int i = 0; i < (sizeof(videochannels)/sizeof(videochannels[0])); i++ ) {
VideoChannel *pvcTemp = videochannels [i];
videochannels [i] = NULL;
delete pvcTemp;
}
}
/* Method: PsDevice::AddBuf
* Purpose: Adds next buffer to be used to the queue
* Input: VideoChan: VxDVideoChannel &
* pBufAddr: PVOID - address of the next buffer
* Output: None
*/
void PsDevice::AddBuffer( VideoChannel &VideoChan, PHW_STREAM_REQUEST_BLOCK pSrb )
{
// bogus channel, bye-bye
if ( !IsOurChannel( VideoChan ) ) {
DebugOut((0, "PsDevice::Addbuffer - not our channel (pSrb=%x) (&VideoChan=%x)\n", pSrb, &VideoChan ) );
return;
}
DebugOut((1, "PsDevice::Addbuffer - adding (pSrb=%x) (&VideoChan=%x)\n", pSrb, &VideoChan ) );
VideoChan.AddSRB( pSrb );
}
void PsDevice::Start( VideoChannel &VidChan )
{
VidChan.Start();
}
void PsDevice::Pause( VideoChannel &VidChan )
{
*(DWORD*)(gpjBaseAddr+0x10c) &= ~3; // disable interrupts [TMZ] [!!!]
// [TMZ] [!!!]
for ( int i = 0; i < (sizeof(videochannels)/sizeof(videochannels[0])); i++ )
{
if ( videochannels[i] == &VidChan )
{
DebugOut((1, "'PsDevice::Pause called on videochannels[%d]\n", i));
}
}
VidChan.Pause();
}
/* Method: PsDevice::Create
* Purpose: Calls into the channel ( stream ) to create RISC programs for it.
* Input: VideoChan: VxDVideoChannel &
* Parms: StartParms &, parameters to create stream with
* Output: ErrorCode
*/
ErrorCode PsDevice::Create( VideoChannel &VidChan )
{
return VidChan.Create();
}
/* Method: PsDevice::Stop
* Purpose: Adds next buffer to be used to the queue
* Input: VideoChan: VxDVideoChannel &
* Output: None
*/
void PsDevice::Stop( VideoChannel &VidChan )
{
*(DWORD*)(gpjBaseAddr+0x10c) &= ~3; // disable interrupts [TMZ] [!!!]
VidChan.Stop();
}
#if NEED_CLIPPING
/* Method: PsDevice::SetClipping
* Purpose: Propagates the call down a video channel
* Input: VideoChan: VxDVideoChannel & - reference
* dwData: DWORD - a pointer to RGNDATA in reality
* Output: None
*/
void PsDevice::SetClipping( VideoChannel &VidChan, const RGNDATA & rgnData )
{
if ( !rgnData.rdh.nCount )
return;
if ( FullSizeChannel_ ) {
// have to decrese hight of all rectangles in half and decrease top in half
unsigned i;
for ( i = 0; i < rgnData.rdh.nCount; i++ ) {
TRect *lpR = (TRect *)rgnData.Buffer + i;
// make all even
lpR->top++;
lpR->top &= ~1;
lpR->bottom++;
lpR->bottom &= ~1;
lpR->top /= 2;
lpR->bottom /= 2;
}
FullSizeChannel_->SetClipping( rgnData );
SlaveChannel_ ->SetClipping( rgnData );
} else
VidChan.SetClipping( rgnData );
}
#endif
/* Method: PsDevice::IsVideoChannel
* Purpose:
*/
bool PsDevice::IsVideoChannel( VideoChannel &aChan )
{
return bool( &aChan == videochannels [VS_Field1] || &aChan == videochannels [VS_Field2] );
}
/* Method: PsDevice::IsVBIChannel
* Purpose:
*/
bool PsDevice::IsVBIChannel( VideoChannel &aChan )
{
return bool( &aChan == videochannels [VS_VBI1] || &aChan == videochannels [VS_VBI2] );
}
/* Method: PsDevice::IsOurChannel
* Purpose: Verifies the channel
* Input: aChan: VideoChannel &, reference to a channel
* Output: true if our, false otherwise
*/
bool PsDevice::IsOurChannel( VideoChannel &aChan )
{
return IsVideoChannel( aChan ) || IsVBIChannel( aChan );
}
/* Method: PsDevice::DoOpen
* Purpose: This function performs opening of a video channel
* Input: st: VideoStream, stream to open
* Output: ErrorCode
*/
ErrorCode PsDevice::DoOpen( VideoStream st )
{
DebugOut((1, "PsDevice::DoOpen(%d)\n", st));
if ( !videochannels [st] )
{
DebugOut((1, " PsDevice::DoOpen(%d) failed - videochannel not created\n", st));
return Fail;
}
videochannels [st]->Init( &CaptureContrll_ );
if ( videochannels [st]->OpenChannel() != Success ) {
DebugOut((1, " PsDevice::DoOpen(%d) failed - videochannel open failed\n", st));
VideoChannel *pvcTemp = videochannels [st];
videochannels [st] = NULL;
delete pvcTemp;
return Fail;
}
return Success;
}
/* Method: PsDevice::OpenChannel
* Purpose: This function opens a channel requested by the capture driver
* Input: hVM: VMHANDLE - handle of the VM making a call
* pRegs: CLIENT_STRUCT * - pointer to the structure with VM's registers
* Output: None
*/
ErrorCode PsDevice::OpenChannel( PVOID pStrmEx, VideoStream st )
{
PVOID addr = &((PSTREAMEX)pStrmEx)->videochannelmem[0];
((PSTREAMEX)pStrmEx)->videochannel = addr;
DebugOut((1, "PsDevice::OpenChannel(%x,%d)\n", addr, st));
if ( videochannels [st] )
{
DebugOut((1, " PsDevice::OpenChannel(%x,%d) failed - already open\n", addr, st));
return Fail;
}
videochannels[st] = new( addr ) VideoChannel( st );
videochannels[st]->SetStrmEx( pStrmEx ) ;
DebugOut((1, " PsDevice::OpenChannel(%x,%d), videochannels[%d] = %x\n", addr, st, st, videochannels[st]));
return DoOpen( st );
}
/* Method: PsDevice::OpenInterChannel
* Purpose: This function opens video channel that produces interleaved fields
* Input: addr: PVOID, address for the palcement new
* st: VideoStream, stream to open ( VBI or video )
* Output: None
*/
ErrorCode PsDevice::OpenInterChannel( PVOID pStrmEx, VideoStream st )
{
PVOID addr = &((PSTREAMEX)pStrmEx)->videochannelmem[0];
((PSTREAMEX)pStrmEx)->videochannel = addr;
DebugOut((1, "PsDevice::OpenInterChannel(%x,%d)\n", addr, st));
// only odd channel can be paired
if ( !( st & 1 ) || videochannels [st] || videochannels [st-1] )
{
DebugOut((1, " PsDevice::OpenInterChannel(%x,%d) failed - stream not odd or already open\n", addr, st));
return Fail;
}
if ( OpenChannel( (PBYTE)addr + sizeof( InterVideoChannel ), VideoStream( st - 1 ) ) == Success )
{
videochannels[st] = new( addr ) InterVideoChannel( st, *videochannels [st-1] );
videochannels[st]->SetStrmEx( pStrmEx ) ;
if ( DoOpen( st ) != Success )
{
DebugOut((1, " PsDevice::OpenInterChannel(%x,%d) failed - DoOpen failed\n", addr, st));
CloseChannel( videochannels [st-1] );
return Fail;
}
}
else
{
DebugOut((1, " PsDevice::OpenInterChannel(%x,%d) failed - OpenChannel failed\n", addr, st));
return Fail;
}
return Success;
}
/* Method: PsDevice::OpenAlterChannel
* Purpose: This function opens video channel that produces alternating fields
* Input: addr: PVOID, address for the palcement new
* st: VideoStream, stream to open ( VBI or video )
* Output: None
*/
ErrorCode PsDevice::OpenAlterChannel( PVOID pStrmEx, VideoStream st )
{
PVOID addr = &((PSTREAMEX)pStrmEx)->videochannelmem[0];
((PSTREAMEX)pStrmEx)->videochannel = addr;
DebugOut((1, "PsDevice::OpenAlterChannel(%x,%d)\n", addr, st));
// only odd channel can be paired
if ( !( st & 1 ) || videochannels [st] || videochannels [st-1] )
{
DebugOut((1, " PsDevice::OpenAlterChannel(%x,%d) failed - stream not odd or already open\n", addr, st));
return Fail;
}
if ( OpenChannel( (PBYTE)addr + sizeof( AlterVideoChannel<VideoChannel> ), VideoStream( st -1 ) ) == Success )
{
videochannels[st] = new( addr ) AlterVideoChannel<VideoChannel>( st, *videochannels [st-1] );
videochannels[st]->SetStrmEx( pStrmEx ) ;
videochannels[st-1]->SetStrmEx( pStrmEx ) ;
if ( DoOpen( st ) != Success )
{
DebugOut((1, " PsDevice::OpenAlterChannel(%x,%d) failed - DoOpen failed\n", addr, st));
CloseChannel( videochannels [st-1] );
return Fail;
}
}
else
{
DebugOut((1, " PsDevice::OpenAlterChannel(%x,%d) failed - OpenChannel failed\n", addr, st));
return Fail;
}
return Success;
}
/* Method: PsDevice::OpenVBIChannel
* Purpose: This function opens video channel that produces alternating fields
* Input: addr: PVOID, address for the palcement new
* st: VideoStream, stream to open ( VBI or video )
* Output: None
*/
ErrorCode PsDevice::OpenVBIChannel( PVOID pStrmEx )
{
PVOID addr = &((PSTREAMEX)pStrmEx)->videochannelmem[0];
((PSTREAMEX)pStrmEx)->videochannel = addr;
DebugOut((1, "PsDevice::OpenVBIChannel(%x)\n", addr));
if ( videochannels [VS_VBI1] || videochannels [VS_VBI2] )
{
DebugOut((1, " PsDevice::OpenVBIChannel(%x) failed - already open\n", addr));
return Fail;
}
VBIChannel *tmp = new( (PBYTE)addr + sizeof( VBIAlterChannel ) ) VBIChannel( VS_VBI1 );
videochannels [VS_VBI1] = tmp;
DebugOut((1, " PsDevice::OpenVBIChannel(%x), videochannels[VS_VBI1(%d)] = %x\n", addr, VS_VBI1, videochannels[VS_VBI1]));
if ( !tmp )
{
DebugOut((1, " PsDevice::OpenVBIChannel(%x) failed - new VBIChannel failed\n", addr));
return Fail;
}
if ( DoOpen( VS_VBI1 ) != Success )
{
DebugOut((1, " PsDevice::OpenVBIChannel(%x) failed - DoOpen(VS_VBI1) failed\n", addr));
return Fail;
}
videochannels [VS_VBI2] = new( addr ) VBIAlterChannel( VS_VBI2, *tmp );
DebugOut((1, " PsDevice::OpenVBIChannel(%x), videochannels[VS_VBI2(%d)] = %x\n", addr, VS_VBI2, videochannels[VS_VBI2]));
if (!videochannels [VS_VBI2])
{
DebugOut((1, " PsDevice::OpenVBIChannel(%x) failed - new VBIAlterChannel failed\n", addr));
return Fail;
}
if ( DoOpen( VS_VBI2 ) != Success )
{
DebugOut((1, " PsDevice::OpenVBIChannel(%x) failed - DoOpen(VS_VBI1) failed\n", addr));
CloseChannel( videochannels [VS_VBI1] );
return Fail;
}
videochannels[VS_VBI1]->SetStrmEx( pStrmEx ) ;
videochannels[VS_VBI2]->SetStrmEx( pStrmEx ) ;
return Success;
}
/* Method: PsDevice::CloseChannel
* Purpose: Closes a video channel
* Input: ToClose: VideoChannel *
* Output: None
*/
void PsDevice::CloseChannel( VideoChannel *ToClose )
{
*(DWORD*)(gpjBaseAddr+0x10c) &= ~3; // disable interrupts [TMZ] [!!!]
DebugOut((1, "PsDevice::CloseChannel(%x)\n", ToClose));
if ( IsOurChannel( *ToClose ) )
{
// this is a bit ugly solution to make CLOSE_STREAM SRB clean
if ( ToClose->GetStreamType() == Single )
{
VideoStream st = ToClose->GetStreamID();
DebugOut((1, " PsDevice::CloseChannel(%x) - closing single channel (stream == %d)\n", ToClose, st));
VideoChannel * pvcTemp = videochannels [st];
videochannels [st] = NULL;
delete pvcTemp;
}
else
{
DebugOut((1, " PsDevice::CloseChannel(%x) - closing paired channel\n", ToClose));
ClosePairedChannel( ToClose );
}
}
else
{
DebugOut((1, " PsDevice::CloseChannel(%x) ignored - not our channel\n", ToClose));
}
}
/* Method: PsDevice::ClosePairedChannel
* Purpose: This function opens a channel requested by the capture driver
* Input: hVM: VMHANDLE - handle of the VM making a call
* pRegs: CLIENT_STRUCT * - pointer to the structure with VM's registers
* Output: None
*/
void PsDevice::ClosePairedChannel( VideoChannel *ToClose )
{
*(DWORD*)(gpjBaseAddr+0x10c) &= ~3; // disable interrupts [TMZ] [!!!]
DebugOut((1, "PsDevice::ClosePairedChannel(%x)\n", ToClose));
if ( IsOurChannel( *ToClose ) )
{
VideoStream st = ToClose->GetStreamID();
DebugOut((1, " PsDevice::ClosePairedChannel(%x) - closing paired channel (stream == %d)\n", ToClose, st));
DebugOut((1, " PsDevice::ClosePairedChannel(%x) - streams[%d] = %x\n", ToClose, st, videochannels[st]));
DebugOut((1, " PsDevice::ClosePairedChannel(%x) - streams[%d] = %x\n", ToClose, st-1, videochannels[st-1]));
VideoChannel *pvcTemp;
pvcTemp = videochannels [st];
videochannels [st] = NULL;
delete pvcTemp;
pvcTemp = videochannels [st-1];
videochannels [st-1] = NULL;
delete pvcTemp;
}
else
{
DebugOut((1, " PsDevice::ClosePairedChannel(%x) ignored - not our channel\n", ToClose));
}
}
/* Method: PsDevice::SetSaturation
* Purpose:
* Input:
* Output: None
*/
void PsDevice::SetSaturation( LONG Data )
{
CaptureContrll_.SetSaturation( Data );
}
/* Method: PsDevice::SetHue
* Purpose:
* Input:
* Output: None
*/
void PsDevice::SetHue( LONG Data )
{
CaptureContrll_.SetHue( Data );
}
/* Method: PsDevice::SetBrightness
* Purpose:
* Input:
* Output: None
*/
void PsDevice::SetBrightness( LONG Data )
{
CaptureContrll_.SetBrightness( Data );
}
/* Method: PsDevice::SetSVideo
* Purpose:
* Input:
* Output: None
*/
void PsDevice::SetSVideo( LONG Data )
{
CaptureContrll_.SetSVideo( Data );
}
/* Method: PsDevice::SetContrast
* Purpose:
* Input:
* Output: None
*/
void PsDevice::SetContrast( LONG Data )
{
CaptureContrll_.SetContrast( Data );
}
/* Method: PsDevice::SetFormat
* Purpose:
* Input:
* Output: None
*/
void PsDevice::SetFormat( LONG Data )
{
CaptureContrll_.SetFormat( Data );
// notify all video channels that video timing has changed
LONG time = Data == KS_AnalogVideo_NTSC_M ? 333667 : 400000;
for ( int i = 0; i < (sizeof(videochannels)/sizeof(videochannels[0])); i++ )
{
if ( videochannels [i] )
{
DebugOut((1, "PsDevice::SetFormat(%d) SetTimePerFrame on videochannels[%d]\n", Data, i));
videochannels [i]->SetTimePerFrame( time );
}
}
}
/* Method: PsDevice::SetConnector
* Purpose:
* Input:
* Output: None
*/
void PsDevice::SetConnector( LONG Data )
{
CaptureContrll_.SetConnector( Data );
}
/* Method: PsDevice::GetSaturation
* Purpose:
* Input: pData: PLONG
* Output: None
*/
LONG PsDevice::GetSaturation()
{
return CaptureContrll_.GetSaturation();
}
/* Method: PsDevice::GetHue
* Purpose:
* Input: pData: PLONG
* Output: None
*/
LONG PsDevice::GetHue()
{
return CaptureContrll_.GetHue();
}
/* Method: PsDevice::GetBrightness
* Purpose:
* Input: pData: PLONG
* Output: None
*/
LONG PsDevice::GetBrightness()
{
return CaptureContrll_.GetBrightness();
}
/* Method: PsDevice::GetSVideo
* Purpose:
* Input: pData: PLONG
* Output: None
*/
LONG PsDevice::GetSVideo()
{
return CaptureContrll_.GetSVideo();
}
/* Method: PsDevice::GetContrast
* Purpose:
* Input: pData: PLONG
* Output: None
*/
LONG PsDevice::GetContrast()
{
return CaptureContrll_.GetContrast();
}
/* Method: PsDevice::GetFormat
* Purpose:
* Input: pData: PLONG
* Output: None
*/
LONG PsDevice::GetFormat()
{
return CaptureContrll_.GetFormat();
}
/* Method: PsDevice::GetConnector
* Purpose:
* Input: pData: PLONG
* Output: None
*/
LONG PsDevice::GetConnector()
{
return CaptureContrll_.GetConnector();
}
/* Method: PsDevice::ChangeNotifyChannels
* Purpose: Invoked to notify channels of some global changes
*/
void PsDevice::ChangeNotifyChannels( IN PHW_STREAM_REQUEST_BLOCK pSrb )
{
// We should only do this once per "system" stream.
// Video streams don't seem to care.
// That just leaves one VBI notification required
videochannels [VS_VBI1]->ChangeNotification( pSrb );
}
/* Method: PsDevice::GetSupportedStandards
* Purpose: Obtains video standards device can support
* Input: None
* Output: LONG
*/
LONG PsDevice::GetSupportedStandards()
{
return CaptureContrll_.GetSupportedStandards();
}
bool PsDevice::InitOK()
{
return CaptureContrll_.InitOK();
}
#ifndef HARDWAREI2C
//===========================================================================
// Bt848 software I2C stuff
//===========================================================================
/*
* If we build with software I2C then these routines fake the Hardware I2C routines
* so the tuner code keeps working
*/
ErrorCode PsDevice::I2CHWRead( BYTE address, BYTE *value )
{
ErrorCode error;
error = I2CSWStart();
if(error) {
return error;
}
error = I2CSWWrite( address | 0x01 );
if(error) {
return error;
}
error = I2CSWRead( value );
if(error) {
return error;
}
error = I2CSWSendNACK();
if(error) {
return error;
}
error = I2CSWStop();
return error;
}
ErrorCode PsDevice::I2CHWWrite3( BYTE address, BYTE value1, BYTE value2 )
{
ErrorCode error;
error = I2CSWStart();
if(error) {
return error;
}
error = I2CSWWrite( address );
if(error) {
return error;
}
error = I2CSWWrite( value1 );
if(error) {
return error;
}
error = I2CSWWrite( value2 );
if(error) {
return error;
}
error = I2CSWStop();
return error;
}
#endif
//////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
#ifdef __cplusplus
}
#endif
// #include "capdebug.h"
#define DEBUG_PRINT_PREFIX " ---: "
// #define DEBUG_PRINT_PREFIX "bt848wdm: "
long DebugLevel = 0;
BOOL bNewLine = TRUE;
extern "C" void MyDebugPrint(long DebugPrintLevel, char * DebugMessage, ... )
{
if (DebugPrintLevel <= DebugLevel)
{
char debugPrintBuffer[256] ;
va_list marker;
va_start( marker, DebugMessage ); // Initialize variable arguments.
vsprintf( debugPrintBuffer,
DebugMessage,
marker );
if( bNewLine )
{
DbgPrint(("%s", DEBUG_PRINT_PREFIX));
}
DbgPrint((debugPrintBuffer));
if( debugPrintBuffer[strlen(debugPrintBuffer)-1] == '\n')
{
bNewLine = TRUE;
}
else
{
bNewLine = FALSE;
}
va_end( marker ); // Reset variable arguments.
}
}
#if TRACE_CALLS
#define MAX_TRACE_DEPTH 10
unsigned long ulTraceDepth = 0;
char achIndentBuffer[100];
char * IndentStr( )
{
unsigned long ul = ulTraceDepth < MAX_TRACE_DEPTH ? ulTraceDepth : MAX_TRACE_DEPTH;
unsigned long x;
char * lpszBuf = achIndentBuffer;
for( x = 0; x < ul; x++)
{
// indent two spaces per depth increment
*lpszBuf++ = ' ';
*lpszBuf++ = ' ';
}
sprintf (lpszBuf, "[%lu]", ulTraceDepth);
return( achIndentBuffer );
}
Trace::Trace(char *pszFunc)
{
psz = pszFunc;
DebugOut((0, "%s %s\n", IndentStr(), psz));
ulTraceDepth++;
}
Trace::~Trace()
{
ulTraceDepth--;
// DebugOut((0, "%s %s\n", IndentStr(), psz));
}
#endif