📄 callback.c
字号:
for (pLsock = v_Sockets[pEvent->hSock.uSocket].pLsock; pLsock != NULL; pLsock = pLsock->Next) {
if (!(pLsock->fFlags & LOG_SOCK_FLAG_NO_SUSPEND_UNLOAD)) {
bUnloadDriver = TRUE;
break;
}
}
}
#if 0
// Check the PnP ID to determine if it's the same card
// ...assuming that it is the same card, since either card is non-user accessible
// or should have been woken on removal
if (!bUnloadDriver) {
LPTSTR pch;
pch = v_Sockets[pEvent->hSock.uSocket].pDevId;
if (CreateDeviceID(pEvent->hSock.uSocket, FALSE) != CERR_SUCCESS) {
bUnloadDriver = TRUE;
} else {
bUnloadDriver = _tcscmp(v_Sockets[pEvent->hSock.uSocket].pDevId, pch);
}
if (v_Sockets[pEvent->hSock.uSocket].pDevId != NULL)
free(v_Sockets[pEvent->hSock.uSocket].pDevId);
v_Sockets[pEvent->hSock.uSocket].pDevId = pch;
}
#endif
// Reconfigure the sockets
if (!bUnloadDriver) {
v_Sockets[pEvent->hSock.uSocket].PowerState = POWER_RESET;
v_Sockets[pEvent->hSock.uSocket].fFlags |= PHYS_SOCK_FLAG_RESETTING;
Sleep(750); // sleep required
for (pLsock = v_Sockets[pEvent->hSock.uSocket].pLsock; pLsock != NULL; pLsock = pLsock->Next) {
if (ConfigureLogSock(pLsock) != CERR_SUCCESS) {
bUnloadDriver = TRUE;
PcmciaPowerOff(
pEvent->hSock.uSocket,
TRUE,
(CARD_CLIENT_HANDLE)CARDSERV_CLIENT_HANDLE);
break;
}
}
}
if (bUnloadDriver) {
v_Sockets[pEvent->hSock.uSocket].fFlags &= ~PHYS_SOCK_FLAG_RESETTING;
CardServFreeDriver(pEvent->hSock.uSocket);
DeleteFunctions(pEvent->hSock.uSocket);
PDCardGetSocket(pEvent->hSock.uSocket, &State);
State.fInterruptEvents = INITIAL_SOCKET_EVENTS;
PDCardSetSocket(pEvent->hSock.uSocket, &State);
//
// If this removal notice was due to a power on/off event,
// then change to the ON power state and signal the
// StatusChangeThread again causing insertion notices to
// be sent for any inserted cards.
//
}
if (v_Sockets[pEvent->hSock.uSocket].PowerState == POWER_OFF ||
v_Sockets[pEvent->hSock.uSocket].PowerState == POWER_KEPT) {
if (!(v_Sockets[pEvent->hSock.uSocket].fFlags & PHYS_SOCK_FLAG_RESETTING))
v_Sockets[pEvent->hSock.uSocket].PowerState = POWER_ON;
DEBUGMSG(ZONE_STSCHG,
(TEXT("PCMCIA:CE_CARD_REMOVAL signal StatusChangeThread PowerState for Socket %d changed to %x\r\n"),pEvent->hSock.uSocket,v_Sockets[pEvent->hSock.uSocket].PowerState));
// Signal IREQThread, so that interrupts can continue
// (Interrupts may have been disabled while PowerState was POWER_OFF)
SetEvent(v_StatusChangeEvent);
SetEvent(v_IREQEvent);
} else if (v_Sockets[pEvent->hSock.uSocket].PowerState == POWER_RESET) {
v_Sockets[pEvent->hSock.uSocket].PowerState = POWER_ON;
DEBUGMSG(ZONE_STSCHG,
(TEXT("PCMCIA:CE_CARD_REMOVAL signal StatusChangeThread PowerState for Socket %d changed to %x\r\n"),pEvent->hSock.uSocket,v_Sockets[pEvent->hSock.uSocket].PowerState));
// Signal IREQThread, so that interrupts can continue
// (Interrupts may have been disabled while PowerState was POWER_OFF)
SetEvent(v_StatusChangeEvent);
SetEvent(v_IREQEvent);
} else {
PcmciaPowerOff(
pEvent->hSock.uSocket,
TRUE,
(CARD_CLIENT_HANDLE)CARDSERV_CLIENT_HANDLE);
}
CallbackPmResume();
goto cbt_next1;
}
if (!(pClient = FindClient(pEvent->pDestClient, TRUE, FALSE))) {
DEBUGMSG(ZONE_CALLBACK|ZONE_WARNING,
(TEXT("PCMCIA:CallbackThread: Invalid destination client!\r\n")));
//
// If this is the last event in a sequence, then there may be
// more processing to do.
//
if (pEvent->fFlags & CALLBACK_FLAG_LAST) {
goto cbt_process_last;
} else {
goto cbt_next1;
}
}
Parms.uClientData = pClient->Parms.uClientData; // supply context
//
// Fill in parameters based on event code
//
switch (pEvent->SubEvent) {
case CE_CARD_INSERTION:
// If device ID is NULL, the card's been pulled.
// Skip the callback, and do the insertion cleanup
if (v_Sockets[pEvent->hSock.uSocket].pDevId == NULL) {
goto cbt_end_insert;
}
Parms.Parm1 = (UINT)v_Sockets[pEvent->hSock.uSocket].pDevId;
Parms.Parm2 = (UINT)pClient->hClient;
break;
case CE_REGISTRATION_COMPLETE:
Parms.Parm1 = (UINT)pClient->hClient;
Parms.Parm2 = 0;
break;
case CE_PM_RESUME:
for (i = 0; i < (UINT8)v_cSockets; i++) {
DEBUGMSG(ZONE_CALLBACK,
(TEXT("CE_PM_RESUME Socket %d PowerState = %x fFlags = %x\r\n"),i,v_Sockets[i].PowerState,v_Sockets[i].fFlags));
v_Sockets[i].PowerState = POWER_NORMAL;
v_Sockets[i].fFlags &= ~PHYS_SOCK_FLAG_FROM_STANDBY;
}
break;
default:
Parms.Parm1 = 0;
Parms.Parm2 = 0;
break;
}
#ifdef DEBUG
MajorName = FindEventName(pEvent->MajorEvent);
SubName = FindEventName(pEvent->SubEvent);
DEBUGMSG(ZONE_CALLBACK,
(TEXT("PCMCIA:CallbackThread: %d:%d MajorEvent=%s, SubEvent=%s\r\n"),
pEvent->hSock.uSocket, pEvent->hSock.uFunction, MajorName, SubName));
#endif // DEBUG
//
// Callback the client
//
status = CallClient(
pClient->CallBackFn,
pEvent->SubEvent,
pEvent->hSock,
&Parms,
pClient);
cbt_fail_query:
if ((status) && (pEvent->fFlags & CALLBACK_FLAG_QUERY)) {
//
// One of the client drivers rejected a query request. Remove
// all events associated with the failing one.
// If this is the last one in the current stage, then there is
// nothing to clean up.
//
if (!(pEvent->fFlags & CALLBACK_FLAG_LAST)) {
RemoveCallbacks(
FindClient(pEvent->pReqClient, TRUE, TRUE),
pEvent->hSock,
pEvent->MajorEvent,
REMOVE_QUERY);
}
//
// Report to the requesting client that the request was denied
//
switch (pEvent->MajorEvent) {
case CE_EXCLUSIVE_REQUEST:
NextEvent = CE_EXCLUSIVE_COMPLETE;
break;
/* These events are not implemented yet
case CE_EJECTION_REQUEST:
NextEvent = CE_EJECTION_COMPLETE;
break;
case CE_INSERTION_REQUEST:
NextEvent = CE_INSERTION_COMPLETE;
break;
*/
default:
NextEvent = 0;
break;
}
if (NextEvent) {
Parms.uClientData = FindClient(pEvent->pReqClient, TRUE, TRUE)->Parms.uClientData; // supply context
Parms.Parm1 = status;
CallClient(
FindClient(pEvent->pReqClient, TRUE, TRUE)->CallBackFn,
NextEvent,
pEvent->hSock,
&Parms,
FindClient(pEvent->pReqClient, TRUE, TRUE));
}
// end of callback request failure case
} else {
//
// If this is the last event in the current stage then figure
// out what to do next.
//
if (pEvent->fFlags & CALLBACK_FLAG_LAST) {
cbt_process_last:
NextEvent = 0; // assume nothing to do next
fCallAll = FALSE; // assume only one client
switch (pEvent->MajorEvent) {
//
// Finish CardRegisterClient callback sequence
//
case CE_REGISTRATION_COMPLETE:
if (pEvent->SubEvent == CE_CARD_INSERTION) {
NextEvent = CE_REGISTRATION_COMPLETE;
//
// Shut down power to the PCMCIA interfaces if they
// are not in use.
//
for (i = 0; i < (UINT)v_cSockets; i++) {
PcmciaPowerOff(
i,
FALSE,
(CARD_CLIENT_HANDLE)CARDSERV_CLIENT_HANDLE);
}
}
break;
//
// Figure out the next stage of the callback sequence for
// CardRequestExclusive
//
case CE_EXCLUSIVE_REQUEST:
switch (pEvent->SubEvent) {
//
// If all clients approved, then tell them the socket
// is going away and tell the requesting client that it
// is available.
//
case CE_EXCLUSIVE_REQUEST:
NextEvent = CE_CARD_REMOVAL;
fCallAll = TRUE;
break;
case CE_CARD_REMOVAL:
NextEvent = CE_CARD_INSERTION;
break;
case CE_CARD_INSERTION:
//
// Requesting client is now exclusive owner
//
pLsock = I_FindSocket(pEvent->hSock);
if (pLsock) {
//
// If the previous owner did not release the socket
// then the requesting client can't get it.
//
if (pLsock->hOwner != 0) {
status = CERR_IN_USE;
goto cbt_fail_query;
}
pLsock->fFlags |= OWNER_FLAG_EXCLUSIVE;
pLsock->hOwner = FindClient(pEvent->pReqClient, TRUE, TRUE);
}
NextEvent = CE_EXCLUSIVE_COMPLETE;
break;
}
break;
//
// Finish CardReleaseExclusive callback sequence
//
case CE_EXCLUSIVE_COMPLETE:
switch (pEvent->SubEvent) {
case CE_CARD_REMOVAL:
//
// Avoid giving invalid insertion notices
//
if (IsCardInserted(pEvent->hSock.uSocket)) {
NextEvent = CE_CARD_INSERTION;
fCallAll = TRUE;
}
break;
}
break;
//
// Real card insertion event
//
cbt_end_insert:
case CE_CARD_INSERTION:
pLsock = I_FindSocket(pEvent->hSock);
if (pLsock) {
if (!(pLsock->fFlags & OWNER_FLAG_INTERRUPT)) {
PDCardGetSocket(pEvent->hSock.uSocket, &State);
State.fInterruptEvents = DETECTED_SOCKET_EVENTS;
PDCardSetSocket(pEvent->hSock.uSocket, &State);
}
//
// If no clients are using this card, shut down power to
// the PCMCIA adapter, until a configuration is requested.
//
PcmciaPowerOff(
pEvent->hSock.uSocket,
FALSE,
(CARD_CLIENT_HANDLE)CARDSERV_CLIENT_HANDLE);
// This completes the off/on processing window.
v_Sockets[pEvent->hSock.uSocket].fFlags &= ~PHYS_SOCK_FLAG_RESUMING;
}
CallbackPmResume();
break;
//
// Real card removal event
//
case CE_CARD_REMOVAL:
//
// Deleting the LOG_SOCKETs had to be delayed to here
// so clients can release resources associated with
// this socket
//
DEBUGMSG(ZONE_STSCHG,
(TEXT("PCMCIA:CallbackThread processing last removal for Socket %d\r\n"),pEvent->hSock.uSocket));
break;
} // switch (MajorEvent)
if (NextEvent) {
if (fCallAll) {
CallbackAll(
pEvent->MajorEvent,
NextEvent,
FindClient(pEvent->pReqClient, TRUE, TRUE),
pEvent->hSock,
//
// Clear CALLBACK_FLAG_LAST if it was set and
// retain CALLBACK_FLAG_QUERY
//
pEvent->fFlags & CALLBACK_FLAG_QUERY);
} else {
//
// Only one client, reuse this CALLBACK_STRUCT
//
if (IsValidClient(pClient)) {
pEvent->SubEvent = NextEvent;
pEvent->pDestClient = pEvent->pReqClient;
EnqueueEvent(pEvent);
StartCallbacks();
continue; // avoid freeing pEvent
}
}
}
} // if (last one in current stage)
}
cbt_next1:
free(pEvent);
} // while (callbacks to do)
DEBUGMSG(ZONE_CALLBACK, (TEXT("PCMCIA:CallbackThread: done %d\r\n"), g_Reentry--));
DEBUGCHK(FALSE); // we should never get here
return ERROR_SUCCESS;
} // CallbackThread
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -