📄 config.c
字号:
//
// 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:
config.c
Abstract:
This file implements the PCMCIA model device driver socket configuration
functions. This is provided as a sample to platform writers and is
expected to be able to be used without modification on most (if not
all) hardware platforms.
Functions:
FindPowerEntry()
CardRequestConfiguration()
CardReleaseConfiguration()
PowerUp()
PowerDown()
PcmciaPowerOn()
PcmciaPowerOff()
CardAccessConfigurationRegister()
Notes:
--*/
#include <windows.h>
#include <types.h>
#include <cardserv.h>
#include <sockserv.h>
#include <pcmcia.h>
#include <nkintr.h>
#include <extern.h>
#define BAD_VOLTAGE_INDEX 0xff
#define NUM_REGISTERS 5 // number of function configuration registers
#define NUM_EXT_REGISTERS 4 // number of additional function configuration registers
DWORD v_SysIntrWake = 0; // SysIntr for wake on CD changes
DWORD v_FuncSysIntrWake = 0;// SysIntr for wake on functional interrupt
//
// Find the power entry index that matches the voltage and supply specified.
//
UINT8
FindPowerEntry(
UINT fSupply,
UINT8 uVoltage
)
{
UINT8 i;
PPDCARD_POWER_ENTRY pPwr = (PPDCARD_POWER_ENTRY)(((PCHAR)v_pAdapterInfo) +
sizeof(PDCARD_ADAPTER_INFO));
for (i = 0; i < v_pAdapterInfo->uPowerEntries; i++, pPwr++) {
if ((pPwr->uPowerLevel == uVoltage) && (pPwr->fSupply & fSupply)) {
return i;
}
}
return BAD_VOLTAGE_INDEX;
}
// Use the stored information in the PHYS_WINDOW struct to restore the window state of a socket
STATUS
RestoreWindowState(
UINT uSocket
)
{
STATUS status = CERR_SUCCESS;
PPHYS_WINDOW pPhys;
PDCARD_WINDOW_STATE WinState;
for (pPhys = v_pWinList; pPhys != NULL; pPhys = pPhys->Next) {
if (pPhys->uSock != uSocket) continue;
if ((status = PDCardGetWindow(pPhys->uWindow, &WinState)) != CERR_SUCCESS)
break;
WinState.uSize = pPhys->uSize;
WinState.uOffset = pPhys->uOffset;
if (pPhys->fFlags & PHYS_WIN_FLAG_ENABLED) {
WinState.fState |= WIN_STATE_ENABLED;
} else {
WinState.fState &= ~WIN_STATE_ENABLED;
}
if (pPhys->fFlags & PHYS_WIN_FLAG_ATTR_MODE) {
WinState.fState |= WIN_STATE_ATTRIBUTE;
} else {
WinState.fState &= ~WIN_STATE_ATTRIBUTE;
}
#ifndef SH4
if (pPhys->fFlags & PHYS_WIN_FLAG_16BIT_MODE) {
WinState.fState |= WIN_STATE_16BIT;
} else {
WinState.fState &= ~WIN_STATE_16BIT;
}
#endif
if ((status = PDCardSetWindow(pPhys->uWindow, &WinState)) != CERR_SUCCESS)
break;
}
return status;
}
//
// Configure the logical socket
//
STATUS
ConfigureLogSock(
PLOG_SOCKET pLsock
)
{
PDCARD_SOCKET_STATE State;
STATUS status;
PUINT8 pRegVal;
UINT i;
PLOG_SOCKET pTmp;
BOOL bIRQ, bPwr;
status = PDCardGetSocket(pLsock->hSock.uSocket, &State);
if (status) {
DEBUGMSG(ZONE_WARNING,
(TEXT("PCMCIA:ConfigureLogSock PDCardGetSocket failed %d\r\n"),
status));
return status;
}
// Socket is non-powered
if (pLsock->FCSR_val & FCR_FCSR_PWR_DOWN)
return CERR_SUCCESS;
bIRQ = bPwr = FALSE;
EnterCriticalSection(&v_SocketCrit);
for (pTmp = v_Sockets[pLsock->hSock.uSocket].pLsock; pTmp != NULL; pTmp = pTmp->Next) {
if (pTmp->fFlags & LOG_SOCK_FLAG_KEEP_POWERED) {
bPwr = TRUE;
State.fSocketCaps |= SOCK_CAP_KEEP_POWERED;
}
if (pTmp->fFlags & LOG_SOCK_FLAG_IRQ_WAKEUP) {
bIRQ = TRUE;
State.fIREQRouting |= SOCK_IREQ_WAKEUP;
}
}
LeaveCriticalSection(&v_SocketCrit);
if (!bIRQ) State.fSocketCaps &= ~SOCK_CAP_KEEP_POWERED;
if (!bPwr) State.fIREQRouting &= ~SOCK_IREQ_WAKEUP;
State.fVcc = pLsock->fVcc;
State.uVpp1 = pLsock->uVpp1;
State.uVpp2 = pLsock->uVpp2;
State.fInterfaceType = pLsock->fInterfaceType;
State.fControlCaps |= pLsock->fControlCaps;
status = PDCardSetSocket(pLsock->hSock.uSocket, &State);
if (status) {
DEBUGMSG(ZONE_WARNING,
(TEXT("PCMCIA:CardRequestConfiguration PDCardSetSocket failed %d\r\n"),
status));
return status;
}
// Don't want to reset the socket
pLsock->COR_val &= ~FCR_COR_SRESET;
if (pLsock->pRegWin != NULL) {
pRegVal = &(pLsock->COR_val);
for (i = 0; i < (NUM_REGISTERS + NUM_EXT_REGISTERS); i++) {
if (pLsock->fCfgRegisters & (1 << i)) {
CardWriteAttrByte(pLsock->pRegWin, i, *pRegVal);
}
pRegVal++;
}
}
return status;
}
void DisableCSCWake()
{
int i;
PLOG_SOCKET pLsock;
// check if CSC is not a wake source
if (v_SysIntrWake == 0) return;
for (i = 0; i < v_cSockets; i++) {
if (!(v_Sockets[i].fFlags & PHYS_SOCK_FLAG_NOT_USER_ACCESS)) {
EnterCriticalSection(&v_SocketCrit);
// Check for:
// log sockets that don't want to unload on resume
// non-powered down log sockets that want IRQ wakeup
for (pLsock = v_Sockets[i].pLsock; pLsock != NULL; pLsock = pLsock->Next) {
if ((pLsock->fFlags & LOG_SOCK_FLAG_NO_SUSPEND_UNLOAD) ||
((pLsock->fFlags & LOG_SOCK_FLAG_IRQ_WAKEUP) &&
!(pLsock->FCSR_val & FCR_FCSR_PWR_DOWN)))
break;
}
LeaveCriticalSection(&v_SocketCrit);
if (pLsock != NULL) break;
}
}
// If no accessible sockets want NO_SUSPEND_UNLOAD or IRQ_WAKEUP
// we can sleep on card insertion/removal
if (i == v_cSockets) {
if (v_SysIntrWake == v_FuncSysIntrWake ||
KernelIoControl(IOCTL_HAL_DISABLE_WAKE, &v_SysIntrWake, sizeof(v_SysIntrWake), NULL, 0, NULL)) {
v_SysIntrWake = 0;
}
}
}
void DisableIRQWake()
{
int i;
PLOG_SOCKET pLsock;
// check if CSC is not a wake source
if (v_FuncSysIntrWake == 0) return;
EnterCriticalSection(&v_SocketCrit);
for (i = 0; i < v_cSockets; i++) {
// Check for non-powered down log socks that want IRQ wakeup
for (pLsock = v_Sockets[i].pLsock; pLsock != NULL; pLsock = pLsock->Next) {
if ((pLsock->fFlags & LOG_SOCK_FLAG_IRQ_WAKEUP) &&
!(pLsock->FCSR_val & FCR_FCSR_PWR_DOWN))
break;
}
if (pLsock != NULL) break;
}
LeaveCriticalSection(&v_SocketCrit);
// If no sockets want IRQ_WAKEUP, we can sleep on functional interrupts
if (i == v_cSockets) {
if (v_SysIntrWake == v_FuncSysIntrWake ||
KernelIoControl(IOCTL_HAL_DISABLE_WAKE, &v_FuncSysIntrWake, sizeof(v_FuncSysIntrWake), NULL, 0, NULL)) {
v_FuncSysIntrWake = 0;
}
}
}
BOOL EnableCSCWake(UINT uSocket)
{
if (v_SysIntrWake == 0 &&
!(v_Sockets[uSocket].fFlags & PHYS_SOCK_FLAG_NOT_USER_ACCESS)) {
if (gIntrPcmciaState != 0 &&
KernelIoControl(IOCTL_HAL_ENABLE_WAKE, &gIntrPcmciaState, sizeof(gIntrPcmciaState), NULL, 0, NULL)) {
v_SysIntrWake = gIntrPcmciaState;
} else {
return FALSE;
}
}
return TRUE;
}
BOOL EnableIRQWake()
{
if (v_FuncSysIntrWake == 0) {
if (KernelIoControl(IOCTL_HAL_ENABLE_WAKE, &gIntrPcmciaLevel, sizeof(gIntrPcmciaLevel), NULL, 0, NULL)) {
v_FuncSysIntrWake = gIntrPcmciaLevel;
}
}
return (v_SysIntrWake != 0);
}
//
// CardModifyConfiguration
//
// @doc DRIVERS
//
// @func STATUS | CardModifyConfiguration | Configure socket and PC card interface type and voltage.
// @rdesc Returns one of CERR_SUCCESS, CERR_BAD_HANDLE, CERR_BAD_SOCKET, CERR_IN_USE, CERR_BAD_ARGS
//
// @comm Change the fAttributes bits on an already existing configuration
// Currently can only change CFG_ATTR_IRQ_WAKEUP, CFG_ATTR_KEEP_POWERED, and
// CFG_ATTR_NO_SUSPEND_UNLOAD
// @xref <f CardRequestConfiguration> <f CardReleaseConfiguration>
//
STATUS
CardModifyConfiguration(
CARD_CLIENT_HANDLE hCardClient, // @parm Handle from <f CardRegisterClient>
CARD_SOCKET_HANDLE hSock, // @parm Socket/function identifier
PUINT16 fAttributes
)
{
PLOG_SOCKET pLsock, pTmp;
STATUS status = CERR_SUCCESS;
PCLIENT_DRIVER pClient;
BOOL bCSC = FALSE, bIRQ = FALSE;
PDCARD_SOCKET_STATE State;
DEBUGMSG(ZONE_FUNCTION, (TEXT("PCMCIA:CardModifyConfiguration entered\r\n")));
pLsock = I_FindSocket(hSock);
if (pLsock == NULL || !(pLsock->fFlags & OWNER_FLAG_CONFIG)) {
status = CERR_BAD_SOCKET;
goto mod_cfg_err_exit;
}
if (hCardClient == NULL ||
(pClient = FindClient(hCardClient, TRUE, TRUE)) == NULL) {
status = CERR_BAD_HANDLE;
goto mod_cfg_err_exit;
} else if (pLsock->hOwner != pClient) {
status = CERR_IN_USE;
goto mod_cfg_err_exit;
}
if (fAttributes == NULL) {
status = CERR_BAD_ARGS;
goto mod_cfg_err_exit;
}
//
// Attempt to set functional interrupts as a wake source
//
if (*fAttributes & CFG_ATTR_IRQ_WAKEUP) {
if (!(pLsock->fFlags & LOG_SOCK_FLAG_IRQ_WAKEUP)) {
pLsock->fFlags |= LOG_SOCK_FLAG_IRQ_WAKEUP;
// Try to make insertion/removal a wake source if it isn't already,
bCSC = FALSE;
if (!EnableCSCWake(hSock.uSocket)) {
pLsock->fFlags &= ~LOG_SOCK_FLAG_IRQ_WAKEUP;
*fAttributes &= ~CFG_ATTR_IRQ_WAKEUP;
goto mod_cfg_irqw1;
}
// Try to make IRQs a wake source if it isn't already,
if (!EnableIRQWake()) {
pLsock->fFlags &= ~LOG_SOCK_FLAG_IRQ_WAKEUP;
*fAttributes &= ~CFG_ATTR_IRQ_WAKEUP;
bCSC = TRUE;
goto mod_cfg_irqw1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -