📄 utils.c
字号:
#endif
}
LeaveCriticalSection(&v_ClientCrit);
return found;
} // IsValidClient
PCLIENT_DRIVER
FindClient(
CARD_CLIENT_HANDLE pClient,
BOOL fCritSec,
BOOL fCCH
)
{
PCLIENT_DRIVER pClient1;
#ifdef DEBUG
int i = 0;
#endif
if (fCCH && pClient == (PCLIENT_DRIVER)CARDSERV_CLIENT_HANDLE)
return CARDSERV_CLIENT_HANDLE;
if (fCritSec)
EnterCriticalSection(&v_ClientCrit);
pClient1 = (PCLIENT_DRIVER)v_ClientList.Flink;
//
// Validate handle
//
while (pClient1 != (PCLIENT_DRIVER)&v_ClientList) {
if (pClient1->hClient == pClient)
break;
pClient1 = (PCLIENT_DRIVER)pClient1->List.Flink;
#ifdef DEBUG
i++;
if (i > 500) {
DEBUGMSG(ZONE_WARNING, (TEXT("PCMCIA.DLL: Problem in IsValidClient()!!!\r\n")));
break;
}
#endif
}
if (pClient1 == (PCLIENT_DRIVER)&v_ClientList)
pClient1 = NULL;
if (fCritSec)
LeaveCriticalSection(&v_ClientCrit);
return pClient1;
} // FindClient
//
// Create a LOG_SOCKET structure for the specified function of a newly inserted
// card, remember stuff about it and link it to the socket structure.
//
PLOG_SOCKET
CreateFunction(
CARD_SOCKET_HANDLE hSock
)
{
PLOG_SOCKET pLsock;
PARSED_CONFIG Cfg;
UINT BufLen;
STATUS status;
UCHAR buf[1024];
PPARSED_CFTABLE pCfTable = (PPARSED_CFTABLE) buf;
UINT i;
PPHYS_WINDOW pPhys;
PDCARD_WINDOW_STATE WinState;
UINT32 CardAddress;
pLsock = alloc(sizeof(LOG_SOCKET));
if (pLsock == NULL) {
DEBUGMSG(ZONE_CALLBACK|ZONE_WARNING,
(TEXT("CreateFunction: Couldn't allocate a logical socket for %d:%d!\r\n"),
hSock.uSocket, hSock.uFunction));
return NULL;
}
pLsock->Next = NULL;
pLsock->hSock = hSock;
pLsock->hOwner = 0;
pLsock->IREQList = 0;
pLsock->pRegWin = NULL;
pLsock->fPrevEvents = 0;
pLsock->fChangedEvents = 0;
pLsock->hQueryDriver = 0;
//
// Link it to the socket structure
//
EnterCriticalSection(&v_SocketCrit);
if (v_Sockets[hSock.uSocket].pLsock != NULL) {
pLsock->Next = v_Sockets[hSock.uSocket].pLsock;
}
v_Sockets[hSock.uSocket].pLsock = pLsock;
LeaveCriticalSection(&v_SocketCrit);
#ifdef FORCE_MODEM
pLsock->fRegisters = 0xf;
Cfg.ConfigBase = 0x100;
Cfg.RegMask = 0xf;
#else
//
// Get the CISTPL_CONFIG tuple and remember the config reg address
// and the register presence mask.
//
BufLen = 1;
status = CardGetParsedTuple(
hSock,
CISTPL_CONFIG,
&Cfg,
&BufLen);
if (status == CERR_SUCCESS) {
pLsock->fRegisters = Cfg.RegMask;
} else {
DEBUGMSG(ZONE_CALLBACK|ZONE_WARNING,
(TEXT("CreateFunction: CardGetParsedTuple(CISTPL_CONFIG) returned %d for %d:%d\r\n"),
status, hSock.uSocket, hSock.uFunction));
Cfg.ConfigBase = 0;
Cfg.RegMask = 0;
}
#endif
#ifndef FORCE_MODEM
if ((Cfg.ConfigBase != 0) && (Cfg.RegMask != 0)) {
//
// Get the CISTPL_CFTABLE_ENTRY information to determine the card's interface type.
// If it's an I/O card, then we need to map a window to attribute memory to
// access the config registers.
//
BufLen = sizeof(buf)/sizeof(PARSED_CFTABLE);
status = CardGetParsedTuple(
hSock,
CISTPL_CFTABLE_ENTRY,
pCfTable,
&BufLen);
if (status == CERR_SUCCESS) {
for (i = 0; i < BufLen; i++, pCfTable++) {
if (pCfTable->IFacePresent) {
if (pCfTable->IFaceType != 1) { // 1 == I/O card
continue;
}
#endif
//
// Find a physical memory window associated with this socket.
//
EnterCriticalSection(&v_WindowCrit);
CardAddress = Cfg.ConfigBase;
// Try first to use the existing attribute window used by Tuple parser
pPhys = v_Sockets[hSock.uSocket].pAttrWin->pPhys;
if (pPhys)
{
PDCardGetWindow(pPhys->uWindow, &WinState);
if ((WinState.uOffset <= CardAddress) &&
(CardAddress + 15 <= (WinState.uOffset + WinState.uSize)))
{
// Map window into attribute space
pLsock->hRegWin = I_MapWindow(pPhys, &CardAddress, 15, TRUE);
pLsock->pRegWin = (PVOID)CardAddress;
DEBUGMSG(ZONE_CALLBACK|ZONE_WARNING,
(TEXT("CreateFunction: Re-using Tuple attribute window, Config registers @ 0x%x for %d:%d\r\n"),
CardAddress, hSock.uSocket, hSock.uFunction));
LeaveCriticalSection(&v_WindowCrit);
goto cf_done;
}
}
// Find another window, not used by Tuple parser
pPhys = v_pWinList;
while (pPhys) {
if (pPhys->uSock == hSock.uSocket) {
if (pPhys->fWindowCaps & WIN_CAP_ATTRIBUTE) {
// Don't use same physical window as the Tuple parser
if (pPhys == v_Sockets[pPhys->uSock].pAttrWin->pPhys)
{
pPhys = pPhys->Next;
continue;
}
// Set PCMCIA offset, which is simply the start address of the page
// containing CardAddress (in the PC Card address space)
PDCardGetWindow(pPhys->uWindow, &WinState);
pPhys->uOffset = WinState.uOffset = PAGE_START(CardAddress);
PDCardSetWindow(pPhys->uWindow, &WinState);
// Map window into attribute space
pLsock->hRegWin = I_MapWindow(pPhys, &CardAddress, 15, TRUE);
pLsock->pRegWin = (PVOID)CardAddress;
DEBUGMSG(ZONE_CALLBACK|ZONE_WARNING,
(TEXT("CreateFunction: Config registers @ 0x%x for %d:%d\r\n"),
CardAddress, hSock.uSocket, hSock.uFunction));
LeaveCriticalSection(&v_WindowCrit);
goto cf_done;
}
}
pPhys = pPhys->Next;
}
LeaveCriticalSection(&v_WindowCrit);
#ifndef FORCE_MODEM
}
}
} else {
DEBUGMSG(ZONE_CALLBACK|ZONE_WARNING,
(TEXT("CreateFunction: CardGetParsedTuple(CISTPL_CFTABLE_ENTRY) returned %d for %d:%d\r\n"),
status, hSock.uSocket, hSock.uFunction));
}
}
#endif
cf_done:
pLsock->COR_val = 0;
return pLsock;
}
//
// Create a LOG_SOCKET structure for each function of a newly inserted card.
//
// Returns the number of functions on the newly inserted card.
//
int CreateFunctions(UINT uSocket)
{
CARD_SOCKET_HANDLE hSock;
UINT8 numfn;
UINT8 fn;
UINT Created;
PCARD_TUPLE_PARMS pTuple;
PCARD_DATA_PARMS pData;
UCHAR buf[BUFFER_SIZE + sizeof(CARD_DATA_PARMS)];
STATUS status;
DEBUGCHK(uSocket < (UINT)v_cSockets);
hSock.uSocket = uSocket;
hSock.uFunction = 0;
Created = 1;
//
// Function 0 must be created in order to use the tuple APIs, so create the
// first function now.
//
if (CreateFunction(hSock) == NULL) {
return 0;
}
//
// Read the CISTPL_LONGLINK_MFC tuple. If one doesn't exist, then assume
// the card has only one function.
//
pTuple = (PCARD_TUPLE_PARMS)buf;
pTuple->hSocket = hSock;
pTuple->fAttributes = TUPLE_RETURN_LINKS;
pTuple->uDesiredTuple = CISTPL_LONGLINK_MFC;
status = CardGetFirstTuple(pTuple);
if (status == CERR_SUCCESS) {
fn = pTuple->uTupleLink; // tuple length
pData = (PCARD_DATA_PARMS)buf;
pData->uTupleOffset = 0;
pData->uBufLen = BUFFER_SIZE;
status = CardGetTupleData(pData);
if (status == CERR_SUCCESS) {
//
// The first byte of a CISTPL_LONGLINK_MFC is the number of functions
//
numfn = buf[sizeof(CARD_DATA_PARMS)];
//
// If the tuple length exactly matches what it should be for the
// number of functions reported, then trust it.
//
DEBUGMSG(ZONE_CALLBACK,
(TEXT("PCMCIA:CreateFunctions - CISTPL_LONGLINK_MFC reports %d functions\r\n"),
numfn));
if ((numfn * 5 + 1) >= fn) {
if (numfn <= MAX_FUNCTIONS) {
for (fn = 1; fn < numfn; fn++) {
hSock.uFunction = fn;
if (CreateFunction(hSock) != NULL) {
Created++;
}
}
}
} else {
DEBUGMSG(ZONE_CALLBACK,
(TEXT("PCMCIA:CreateFunctions - CISTPL_LONGLINK_MFC length=%d should be %d\r\n"),
fn, numfn * 5 + 1));
}
}
} else {
DEBUGMSG(ZONE_CALLBACK|ZONE_WARNING,
(TEXT("CreateFunctions: CardGetFirstTuple(CISTPL_LONGLINK_MFC) returned %d for %d:%d\r\n"),
status, hSock.uSocket, hSock.uFunction));
}
DEBUGMSG(ZONE_CALLBACK,
(TEXT("PCMCIA:CreateFunctions - Created %d functions\r\n"),
Created));
v_Sockets[uSocket].cFunctions = Created;
return Created;
} // CreateFunctions
//
// Delete the LOG_SOCKET structures for all functions of a removed card.
//
// This function is called after the last card removal callback has returned
// so all references can be safely removed.
//
STATUS DeleteFunctions(UINT uSocket)
{
PLOG_SOCKET pLsock;
PCLIENT_SOCKET pCsock;
PCLIENT_DRIVER pClient;
//
// Walk the list of logical sockets and remove any outstanding references.
//
EnterCriticalSection(&v_FindDriverCrit);
EnterCriticalSection(&v_SocketCrit);
while (v_Sockets[uSocket].pLsock) {
pLsock = v_Sockets[uSocket].pLsock;
if (pLsock->hQueryDriver != 0) {
if (v_hGwesEvent == NULL ||
WaitForSingleObject(v_hGwesEvent, INFINITE) != WAIT_OBJECT_0 ||
(NULL == v_pfnPostThreadMessageW) ||
!v_pfnPostThreadMessageW(pLsock->hQueryDriver, WM_QUIT, 0, 0)) {
DEBUGMSG(ZONE_ERROR, (TEXT("DeleteFunctions(%d.%d): v_pfnPostThreadMessage failed(%d)\r\n"),
uSocket, pLsock->hSock.uFunction, GetLastError()));
}
pLsock->hQueryDriver = 0;
}
//
// Find and remove all client references to this logical socket.
//
EnterCriticalSection(&v_ClientCrit);
pClient = (PCLIENT_DRIVER)v_ClientList.Flink;
while (pClient != (PCLIENT_DRIVER)&v_ClientList) {
if (pClient->pCsock) {
pCsock = I_FindClientSocket(pLsock->hSock, pClient);
if (pCsock) {
I_RemoveClientSocket(pCsock, pClient);
}
}
pClient = (PCLIENT_DRIVER)pClient->List.Flink;
}
LeaveCriticalSection(&v_ClientCrit);
v_Sockets[uSocket].pLsock = pLsock->Next;
if (pLsock->hRegWin) {
I_DeleteLogicalWindow(pLsock->hRegWin);
}
free(pLsock);
}
//
// Free the memory mappings to the card's CIS
//
if (v_Sockets[uSocket].pAttrWin) {
I_DeleteLogicalWindow(v_Sockets[uSocket].pAttrWin);
v_Sockets[uSocket].pAttrWin = NULL;
}
if (v_Sockets[uSocket].pCmnWin) {
I_DeleteLogicalWindow(v_Sockets[uSocket].pCmnWin);
v_Sockets[uSocket].pCmnWin = NULL;
}
//
// Free the device id string
//
if (v_Sockets[uSocket].pDevId) {
free(v_Sockets[uSocket].pDevId);
v_Sockets[uSocket].pDevId = NULL;
}
v_Sockets[uSocket].cFunctions = 0;
LeaveCriticalSection(&v_SocketCrit);
LeaveCriticalSection(&v_FindDriverCrit);
return CERR_SUCCESS;
} // DeleteFunctions
//
// RemoveCallbacks - remove all callbacks for a deregistering client or
// for an aborted multi-callback event or CE_PM_RESUMEs.
//
VOID
RemoveCallbacks(
PCLIENT_DRIVER pClient,
CARD_SOCKET_HANDLE hSock,
CARD_EVENT MajorEvent,
DWORD evType
)
{
PCALLBACK_STRUCT pCur, pPrev, pDel;
BOOL bRemove;
//
// Callback events are removed for these 3 situations:
// 1. One of the client drivers rejected a query request. Remove
// all events associated with the failing one.
//
// 2. A client driver is deregistering. All callbacks associated
// with this client are removed except those that are the last in a
// callback sequence.
//
// 3. Remove all CE_PM_RESUMEs on power on to in case the sequence of
// removals and inserts got interrupted by a power off.
//
switch (evType) {
case REMOVE_QUERY:
case REMOVE_DEREGISTER:
case REMOVE_PM_RESUME:
case REMOVE_INIT_MFC:
break;
default:
return;
}
EnterCriticalSection(&v_CallbackCrit);
pCur = pPrev = v_CallbackHead;
while (pCur) {
bRemove = FALSE;
switch (evType) {
case REMOVE_QUERY:
if ((pCur->pReqClient == pClient) &&
(pCur->hSock.uSocket == hSock.uSocket) &&
(pCur->hSock.uFunction == hSock.uFunction)&&
(pCur->MajorEvent == MajorEvent)) {
bRemove = TRUE;
}
break;
case REMOVE_DEREGISTER:
if ((!(pCur->fFlags & CALLBACK_FLAG_LAST)) &&
((pCur->pReqClient == pClient) ||
(pCur->pDestClient == pClient))) {
bRemove = TRUE;
}
break;
case REMOVE_PM_RESUME:
if (pCur->MajorEvent == CE_PM_RESUME) {
bRemove = TRUE;
}
break;
case REMOVE_INIT_MFC:
if ((pCur->hSock.uSocket == hSock.uSocket) &&
(pCur->hSock.uFunction == hSock.uFunction)&&
(pCur->MajorEvent == CE_CARD_INSERTION)) {
bRemove = TRUE;
}
break;
}
if (bRemove) {
pDel = pCur;
if (v_CallbackTail == pCur) {
v_CallbackTail = pPrev;
}
if (pPrev == pCur) {
v_CallbackHead = pCur->Next;
if (v_CallbackHead == NULL) {
v_CallbackTail = NULL;
}
pPrev = pCur->Next;
pCur = pPrev;
} else {
pPrev->Next = pCur->Next;
pCur = pPrev->Next;
}
free(pDel);
} else {
pPrev = pCur;
pCur = pCur->Next;
}
}
#ifdef DEBUG
if (v_CallbackHead == NULL) {
if (v_CallbackTail != NULL) {
DEBUGMSG(1|ZONE_ERROR|ZONE_CALLBACK,
(TEXT("RemoveCallbacks:v_CallbackHead=0 but v_CallbackTail = 0x%x\r\n"),
v_CallbackTail));
}
}
if (v_CallbackTail == NULL) {
if (v_CallbackHead != NULL) {
DEBUGMSG(1|ZONE_ERROR|ZONE_CALLBACK,
(TEXT("RemoveCallbacks:v_CallbackTail=0 but v_CallbackHead = 0x%x\r\n"),
v_CallbackHead));
}
}
#endif
LeaveCriticalSection(&v_CallbackCrit);
} // RemoveCallbacks
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -