📄 pcmsock.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
/*++
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:
Plato PCMCIA Socket Services Object for PCMCIA(16-bit) Interface.
Notes:
--*/
#include <windows.h>
#include <types.h>
#include <socksv2.h>
#include <cardsv2.h>
#include <memory.h>
#include <ceddk.h>
#include <xllp_defs.h>
#define ZONE_SOCKET ZONE_PDD
#include "pdsocket.h"
//--------------------Pcmcia Socket Implementation--------------------------------------------
const SS_SOCKET_INFO CPcmciaCardSocket::ms_SocketInitInfo =
{
SOCK_CAP_IO_MEMORY_CARD,
SOCK_CAP_PWRCYCLE |
SOCK_CAP_CD |
SOCK_CAP_BVD1 |
SOCK_CAP_BVD2, // Socket Interrupt Capability Set follow bitmap.
SOCK_CAP_PWRCYCLE |
SOCK_CAP_CD |
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.
Isa, // PCCARD Bus Type is ISA/built-in.
( DWORD ) -1, // CardBus Card Number.
{ - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}
};
const SS_SOCKET_STATE CPcmciaCardSocket::ms_SocketInitState =
{
SOCK_EVENT_PWRCYCLE |
SOCK_EVENT_CD |
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
};
void CPcmciaCardSocket::SocketEventHandle( DWORD dwStatesChange, DWORD dwStates )
{
SS_SOCKET_STATE sSockState;
Lock();
CardGetSocket( &sSockState );
sSockState.dwEventChanged |= dwStatesChange;
sSockState.dwEventStatus |= dwStates;
sSockState.dwEventChanged &= ~( SOCK_EVENT_CD );
m_SockState.dwEventChanged = sSockState.dwEventChanged;
Unlock();
m_pBridge->CallBackToCardService(m_pBridge->GetSocketNumber(), GetSocketHandle(), &sSockState);
}
CPcmciaCardSocket::CPcmciaCardSocket(CPcmciaBusBridge* pBridge, UINT16 nSlotNumber) : CPCMCIASocketBase<CStaticMemoryWindow<CPcmciaCardSocket>, CStaticIOWindow<CPcmciaCardSocket>, CStaticWindowBridgeContainer<CPcmciaBusBridge>, CPcmciaBusBridge>( pBridge )
{
DWORD dwPowerOption = 0;
DEBUGMSG(ZONE_SOCKET, (TEXT("+CPcmciaCardSocket::CPcmciaCardSocket\r\n")));
m_pBridge = pBridge;
m_SockState = ms_SocketInitState;
m_PcmciaSocketInfo = ms_SocketInitInfo;
for( DWORD dwIndex = 0; dwIndex < IRQ_ROUTINGTABLE_SIZE; dwIndex++ )
{
m_PcmciaSocketInfo.bArrayIrqRouting[dwIndex] = (BYTE) pBridge->GetFunctionIrq();
}
m_PcmciaSocketInfo.dwNumOfPowerEntry = NUM_POWER_ENTRIES;
m_PcmciaSocketInfo.dwNumOfWindows = pBridge->GetMemWindowCount() +
pBridge->GetIoWindowCount();
m_PcmciaSocketInfo.dwBusNumber = 0;
m_bResuming = FALSE;
if(pBridge->GetRegPowerOption(&dwPowerOption))
{
m_SockState.dwInteruptStatus |= ((dwPowerOption & REG_POWER_KEEP_DRIVER) !=
0 ?
SOCK_INT_STATUS_CHG_WAKE :
0 );
m_SockState.dwInteruptStatus |= ((dwPowerOption & REG_POWER_KEEP_POWER) !=
0 ?
(SOCK_INT_STATUS_CHG_WAKE |
SOCK_INT_FUNC_IRQ_WAKE) :
0);
}
if((m_SockState.dwInteruptStatus & SOCK_INT_STATUS_CHG_WAKE) != 0)
{
m_pBridge->SetupWakeupSource((m_SockState.dwInteruptStatus & SOCK_INT_STATUS_CHG_WAKE) !=
0 );
}
// Map device registers.
//
if (!MapDeviceRegisters(pBridge))
{
RETAILMSG(TRUE, (TEXT("ERROR: CPcmciaCardSocket: MapDeviceRegisters failed.\r\n")));
return;
}
// Get a unique socket index value to be used as the socket handle.
m_dwSocketIndex = 0;
while(m_dwSocketIndex == 0)
{
m_dwSocketIndex = ( DWORD )
InterlockedIncrement( ( LONG * ) &m_dwSocketLastIndex );
//Make sure it does not already exist.
CPcmciaCardSocket* pSocket = GetSocket( ( HANDLE ) m_dwSocketIndex );
if( pSocket != NULL )
{
// Duplicated, retry.
m_dwSocketIndex = 0;
pSocket->DeRef();
}
}
DEBUGMSG(ZONE_SOCKET, (TEXT("-CPcmciaCardSocket::CPcmciaCardSocket\r\n")));
}
CPcmciaCardSocket::~CPcmciaCardSocket()
{
DEBUGMSG(ZONE_SOCKET, (TEXT("+CPcmciaCardSocket::Deinitialize()\r\n")));
Lock();
m_pBridge->SetupWakeupSource(FALSE );
BOOL bInitWindow = CardDeInitWindow();
DEBUGCHK( bInitWindow );
Unlock();
DEBUGMSG(ZONE_SOCKET, (TEXT("-CPcmciaCardSocket::Deinitialize()\r\n")));
}
BOOL CPcmciaCardSocket::MapDeviceRegisters(CPcmciaBusBridge* pBridge)
{
m_pGPIORegs = pBridge->m_pGPIORegs;
m_pMemCtrlRegs = pBridge->m_pMemCtrlRegs;
m_strPCCardSocketHandle.pstrGpioRegsHandle = (XLLP_GPIO_T *) m_pGPIORegs;
m_strPCCardSocketHandle.pstrMemCtrlRegsHandle = (XLLP_MEMORY_CONTROL_REGISTER_T *) m_pMemCtrlRegs;
m_pstrPCCardSocketHandle = &m_strPCCardSocketHandle;
return(TRUE);
}
//
// 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 CPcmciaCardSocket::CardGetSocket( PSS_SOCKET_STATE pState )
{
DEBUGMSG( ZONE_SOCKET, ( TEXT( "+CPcmciaCardSocket::GetSocket()\r\n" ) ) );
Lock();
if( pState )
{
m_SockState.dwEventStatus = SOCK_EVENT_CD | SOCK_EVENT_READY;
m_SockState.dwEventChanged |= 0;
*pState = m_SockState;
DEBUGMSG( ZONE_SOCKET,
( TEXT( "-CPcmciaCardSocket::GetSocket(): dwEventMask: %x dwEventChanged: %x dwEventStatus: %x\r\n" ),
pState->dwEventMask,
pState->dwEventChanged,
pState->dwEventStatus ) );
}
Unlock();
return CERR_SUCCESS;
}
void CPcmciaCardSocket::PowerMgrCallback( BOOL bPowerOff )
{
SS_SOCKET_STATE sSocketState = m_SockState;
sSocketState.dwEventChanged = SOCK_EVENT_SUSPEND_RESUME;
sSocketState.dwEventStatus = (bPowerOff ?
SOCK_EVENT_CD :
(SOCK_EVENT_CD |
SOCK_EVENT_SUSPEND_RESUME ) );
m_pBridge->CallBackToCardService(m_pBridge->GetSocketNumber(),
GetSocketHandle(),
&sSocketState );
}
void CPcmciaCardSocket::PowerMgr( BOOL bPowerDown )
{
RETAILMSG(TRUE, (TEXT("CPcmciaCardSocket::PowerMgr: calling PowerMgrCallback(%s).\r\n"), bPowerDown ? TEXT("TRUE") : TEXT("FALSE")));
PowerMgrCallback( bPowerDown );
}
BOOL CPcmciaCardSocket::Resuming() // This routine can not call sleep because it could endup yeild to other thread.
{
return(FALSE);
}
//
// 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 CPcmciaCardSocket::CardSetSocket(PSS_SOCKET_STATE pState)
{
STATUS retValue = CERR_SUCCESS;
if(m_pBridge && pState)
{
Lock();
// Indicate to the memory controller that a card is present in the socket.
//
// Done in InitializeBridgeHw since card always present
// m_pMemCtrlRegs->mecr = 0x00000002;
m_SockState.dwEventMask = pState->dwEventMask;
m_SockState.dwEventChanged &= ~pState->dwEventChanged;
//
// Check the power settings for the socket.
//
if( ( pState->dwEventStatus & SOCK_EVENT_EJECT ) != 0 ||
( pState->dwEventStatus & SOCK_EVENT_INSERT ) != 0 )
{
// Ask for ejection of the card.
DEBUGMSG( ZONE_PDD,
( TEXT( "PDCardSetSocket PCMSocket. Gernerate Artificial Eject\r\n" ) ) );
// We have to force
m_pBridge->ForceEjectEvent(m_pBridge->GetSlotNumber());
}
else
if ((pState->fVcc != m_SockState.fVcc) ||
(pState->uVpp1 != m_SockState.uVpp1)||
(pState->uVpp2 != m_SockState.uVpp2))
{
// We don't support changing Vpp.
if (pState->uVpp1 != pState->uVpp2 ||
m_SockState.uVpp1 != pState->uVpp1 ||
m_SockState.uVpp2 != pState->uVpp2)
{
Unlock();
return(CERR_BAD_VPP);
}
if ((pState->fVcc & SOCK_VCC_LEVEL_MASK ) >= NUM_POWER_ENTRIES ||
!(m_rgPowerEntries[pState->fVcc & SOCK_VCC_LEVEL_MASK].fSupply & PWR_SUPPLY_VCC))
{
Unlock();
return (CERR_BAD_VCC);
}
else
{
retValue = CardPowerHandler(m_rgPowerEntries[pState->fVcc & SOCK_VCC_LEVEL_MASK].uPowerLevel);
if (retValue == CERR_SUCCESS)
{
m_SockState.fVcc = pState->fVcc;
m_SockState.uVpp1 = pState->uVpp1;
m_SockState.uVpp2 = pState->uVpp2;
}
}
}
Unlock();
}
return (STATUS)retValue;
}
STATUS CPcmciaCardSocket::CardPowerHandler(UINT8 nVcc)
{
XLLP_STATUS_T retValue = XLLP_STATUS_FAILURE;
XLLP_UINT32_T pins[3];
switch(nVcc)
{
case 0: // Off
if(m_pBridge->GetSlotNumber() == 0)
{
DEBUGMSG(TRUE, (TEXT("CPcmciaCardSocket::CardPowerHandler: Forcing WiFi chip to Power Down state.\r\n")));
pins[0] = 1; //number of pins in array
pins[1] = WIFI_POWER_DOWN_PIN; //pin to modify
XllpGpioSetOutput0(m_strPCCardSocketHandle.pstrGpioRegsHandle, pins);
retValue = XLLP_STATUS_SUCCESS;
}
break;
case 33: // 3.3v
if (m_pBridge->GetSlotNumber() == 0)
{
DEBUGMSG(TRUE, (TEXT("CPcmciaCardSocket::CardPowerHandler: Bringing WiFi chip out of Power Down state.).\r\n")));
pins[0] = 1; //number of pins in array
pins[1] = WIFI_POWER_DOWN_PIN; //pin to modify
XllpGpioSetOutputState1(m_strPCCardSocketHandle.pstrGpioRegsHandle, pins);
retValue = XLLP_STATUS_SUCCESS;
}
break;
default:
break;
}
return((retValue == XLLP_STATUS_SUCCESS) ? CERR_SUCCESS : CERR_BAD_VCC);
}
void CPcmciaCardSocket::PowerCycleEvent()
{
m_pBridge->PowerCycleEvent(m_pBridge->GetSlotNumber());
}
//
// ResetSocket - do a PCMCIA reset
// return CERR_SUCCESS on success, CERR_UNSUPPORTED_SERVICE if size is anomolous
//
STATUS CPcmciaCardSocket::CardResetSocket()
{
STATUS retValue = CERR_SUCCESS;
XLLP_UINT32_T pins[3];
BOOL fRollover = FALSE;
DWORD dwTimoutCount = 0;
Lock();
if( m_pBridge )
{
DEBUGMSG(1, (_T("CPcmciaCardSocket::CardResetSocket: Resetting Plato WIFI hardware\r\n")));
//reset the chip
pins[0] = 1; //number of pins in array
pins[1] = WIFI_RESET_PIN; //pin to modify
XllpGpioSetOutputState1(m_strPCCardSocketHandle.pstrGpioRegsHandle, pins);
//hold reset low for at least 10uSec
Sleep(0);
//disable reset
XllpGpioSetOutput0(m_strPCCardSocketHandle.pstrGpioRegsHandle, pins);
//poll WIFI_IRQ_PIN until Power On Self Test is over
dwTimoutCount = GetTickCount();
fRollover = ((dwTimoutCount +1000) < dwTimoutCount)?TRUE:FALSE;
dwTimoutCount += 1000;
while(1)
{
Sleep(1);
if(fRollover)
{
if(GetTickCount() <= dwTimoutCount)
{
fRollover = FALSE;
}
}
else
{
if(GetTickCount() > dwTimoutCount)
{
RETAILMSG(1, (_T("SetupPlatoWiFiHardware: Timeout waiting for Power On Self Test\r\n")));
break;
}
if(XllpGpioGetState(m_strPCCardSocketHandle.pstrGpioRegsHandle, WIFI_IRQ_PIN))
{
//out of post mode
break;
}
}
}
m_SockState.fVcc = 1; //XLLP_PCCARD_3_30VOLTS
m_SockState.uVpp1 = 0;
m_SockState.uVpp2 = 0;
// Notify the MDD of a power-on status change.
SocketEventHandle(SOCK_EVENT_PWRCYCLE, SOCK_EVENT_PWRCYCLE);
}
Unlock();
return (retValue);
}
CPcmciaCardSocket* CreatePCMCIASocket(CPcmciaBusBridge* pBridge,
UINT16 m_SlotNumber )
{
CPcmciaCardSocket* pNewSocket = new CPcmciaCardSocket(pBridge, m_SlotNumber);
if( pNewSocket != NULL )
{
if( pNewSocket->CardInitWindow( pNewSocket ) )
{
return pNewSocket;
}
else
{
delete pNewSocket;
}
}
return NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -