📄 pdsocket.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
Abstract:
Platform dependent PCMCIA initialization functions
Notes:
--*/
#include <windows.h>
#include <types.h>
#include <socksv2.h>
#include <memory.h>
#include <ceddk.h>
#include <nkintr.h>
#include "PDSocket.h"
//////////////////////////////////////////////////////////////////////////
//#define PCMCIA_DRIVER_KEY TEXT("Drivers\\PCMCIA")
#define FN_SYSINTR_VALUE_NAME TEXT("FnSysIntr")
#define FN_IRQ_VALUE_NAME TEXT("FnIrq")
#define FORCE_FN_SYSINTR_NAME TEXT("ForceFnSysIntr")
#define CONTROLLER_FN_INT_VALUE_NAME TEXT("ControllerFnInt")
#define CSC_SYSINTR_VALUE_NAME TEXT("CSCSysIntr")
#define CSC_IRQ_VALUE_NAME TEXT("CSCIrq")
#define POLLING_MODE_NAME TEXT("PollingMode")
#define POLL_TIMEOUT_NAME TEXT("PollTimeout")
#define DISABLE_SOCKET_NAME TEXT("DisableSocket")
#define CSC_INTERRUPT_DELAY_NAME TEXT("CSCInterruptDelay")
#define CHIPSET_ID_CNT 32
#define CHIPSET_ID_LEN ((CHIPSET_ID_CNT * 9) + 1)
const SS_POWER_ENTRY CPcmciaCardSocket::m_rgPowerEntries[NUM_POWER_ENTRIES] =
{
{ 0, PWR_SUPPLY_VCC | PWR_SUPPLY_VPP1 | PWR_SUPPLY_VPP2 },
{ 33, PWR_SUPPLY_VCC },
{ 50, PWR_SUPPLY_VCC | PWR_SUPPLY_VPP1 | PWR_SUPPLY_VPP2 },
{ 120, PWR_SUPPLY_VPP1 | PWR_SUPPLY_VPP2 }
};
DWORD CPcmciaCardSocket::ms_dwSocketLastIndex = 1;
CPcmciaCardSocket::CPcmciaCardSocket( CPcmciaBusBridge* pBridge )
{
m_pBridge = pBridge;
m_dwSocketIndex = 0;
while( m_dwSocketIndex == 0 )
{
m_dwSocketIndex = ( DWORD )
InterlockedIncrement( ( LONG * ) &ms_dwSocketLastIndex );
//Make it is it does not exist.
CPcmciaCardSocket* pSocket = GetSocket( ( HANDLE ) m_dwSocketIndex );
if( pSocket != NULL )
{
// Duplicated , Retry.
m_dwSocketIndex = 0;
pSocket->DeRef();
}
}
DEBUGCHK( m_pBridge );
while( m_pBridge->LockOwner( 1000 ) != TRUE )
{
DEBUGCHK( FALSE );
}
DEBUGMSG( ZONE_INIT,
( TEXT( "CARDBUS: CPcmciaCardSocket (Socket=%d) Created\r\n" ),
GetSocketHandle() ) );
}
CPcmciaCardSocket::~CPcmciaCardSocket()
{
m_pBridge->ReleaseOwner();
DEBUGMSG( ZONE_INIT,
( TEXT( "CARDBUS: CPcmciaCardSocket (Socket=%d) Deleted\r\n" ),
GetSocketHandle() ) );
}
STATUS CPcmciaCardSocket::GetPowerEntry( PDWORD pdwNumOfEnery,
PSS_POWER_ENTRY pPowerEntry )
{
STATUS status = CERR_BAD_ARGS;
if( pdwNumOfEnery != NULL && pPowerEntry != NULL )
{
DWORD dwNumOfCopied = min( *pdwNumOfEnery, NUM_POWER_ENTRIES );
if( dwNumOfCopied != 0 )
{
memcpy( pPowerEntry,
m_rgPowerEntries,
dwNumOfCopied * sizeof( SS_POWER_ENTRY ) );
*pdwNumOfEnery = dwNumOfCopied;
status = CERR_SUCCESS;
}
}
return status;
}
UINT16 CPcmciaCardSocket::GetSocketNo()
{
return m_pBridge->GetSocketNo();
};
CPcmciaBusBridge::CPcmciaBusBridge( LPCTSTR RegPath ) : CPCCardBusBridgeBase( RegPath ),
CMiniThread( 0,
TRUE )
{
m_dwFnIrq = -1;
m_fPCICCritSecInitialized = false;
m_pCardBusResource = NULL;
m_hISTEvent = NULL;
m_uSocketNum = ( WORD ) - 1;
m_pCardSocket = NULL;
m_fPowerCycleEvent = FALSE;
m_fCardInjectEvent = FALSE;
m_fPollingMode = TRUE;
m_dwCSCInterruptDelay = 0;
};
CPcmciaBusBridge::~CPcmciaBusBridge()
{
// Terminate IST
m_bTerminated = TRUE;
if( m_hISTEvent )
{
SetEvent( m_hISTEvent );
ThreadTerminated( 1000 );
if( !m_fPollingMode )
{
InterruptDisable( m_dwCSCSysIntr );
}
CloseHandle( m_hISTEvent );
};
if( m_uSocketNum != ( UINT16 ) - 1 )
{
GetSocketNumberFromCS( FALSE );
m_uSocketNum = ( UINT16 ) - 1;
}
RemovePcmciaCardSocket();
if( m_pCardBusResource != NULL )
{
delete m_pCardBusResource;
}
if( m_fPCICCritSecInitialized )
{
DeleteCriticalSection( &m_PCICCritSec );
}
}
BOOL CPcmciaBusBridge::InstallIsr()
{
UINT8 tmp;
//
// Disable interrupts
//
WritePCICRegister( REG_INTERRUPT_AND_GENERAL_CONTROL, 0 );
// Management int -> edge triggering(PULSE), System int -> LEVEL triggering
WritePCICRegister( REG_GENERAL_CONTROL, MISC1_VCC_33|MISC1_PM_IRQ|MISC1_SPK_ENABLE );
UINT8 bPat = ReadPCICRegister( REG_GENERAL_CONTROL );
// 25Mhz_bypass,low_power_dynamic,IRQ12=drive_LED
WritePCICRegister( REG_GLOBAL_CONTROL, MISC2_LOW_POWER_MODE|MISC2_LED_ENABLE);
// before configuring timing register, FIFO should be cleared.
WritePCICRegister( REG_FIFO_CTRL, FIFO_EMPTY_WRITE); //Flush FIFO
//default access time is 300ns
WritePCICRegister( REG_SETUP_TIMING0, 5); //80ns(no spec)
WritePCICRegister( REG_CMD_TIMING0, 20); //320ns(by spec,25Mhz clock)
WritePCICRegister( REG_RECOVERY_TIMING0, 5); //80ns(no spec)
//default access time is 300ns
WritePCICRegister( REG_SETUP_TIMING1, 2); //80ns(no spec)
WritePCICRegister( REG_CMD_TIMING1, 8); //320ns(by spec,25Mhz clock)
WritePCICRegister( REG_RECOVERY_TIMING1, 2); //80ns(no spec)
if( !m_fPollingMode )
{
// PD6710 specific code to enable CSC interrupt (routed to -INTR)
tmp = CFG_CARD_DETECT_ENABLE | CFG_READY_ENABLE;
WritePCICRegister( REG_STATUS_CHANGE_INT_CONFIG, tmp );
// Enable Manage Interrupt
tmp = ReadPCICRegister( REG_INTERRUPT_AND_GENERAL_CONTROL );
tmp |= INT_ENABLE_MANAGE_INT;
WritePCICRegister( REG_INTERRUPT_AND_GENERAL_CONTROL, tmp );
}
else
{
WritePCICRegister( REG_STATUS_CHANGE_INT_CONFIG, 0 );
}
// CreateIST Event
m_hISTEvent = CreateEvent( 0, FALSE, FALSE, NULL );
if( !m_fPollingMode )
{
// Run IST
BOOL r = InterruptInitialize( m_dwCSCSysIntr, m_hISTEvent, 0, 0 );
ASSERT( r );
}
return TRUE;
}
#ifdef DEBUG
VOID CPcmciaBusBridge::DumpAllRegisters()
{
DEBUGMSG( ZONE_FUNCTION, ( TEXT( "Dumping all PCIC registers\r\n" ) ) );
for( UINT8 nRegNum = 0; nRegNum < 0x40; nRegNum++ )
{
UINT8 val;
if( nRegNum == REG_CARD_STATUS_CHANGE )
val = -1;
else
val = ReadPCICRegister( nRegNum );
DEBUGMSG( ZONE_FUNCTION,
( TEXT( "%02x: %02x\r\n" ), nRegNum, val ) );
}
DEBUGMSG( ZONE_FUNCTION, ( TEXT( "Dump completed.\r\n" ) ) );
}
#endif
//
// Function to set the PCIC index register
//
VOID CPcmciaBusBridge::PCICIndex( UINT8 register_num )
{
WRITE_PORT_UCHAR( m_PCICIndex, ( UINT8 )( register_num ) );
}
//
// Function to write to the PCIC data register
//
VOID CPcmciaBusBridge::PCICDataWrite( UINT8 value )
{
WRITE_PORT_UCHAR( m_PCICData, value );
}
//
// Function to read the PCIC data register
//
UINT8 CPcmciaBusBridge::PCICDataRead( VOID )
{
return READ_PORT_UCHAR( m_PCICData );
}
//
// Verify the PCIC's REG_CHIP_REVISION
//
// This bit of code looks in the 82365 chip revision register (PCIC index 0)
// to see if a valid 82365 is in the system. The original code only
// recognized the 83h silicon revision. This indicates REV C silicon from
// Intel. However, Intel also had a very popular rev B version, and that's
// what the integrated PCMCIA controller on the AMD ElanSC400 emulated. The
// silicon revision register for that version returned 82h.
//
BOOL CPcmciaBusBridge::IsValidPCICSig( void )
{
switch( m_vRevision = ReadPCICRegister( REG_CHIP_REVISION ) )
{
case 0x82:
case 0x83:
case 0x84:
// for newer chip - can handle 3.3v
DEBUGMSG( 1,
( TEXT( "PCMCIA:IsValidPCICSig Valid CHIP_REVISION detected = 0x%x at 0x%x\r\n" ),
m_vRevision,
m_PCICIndex ) );
return TRUE;
}
DEBUGMSG( 1,
( TEXT( "PCMCIA:IsValidPCICSig Invalid CHIP_REVISION = 0x%x at 0x%x!!!\r\n" ),
m_vRevision,
m_PCICIndex ) );
return FALSE;
}
//
// Function to get the initial settings from the registry
//
// NOTE: lpRegPath is assumed to be under HKEY_LOCAL_MACHINE
//
// Returns ERROR_SUCCESS on success or a Win32 error code on failure
//
DWORD CPcmciaBusBridge::GetRegistryConfig()
{
DWORD dwRet = 1;
DWORD dwSize, dwType, dwData;
// get the PCMCIA windows configuration
if( !LoadWindowsSettings() )
{
dwRet = ERROR_INVALID_DATA;
goto grc_fail;
}
// get the polling mode value
dwSize = sizeof( DWORD );
if( !RegQueryValueEx( POLLING_MODE_NAME,
&dwType,
( PUCHAR ) & dwData,
&dwSize ) )
{
m_fPollingMode = FALSE; // RegQueryValueEx failed, default to FALSE
}
else
{
m_fPollingMode = dwData ? TRUE : FALSE;
}
// get the function interrupt routing configuration
// Get the controller function interrupt number
dwSize = sizeof( DWORD );
if( RegQueryValueEx( CONTROLLER_FN_INT_VALUE_NAME,
&dwType,
( PUCHAR ) & dwData,
&dwSize ) )
{
m_dwControllerFnIntNo = dwData;
}
else
{
dwRet = FALSE;
goto grc_fail;
}
// Get the function interrupt SYSINTR or IRQ value
// First try to get the IRQ value
dwSize = sizeof( DWORD );
if( RegQueryValueEx( FN_IRQ_VALUE_NAME,
&dwType,
( PUCHAR ) & dwData,
&dwSize ) )
{
m_dwFnSysIntr = SYSINTR_UNDEFINED;
m_dwFnIrq = dwData;
// check if we should automatically convert the IRQ to SYSINTR value
dwSize = sizeof( DWORD );
if( RegQueryValueEx( FORCE_FN_SYSINTR_NAME,
&dwType,
( PUCHAR ) & dwData,
&dwSize ) )
{
if( dwData )
{
// Convert the interrupt to a logical sysintr value.
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &m_dwFnIrq, sizeof(DWORD), &m_dwFnSysIntr, sizeof(DWORD), NULL))
{
RETAILMSG(1, (TEXT("PCMCIA: Failed to obtain function interrupt information!\r\n")));
m_dwFnSysIntr = SYSINTR_UNDEFINED;
dwRet = ERROR_INVALID_DATA;
goto grc_fail;
}
m_dwFnIrq = -1;
}
}
}
else
{
// IRQ value was not specified, try to get the SYSINTR value
dwSize = sizeof( DWORD );
if( RegQueryValueEx( FN_SYSINTR_VALUE_NAME,
&dwType,
( PUCHAR ) & dwData,
&dwSize ) )
{
m_dwFnSysIntr = dwData;
m_dwFnIrq = -1;
}
else
{
RETAILMSG(1, (TEXT("PCMCIA: Failed to obtain function interrupt information!\r\n")));
dwRet = ERROR_INVALID_DATA;
goto grc_fail;
}
}
// get card status change interrupt routing configuration
m_dwCSCSysIntr = SYSINTR_UNDEFINED;
dwSize = sizeof( DWORD );
if( RegQueryValueEx( CSC_SYSINTR_VALUE_NAME,
&dwType,
( PUCHAR ) & dwData,
&dwSize ) )
{
m_dwCSCSysIntr = dwData;
}
else
{
dwSize = sizeof( DWORD );
if( !RegQueryValueEx( CSC_IRQ_VALUE_NAME,
&dwType,
( PUCHAR ) & dwData,
&dwSize ) )
{
m_fPollingMode = TRUE;
}
else
{
// Convert the interrupt to a logical sysintr value.
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwData, sizeof(DWORD), &m_dwCSCSysIntr, sizeof(DWORD), NULL))
{
RETAILMSG(1, (TEXT("PCMCIA: Failed to obtain sysintr value for CSC interrupt.\r\n")));
m_dwCSCSysIntr = SYSINTR_UNDEFINED;
m_fPollingMode = TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -