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.
1192 lines
34 KiB
1192 lines
34 KiB
//
|
|
// 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
|
|
|
|
|
|
|