windows-nt/Source/XPSP1/NT/drivers/wdm/capture/mini/tecra750/bert.c

1193 lines
33 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//
// TOSHIBA CORPORATION PROPRIETARY INFORMATION
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with TOSHIBA Corporation and may not be copied
// or disclosed except in accordance with the terms of that agreement.
// Copyright (c) 1997 TOSHIBA Corporation. All Rights Reserved.
//
// Workfile: BERT.C
//
// Purpose:
//
// Contents:
//
#include "strmini.h"
#include "ksmedia.h"
#include "capmain.h"
#include "capdebug.h"
#include "bert.h"
#include "image.h"
#ifdef TOSHIBA // '99-01-20 Added
extern ULONG CurrentOSType;
ULONG ulConfigAddress;
#endif//TOSHIBA
//--------------------------------------------------------------------
// ReadRegUlong
//--------------------------------------------------------------------
ULONG
ReadRegUlong(PHW_DEVICE_EXTENSION pHwDevExt, ULONG offset)
{
PUCHAR pBase = (PUCHAR)(pHwDevExt->ioBaseLocal);
#ifndef TOSHIBA
if (!pHwDevExt->IsCardIn) return 0L;
#endif//TOSHIBA
return *(PULONG)(pBase + offset);
}
//--------------------------------------------------------------------
// WriteRegUlong
//--------------------------------------------------------------------
VOID
WriteRegUlong(PHW_DEVICE_EXTENSION pHwDevExt, ULONG offset, ULONG data)
{
ULONG volatile *temp;
PUCHAR pBase = (PUCHAR)(pHwDevExt->ioBaseLocal);
#ifndef TOSHIBA
if (!pHwDevExt->IsCardIn) return;
#endif//TOSHIBA
temp = (PULONG)(pBase + offset);
*temp = data;
}
//--------------------------------------------------------------------
// ReadModifyWriteRegUlong
//--------------------------------------------------------------------
VOID
ReadModifyWriteRegUlong(PHW_DEVICE_EXTENSION pHwDevExt,
ULONG offset,
ULONG a_mask,
ULONG o_mask)
{
ULONG tdata;
ULONG volatile *temp;
PUCHAR pBase = (PUCHAR)(pHwDevExt->ioBaseLocal);
#ifndef TOSHIBA
if (!pHwDevExt->IsCardIn) return;
#endif//TOSHIBA
temp = (PULONG)(pBase + offset);
tdata = *temp;
tdata = (tdata & a_mask) | o_mask;
*temp = tdata;
}
BOOL
BertIsCardIn(
IN PHW_DEVICE_EXTENSION pHwDevExt
)
{
DWORD value;
value = ReadRegUlong(pHwDevExt, BERT_CAPSTAT_REG);
if ((value == 0) || (value == 0xffffffff))
return FALSE;
else
return TRUE;
}
//--------------------------------------------------------------------
// BertInterruptEnable
//--------------------------------------------------------------------
VOID
BertInterruptEnable(
IN PHW_DEVICE_EXTENSION pHwDevExt,
IN BOOL bStatus
)
{
WriteRegUlong(pHwDevExt, BERT_INTRST_REG , 0xFFFF);
if (!bStatus)
{
ReadModifyWriteRegUlong(pHwDevExt, BERT_INTSTAT_REG, (ULONG)~ACTIVE_CAPTURE_IRQS, 0);
}
else
{
ReadModifyWriteRegUlong(pHwDevExt, BERT_INTSTAT_REG, ~0UL, (ULONG)ACTIVE_CAPTURE_IRQS);
}
}
//--------------------------------------------------------------------
// BertDMAEnable
//--------------------------------------------------------------------
VOID
BertDMAEnable(
IN PHW_DEVICE_EXTENSION pHwDevExt,
IN BOOL bStatus
)
{
DWORD dwAddr;
if (bStatus) // Turn On Video Transfer.
{
dwAddr = (DWORD)pHwDevExt->pPhysRpsDMABuf.LowPart;
#if 0
dwAddr = (dwAddr + 0x1FFF) & 0xFFFFE000;
#endif
WriteRegUlong(pHwDevExt, BERT_RPSADR_REG, dwAddr);
WriteRegUlong(pHwDevExt, BERT_RPSPAGE_REG, dwAddr);
BertVsncSignalWait(pHwDevExt);
// Let the RPS turn on/off EBMV
WriteRegUlong(pHwDevExt, BERT_CAPSTAT_REG, (ERPS | CKRE | CKMD)); // mod passive_enable -> ERPS 97-03-15(Sat) Mod 97-05-08(Thu)
}
else // Turn Off Video Transfer.
{
if (ReadRegUlong(pHwDevExt, BERT_CAPSTAT_REG) & ERPS)
{
ReadModifyWriteRegUlong(pHwDevExt, BERT_CAPSTAT_REG, (ULONG)~ERPS, 0UL);
}
if (!BertIsCAPSTATReady(pHwDevExt))
{
ReadModifyWriteRegUlong(pHwDevExt, BERT_CAPSTAT_REG, (ULONG)~EBMV, 0UL);
}
if (ReadRegUlong(pHwDevExt, BERT_CAPSTAT_REG) & RPSS)
{
pHwDevExt->NeedHWInit = TRUE;
}
}
}
//--------------------------------------------------------------------
// BertIsLocked
//--------------------------------------------------------------------
BOOL
BertIsLocked(
IN PHW_DEVICE_EXTENSION pHwDevExt
)
/*++
Routine Description :
Check if the decoder has been locked or not.
Arguments :
pDevInfo - Device Info for the driver
Return Value :
TRUE - configuration success
--*/
{
return ((ReadRegUlong(pHwDevExt, BERT_CAPSTAT_REG) & LOCK) != 0);
}
//--------------------------------------------------------------------
// BertFifoConfig
//--------------------------------------------------------------------
BOOL
BertFifoConfig(
IN PHW_DEVICE_EXTENSION pHwDevExt,
IN ULONG ulFormat
)
/*++
Routine Description :
Configure the BERT fifo for the format choosen.
Arguments :
pDevInfo - Device Info for the driver
dwFormat - format index as defined in wally.h
Return Value :
TRUE - configuration success
--*/
{
DWORD dwFifo;
switch (ulFormat)
{
case FmtYUV12:
dwFifo = 0xe;
break;
case FmtYUV9:
dwFifo = 0xd;
break;
default:
return FALSE;
}
dwFifo=(dwFifo<<24)| 0x100000l; // Modify 97-04-02
WriteRegUlong(pHwDevExt, BERT_FIFOCFG_REG, dwFifo);
WriteRegUlong(pHwDevExt, BERT_BURST_LEN, 0x00000002);
// DATA=8 DWORD, RPS=2DWORD
WriteRegUlong(pHwDevExt, BERT_YSTRIDE_REG, pHwDevExt->Ystride);
WriteRegUlong(pHwDevExt, BERT_USTRIDE_REG, pHwDevExt->Ustride);
WriteRegUlong(pHwDevExt, BERT_VSTRIDE_REG, pHwDevExt->Vstride);
return TRUE;
}
//--------------------------------------------------------------------
// BertInitializeHardware
//--------------------------------------------------------------------
BOOL
BertInitializeHardware(
IN PHW_DEVICE_EXTENSION pHwDevExt
)
/*++
Routine Description :
This function initializes the bert asic to the default values.
Arguments :
pDevInfo - Device Info for the driver
pHw - pointer to hardware info data structure
Return Value :
TRUE - initialization success
--*/
{
WriteRegUlong(pHwDevExt, BERT_CAPSTAT_REG, (CAMARA_OFF | CKRE | CKMD)); // Mod 97-05-08(Thu)
return TRUE;
}
//--------------------------------------------------------------------
// BertEnableRps
//--------------------------------------------------------------------
VOID
BertEnableRps(
IN PHW_DEVICE_EXTENSION pHwDevExt
)
/*++
Routine Description :
enable the rps execution by setting ERPS and EROO bits
in the CAPSTAT reg
Arguments :
pDevInfo - Device Info for the driver
Return Value :
None
--*/
{
ReadModifyWriteRegUlong(pHwDevExt, BERT_CAPSTAT_REG, 0xf0ffffff, 0x08000000); // MOD 97-03-17(Mon)
}
//--------------------------------------------------------------------
// BertDisableRps
//--------------------------------------------------------------------
VOID
BertDisableRps(
IN PHW_DEVICE_EXTENSION pHwDevExt
)
/*++
Routine Description :
disable the rps execution by reseting the ERPS bit
in the CAPSTAT reg
Arguments :
pDevInfo - Device Info for the driver
Return Value :
None
--*/
{
ReadModifyWriteRegUlong(pHwDevExt, BERT_CAPSTAT_REG, (ULONG)~ERPS, 0L);
}
BOOL
BertIsCAPSTATReady(PHW_DEVICE_EXTENSION pHwDevExt)
{
LARGE_INTEGER CurrentTime;
LARGE_INTEGER StartTime;
KeQuerySystemTime( &StartTime );
// Wait until EBMV is cleared by the RPS
while (ReadRegUlong(pHwDevExt, BERT_CAPSTAT_REG) & EBMV)
{
KeQuerySystemTime( &CurrentTime );
if ((CurrentTime.QuadPart - StartTime.QuadPart) > EBMV_TIMEOUT)
{
return FALSE;
}
}
return TRUE;
}
VOID
BertVsncSignalWait(PHW_DEVICE_EXTENSION pHwDevExt)
{
ULONG ulCount;
// Wait until VSNC is low
for (ulCount = 0; ulCount < 500; ulCount++ )
{
if (!(ReadRegUlong(pHwDevExt, BERT_VINSTAT_REG) & VSNC)) break;
VC_Delay(2);
}
}
VOID
BertDMARestart(
IN PHW_DEVICE_EXTENSION pHwDevExt
)
{
DWORD dwAddr;
dwAddr = (DWORD)pHwDevExt->pPhysRpsDMABuf.LowPart;
#if 0
dwAddr = (dwAddr + 0x1FFF) & 0xFFFFE000;
#endif
WriteRegUlong(pHwDevExt, BERT_RPSADR_REG, dwAddr);
WriteRegUlong(pHwDevExt, BERT_RPSPAGE_REG, dwAddr);
WriteRegUlong(pHwDevExt, BERT_CAPSTAT_REG, (ERPS | CKRE | CKMD));
}
void
ActiveField(
IN PHW_DEVICE_EXTENSION pHwDevExt,
IN DWORD *addr,
IN DWORD *PhysAddr, /* Insert BUN 97-03-25(Tue) */
IN DWORD bNoCopy,
IN DWORD *y_DMA_addr,
IN DWORD *v_DMA_addr,
IN DWORD *u_DMA_addr,
IN DWORD *nextRPSaddr,
IN DWORD *readRegAddr,
IN BOOL genIRQ /* = FALSE */,
IN DWORD fieldsToCapture /* = CAPTURE_BOTH */ )
{
// Set DmaActive flag right away since this is the indicator register for whether DMA is pending.
// If the DmaActive flag is zero, it is safe to copy the DMA frame buffer. The YPTR register is
// used as a scratch register to be read into the DmaActive flag.
*addr++ = RPS_CONTINUE_CMD | BERT_YPTR_REG;
*addr++ = (DWORD)y_DMA_addr; // Address of y DMA buffer.
*addr++ = RPS_CONTINUE_CMD | ((genIRQ) ? RPS_INT_CMD : 0) | BERT_RPSPAGE_REG;
*addr++ = (pHwDevExt->s_physDmaActiveFlag-0x1860); // Page s_DmaActiveFlag is on mod BUN
*addr++ = RPS_CONTINUE_CMD | BERT_VPTR_REG;
*addr++ = (DWORD)v_DMA_addr; // Address of v DMA buffer.
*addr++ = RPS_CONTINUE_CMD | BERT_UPTR_REG;
*addr++ = (DWORD)u_DMA_addr; // Address of u DMA buffer.
*addr++ = BERT_CAPSTAT_REG; // LAST RPS command this VSYNC
*addr++ = fieldsToCapture; // Switch on bus master bit.
*addr++ = RPS_CONTINUE_CMD | BERT_RPSADR_REG;
*addr = (DWORD)nextRPSaddr; // Address of next RPS.
}
//
// SKIP_FIELD_RPS is the size of a RPS node that skips a field.
// Skip frame is programmed as follows:
// DWORD -- RPS command register
// DWORD -- Value of register programming.
//---------------- Actual RPS for Skip Frame ------------------------
// RPS_CONTINUE_CMD | CAPSTAT - RPS, read next RPS, select CAPSTAT
// ERPS | EROO | GO0 - Enable RPS & Power to camara (off bus master)
// INTSTAT - Don't continue & select INITSTAT register.
// m_passive_cap_IRQs - Don't interrupt end of field.
// RPS_CONTINUE_CMD | RPSADDR - Set up address
// Address field - Program at init for next field.
//-------------------------------------------------------------------
//
VOID
SkipField(
IN PHW_DEVICE_EXTENSION pHwDevExt,
IN DWORD *addr,
IN DWORD *PhysAddr, /* Insert BUN 97-03-25(Tue) */
IN DWORD *nextRPSaddr,
IN DWORD *readRegAddr,
IN BOOL genIRQ /* = FALSE */,
IN DWORD fieldToSkip /* = SKIP_BOTH */ )
{
// Set YPTR right away since this is the indicator register for whether DMA is pending.
// If DmaActive flag is zero, it is safe to copy the DMA frame buffer.
*addr++ = RPS_CONTINUE_CMD | BERT_YPTR_REG;
*addr++ = (DWORD)PhysAddr;
*addr++ = RPS_CONTINUE_CMD | ((genIRQ) ? RPS_INT_CMD : 0) | BERT_RPSPAGE_REG;
*addr++ = (pHwDevExt->s_physDmaActiveFlag-0x1860); // Page s_physDmaActiveFlag is on MOD bun
*addr++ = BERT_CAPSTAT_REG; /* mod BUN 97-04-16(Wed) */
*addr++ = fieldToSkip; // Switch off bus master bit.
*addr++ = RPS_CONTINUE_CMD | BERT_RPSADR_REG;
*addr = (DWORD)nextRPSaddr; // Address of next RPS.
}
BOOL
BertBuildNodes(
IN PHW_DEVICE_EXTENSION pHwDevExt
)
{
DWORD* addr;
DWORD* physAddr;
DWORD* physBase;
ULONG ulTemp;
unsigned framesPerSecond;
unsigned f;
unsigned max_rps;
BOOL lastOneActive = FALSE;
framesPerSecond = pHwDevExt->uiFramePerSecond;
max_rps = DEF_RPS_FRAMES;
ulTemp = (ULONG)pHwDevExt->pRpsDMABuf;
#if 0
ulTemp = (ulTemp + 0x1FFF) & 0xFFFFE000;
#endif
addr = (DWORD *)ulTemp;
ulTemp = (ULONG)pHwDevExt->pPhysRpsDMABuf.LowPart;
#if 0
ulTemp = (ulTemp + 0x1FFF) & 0xFFFFE000;
#endif
physAddr = (DWORD *)ulTemp;
physBase = physAddr;
if (addr == NULL) return FALSE;
// Build an RPS per frame.
// Building 2 nodes per iteration when capturing both fields, so always
// go thru only DEF_RPS_FRAMES iterations.
for (f = max_rps ; f >= 1 ; f-- )
{
if (((framesPerSecond * f) % DEF_RPS_FRAMES) < framesPerSecond)
{
ActiveField(pHwDevExt,addr,(DWORD *)0,
TRUE, // No buffer copying during the processing of this node
(DWORD *)((BYTE *)pHwDevExt->pPhysCaptureBufferY.LowPart + pHwDevExt->YoffsetOdd), // Position Y data.
(DWORD *)((BYTE *)pHwDevExt->pPhysCaptureBufferV.LowPart + pHwDevExt->VoffsetOdd), // Position V data.
(DWORD *)((BYTE *)pHwDevExt->pPhysCaptureBufferU.LowPart + pHwDevExt->UoffsetOdd), // Position U data.
((f == 1 )
? physBase
: physAddr + 0x1A),
physAddr + 0x19, // Put the read value at the end of the list.
lastOneActive,
(CAPTURE_ODD | CKRE | CKMD)); // Mod 97-05-08(Thu)
lastOneActive = TRUE;
}
else
{
// Don't generate interrupts for skipped frames
SkipField(pHwDevExt,addr,
(DWORD *)((BYTE *)pHwDevExt->pPhysCapBuf2Y.LowPart + pHwDevExt->YoffsetOdd),
((f == 1 )
? physBase
: physAddr + 0x1A),
physAddr + 0x19, // Put the read value at the end of the list.
lastOneActive,
(SKIP_ODD | CKRE | CKMD)); // Mod 97-05-08(Thu)
lastOneActive = FALSE;
}
addr += 0x1A;
physAddr += 0x1A;
}
return TRUE;
}
BOOL
BertTriBuildNodes(
IN PHW_DEVICE_EXTENSION pHwDevExt
)
{
DWORD* addr;
DWORD* physAddr;
DWORD* physBase;
ULONG ulTemp;
unsigned framesPerSecond;
unsigned f;
unsigned max_rps;
BOOL lastOneActive = FALSE;
DWORD* CapphysAddrY;
DWORD* CapphysAddrV;
DWORD* CapphysAddrU;
framesPerSecond = pHwDevExt->uiFramePerSecond;
max_rps = DEF_RPS_FRAMES;
ulTemp = (ULONG)pHwDevExt->pRpsDMABuf;
#if 0
ulTemp = (ulTemp + 0x1FFF) & 0xFFFFE000;
#endif
addr = (DWORD *)ulTemp;
ulTemp = (ULONG)pHwDevExt->pPhysRpsDMABuf.LowPart;
#if 0
ulTemp = (ulTemp + 0x1FFF) & 0xFFFFE000;
#endif
physAddr = (DWORD *)ulTemp;
physBase = physAddr;
if (addr == NULL) return FALSE;
// Build an RPS per frame.
// Building 2 nodes per iteration when capturing both fields, so always
// go thru only DEF_RPS_FRAMES iterations.
lastOneActive = ( ((framesPerSecond*1)%DEF_RPS_FRAMES) < framesPerSecond ) ? TRUE : FALSE ;
for (f = max_rps ; f >= 1 ; f-- )
{
if( f%2 ){
CapphysAddrY=(DWORD *)pHwDevExt->pPhysCapBuf2Y.LowPart;
CapphysAddrV=(DWORD *)pHwDevExt->pPhysCapBuf2V.LowPart;
CapphysAddrU=(DWORD *)pHwDevExt->pPhysCapBuf2U.LowPart;
}
else{
CapphysAddrY=(DWORD *)pHwDevExt->pPhysCaptureBufferY.LowPart;
CapphysAddrV=(DWORD *)pHwDevExt->pPhysCaptureBufferV.LowPart;
CapphysAddrU=(DWORD *)pHwDevExt->pPhysCaptureBufferU.LowPart;
}
if (((framesPerSecond * f) % DEF_RPS_FRAMES) < framesPerSecond)
{
ActiveField(pHwDevExt,addr,(DWORD *)0,
TRUE, // No buffer copying during the processing of this node
(DWORD *)((BYTE *)CapphysAddrY + pHwDevExt->YoffsetOdd), // Position Y data.
(DWORD *)((BYTE *)CapphysAddrV + pHwDevExt->VoffsetOdd), // Position V data.
(DWORD *)((BYTE *)CapphysAddrU + pHwDevExt->UoffsetOdd), // Position U data.
((f == 1 )
? physBase
: physAddr + 0x1A),
physAddr + 0x19, // Put the read value at the end of the list.
lastOneActive,
(CAPTURE_ODD | CKRE | CKMD)); // Mod 97-05-08(Thu)
lastOneActive = TRUE;
}
else
{
// Don't generate interrupts for skipped frames
SkipField(pHwDevExt,addr,(DWORD *)((BYTE *)CapphysAddrY + pHwDevExt->YoffsetOdd),
((f == 1 )
? physBase
: physAddr + 0x1A),
physAddr + 0x19, // Put the read value at the end of the list.
lastOneActive,
(SKIP_ODD | CKRE | CKMD)); // Mod 97-05-08(Thu)
lastOneActive = FALSE;
}
addr += 0x1A;
physAddr += 0x1A;
}
return TRUE;
}
//--------------------------------------------------------------------
// BertSetDMCHE
//--------------------------------------------------------------------
VOID
BertSetDMCHE(IN PHW_DEVICE_EXTENSION pHwDevExt)
{
switch(pHwDevExt->dwAsicRev){
case 0: // Pistachio #1
case 1: // Pistachio #2
case 2: // Pistachio #3
WriteRegUlong(pHwDevExt, BERT_P_SUP3_REG, 0x00);
break;
default: // Pistachio #4~
WriteRegUlong(pHwDevExt, BERT_P_SUP3_REG, 0x0100);
break;
}
}
VOID
HW_ApmResume(PHW_DEVICE_EXTENSION pHwDevExt)
{
BertSetDMCHE(pHwDevExt);
CameraChkandON(pHwDevExt, MODE_VFW);
BertInitializeHardware(pHwDevExt);
pHwDevExt->NeedHWInit = TRUE;
pHwDevExt->IsRPSReady = FALSE;
}
VOID
HW_ApmSuspend(PHW_DEVICE_EXTENSION pHwDevExt)
{
BertInterruptEnable(pHwDevExt, FALSE);
BertDMAEnable(pHwDevExt, FALSE);
pHwDevExt->bRequestDpc = FALSE;
CameraChkandOFF(pHwDevExt, MODE_VFW);
}
VOID
HW_SetFilter(PHW_DEVICE_EXTENSION pHwDevExt, BOOL bFlag)
{
if( bFlag )
{
ImageFilterON(pHwDevExt);
}
else
{
ImageFilterOFF(pHwDevExt);
}
}
ULONG
HW_ReadFilter(PHW_DEVICE_EXTENSION pHwDevExt, BOOL bFlag)
{
ULONG ulRet;
if( bFlag )
{
ulRet = ImageGetFilteringAvailable(pHwDevExt);
}
else
{
ulRet = ImageGetFilterInfo(pHwDevExt);
}
return ulRet;
}
BOOL
HWInit(PHW_DEVICE_EXTENSION pHwDevExt)
{
if (pHwDevExt->NeedHWInit == FALSE) return TRUE;
// reset hardware to power up state
if ( !BertInitializeHardware(pHwDevExt) ) // MOD 97-03-31(Fri)
{
return FALSE;
}
else
{
pHwDevExt->NeedHWInit = FALSE;
}
return TRUE;
}
#ifdef TOSHIBA // '99-01-20 Added
//--------------------------------------------------------------------
// InitConfigAddress
//--------------------------------------------------------------------
VOID
InitConfigAddress( PHW_DEVICE_EXTENSION pHwDevExt )
{
ULONG OldPort;
ULONG Id;
ULONG Data;
ULONG i, j;
ulConfigAddress = 0xFFFFFFFF;
#ifdef TOSHIBA // '99-02-05 Modified
return;
#else //TOSHIBA
if ( CurrentOSType ) return; // NT5.0
if ( !StreamClassReadWriteConfig(
pHwDevExt,
TRUE, // indicates a READ
(PVOID)&Id,
0, // this is the offset into the PCI space
4 // this is the # of bytes to read.
)) {
return;
}
if ( Id == 0 || Id == 0xFFFFFFFF ) return;
OldPort = READ_PORT_ULONG( (PULONG)0xCF8 );
for ( i = 0 ; i < 256; i++ ) { // PCI_MAX_BRIDGE_NUMBER
for ( j = 0 ; j < 32; j++ ) {// PCI_MAX_DEVICE
WRITE_PORT_ULONG( (PULONG)0xCF8, (i << 16) | (j << 11) | 0x80000000 );
Data = READ_PORT_ULONG( (PULONG)0xCFC );
if ( Data == Id ) {
ulConfigAddress = (i << 16) | (j << 11) | 0x80000000;
break;
}
}
if ( Data == Id ) break;
}
WRITE_PORT_ULONG( (PULONG)0xCF8, OldPort );
#endif//TOSHIBA
}
#endif//TOSHIBA
//--------------------------------------------------------------------
// InitializeConfigDefaults
//--------------------------------------------------------------------
VOID
InitializeConfigDefaults(PHW_DEVICE_EXTENSION pHwDevExt)
{
ULONG ImageSize;
#ifdef TOSHIBA // '99-01-20 Added
InitConfigAddress( pHwDevExt );
#endif//TOSHIBA
#ifndef TOSHIBA
pHwDevExt->VideoStd = NTSC;
#endif//TOSHIBA
pHwDevExt->Format = FmtYUV9;
pHwDevExt->ulWidth = 320;
pHwDevExt->ulHeight = 240;
pHwDevExt->MaxRect.right = NTSC_MAX_PIXELS_PER_LINE;
pHwDevExt->MaxRect.bottom = NTSC_MAX_LINES_PER_FIELD * 2; // Mod 97-04-08(Tue)
pHwDevExt->SrcRect = pHwDevExt->MaxRect;
#ifdef TOSHIBA
pHwDevExt->Hue = 0x80;
pHwDevExt->Contrast = 0x80;
pHwDevExt->Brightness = 0x80;
pHwDevExt->Saturation = 0x80;
ImageSetChangeColorAvail(pHwDevExt, IMAGE_CHGCOL_AVAIL);
#else //TOSHIBA
pHwDevExt->ulHue = 0x80;
pHwDevExt->ulContrast = 0x80;
pHwDevExt->ulBrightness = 0x80;
pHwDevExt->ulSaturation = 0x80;
ImageSetChangeColorAvail(pHwDevExt, IMAGE_CHGCOL_NOTAVAIL);
#endif//TOSHIBA
}
BOOL SetupPCILT( PHW_DEVICE_EXTENSION pHwDevExt )
{
BYTE byte_buffer;
ULONG ulCommand;
#define PCI_LTIME_OFFSET 0x0d /* offset of Latency timer from PCI base */
#define PCI_CACHELINE_OFFSET 0x0c /* offset of cache line size from PCI base */
#define PCI_STATUSorCOMMAND 0x04 /* offset of Pistachio Status and Command regster */
byte_buffer = 255;
VC_SetPCIRegister(pHwDevExt,
PCI_LTIME_OFFSET,
&byte_buffer,
0x01);
byte_buffer=(BYTE) 0;
VC_SetPCIRegister(pHwDevExt,
PCI_CACHELINE_OFFSET,
&byte_buffer,
0x01);
ulCommand = 0x02000006;
VC_SetPCIRegister(pHwDevExt,
PCI_STATUSorCOMMAND,
&ulCommand,
0x04);
ulCommand = IGNORE100msec ; // Set ignore time for chattering
VC_SetPCIRegister(pHwDevExt,
PCI_Wake_Up,
&ulCommand,
0x04);
return TRUE;
}
BOOL CameraChkandON( PHW_DEVICE_EXTENSION pHwDevExt, ULONG ulMode )
{
ULONG dd_buffer;
if (!VC_GetPCIRegister(pHwDevExt,
PCI_Wake_Up,
&dd_buffer,
0x04) )
{
return FALSE;
}
if( (dd_buffer&0x10000l) == 0)
{
return TRUE;
}
dd_buffer = IGNORE100msec | 0x101l; // Set Wake Up enable
if (!VC_SetPCIRegister(pHwDevExt,
PCI_Wake_Up,
&dd_buffer,
0x04) )
{
return FALSE;
}
switch(ulMode){
case MODE_VFW:
dd_buffer = CAVCE_CFGPAT | CADTE_CFGPAT | PXCCE_CFGPAT | PXCSE_CFGPAT
| PCIFE_CFGPAT | PCIME_CFGPAT | PCIDS_CFGPAT | GPB_CFGPAT; // Mod 97-05-06(Tue)
break;
case MODE_ZV:
dd_buffer = CAVCE_CFGPAT | CADTE_CFGPAT | PXCCE_CFGPAT | PCIFE_CFGPAT
| PCIME_CFGPAT | PCIDS_CFGPAT | GPB_CFGPAT; // Add 97-05-06(Tue)
break;
}
// Power ON to camera.
if (!VC_SetPCIRegister(pHwDevExt,
PCI_DATA_PATH,
&dd_buffer,
0x04) )
{
return FALSE;
}
return TRUE;
}
BOOL CameraChkandOFF( PHW_DEVICE_EXTENSION pHwDevExt, ULONG ulMode )
{
DWORD dwBuffer;
DWORD dwSystemWait; // Add 97-05-06(Tue)
switch(ulMode){
case MODE_VFW:
break;
case MODE_ZV:
SetZVControl(pHwDevExt, ZV_DISABLE);
break;
}
dwBuffer = GPB_CFGPAT; // Camera Power Off
if (!VC_SetPCIRegister(pHwDevExt,
PCI_CFGPAT,
&dwBuffer,
0x04) )
{
return FALSE;
}
return TRUE;
}
BOOL CheckCameraStatus(PHW_DEVICE_EXTENSION pHwDevExt) // Add 97-05-06(Tue)
{
DWORD dwBuffer;
BOOL crStatus;
if (!VC_GetPCIRegister(pHwDevExt,
PCI_CFGPAT,
&dwBuffer,
0x04) )
{
return FALSE;
}
if(dwBuffer & CAVCE_CFGPAT){
crStatus = TRUE;
}
else{
crStatus = FALSE;
}
return crStatus;
}
BOOL SetZVControl(PHW_DEVICE_EXTENSION pHwDevExt, ULONG ulZVStatus) // Add 97-05-02(Fri)
{
DWORD dwBuffer, dwBuffer2;
BOOL crStatus = TRUE;
if (!VC_GetPCIRegister(pHwDevExt,
PCI_CFGPAT,
&dwBuffer,
0x04) )
{
return FALSE;
}
if (!VC_GetPCIRegister(pHwDevExt,
PCI_CFGWAK,
&dwBuffer2,
0x04) )
{
return FALSE;
}
if(!(dwBuffer2 & CASL_CFGWAK)) // Camera Not Connect
{
return FALSE;
}
switch(ulZVStatus){
case ZV_ENABLE:
if(!(dwBuffer & CAVCE_CFGPAT)){ // Check CAVCE Status
crStatus = CameraChkandON(pHwDevExt, MODE_ZV);
if(!crStatus){
return FALSE;
}
}
case ZV_DISABLE:
dwBuffer = (dwBuffer & 0xfffffffe) | ulZVStatus;
if (!VC_SetPCIRegister(pHwDevExt,
PCI_CFGPAT,
&dwBuffer,
0x04) )
{
return FALSE;
}
crStatus = TRUE;
break;
case ZV_GETSTATUS:
if(dwBuffer & ZV_ENABLE){
crStatus = TRUE;
}
else{
crStatus = FALSE;
}
break;
}
return crStatus;
}
BOOL SetASICRev(PHW_DEVICE_EXTENSION pHwDevExt) // Add 97-05-12(Mon)
{
DWORD dwBuffer;
DWORD dwAsicRev;
if (!VC_GetPCIRegister(pHwDevExt,
PCI_CFGCCR,
&dwBuffer,
0x04) )
{
return FALSE;
}
dwAsicRev = dwBuffer & 0x0f;
pHwDevExt->dwAsicRev = dwAsicRev;
return TRUE;
}
BOOL
Alloc_TriBuffer(PHW_DEVICE_EXTENSION pHwDevExt)
{
ULONG ulSize;
PUCHAR puTemp;
ulSize = pHwDevExt->BufferSize;
puTemp = (PUCHAR)pHwDevExt->pCaptureBufferY;
pHwDevExt->pCapBuf2Y = puTemp + ulSize;
puTemp = (PUCHAR)pHwDevExt->pCaptureBufferU;
pHwDevExt->pCapBuf2U = puTemp + ulSize;
puTemp = (PUCHAR)pHwDevExt->pCaptureBufferV;
pHwDevExt->pCapBuf2V = puTemp + ulSize;
pHwDevExt->pPhysCapBuf2Y.LowPart = pHwDevExt->pPhysCaptureBufferY.LowPart + ulSize;
pHwDevExt->pPhysCapBuf2U.LowPart = pHwDevExt->pPhysCaptureBufferU.LowPart + ulSize;
pHwDevExt->pPhysCapBuf2V.LowPart = pHwDevExt->pPhysCaptureBufferV.LowPart + ulSize;
return TRUE;
}
BOOL
Free_TriBuffer(PHW_DEVICE_EXTENSION pHwDevExt)
{
pHwDevExt->pCapBuf2Y = NULL;
pHwDevExt->pCapBuf2U = NULL;
pHwDevExt->pCapBuf2V = NULL;
pHwDevExt->pPhysCapBuf2Y.LowPart = 0;
pHwDevExt->pPhysCapBuf2U.LowPart = 0;
pHwDevExt->pPhysCapBuf2V.LowPart = 0;
return TRUE;
}
BOOL
VC_GetPCIRegister(
PHW_DEVICE_EXTENSION pHwDevExt,
ULONG ulOffset,
PVOID pData,
ULONG ulLength)
{
#ifdef TOSHIBA // '99-01-20 Added
if( ulConfigAddress != 0xFFFFFFFF ) {
ULONG OldPort;
ULONG DataPort;
OldPort = READ_PORT_ULONG( (PULONG)0xCF8 );
WRITE_PORT_ULONG( (PULONG)0xCF8, ( ulConfigAddress | ulOffset) & 0xFFFFFFFC );
DataPort = 0xCFC + (ulOffset % 4);
switch ( ulLength ) {
case 1:
*((PUCHAR)pData) = READ_PORT_UCHAR( (PUCHAR)DataPort );
break;
case 2:
*((PUSHORT)pData) = READ_PORT_USHORT( (PUSHORT)DataPort );
break;
case 4:
*((PULONG)pData) = READ_PORT_ULONG( (PULONG)DataPort );
break;
}
WRITE_PORT_ULONG( (PULONG)0xCF8, OldPort );
return TRUE;
}
#endif//TOSHIBA
if( StreamClassReadWriteConfig(
pHwDevExt,
TRUE, // indicates a READ
pData,
ulOffset, // this is the offset into the PCI space
ulLength // this is the # of bytes to read.
)) {
return TRUE;
} else {
return FALSE;
}
}
BOOL
VC_SetPCIRegister(
PHW_DEVICE_EXTENSION pHwDevExt,
ULONG ulOffset,
PVOID pData,
ULONG ulLength)
{
#ifdef TOSHIBA // '99-01-20 Added
if( ulConfigAddress != 0xFFFFFFFF ) {
ULONG OldPort;
ULONG DataPort;
OldPort = READ_PORT_ULONG( (PULONG)0xCF8 );
WRITE_PORT_ULONG( (PULONG)0xCF8, ( ulConfigAddress | ulOffset) & 0xFFFFFFFC );
DataPort = 0xCFC + (ulOffset % 4);
switch ( ulLength ) {
case 1:
WRITE_PORT_UCHAR( (PUCHAR)DataPort, *((PUCHAR)pData) );
break;
case 2:
WRITE_PORT_USHORT( (PUSHORT)DataPort, *((PUSHORT)pData) );
break;
case 4:
WRITE_PORT_ULONG( (PULONG)DataPort, *((PULONG)pData) );
break;
}
WRITE_PORT_ULONG( (PULONG)0xCF8, OldPort );
return TRUE;
}
#endif//TOSHIBA
if( StreamClassReadWriteConfig(
pHwDevExt,
FALSE, // indicates a WRITE
pData,
ulOffset, // this is the offset into the PCI space
ulLength // this is the # of bytes to read.
)) {
return TRUE;
} else {
return FALSE;
}
}
/*
* delay for a number of milliseconds. This is accurate only to
* +- 15msecs at best.
*/
VOID
VC_Delay(int nMillisecs)
{
LARGE_INTEGER Delay;
/*
* relative times are negative, in units of 100 nanosecs
*/
// first wait for the minimum length of time - this ensures that
// our wait is never less than nMillisecs.
Delay = RtlConvertLongToLargeInteger(-1);
KeDelayExecutionThread(KernelMode,
FALSE, //non-alertable
&Delay);
// now wait for the requested time.
Delay = RtlConvertLongToLargeInteger(-(nMillisecs * 10000));
KeDelayExecutionThread(KernelMode,
FALSE, //non-alertable
&Delay);
}
#if DBG
void
DbgDumpPciRegister( PHW_DEVICE_EXTENSION pHwDevExt )
{
ULONG i;
ULONG data;
DbgPrint("\n+++++ PCI Config Register +++++\n");
for( i=0; i<0x48; i+=4 )
{
if (VC_GetPCIRegister(pHwDevExt,
i,
&data,
0x04) )
{
DbgPrint("0x%02X: 0x%08X\n", i, data);
}
else
{
DbgPrint("0x%02X: Read Error.\n", i);
}
}
}
void
DbgDumpCaptureRegister( PHW_DEVICE_EXTENSION pHwDevExt )
{
ULONG i;
ULONG data;
DbgPrint("\n+++++ Capture Register +++++\n");
for( i=0; i<0xA4; i+=4 )
{
data = ReadRegUlong(pHwDevExt, i);
DbgPrint("0x%02X: 0x%08X\n", i, data);
}
}
#endif