?? pcmsock.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:
Samsung SMDK2440 PCMCIA Socket Services Object for PCMCIA(16-bit) Interface.
Notes:
--*/
#include <windows.h>
#include <types.h>
#include <socksv2.h>
#include <memory.h>
#include <ceddk.h>
#include <debug.h>
#define ZONE_SOCKET ZONE_PDD
#include "PCMSock.h"
#define DATA_INT_IRQ (INT_IRQ_BIT0 | INT_IRQ_BIT1) // SMDK2440 board routes PD6710 IRQ3 to EINT8.
//--------------------Pcmcia Socket Implementation--------------------------------------------
const SS_SOCKET_INFO CPCMSocket::ms_SocketInitInfo =
{
SOCK_CAP_MEM_CARD |
SOCK_CAP_IO_MEMORY_CARD |
SOCK_CAP_ONLY_SYSINTR, //dwSocketCaps
SOCK_CAP_PWRCYCLE |
SOCK_CAP_CD |
SOCK_CAP_SUSPEND_RESUME |
SOCK_CAP_WP |
SOCK_CAP_BVD1 |
SOCK_CAP_BVD2, // Socket Interrupt Capability Set follow bitmap.
SOCK_CAP_PWRCYCLE |
SOCK_CAP_CD |
SOCK_CAP_SUSPEND_RESUME |
SOCK_CAP_WP |
SOCK_CAP_BVD1 |
SOCK_CAP_BVD2, // Socket status report capability
0, // Socket status indicate capability
0, // Number of power entry this socket have.
0, // Number of Window supported in this Socket.
Internal, // Bus Type is Internal.
(DWORD) -1, // Bus Number.
{ - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}
};
const SS_SOCKET_STATE CPCMSocket::ms_SocketInitState =
{
SOCK_EVENT_PWRCYCLE |
SOCK_EVENT_CD |
SOCK_EVENT_SUSPEND_RESUME |
SOCK_EVENT_WP |
SOCK_EVENT_BVD1 |
SOCK_EVENT_BVD2, // Initial EventMask
0, // Event Changed.
0, // Event Status
CFG_IFACE_MEMORY, //default interface type
0, // Interrupt Enable.
0, // Vcc
0, // Vpp1
0 // Vpp2
};
CPCMSocket::CPCMSocket( CPcmciaBusBridge* pBridge, UINT8 nSocketNumber ) : CPCMCIASocketBase<CPcmciaMemWindows, CPcmciaIoWindows, CPcmciaCardSocket, CPcmciaBusBridge>( pBridge )
{
DEBUGMSG( ZONE_SOCKET, ( TEXT( "+CPCMSocket::CPCMSocket\r\n" ) ) );
m_nSlotNumber = nSocketNumber;
m_SocketState = ms_SocketInitState;
m_SocketInfo = ms_SocketInitInfo;
// Use Default Setting the Function interrupt is routed same IRQ as the Bridge
for( DWORD dwIndex = 0; dwIndex < IRQ_ROUTINGTABLE_SIZE; dwIndex++ )
{
m_SocketInfo.bArrayIrqRouting[dwIndex] = ( BYTE )
pBridge->GetClientSysInt();
}
m_SocketInfo.dwNumOfPowerEntry = NUM_POWER_ENTRIES;
m_SocketInfo.dwNumOfWindows = pBridge->GetMemWindowCount() +
pBridge->GetIoWindowCount();
m_SocketInfo.dwBusNumber = 0;
if( !pBridge->PollingMode() )
{
PCICRegisterWrite( REG_STATUS_CHANGE_INT_CONFIG,
( ( ( UINT8 ) pBridge->GetBridgeCSCIrq() ) << 4 ) |
CFG_BATTERY_DEAD_ENABLE |
CFG_BATTERY_WARNING_ENABLE |
CFG_CARD_DETECT_ENABLE |
CFG_READY_ENABLE );
}
m_bResuming = FALSE;
DEBUGMSG( ZONE_SOCKET, ( TEXT( "-CPCMSocket::CPCMSocket\r\n" ) ) );
}
CPCMSocket::~CPCMSocket()
{
DEBUGMSG( ZONE_SOCKET, ( TEXT( "+CPCMSocket::Deinitialize()\r\n" ) ) );
Lock();
BOOL bInitWindow = CardDeInitWindow();
DEBUGCHK( bInitWindow );
PCICRegisterWrite( REG_POWER_CONTROL,
PCICRegisterRead( REG_POWER_CONTROL ) & ~PWR_OUTPUT_ENABLE );
Unlock();
DEBUGMSG( ZONE_SOCKET, ( TEXT( "-CPCMSocket::Deinitialize()\r\n" ) ) );
}
//
// GetSocket - return Socket state
// [In/Out] pBuf - pointer to SS_SOCKET_STATE struct
// [In/Out] pnBuf - pointer to size of struct pointed to by pBuf
// return CERR_SUCCESS on success, CERR_UNSUPPORTED_SERVICE if size is anomolous
//
STATUS CPCMSocket::CardGetSocket( PSS_SOCKET_STATE pState )
{
DWORD dwReg;
DEBUGMSG( ZONE_SOCKET, ( TEXT( "+CPCMSocket::GetSocket()\r\n" ) ) );
Lock();
if( pState )
{
// Read voltage information
dwReg = PCICRegisterRead( REG_POWER_CONTROL );
if( dwReg & PWR_VCC_POWER )
{
dwReg = PCICRegisterRead( REG_GENERAL_CONTROL );
if( dwReg & MISC1_VCC_33 ) // Vcc = 3V
{
// Vcc = 3V
m_SocketState.fVcc = 0x1;
}
else
{
// Vcc = 5V
m_SocketState.fVcc = 0x2;
}
}
else
{
// Vcc = 0V
m_SocketState.fVcc = 0x0;
}
m_SocketState.uVpp1 = m_SocketState.uVpp2 = 0; //m_SocketState.fVcc;
BYTE uStatusChange = 0;
m_SocketState.dwEventChanged |= ( ( uStatusChange & CSC_DETECT_CHANGE ) !=
0 ?
SOCK_EVENT_CD :
0 );
m_SocketState.dwEventChanged |= ( ( uStatusChange & CSC_BATTERY_DEAD_OR_STS_CHG ) !=
0 ?
SOCK_EVENT_BVD1 :
0 );
m_SocketState.dwEventChanged |= ( ( uStatusChange & CSC_BATTERY_WARNING ) !=
0 ?
SOCK_EVENT_BVD2 :
0 );
m_SocketState.dwEventChanged |= ( ( uStatusChange & CSC_READY_CHANGE ) !=
0 ?
SOCK_EVENT_READY :
0 );
BYTE uCurrentStatus = PCICRegisterRead( REG_INTERFACE_STATUS );
m_SocketState.dwEventStatus = 0;
m_SocketState.dwEventStatus |= ( ( uCurrentStatus & ( STS_CD1 | STS_CD2 ) ) ==
( STS_CD1 | STS_CD2 ) ?
SOCK_EVENT_CD :
0 );
m_SocketState.dwEventStatus |= ( ( uCurrentStatus & STS_BVD1 ) ==
0 ?
SOCK_EVENT_BVD1 :
0 );
m_SocketState.dwEventStatus |= ( ( uCurrentStatus & STS_BVD2 ) ==
0 ?
SOCK_EVENT_BVD2 :
0 );
m_SocketState.dwEventStatus |= ( ( uCurrentStatus & STS_CARD_READY ) !=
0 ?
SOCK_EVENT_READY :
0 );
m_SocketState.dwEventStatus |= ( ( uCurrentStatus & STS_WRITE_PROTECT ) !=
0 ?
SOCK_EVENT_WP :
0 );
m_SocketState.dwEventStatus &= ~SOCK_EVENT_CARDBUS_CARD;
*pState = m_SocketState;
pState->dwEventChanged &= pState->dwEventMask;
DEBUGMSG( ZONE_SOCKET,
( TEXT( "-CPCMSocket::GetSocket(): dwEventMask: %x dwEventChanged: %x dwEventStatus: %x\r\n" ),
pState->dwEventMask,
pState->dwEventChanged,
pState->dwEventStatus ) );
}
Unlock();
return CERR_SUCCESS;
}
void CPCMSocket::PowerMgrCallback( BOOL bPowerOff )
{
SS_SOCKET_STATE sSocketState = m_SocketState;
sSocketState.dwEventChanged = SOCK_EVENT_SUSPEND_RESUME;
sSocketState.dwEventStatus = ( bPowerOff ?
SOCK_EVENT_CD :
( SOCK_EVENT_CD |
SOCK_EVENT_SUSPEND_RESUME ) );
m_pBridge->CallBackToCardService( GetSlotNumber(),
GetSocketHandle(),
&sSocketState );
}
void CPCMSocket::PowerMgr( BOOL bPowerDown )
{
if( bPowerDown )
{
// Power Off Socket If it is applied.
PowerMgrCallback( bPowerDown );
if( ( m_SocketState.dwInteruptStatus & SOCK_INT_FUNC_IRQ_WAKE ) == 0 ) // We can shut down this function card
{
m_bBackupPCICPwrCtrlReg = PCICRegisterRead( REG_POWER_CONTROL );
// Disable Socket Power.
PCICRegisterWrite( REG_POWER_CONTROL, 0 );
m_bResuming = TRUE;
}
}
else
{
if( m_bResuming )
{
PCICRegisterWrite( REG_POWER_CONTROL, m_bBackupPCICPwrCtrlReg );
m_pBridge->NeedPowerResuming();
}
else
{
PowerMgrCallback( bPowerDown );
}
}
}
BOOL CPCMSocket::Resuming()
{
if( m_bResuming )
{
Lock();
DWORD dwStartTickCount = GetTickCount();
// Wait for 100MS for power set .
while( GetTickCount() - dwStartTickCount < 100 )
Sleep( 0 ); //Yeild among same priority thread.
//Assert Resetting.
dwStartTickCount = GetTickCount();
while( GetTickCount() - dwStartTickCount < 20 )
Sleep( 0 ); //Yeild among same priority thread.
// Deassert Reset.
PCICRegisterWrite( REG_INTERRUPT_AND_GENERAL_CONTROL,
INT_CARD_NOT_RESET/*|INT_ENABLE_MANAGE_INT*/ );
dwStartTickCount = GetTickCount();
while( GetTickCount() - dwStartTickCount < 20 )
Sleep( 0 ); //Yeild among same priority thread.
m_bResuming = FALSE;
dwStartTickCount = GetTickCount();
PowerMgrCallback( FALSE );
Unlock();
return TRUE;
}
return FALSE;
}
#ifdef DEBUG
VOID CPCMSocket::DumpAllRegisters()
{
DEBUGMSG( ZONE_FUNCTION,
( TEXT( "Dumping all PCIC registers for socket %d\r\n" ),
GetSlotNumber() ) );
for( UINT8 nRegNum = 0; nRegNum < 0x40; nRegNum++ )
{
UINT8 val = PCICRegisterRead( nRegNum );
DEBUGMSG( ZONE_FUNCTION,
( TEXT( "PCIC Register %02x: %02x\r\n" ), nRegNum, val ) );
}
}
#endif DEBUG
//
// PDCardSetSocket
//
// @func STATUS | PDCardSetSocket | Set the socket state of the specified socket.
// @rdesc Returns one of the CERR_* return codes in cardserv.h.
//
// @comm This function sets the specified socket's state and adjusts the socket
// controller appropriately.
// PDCardGetSocketState will usually be called first and adjustments will
// be made to the PDCARD_SOCKET_STATE structure before PDCardSetSocketState
// is called. This avoids duplicated socket state on different layers and
// it avoids unintentionally setting socket parameters.
//
// @xref <f PDCardGetSocketState>
//
STATUS CPCMSocket::CardSetSocket( PSS_SOCKET_STATE pState )
{
Lock();
STATUS status = CERR_SUCCESS;
if( m_pBridge && pState )
{
m_SocketState.dwEventMask = pState->dwEventMask;
m_SocketState.dwEventChanged &= ~pState->dwEventChanged;
BYTE tmp = PCICRegisterRead( REG_INTERRUPT_AND_GENERAL_CONTROL ) & ( INT_RING_INDICATE_ENABLE |
INT_CARD_NOT_RESET |
0x0f );
tmp |= INT_CARD_NOT_RESET ;
if( ( pState->dwInteruptStatus & SOCK_INT_FUNC_IRQ_ROUTING ) !=
( m_SocketState.dwInteruptStatus & SOCK_INT_FUNC_IRQ_ROUTING ) )
{
if( pState->dwInteruptStatus & SOCK_INT_FUNC_IRQ_ROUTING )
{
tmp |= DATA_INT_IRQ; // enable interrupt routing
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -