|
|
//
// 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
|