📄 utils.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:
utils.c
Abstract:
This file implements the PCMCIA model device driver internal 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:
I_FindSocket()
I_FindClientSocket()
I_AttachClientSocket()
I_RemoveClientSocket()
I_GetClientSocket()
I_LinkLogicalWindow()
I_UnlinkLogicalWindow()
I_CreateLogicalWindow()
I_DeleteLogicalWindow()
I_MapWindow()
IsCardInserted()
IsValidClient()
FindClient()
CreateFunction()
CreateFunctions()
DeleteFunctions()
RemoveCallbacks()
Notes:
--*/
#include <windows.h>
#include <types.h>
#include <tchar.h>
#include <cardserv.h>
#include <sockserv.h>
#include <linklist.h>
#include <pcmcia.h>
#include <tuple.h>
#include <extern.h>
#ifdef INSTRUM_DEV
#include <instrumd.h>
#endif
// Calculates start address of page containing address X
#define PAGE_START(X) (((UINT)(X) / v_PageSize) * v_PageSize)
//
// Return a pointer to the PLOG_SOCKET structure that represents the
// specified socket/function pair. Return NULL if none found.
//
PLOG_SOCKET I_FindSocket(CARD_SOCKET_HANDLE hSock)
{
PLOG_SOCKET pSock;
if (hSock.uSocket >= v_cSockets) {
return NULL;
}
EnterCriticalSection(&v_SocketCrit);
pSock = v_Sockets[hSock.uSocket].pLsock;
while (pSock) {
if (pSock->hSock.uFunction == hSock.uFunction) {
LeaveCriticalSection(&v_SocketCrit);
return pSock;
}
pSock = pSock->Next;
}
LeaveCriticalSection(&v_SocketCrit);
return NULL;
}
//
// Return a pointer to the PCLIENT_SOCKET structure that represents the
// specified logical socket/client pair. Return NULL if none found.
//
PCLIENT_SOCKET
I_FindClientSocket(
CARD_SOCKET_HANDLE hSock,
PCLIENT_DRIVER pClient
)
{
PCLIENT_SOCKET pCsock;
pCsock = pClient->pCsock;
while (pCsock) {
if ((pCsock->pLsock->hSock.uSocket == hSock.uSocket) &&
(pCsock->pLsock->hSock.uFunction == hSock.uFunction)) {
return pCsock;
}
pCsock = pCsock->Next;
}
return NULL;
}
//
// Link the PCLIENT_SOCKET structure to the client's list.
//
VOID
I_AttachClientSocket(
PCLIENT_SOCKET pCsock,
PCLIENT_DRIVER pClient
)
{
PCLIENT_SOCKET pCsockP;
//
// Link this socket to the client
//
if (pClient->pCsock == NULL) {
pClient->pCsock = pCsock;
} else {
//
// Link it at the end of the list.
//
pCsockP = pClient->pCsock;
while (pCsockP->Next) {
pCsockP = pCsockP->Next;
}
pCsockP->Next = pCsock;
}
}
//
// Unlink the PCLIENT_SOCKET structure from the client's list and free it.
//
VOID
I_RemoveClientSocket(
PCLIENT_SOCKET pCsock,
PCLIENT_DRIVER pClient
)
{
PCLIENT_SOCKET pCsockP;
if (pClient->pCsock == pCsock) {
pClient->pCsock = pCsock->Next; // unlink it
goto freeit;
} else {
pCsockP = pClient->pCsock;
while (pCsockP->Next) {
if (pCsockP->Next == pCsock) {
pCsockP->Next = pCsock->Next; // unlink it
goto freeit;
}
pCsockP = pCsockP->Next;
}
}
DEBUGMSG(ZONE_WARNING, (TEXT("I_RemoveClientSocket: Something's wrong!\r\n")));
return;
freeit:
free(pCsock);
return;
} // I_RemoveClientSocket
//
// Either find the specified CLIENT_SOCKET or allocate one and link it in.
//
PCLIENT_SOCKET
I_GetClientSocket(
PLOG_SOCKET pLsock,
PCLIENT_DRIVER pClient
)
{
PCLIENT_SOCKET pCsock;
pCsock = I_FindClientSocket(pLsock->hSock, pClient);
if (pCsock == NULL) {
pCsock = alloc(sizeof(CLIENT_SOCKET));
if (pCsock == NULL) {
return NULL;
}
pCsock->pLsock = pLsock;
I_AttachClientSocket(pCsock, pClient);
}
return pCsock;
} // I_GetClientSocket
//
// Attach a logical window structure to the specified physical window's list
//
VOID
I_LinkLogicalWindow(
PPHYS_WINDOW pPhys,
PLOG_WINDOW pWin
)
{
//
// Link this new logical window to the physical window.
//
EnterCriticalSection(&v_WindowCrit);
pWin->pPhys = pPhys;
pWin->Next = pPhys->pLog;
pPhys->pLog = pWin;
LeaveCriticalSection(&v_WindowCrit);
} // I_LinkLogicalWindow
//
// Unlink a logical window structure from the associated physical window
//
VOID
I_UnlinkLogicalWindow(
PLOG_WINDOW pWin
)
{
PLOG_WINDOW pTmp;
//
// Unlink from list.
//
EnterCriticalSection(&v_WindowCrit);
if (pWin->pPhys->pLog == pWin) {
pWin->pPhys->pLog = pWin->Next;
} else {
pTmp = pWin->pPhys->pLog;
while (pTmp) {
if (pTmp->Next == pWin) {
pTmp->Next = pWin->Next;
pWin->Next = NULL;
pWin->pPhys = NULL;
break;
}
pTmp = pTmp->Next;
}
}
LeaveCriticalSection(&v_WindowCrit);
} // I_UnlinkLogicalWindow
//
// Create a logical window and link it to the physical window.
//
// Return NULL on failure or valid PLOG_WINDOW on success.
//
PLOG_WINDOW
I_CreateLogicalWindow(
PPHYS_WINDOW pPhys
)
{
PLOG_WINDOW pWin;
pWin = alloc(sizeof(LOG_WINDOW));
if (pWin) {
pWin->Next = NULL;
pWin->hOwner = 0;
pWin->pVirtMem = NULL;
I_LinkLogicalWindow(pPhys, pWin);
}
return pWin;
} // I_CreateLogicalWindow
//
// Unlink a logical window from the physical window and free its memory and
// the mapped memory.
//
VOID
I_DeleteLogicalWindow(
PLOG_WINDOW pWin
)
{
//
// Free the mapped memory.
//
if (pWin->pVirtMem) {
DEBUGMSG(ZONE_MEM,
(TEXT("I_DeleteLogicalWindow calling VirtualFree(0x%x).\r\n"),
pWin->pVirtMem));
if (VirtualFree( pWin->pVirtMem, 0, MEM_RELEASE) == FALSE) {
DEBUGMSG(ZONE_MEM|ZONE_ERROR,
(TEXT("I_DeleteLogicalWindow: VirtualFree failed %d\r\n"),
GetLastError()));
}
#ifdef INSTRUM_DEV
ics_deleteCardRange(pWin->pVirtMem);
#endif
}
I_UnlinkLogicalWindow(pWin);
free(pWin);
} // I_DeleteLogicalWindow
//
// Map a physical memory window to a virtual/logical window
//
// Returns NULL on failure.
//
// On exit, pCardAddress points to the virtual address of the requested region.
//
PLOG_WINDOW
I_MapWindow(
PPHYS_WINDOW pPhys,
PUINT pCardAddress,
UINT uSize,
BOOL bAttribute
)
{
PLOG_WINDOW pWin;
PDCARD_WINDOW_STATE WinState;
UINT32 uStart;
UINT32 uEnd;
UINT32 uVirtSize;
UINT32 uPhysAddr;
UINT32 uWinOffset;
pWin = I_CreateLogicalWindow(pPhys);
if (pWin == NULL) {
DEBUGMSG(ZONE_WARNING,
(TEXT("I_MapWindow: I_CreateLogicalWindow failed\r\n")));
return NULL;
}
//
// Compute beginning and ending addresses of the mapping region (must be on page boundaries)
//
uStart = PAGE_START(*pCardAddress);
uEnd = (((*pCardAddress + uSize) + v_PageSize - 1) / v_PageSize) * v_PageSize;
uVirtSize = uEnd - uStart;
DEBUGMSG(ZONE_MEM,
(TEXT("I_MapWindow: pCardAddress = 0x%x, v_PageSize = 0x%x\n"),
*pCardAddress, v_PageSize));
pWin->uReqOffset = *pCardAddress;
pWin->uReqSize = uSize;
pWin->pVirtMem = VirtualAlloc(
0,
uVirtSize,
MEM_RESERVE,
PAGE_NOACCESS);
if (pWin->pVirtMem == NULL) {
DEBUGMSG(ZONE_WARNING,
(TEXT("I_MapWindow: VirtualAlloc failed %d\r\n"), GetLastError()));
I_DeleteLogicalWindow(pWin);
return NULL;
}
// Map the memory.
#ifdef DEBUG
if (pPhys->uBase & 0xE0000000) {
DEBUGMSG(ZONE_WARNING|ZONE_ERROR|ZONE_MEM,
(TEXT("PCMCIA:I_MapWindow MAKE SURE THIS PLATFORM'S PCMCIA MEMORY AREAS ARE SPECIFIED AS ACTUAL PHYSICAL ADDRESSES\r\n")));
}
#endif
// If window has programmable base address in hardware (PCIC), find out
// the base of the memory window on the PC Card size (uWinOffset). For
// memory-mapped PCMCIA space, there is no mapping from uBase to uWinOffset,
// so set it to 0.
if (pWin->pPhys->fOtherCaps & MEM_CAP_PRG_BASE)
{
PDCardGetWindow(pPhys->uWindow, &WinState);
uWinOffset = WinState.uOffset;
}
else
{
uWinOffset = 0;
}
// Physical address to be used is the base of the memory window (from host side) plus
// the difference of the start of the page the CardAddress is in (uStart) and the
// base of the memory window on the PC Card side. The resulting address is page
// adjusted.
uPhysAddr = pPhys->uBase + uStart - uWinOffset;
DEBUGMSG(ZONE_MEM,
(TEXT("I_MapWindow: uBase = 0x%x, uStart = 0x%x, uWinOffset= 0x%x, uPhysAddr = 0x%x\n"),
pPhys->uBase, uStart, uWinOffset, uPhysAddr));
uPhysAddr >>= 8;
if (!VirtualCopy(
pWin->pVirtMem,
(PVOID)uPhysAddr,
uVirtSize,
PAGE_READWRITE|PAGE_NOCACHE|PAGE_PHYSICAL)) {
DEBUGMSG(ZONE_WARNING,
(TEXT("I_MapWindow: VirtualCopy failed %d\r\n"), GetLastError()));
I_DeleteLogicalWindow(pWin);
return NULL;
}
#ifdef SH4
//
// On SH4 we need to set some extra page table bits associated with PCMCIA
// (the SH4 PCMCIA controller is integrated with the CPU's paging mechanism)
//
if (!VirtualSetPageFlags(
pWin->pVirtMem,
uVirtSize,
(bAttribute ? VSPF_ATTRIBUTE : VSPF_COMMON) | (isSh4Area6(pPhys->uWindow)?VSPF_TC:0),
NULL)) {
DEBUGMSG(ZONE_WARNING,
(TEXT("I_MapWindow: VirtualSetPageFlags failed %d\r\n"),
GetLastError()));
I_DeleteLogicalWindow(pWin);
return NULL;
}
#endif
#ifdef INSTRUM_DEV
ics_addCardRange(0, pWin->pVirtMem, (PVOID)(pPhys->uBase+uStart), uVirtSize, 0);
#endif
DEBUGMSG(ZONE_MEM,
(TEXT("I_MapWindow: Window %d @ %x (phys = %x), size = %d\r\n"),
pPhys->uWindow, pWin->pVirtMem, uPhysAddr << 8, pWin->uReqSize));
pWin->hOwner = CARDSERV_CLIENT_HANDLE;
*pCardAddress = (UINT)pWin->pVirtMem + *pCardAddress - uStart;
return pWin;
} // I_MapWindow
//
// Detect whether a card is inserted in the specified socket.
//
// Return: TRUE => card is inserted
// FALSE => card not inserted
//
BOOL
IsCardInserted(
UINT uSocket
)
{
PDCARD_SOCKET_STATE State;
if (PDCardGetSocket(uSocket, &State) != CERR_SUCCESS) {
return FALSE;
}
if (State.fNotifyEvents & EVENT_MASK_CARD_DETECT) {
return TRUE;
}
return FALSE;
}
//
// Determine whether the specified CARD_CLIENT_HANDLE is valid
// Caller must aquire the controlling critical section (v_ClientCrit)
//
// Return: TRUE => valid client handle
// FALSE => not valid
//
BOOL
IsValidClient(
PCLIENT_DRIVER pClient
)
{
PCLIENT_DRIVER pClient1;
BOOL found = FALSE;
#ifdef DEBUG
int i = 0;
#endif
EnterCriticalSection(&v_ClientCrit);
pClient1 = (PCLIENT_DRIVER)v_ClientList.Flink;
//
// Validate handle
//
while (pClient1 != (PCLIENT_DRIVER)&v_ClientList) {
if (pClient1 == pClient) {
found = TRUE;
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -