Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

646 lines
15 KiB

//**************************************************************************
//
// Title : WDMKServ.cpp
//
// Date : 1997.12.02 1st making
//
// Author : Toshiba [PCS](PSY) Hideki Yagi
//
// Copyright 1997 Toshiba Corporation. All Rights Reserved.
//
// -------------------------------------------------------------------------
//
// Change log :
//
// Date Revision Description
// ------------ ---------- -----------------------------------------------
// 1997.12.02 000.0000 1st making.
//
//**************************************************************************
#include "includes.h"
#include "hal.h"
#include "wdmkserv.h"
#include "mpevent.h"
#include "classlib.h"
#include "ctime.h"
#include "schdat.h"
#include "ccque.h"
#include "ctvctrl.h"
#include "hlight.h"
#include "hwdevex.h"
// 1998.06.09 Seichan
// このDefineを有効にすると、PCIのコンフィグ空間を直接操作するようになる
//#define DIRECTPCICONFIG
BOOL CWDMKernelService::Init( DWORD address, HW_DEVICE_EXTENSION *pHwDevExt, PCHAR szID )
{
if( address==0 || pHwDevExt==NULL ){
return( FALSE );
}
m_ioBase = address;
m_pHwDevExt = pHwDevExt;
m_IntCount = 0;
m_OldIrql = 0;
m_pThread = NULL;
m_Irql = (KIRQL)((pHwDevExt->Irq) & 0xFF );
if( m_Irql>31 ){
DBG_PRINTF( ("DVDWDM: Invalid IRQL!!\n\r") );
DBG_BREAK();
return( FALSE );
}
KeInitializeEvent( &m_Event, NotificationEvent, FALSE );
DBG_PRINTF( ("KSERV:HwDevExt=%08x\n\r", m_pHwDevExt) );
// save MAchine informaton.
strncpy( m_MachineID, szID, 19 );
m_MachineID[19] = '0';
DBG_PRINTF( ("KSERV:MachineID = %s\n\r", m_MachineID ) );
return( TRUE );
}
BOOL CWDMKernelService::InitConfig( DWORD Id )
{
#ifdef DIRECTPCICONFIG
if( Id==0 ){
return( FALSE );
}
ULONG OldPort = READ_PORT_ULONG( (PULONG)0xcf8 );
m_PCIConfigData = 0xffffffff;
for( ULONG i = 0 ; i < 32; i ++ )
{
for( ULONG j = 0 ; j < 32; j ++ )
{
WRITE_PORT_ULONG( (PULONG)0xcf8, ( i << 16 ) | (j << 11 ) | 0x80000000 );
ULONG Data = READ_PORT_ULONG( (PULONG)0xcfc );
if( Data != 0xffffffff )
{
DBG_PRINTF(("(%d,%d)=0x%x", i,j,Data ));
};
if( Data == Id )
{
DBG_PRINTF(("!!!!!!\r\n"));
m_PCIConfigData = (i << 16 ) | (j << 11 ) | 0x80000000;
break;
}
};
};
WRITE_PORT_ULONG( (PULONG)0xcf8, OldPort );
#endif
return( TRUE );
}
BOOL CWDMKernelService::SetPCIConfigData( DWORD address, DWORD data )
{
if( m_ioBase==0 || m_pHwDevExt==NULL ){
return( FALSE );
}
if( address>0xFF ){
DBG_BREAK();
return( FALSE );
}
#ifdef DIRECTPCICONFIG
// DBG_PRINTF( ("XXXPCIConfigData currIrql = 0x%0x LINE=%d\n\r", KeGetCurrentIrql(),__LINE__ ) );
if( m_PCIConfigData == 0xffffffff )
return FALSE;
ULONG OldPort = READ_PORT_ULONG( (PULONG)0xcf8 );
WRITE_PORT_ULONG( (PULONG)0xcf8, ( m_PCIConfigData | address) & 0xfffffffc );
WRITE_PORT_ULONG( (PULONG)0xcfc, data );
WRITE_PORT_ULONG( (PULONG)0xcf8, OldPort );
return TRUE;
#else
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
return( StreamClassReadWriteConfig( m_pHwDevExt,
FALSE,
&data,
address,
4 ) );
#endif
}
BOOL CWDMKernelService::SetPCIConfigData( DWORD address, WORD data )
{
if( m_ioBase==0 || m_pHwDevExt==NULL ){
return( FALSE );
}
if( address>0xFF ){
DBG_BREAK();
return( FALSE );
}
#ifdef DIRECTPCICONFIG
// DBG_PRINTF( ("XXXPCIConfigData currIrql = 0x%0x LINE=%d\n\r", KeGetCurrentIrql(),__LINE__ ) );
if( m_PCIConfigData == 0xffffffff )
return FALSE;
ULONG OldPort = READ_PORT_ULONG( (PULONG)0xcf8 );
WRITE_PORT_ULONG( (PULONG)0xcf8, (m_PCIConfigData | address) & 0xfffffffc );
ULONG OrgData = READ_PORT_ULONG( (PULONG)0xcfc );
switch( address % 4 )
{
case 0:
WRITE_PORT_ULONG( (PULONG)0xcfc, (OrgData & 0xffff0000 ) | (DWORD)data );
break;
case 2:
WRITE_PORT_ULONG( (PULONG)0xcfc, (OrgData & 0x0000ffff ) | ((DWORD)data << 16) );
break;
default:
DBG_BREAK();
};
WRITE_PORT_ULONG( (PULONG)0xcf8, OldPort );
return TRUE;
#else
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
return( StreamClassReadWriteConfig( m_pHwDevExt,
FALSE,
&data,
address,
2 ) );
#endif
}
BOOL CWDMKernelService::SetPCIConfigData( DWORD address, BYTE data )
{
if( m_ioBase==0 || m_pHwDevExt==NULL ){
return( FALSE );
}
if( address>0xFF ){
DBG_BREAK();
return( FALSE );
}
#ifdef DIRECTPCICONFIG
// DBG_PRINTF( ("XXXPCIConfigData currIrql = 0x%0x LINE=%d\n\r", KeGetCurrentIrql(),__LINE__ ) );
if( m_PCIConfigData == 0xffffffff )
return FALSE;
ULONG OldPort = READ_PORT_ULONG( (PULONG)0xcf8 );
WRITE_PORT_ULONG( (PULONG)0xcf8, (m_PCIConfigData | address) & 0xfffffffc );
ULONG OrgData = READ_PORT_ULONG( (PULONG)0xcfc );
switch( address % 4 )
{
case 0:
WRITE_PORT_ULONG( (PULONG)0xcfc, (OrgData & 0xffffff00 ) | (DWORD)data );
break;
case 1:
WRITE_PORT_ULONG( (PULONG)0xcfc, (OrgData & 0xffff00ff ) | ((DWORD)data << 8) );
break;
case 2:
WRITE_PORT_ULONG( (PULONG)0xcfc, (OrgData & 0xff00ffff ) | ((DWORD)data << 16) );
break;
case 3:
WRITE_PORT_ULONG( (PULONG)0xcfc, (OrgData & 0x00ffffff ) | ((DWORD)data << 24) );
break;
};
WRITE_PORT_ULONG( (PULONG)0xcf8, OldPort );
return TRUE;
#else
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
return( StreamClassReadWriteConfig( m_pHwDevExt,
FALSE,
&data,
address,
1 ) );
#endif
}
BOOL CWDMKernelService::GetPCIConfigData( DWORD address, DWORD *data )
{
if( m_ioBase==0 || m_pHwDevExt==NULL ){
return( FALSE );
}
if( address>0xFF ){
DBG_BREAK();
return( FALSE );
}
#ifdef DIRECTPCICONFIG
// DBG_PRINTF( ("XXXPCIConfigData currIrql = 0x%0x LINE=%d\n\r", KeGetCurrentIrql(),__LINE__ ) );
if( m_PCIConfigData == 0xffffffff )
return FALSE;
ULONG OldPort = READ_PORT_ULONG( (PULONG)0xcf8 );
WRITE_PORT_ULONG( (PULONG)0xcf8, ( m_PCIConfigData | address) & 0xfffffffc );
*data = READ_PORT_ULONG( (PULONG)0xcfc );
WRITE_PORT_ULONG( (PULONG)0xcf8, OldPort );
// return TRUE;
#else
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
StreamClassReadWriteConfig( m_pHwDevExt,
TRUE,
data,
address,
4 );
#endif
if( address==0x2C ){
if( *data!=0x8888123F ){
return( TRUE );
}
if( strncmp( m_MachineID, "TECRA", 5 )==0 ){
*data = 0x00011179;
}else if( strncmp( m_MachineID, "PORTEGE", 7 )==0 ){
*data = 0x00021179;
}
}
return( TRUE );
}
BOOL CWDMKernelService::GetPCIConfigData( DWORD address, WORD *data )
{
if( m_ioBase==0 || m_pHwDevExt==NULL ){
return( FALSE );
}
if( address>0xFF ){
DBG_BREAK();
return( FALSE );
}
#ifdef DIRECTPCICONFIG
// DBG_PRINTF( ("XXXPCIConfigData currIrql = 0x%0x LINE=%d\n\r", KeGetCurrentIrql(),__LINE__ ) );
if( m_PCIConfigData == 0xffffffff )
return FALSE;
ULONG OldPort = READ_PORT_ULONG( (PULONG)0xcf8 );
WRITE_PORT_ULONG( (PULONG)0xcf8, ( m_PCIConfigData | address) & 0xfffffffc );
switch( address % 4 )
{
case 0:
*data = (WORD)(READ_PORT_ULONG( (PULONG)0xcfc ) & 0xffff);
break;
case 2:
*data = (WORD)((READ_PORT_ULONG( (PULONG)0xcfc ) >> 16 ) & 0xffff );
break;
default:
*data = 0xffff;
DBG_BREAK();
};
WRITE_PORT_ULONG( (PULONG)0xcf8, OldPort );
// return TRUE;
#else
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
StreamClassReadWriteConfig( m_pHwDevExt,
TRUE,
data,
address,
2 );
#endif
if( address==0x2C ){
if( *data!=0x123F ){
return( TRUE );
}
if( strncmp( m_MachineID, "TECRA", 5 )==0 ){
*data = 0x1179;
}else if( strncmp( m_MachineID, "PORTEGE", 7 )==0 ){
*data = 0x1179;
}
}
if( address==0x2E ){
if( *data!=0x8888 ){
return( TRUE );
}
if( strncmp( m_MachineID, "TECRA", 5 )==0 ){
*data = 0x0001;
}else if( strncmp( m_MachineID, "PORTEGE", 7 )==0 ){
*data = 0x0002;
}
}
return( TRUE );
}
BOOL CWDMKernelService::GetPCIConfigData( DWORD address, BYTE *data )
{
if( m_ioBase==0 || m_pHwDevExt==NULL ){
return( FALSE );
}
if( address>0xFF ){
DBG_BREAK();
return( FALSE );
}
#ifdef DIRECTPCICONFIG
// DBG_PRINTF( ("XXXPCIConfigData currIrql = 0x%0x LINE=%d\n\r", KeGetCurrentIrql(),__LINE__ ) );
if( m_PCIConfigData == 0xffffffff )
return FALSE;
ULONG OldPort = READ_PORT_ULONG( (PULONG)0xcf8 );
WRITE_PORT_ULONG( (PULONG)0xcf8, ( m_PCIConfigData | address) & 0xfffffffc );
switch( address % 4 )
{
case 0:
*data = (BYTE)(READ_PORT_ULONG( (PULONG)0xcfc ) & 0xff);
break;
case 1:
*data = (BYTE)((READ_PORT_ULONG( (PULONG)0xcfc ) >> 8 ) & 0xff );
break;
case 2:
*data = (BYTE)((READ_PORT_ULONG( (PULONG)0xcfc ) >> 16 ) & 0xff );
break;
case 3:
*data = (BYTE)((READ_PORT_ULONG( (PULONG)0xcfc ) >> 24 ) & 0xff );
break;
};
WRITE_PORT_ULONG( (PULONG)0xcf8, OldPort );
return TRUE;
#else
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
return( StreamClassReadWriteConfig( m_pHwDevExt,
TRUE,
data,
address,
1 ) );
#endif
}
BOOL CWDMKernelService::SetPortData( DWORD address, DWORD data )
{
if( m_ioBase==0 || m_pHwDevExt==NULL ){
return( FALSE );
}
if( address>0xFFFF ){
DBG_BREAK();
return( FALSE );
}
PULONG addr = (PULONG)(m_ioBase + address);
ULONG o_data = (ULONG)data;
WRITE_PORT_ULONG( addr, o_data );
return( TRUE );
}
BOOL CWDMKernelService::SetPortData( DWORD address, WORD data )
{
if( m_ioBase==0 || m_pHwDevExt==NULL ){
return( FALSE );
}
if( address>0xFFFF ){
DBG_BREAK();
return( FALSE );
}
PUSHORT addr = (PUSHORT)(m_ioBase + address);
USHORT o_data = (USHORT)data;
WRITE_PORT_USHORT( addr, o_data );
return( TRUE );
}
BOOL CWDMKernelService::SetPortData( DWORD address, BYTE data )
{
if( m_ioBase==0 || m_pHwDevExt==NULL ){
return( FALSE );
}
if( address>0xFFFF ){
DBG_BREAK();
return( FALSE );
}
PUCHAR addr = (PUCHAR)(m_ioBase + address);
UCHAR o_data = (UCHAR)data;
WRITE_PORT_UCHAR( addr, o_data );
return( TRUE );
}
BOOL CWDMKernelService::GetPortData( DWORD address, DWORD *data )
{
if( m_ioBase==0 || m_pHwDevExt==NULL ){
return( FALSE );
}
if( address>0xFFFF ){
DBG_BREAK();
return( FALSE );
}
PULONG addr = (PULONG)(m_ioBase + address);
*data = READ_PORT_ULONG( addr );
return( TRUE );
}
BOOL CWDMKernelService::GetPortData( DWORD address, WORD *data )
{
if( m_ioBase==0 || m_pHwDevExt==NULL ){
return( FALSE );
}
if( address>0xFFFF ){
DBG_BREAK();
return( FALSE );
}
PUSHORT addr = (PUSHORT)(m_ioBase + address);
*data = READ_PORT_USHORT( addr );
return( TRUE );
}
BOOL CWDMKernelService::GetPortData( DWORD address, BYTE *data )
{
if( m_ioBase==0 || m_pHwDevExt==NULL ){
return( FALSE );
}
if( address>0xFFFF ){
DBG_BREAK();
return( FALSE );
}
PUCHAR addr = (PUCHAR)(m_ioBase + address);
*data = READ_PORT_UCHAR( addr );
return( TRUE );
}
BOOL CWDMKernelService::GetTickCount( DWORD *pTickCount )
{
ULONGLONG ticks;
ULONGLONG rate;
DWORD time;
ticks = (ULONGLONG)KeQueryPerformanceCounter((PLARGE_INTEGER)&rate).QuadPart;
//
// convert from ticks to 100ns clock
//
ticks = ( (ticks & 0xFFFFFFFF00000000) / rate * 10000000 +
(ticks & 0xFFFFFFFF) * 10000000 /rate );
//
// convert from ticks to 1ms clock
//
time = (DWORD)( ticks / 10000 );
*pTickCount = time;
return( TRUE );
}
BOOL CWDMKernelService::Sleep( DWORD SleepCount )
{
DWORD StartTime, EndTime, CurrentTime;
LARGE_INTEGER time, rate;
LARGE_INTEGER waittime;
time = KeQueryPerformanceCounter( &rate );
CurrentTime = (DWORD)(( (time.QuadPart*1000)/(rate.QuadPart) ));
// DBG_PRINTF(("Sleep: Start = x0x%x\n\r", CurrentTime ));
time = KeQueryPerformanceCounter( &rate );
StartTime = (DWORD)( (time.QuadPart*1000)/rate.QuadPart );
EndTime = StartTime + SleepCount;
if( KeGetCurrentIrql() > PASSIVE_LEVEL ){
while( TRUE ){
KeStallExecutionProcessor( 1000 );
time = KeQueryPerformanceCounter( &rate );
CurrentTime = (DWORD)(( (time.QuadPart*1000)/(rate.QuadPart) ));
//DBG_PRINTF(("Sleep: Current = x0%x, End = 0x%x\r\n", CurrentTime, EndTime ));
if( CurrentTime>=EndTime )
break;
}
}else{
waittime.QuadPart = SleepCount * 10000;
while( TRUE ){
KeWaitForSingleObject( &m_Event, Executive,
KernelMode, FALSE, &waittime );
time = KeQueryPerformanceCounter( &rate );
CurrentTime = (DWORD)(( (time.QuadPart*1000)/(rate.QuadPart) ));
if( CurrentTime >= EndTime ){
break;
}else{
waittime.QuadPart = (EndTime-CurrentTime) * 10000;
}
}
}
time = KeQueryPerformanceCounter( &rate );
CurrentTime = (DWORD)(( (time.QuadPart*1000)/(rate.QuadPart) ));
// DBG_PRINTF(("Sleep: End = 0x%x\n\r", CurrentTime ));
return( TRUE );
}
void CWDMKernelService::DisableHwInt( void )
{
KIRQL currIrql;
currIrql = KeGetCurrentIrql();
if( m_IntCount==0 ){
if( currIrql == m_Irql ){
m_OldIrql = m_Irql;
m_IntCount++;
return;
}
KeRaiseIrql( m_Irql, &m_OldIrql );
}
m_IntCount++;
return;
}
void CWDMKernelService::EnableHwInt( void )
{
m_IntCount--;
if( m_IntCount==0 ){
if( m_OldIrql == m_Irql ){
return;
}
KeLowerIrql( m_OldIrql );
}
return;
}
BOOL CWDMKernelService::CheckInt( void )
{
if( m_IntCount != 0 ){
DBG_BREAK();
}
return(TRUE);
}