📄 intr.c
字号:
} else
DEBUGMSG(ZONE_POWER|ZONE_WARNING,
(TEXT("PCMCIA:BatteryCheck: Thread already replaced\r\n")));
LeaveCriticalSection(&v_BatteryCrit);
return FALSE;
}
EnterCriticalSection(&v_BatteryCrit);
if (GetCurrentThreadId() == v_hBatteryThread[uSocket]) {
v_hBatteryThread[uSocket] = 0;
v_fBattery[uSocket] = TRUE;
bCallback = TRUE;
v_Sockets[uSocket].fFlags |= PHYS_SOCK_FLAG_POWER_ON;
} else
DEBUGMSG(ZONE_POWER|ZONE_WARNING,
(TEXT("PCMCIA:BatteryCheck: Thread already replaced\r\n")));
LeaveCriticalSection(&v_BatteryCrit);
if (bCallback) {
hSock.uSocket = uSocket;
hSock.uFunction = 0;
CallbackOne(CE_CARDSERV_LOAD, 0, NULL, hSock);
}
return TRUE;
}
//
// Function to query the user about using a PC card while on battery power.
//
// Return TRUE if the user wants to use the PC card on battery power or if the
// system is running on AC power.
//
BOOL
BatteryCheck(
UINT8 uSocket
)
{
SYSTEM_POWER_STATUS_EX PowerStatus;
DWORD dwLen;
DWORD dwValue;
dwValue = FALSE; // Set default
dwLen = sizeof(dwValue);
RegQueryValueEx(HKEY_LOCAL_MACHINE, L"NoBatteryCheck",
(LPDWORD) L"Drivers\\Pcmcia", NULL,
(LPBYTE) &dwValue, &dwLen);
if (dwValue) {
DEBUGMSG (1, (TEXT("Ignoring battery check\r\n")));
v_Sockets[uSocket].fFlags |= PHYS_SOCK_FLAG_POWER_ON;
return TRUE;
}
//
// If we are on battery power, prompt the user to see if he wants his
// battery drained (PC cards are typically very power hungry). Remember his
// response in the physical socket structure so we don't have to re-prompt
// everytime we come back from standby. The user will have to remove and
// reinsert the card with power on in order to get prompted again.
//
DEBUGMSG(ZONE_POWER, (TEXT("Before Battery Check fFlags for socket %d = %x\r\n"),uSocket,v_Sockets[uSocket].fFlags));
if (v_Sockets[uSocket].fFlags & PHYS_SOCK_FLAG_FROM_STANDBY) {
DEBUGMSG(ZONE_POWER|ZONE_STSCHG,
(TEXT("PCMCIA:BatteryCheck returning %s.\r\n"),
(v_Sockets[uSocket].fFlags & PHYS_SOCK_FLAG_POWER_ON) ?
TEXT("TRUE") : TEXT("FALSE")));
return (v_Sockets[uSocket].fFlags & PHYS_SOCK_FLAG_POWER_ON) ? TRUE:FALSE;
}
if (NULL == v_pfnGetSystemPowerStatusEx) {
DEBUGMSG(ZONE_POWER|ZONE_STSCHG,
(TEXT("PCMCIA:Couldn't getprocaddr of GetSystemPowerStatusEx\r\n")));
goto BatteryCheckExit;
}
if (v_pfnGetSystemPowerStatusEx(&PowerStatus, TRUE)) {
DEBUGMSG(ZONE_POWER|ZONE_STSCHG,
(TEXT("PCMCIA:BatteryCheck:ACLineStatus = %d\r\n"), PowerStatus.ACLineStatus));
if (PowerStatus.ACLineStatus != AC_LINE_ONLINE && !v_fBattery[uSocket]) {
HANDLE hThd;
DWORD dSocket;
if (v_hBatteryThread[uSocket] != 0) {
DEBUGMSG(ZONE_POWER|ZONE_WARNING,
(TEXT("PCMCIA:BatteryCheck: Warning! Battery Thread not NULL!\r\n")));
v_Sockets[uSocket].fFlags &= ~PHYS_SOCK_FLAG_POWER_ON;
return FALSE;
}
EnterCriticalSection(&v_BatteryCrit);
dSocket = uSocket;
hThd = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)DisplayBatteryMsg,
(LPVOID)dSocket,
0,
&v_hBatteryThread[uSocket]);
if (hThd) {
CloseHandle(hThd);
} else {
DEBUGMSG(ZONE_POWER,
(TEXT("PCMCIA:BatteryCheck: CreateThread failed %d\r\n"),
GetLastError()));
}
LeaveCriticalSection(&v_BatteryCrit);
v_Sockets[uSocket].fFlags &= ~PHYS_SOCK_FLAG_POWER_ON;
return FALSE;
/*
if (DisplayBatteryMsg(uSocket) == FALSE) {
v_Sockets[uSocket].fFlags &= ~PHYS_SOCK_FLAG_POWER_ON;
DEBUGMSG(ZONE_POWER|ZONE_STSCHG,
(TEXT("PCMCIA:BatteryCheck returning FALSE\r\n")));
return FALSE;
}
*/
}
} else {
DEBUGMSG(ZONE_POWER|ZONE_STSCHG,
(TEXT("PCMCIA:BatteryCheck:GetSystemPowerStatusEx failed %d\r\n"),
GetLastError()));
}
BatteryCheckExit:
v_Sockets[uSocket].fFlags |= PHYS_SOCK_FLAG_POWER_ON;
DEBUGMSG(ZONE_POWER|ZONE_STSCHG, (TEXT("PCMCIA:BatteryCheck TRUE-fFlag for Socket %d is %x\r\n"),uSocket,v_Sockets[uSocket].fFlags));
return TRUE;
} // BatteryCheck
//
// Function to process PCMCIA status change interrupts. When the status change
// event gets signaled, this thread will determine what caused the interrupt
// and then perform appropriate callbacks to the client drivers.
//
UINT
StatusChangeThread(
UINT Nothing
)
{
UINT16 fChanged;
UINT16 fChangeBack;
// UINT16 fPRROn;
UINT16 fCurr;
UINT uSocket;
UINT uFunction;
UINT ret;
UINT uTimeOut = INFINITE;
PDCARD_SOCKET_STATE State;
CARD_SOCKET_HANDLE hSock;
CARD_EVENT EventCode;
// UINT CallbackFlags;
UINT8 fEvents[MAX_FUNCTIONS];
UINT bChanged;
PPHYS_SOCKET pPsock;
PLOG_SOCKET pLsock;
UINT8 uPRR;
#ifdef DEBUG
TCHAR OutBuf[128];
#endif
//
// Check if we need to poll card status
//
for (uSocket = 0; uSocket < (UINT8)v_cSockets; uSocket++) {
v_fPrevEvents[uSocket] = 0;
//
// See if we need to poll for card detect and other events
// (The interrupt events are in the low byte of the fFlags field)
//
if (!(v_Sockets[uSocket].fFlags & REQUIRED_INTR_EVENTS)) {
// uTimeOut = POLL_TIMEOUT;
}
}
//
// We'll need to poll for status change if we were unable to get an interrupt
//
if (v_StatusChangeEvent == NULL) {
v_StatusChangeEvent = CreateEvent(NULL, FALSE, FALSE , NULL);
uTimeOut = POLL_TIMEOUT;
}
#ifdef DEBUG
if (uTimeOut == POLL_TIMEOUT) {
DEBUGMSG(ZONE_INIT|ZONE_STSCHG|ZONE_WARNING,
(TEXT("PCMCIA:StatusChangeThread - PCMCIA driver is resorting to polling for Status Change.\r\n")));
}
#endif
//
// Wait for PCMCIA interrupts and process them
//
while (1) {
ret = WaitForSingleObject(v_StatusChangeEvent, uTimeOut);
DEBUGMSG(ZONE_STSCHG, (TEXT("PCMCIA:StatusChangeInt signalled\r\n")));
for (uSocket = 0, pPsock = v_Sockets; uSocket < (UINT8)v_cSockets; uSocket++, pPsock++) {
if (PDCardGetSocket(uSocket, &State) != CERR_SUCCESS) {
DEBUGMSG(ZONE_STSCHG|ZONE_WARNING,
(TEXT("PCMCIA:StatusChangeInt - Unable to get status of socket %d\r\n"),
uSocket));
continue;
}
hSock.uFunction = 0;
DEBUGMSG(ZONE_STSCHG, (TEXT("PCMCIA:StatusChangeInt socket %d events = %x\r\n"),uSocket,State.fNotifyEvents));
hSock.uSocket = uSocket;
for (uFunction = 0; uFunction < MAX_FUNCTIONS; uFunction++)
fEvents[uFunction] = 0;
bChanged = FALSE;
// fPRROn = 0;
//
// Check for events which may have been caused by STSCHG -- the PDD may report
// these as battery low events, since the STSCHG pin is mapped to BVD1 in IO mode.
//
if ((State.fNotifyEvents & EVENT_MASK_CARD_DETECT) &&
(State.fNotifyEvents &
(EVENT_MASK_STATUS_CHANGE | EVENT_MASK_BATTERY_DEAD | EVENT_MASK_BATTERY_LOW))) {
//
// If card is in I/O mode, and supports a pin replacement
// register, read status from PRR. Note -- won't work for multi function cards.
//
pLsock = pPsock->pLsock;
if (pLsock == NULL) {
DEBUGMSG(ZONE_STSCHG|ZONE_WARNING,
(TEXT("PCMCIA:StatusChangeInt - Unable to get logical socket %d\r\n"),
uSocket));
} else if (v_Sockets[uSocket].PowerState != POWER_OFF &&
v_Sockets[uSocket].PowerState != POWER_KEPT &&
v_Sockets[uSocket].PowerState != POWER_RESET) {
for (; pLsock != NULL; pLsock = pLsock->Next) {
uFunction = pLsock->hSock.uFunction;
if (uFunction < 0 || uFunction >= MAX_FUNCTIONS) {
DEBUGMSG((ZONE_STSCHG|ZONE_WARNING),
(TEXT("PCMCIA:StatusChangeThread: invalid function %d\n\r"),
uFunction));
continue;
}
if ((!(pLsock->FCSR_val & FCR_FCSR_PWR_DOWN)) && // Not powered down
(pLsock->fFlags & OWNER_FLAG_CONFIG) && // IO mode
(pLsock->fRegisters & CFG_REGISTER_PIN)) {
// Using Pin Replacement Register, clear existing event mask
if (!bChanged)
State.fNotifyEvents &= ~(EVENT_MASK_STATUS_CHANGE |
EVENT_MASK_BATTERY_DEAD |
EVENT_MASK_BATTERY_LOW);
bChanged = TRUE;
CardReadAttrByte(pLsock->pRegWin,FCR_OFFSET_PRR,&uPRR);
DEBUGMSG(ZONE_STSCHG,
(TEXT("PCMCIA:StatusChangeInt: Read value 0x%X from PRR on socket %d %d\n\r"),
uPRR, uSocket, uFunction));
if (uPRR & FCR_PRR_CBVD1) {
if (!(uPRR & FCR_PRR_RBVD1)) {
fEvents[uFunction] |= (EVENT_MASK_BATTERY_DEAD & State.fInterruptEvents);
// fPRROn |= EVENT_MASK_BATTERY_DEAD;
}
uPRR &= ~FCR_PRR_CBVD1;
}
if (uPRR & FCR_PRR_CBVD2) {
if (!(uPRR & FCR_PRR_RBVD2)) {
fEvents[uFunction] |= (EVENT_MASK_BATTERY_LOW & State.fInterruptEvents);
// fPRROn |= EVENT_MASK_BATTERY_LOW;
}
uPRR &= ~FCR_PRR_CBVD2;
}
if (uPRR & FCR_PRR_CRDY) {
if (uPRR & FCR_PRR_RREADY) {
fEvents[uFunction] |= (EVENT_MASK_CARD_READY & State.fInterruptEvents);
// fPRROn |= EVENT_MASK_CARD_READY;
}
uPRR &= ~FCR_PRR_CRDY;
}
if (uPRR & FCR_PRR_CWP) {
if (uPRR & FCR_PRR_RWP) {
fEvents[uFunction] |= (EVENT_MASK_WRITE_PROTECT & State.fInterruptEvents);
// fPRROn |= EVENT_MASK_WRITE_PROTECT;
}
uPRR &= ~FCR_PRR_CWP;
}
// Clear the PRR
CardWriteAttrByte(pLsock->pRegWin,FCR_OFFSET_PRR, uPRR);
} else {
if (!(pLsock->fRegisters & CFG_REGISTER_PIN)) {
DEBUGMSG(ZONE_WARNING,
(TEXT("PCMCIA:Card doesn't support PRR (0x%X)\n\r"),
pLsock->fRegisters));
} else {
DEBUGMSG(ZONE_WARNING,
(TEXT("PCMCIA:Card not in I/O mode (fl 0x%X)\n\r"),
pLsock->fFlags));
}
}
}
}
}
//
// Determine what changed. The below XOR computes the
// bits that have changed. Then that result is ANDed with
// the bitmask of what the socket is capable of reporting.
//
fChanged = (State.fInterruptEvents|EVENT_MASK_CARD_DETECT) &
(v_fPrevEvents[uSocket] ^ State.fNotifyEvents);
fCurr = State.fNotifyEvents;
v_fChangedEvents[uSocket] = fChanged;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -