📄 intr.c
字号:
pLsock->pRegWin,
FCR_OFFSET_FCSR,
&uFSCR);
uFSCR &= ~FCR_FCSR_INTR;
uFSCR |= FCR_FCSR_INTR_ACK;
CardWriteAttrByte(pLsock->pRegWin,FCR_OFFSET_FCSR, uFSCR);
}
} // ClearFCSRInterrupt
//
// Call client driver's "ISR" in a protected manner.
//
// Return TRUE if client serviced the interrupt without problems.
//
BOOL
CallClientISR(
CARD_ISR ISRFn,
UINT32 uISRContext
)
{
BOOL ret = FALSE;
if (ISRFn) {
try {
(ISRFn)(uISRContext);
ret = TRUE;
DEBUGMSG(ZONE_IREQ,
(TEXT("PCMCIA:CallClientISR - returned from Client ISR\r\n")));
} except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
DEBUGMSG(ZONE_IREQ,
(TEXT("PCMCIA:CallClientISR - Client ISR caused an exception\r\n")));
}
}
return ret;
} // CallClientISR
//
// Function to notify all the interrupt owners of a logical socket.
//
// Return TRUE if at least one of the clients serviced the interrupt.
//
BOOL
CallClientISRs(
PLOG_SOCKET pLsock
)
{
PIREQ_OBJ pIREQ;
BOOL ret;
//
// If there are no interrupt owners, then bail.
//
if (!(pLsock->fFlags & OWNER_FLAG_INTERRUPT)) {
return FALSE;
}
ret = FALSE;
EnterCriticalSection(&v_SocketCrit);
pIREQ = pLsock->IREQList;
while (pIREQ) {
if (CallClientISR(pIREQ->ISRFn, pIREQ->uISRContext)) {
ret = TRUE;
}
pIREQ = pIREQ->Next;
}
LeaveCriticalSection(&v_SocketCrit);
return ret;
} // CallClientISRs
//
// Function to process PCMCIA "data" interrupts (IREQ). When the the IREQ event
// gets signaled, this function will determine which socket and function caused
// the interrupt and will call the associated client's "ISR" (registered with
// CardRequestIRQ).
//
UINT IREQThread(UINT Nothing)
{
PDCARD_SOCKET_STATE State;
UINT8 uFSCR;
UINT uSocket;
PLOG_SOCKET pLsock;
PPHYS_SOCKET pPsock;
BOOL bKeepIntEnabled;
BOOL stat;
BOOL bLoop;
while (1) {
stat = WaitForSingleObject(v_IREQEvent, INFINITE);
if (v_bSharedIntr) SetEvent(v_StatusChangeEvent);
do {
bLoop = FALSE;
for (uSocket = 0, pPsock = v_Sockets;
uSocket < (UINT8)v_cSockets;
uSocket++, pPsock++) {
bKeepIntEnabled = FALSE;
if (PDCardGetSocket(uSocket, &State) != CERR_SUCCESS) {
DEBUGMSG(ZONE_IREQ|ZONE_WARNING,
(TEXT("PCMCIA:IREQInt - Unable to get status of socket %d\r\n"),
uSocket));
continue;
}
//
// If sharing interrupts, check for missed card insertion/removal
//
if (v_bSharedIntr &&
(State.fNotifyEvents & EVENT_MASK_CARD_DETECT) != (v_fPrevEvents[uSocket] & EVENT_MASK_CARD_DETECT)) {
DEBUGMSG(ZONE_IREQ,
(TEXT("PCMCIA:IREQInt Current CD does not match v_fPrevEvents CD\r\n")));
SetEvent(v_StatusChangeEvent);
}
//
// Ignore if there is no card inserted.
//
if (!(State.fNotifyEvents & EVENT_MASK_CARD_DETECT) ||
v_Sockets[uSocket].PowerState == POWER_OFF ||
v_Sockets[uSocket].PowerState == POWER_RESET) {
if (State.fIREQRouting & SOCK_IREQ_ENABLE) {
DEBUGMSG(ZONE_IREQ,
(TEXT("PCMCIA:IREQInt clearing SOCK_IREQ_ENABLE for socket %d\r\n"),
uSocket));
State.fIREQRouting &= ~SOCK_IREQ_ENABLE;
PDCardSetSocket(uSocket, &State);
}
continue;
}
pLsock = pPsock->pLsock;
if (pLsock == NULL) {
if (State.fIREQRouting & SOCK_IREQ_ENABLE) {
RETAILMSG(1,
(TEXT("PCMCIA:IREQInt: Got interrupt, but no IREQ owner!!!\r\n")));
State.fIREQRouting &= ~SOCK_IREQ_ENABLE;
PDCardSetSocket(uSocket, &State);
}
continue;
}
//
// Turn on IREQ interrupt due to CardRequestIRQ or CardRequestConfiguration
//
if (!(State.fIREQRouting & SOCK_IREQ_ENABLE)) {
//
// Check each function for an interrupt owner
//
while (pLsock) {
if ((pLsock->fFlags & OWNER_FLAG_INTERRUPT) &&
(pLsock->fFlags & OWNER_FLAG_CONFIG)) {
break; // found an owner, so enable interrupts
}
pLsock = pLsock->Next;
}
if (pLsock == NULL) {
continue;
}
DEBUGMSG(ZONE_IREQ,
(TEXT("PCMCIA:IREQInt setting SOCK_IREQ_ENABLE for socket %d\r\n"),
uSocket));
State.fIREQRouting |= SOCK_IREQ_ENABLE;
PDCardSetSocket(uSocket, &State);
}
//
// Check each function to see if it interrupted
//
pLsock = pPsock->pLsock;
while (pLsock) {
if (!(pLsock->FCSR_val & FCR_FCSR_PWR_DOWN)) {
if (!(pLsock->fFlags & LOG_SOCK_FLAG_NO_INTR_ACK) &&
pLsock->fRegisters & (1 << FCR_OFFSET_FCSR)) {
CardReadAttrByte(
pLsock->pRegWin,
FCR_OFFSET_FCSR,
&uFSCR);
if (!(uFSCR & FCR_FCSR_INTR)) {
pLsock = pLsock->Next;
bKeepIntEnabled |= TRUE;
continue;
}
ClearFCSRInterrupt(pLsock);
bKeepIntEnabled |= CallClientISRs(pLsock);
bLoop = TRUE;
} else {
bKeepIntEnabled |= CallClientISRs(pLsock);
}
}
pLsock = pLsock->Next;
}
//
// If no clients are interested in interrupts for this socket, then disable them
//
if (bKeepIntEnabled == FALSE) {
DEBUGMSG(ZONE_IREQ, (TEXT("PCMCIA:IREQInt clearing SOCK_IREQ_ENABLE for socket %d\r\n"), uSocket));
State.fIREQRouting &= ~SOCK_IREQ_ENABLE;
PDCardSetSocket(uSocket, &State);
}
} // for all sockets
} while (bLoop);
InterruptDone(gIntrPcmciaLevel);
}
return 0;
// return bKeepIntEnabled;
} // IREQThread
//
// Function to display the "using a PC card on battery power" message.
//
// Return TRUE if the user wants to use the PC card on battery power
//
DWORD WINAPI
DisplayBatteryMsg(
LPVOID lpvarg
)
{
#define MAX_TITLE 100
BOOL bCallback = FALSE;
CARD_SOCKET_HANDLE hSock;
UINT uSocket = (int)lpvarg;
LPCTSTR NewCardTitle;
TCHAR TitleOut[MAX_TITLE] = TEXT("");
LPCTSTR NewCardMsg;
//
// If gwes.exe is not running yet, then can't call its API functions
//
if (v_hGwesEvent == NULL) {
v_Sockets[uSocket].fFlags |= PHYS_SOCK_FLAG_POWER_ON;
return TRUE;
}
WaitForSingleObject(v_hGwesEvent, INFINITE);
if ((v_pfnLoadStringW == NULL) || (v_pfnMessageBoxW == NULL)) {
DEBUGMSG(ZONE_POWER|ZONE_STSCHG,
(TEXT("PCMCIA:Can't find LoadString or MessageBox\r\n")));
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;
}
NewCardTitle = (LPCTSTR) v_pfnLoadStringW(g_hPcmDll,
IDS_PCMCIA_NEW_CARD_TITLE, NULL, 0);
if (NewCardTitle == 0) {
EnterCriticalSection(&v_BatteryCrit);
if (GetCurrentThreadId() == v_hBatteryThread[uSocket]) {
v_hBatteryThread[uSocket] = 0;
v_fBattery[uSocket] = FALSE;
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);
return FALSE;
}
NewCardMsg = (LPCTSTR) v_pfnLoadStringW(g_hPcmDll,
IDS_PCMCIA_NEW_CARD_MSG, NULL, 0);
if (NewCardMsg == 0) {
EnterCriticalSection(&v_BatteryCrit);
if (GetCurrentThreadId() == v_hBatteryThread[uSocket]) {
v_hBatteryThread[uSocket] = 0;
v_fBattery[uSocket] = FALSE;
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);
return FALSE;
}
if (_tcslen(NewCardTitle) < MAX_TITLE) {
//
// There's enough room to copy the formatted title, else use empty string.
//
wsprintf(TitleOut, NewCardTitle, uSocket+1);
} else {
DEBUGMSG(1, (TEXT("PCMCIA:Title string too long! (%a @ %d)\r\n"), __FILE__, __LINE__));
}
if (v_pfnMessageBoxW(NULL, NewCardMsg, TitleOut,
MB_YESNO|MB_SETFOREGROUND|MB_TOPMOST|MB_DEFBUTTON2) != IDYES) {
EnterCriticalSection(&v_BatteryCrit);
if (GetCurrentThreadId() == v_hBatteryThread[uSocket]) {
v_hBatteryThread[uSocket] = 0;
v_fBattery[uSocket] = FALSE;
v_Sockets[uSocket].fFlags &= ~PHYS_SOCK_FLAG_POWER_ON;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -