📄 wendyser.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.
Copyright (c) 1997 Socket Communications, Inc.
Module Name:
wendyser.c
Abstract:
Holds implementation of pcmcia serial driver interface for the WENDY CF+ BlueTooth
card (Wendy). Makes use of the ser16550 library to do most of the work.
Functions:
Notes:
--*/
#include <windows.h>
#include <types.h>
#include <memory.h>
#include <tchar.h>
#include <cardserv.h>
#include <sockserv.h>
#include <tuple.h>
#include <serhw.h>
#include "ser16950.h"
#include <hw16550.h>
#include "wendyser.h"
#include <devload.h>
#include "serpriv.h"
#include <excpt.h>
#include <pcmfuncs.h>
#include <serdbg.h>
#ifdef DEBUG
#pragma message ("Compile DEBUG is on:WendySer[wendyser.c]")
#endif
#define BASE_EVENT_MASK 0x02FF // all of them.
//#define INB(pInfo, reg) (*((pInfo)->reg))
//#define OUTB(pInfo, reg, value) (*((pInfo)->reg)) = ((unsigned char)(value))
#define EXCEPTION_ACCESS_VIOLATION STATUS_ACCESS_VIOLATION
#define INB(pInfo, reg) (READ_PORT_UCHAR((UCHAR *)((pInfo)->reg)))
#define OUTB(pInfo, reg, value) (WRITE_PORT_UCHAR((UCHAR *)((pInfo)->reg), (unsigned char)(value)))
// Declare table of function pointers for PCMCIA.DLL
DECLARE_CARDSERVICES_TABLE;
// Declare an array of pointers to CARD_INFO structures. This should really
// be a linked list, but that seems like overkill since we currently have
// no products with more than two slots.
#define MAX_CARDS 4
PWENDY_CARD_SER_INFO CardInfoList[MAX_CARDS];
VOID
WendySerialEventHandler(UINT32 uISRContext)
{
extern SerialEventHandler(PVOID);
PWENDY_CARD_SER_INFO pCardInfo = (PWENDY_CARD_SER_INFO)uISRContext;
DEBUGMSG (ZONE_THREAD | ZONE_FUNCTION,
(TEXT("+CFTestSerialEventHandler : Context x%X\r\n"),
uISRContext ));
//$$$$bugbug$$$$
// if (pCardInfo != CardInfoList[0])
// return;
//$$$$bugbug$$$$
if (pCardInfo->cOpenCount)
{
DEBUGMSG (ZONE_THREAD | ZONE_FUNCTION,
(TEXT("CioEventHandler : Check serial port (x%X) interrupt\r\n"),
pCardInfo ));
SerialEventHandler((PVOID)(pCardInfo->pMddHead));
}
}
//
// FindComConfig -
//
// Return the configuration information in the first CIS config found
// in pConfigIndex, pIOAddress and pIOLen and return TRUE.
//
// Return FALSE if any error getting Config Table.
//
// CIo : Device Configuration
BOOL
FindComConfig(
PWENDY_CARD_SER_INFO pHWHead,
PUCHAR pConfigIndex,
PUINT pIOAddress,
PUINT pIOLen
)
{
UCHAR CFBuf[1024];
#ifdef DEBUG // For debug loads, dump info about card
UINT i;
#endif
PPARSED_CFTABLE pCf = (PPARSED_CFTABLE)CFBuf;
UINT dataLen;
STATUS status;
//
// Get the list of parsed CISTPL_CFTABLE_ENTRYs for this PC card
//
dataLen = sizeof( CFBuf )/sizeof(PARSED_CFTABLE);
status = CallCardServices(CardGetParsedTuple)(pHWHead->hCardSock,
CISTPL_CFTABLE_ENTRY,
(PVOID) pCf,
(PUINT) &dataLen);
if (status)
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("CFIo : CardGetParsedTuple returned %d\n"),
status) );
return FALSE;
}
if (dataLen == 0)
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("CFIo : CardGetParsedTuple datalen = %d\n"), dataLen) );
return FALSE;
}
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("CFIo: CardGetParsedTuple : %d entries\n"),
dataLen));
#ifdef DEBUG // For debug loads, dump info about card
DEBUGMSG (ZONE_INIT, (TEXT("\r\nCFIo : Device Configuration\r\n")) );
for( i=0; i<dataLen; i++, pCf++ )
{
int j;
DEBUGMSG (ZONE_INIT, (TEXT("\tConfigIndex = 0x%x (%d entries)\r\n"),
pCf->ConfigIndex, pCf->NumIOEntries));
for (j = 0; j < pCf->NumIOEntries; j++)
{
DEBUGMSG (ZONE_INIT, (TEXT("\t\tRange %d at 0x%x (%d bytes)\r\n"),
j+1, pCf->IOBase[j], pCf->IOLength[j]));
}
}
pCf = (PPARSED_CFTABLE)CFBuf;
#endif
// Just use the FIRST config...
*pConfigIndex = pCf->ConfigIndex;
//*pConfigIndex = 4;// added by EricG, need to be fix
//#pragma message ("Using 0x60 for address!")
#pragma message ("Using 0x60 for address!")
#ifdef x86
*pIOAddress = pCf->IOBase[0]+0x100;
#else
*pIOAddress = pCf->IOBase[0]+0x60;
#endif
// *pIOAddress = pCf->IOBase[0]+0x60;
// *pIOAddress = pCf->IOBase[0];
#pragma message ("get true length from CONFIG")
*pIOLen = 8;
#ifdef TODO // -- Need to store the base addr for each port
pHWHead->pCardInfo->wBaseAddr[0] = pCf->IOBase[0];
#endif
return TRUE;
} // FindComConfig
//
// DetectModem - called by device.exe to allow this driver to detect modem cards
//
// Return is NULL for an undetected card or else it is the name of the device key
// under HLM\Drivers\PCMCIA for this driver (i.e. "Modem")
//
// Note:
//
LPTSTR
DetectModem(
CARD_SOCKET_HANDLE hSock,
UCHAR DevType,
LPTSTR DevKey,
DWORD DevKeyLen
)
{
// We never want to pick up a card that wasn't explicitly identified
// as a WENDY Wendy CF Card.
// Leave that type of work up to the generic ser_card driver
return NULL;
} // DetectModem
// Miscellaneous internal routines.
STATUS CallBackFn(
CARD_EVENT EventCode,
CARD_SOCKET_HANDLE hSocket,
PCARD_EVENT_PARMS pParms
)
{
PWENDY_CARD_SER_INFO pCardInfo;
STATUS status = CERR_SUCCESS;
STATUS ret = CERR_SUCCESS;
//
// Make sure everything comes in as expected.
//
if (pParms == NULL)
{
DEBUGMSG (ZONE_THREAD, (TEXT("CLNTX:CallBackFn - pParms == NULL!!!\r\n")));
goto CBF_END;
}
pCardInfo = (PWENDY_CARD_SER_INFO)pParms->uClientData;
DEBUGMSG (ZONE_THREAD, (TEXT("CallBackFn 0x%X - 0x%X\r\n"),
pParms->uClientData, EventCode ));
switch (EventCode)
{
case CE_CARD_REMOVAL:
//
// Determine whether this is an artificial removal notice.
//
#ifdef TODO // How to determine what card is being removed?
CardStatus.hSocket = CardInfo.hCardSock;
ret = CallCardServices(CardGetStatus)(&CardStatus);
if (ret)
{
// Hmm, this should never happen. What do we want to do here?
DEBUGMSG (ZONE_THREAD | ZONE_ERROR, (TEXT("CallBackFn - CardGetStatus returned %d\r\n"),
ret));
}
else
{
if (! (CardStatus.fCardState & EVENT_MASK_CARD_DETECT) )
{
DEBUGMSG (ZONE_THREAD, (TEXT("CallBackFn - removal notice\r\n")));
}
}
#endif
break;
// added by EricG. to see if the reset operation was done completly
case CE_RESET_COMPLETE:
break;
default:
// We didn't ask for any other events. we should never get here.
break;
}
CBF_END:
return status;
} // CallBackFn
BOOL
GetCardHandle( ULONG Identifier,
CARD_SOCKET_HANDLE *pCardSock
)
{
CARD_SOCKET_HANDLE hCardSock;
DWORD status;
DWORD ValType;
DWORD ValLen;
HKEY ActiveKey;
status = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
(LPCWSTR)Identifier,
0,
0,
&ActiveKey);
if (status) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("CF_INIT - RegOpenKeyEx returned %d!!!\r\n"),
status));
return FALSE;
}
ValLen = sizeof(hCardSock);
status = RegQueryValueEx(
ActiveKey,
DEVLOAD_SOCKET_VALNAME,
NULL,
&ValType,
(PUCHAR)&hCardSock,
&ValLen);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("CF_INIT: RegQueryValueEx(%s) returned %d\r\n"),
DEVLOAD_SOCKET_VALNAME, status));
//
// We can't do PCMCIA without our handle
//
RegCloseKey(ActiveKey);
return FALSE;
}
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("_INIT: RegQueryValueEx(%s) Val = %d\r\n"),
DEVLOAD_SOCKET_VALNAME, hCardSock));
// When we finish with registry, be sure to close it
RegCloseKey(ActiveKey);
// OK, we got the handle from the registry, return it
*pCardSock = hCardSock;
return TRUE;
}
BOOL
InitPCMCIACard( PWENDY_CARD_SER_INFO pCardInfo )
{
UCHAR ConfigNum;
UINT32 IOAddress;
UINT32 IOLen;
CARD_CONFIG_INFO ConfigInfo;
CARD_REGISTER_PARMS Parms;
CARD_WINDOW_PARMS WinParms; // For CardRequestWindow
DEBUGMSG (ZONE_INIT, (TEXT("WendySer : Attempting to register\r\n")));
Parms.fEventMask = 0xffff;
Parms.uClientData = (UINT32)pCardInfo;
//
// Register as an IO client.
//
Parms.fAttributes = CLIENT_ATTR_IO_DRIVER | CLIENT_ATTR_NOTIFY_SHARED |
CLIENT_ATTR_NOTIFY_EXCLUSIVE;
pCardInfo->hCardClient = CallCardServices(CardRegisterClient) (CallBackFn, &Parms);
DEBUGMSG (ZONE_INIT, ( TEXT("head @ 1 = 0x%X\r\n"), pCardInfo));
if (pCardInfo->hCardClient == 0)
{
DEBUGMSG (ZONE_INIT, (
TEXT("WendySer : RegisterClient - failed (%d)\r\n"),
GetLastError()));
return FALSE;
}
// Request the window.
WinParms.fAttributes = WIN_ATTR_IO_SPACE;
WinParms.uWindowSize = 32;
#pragma message ("Should this match what the card CIS says?")
WinParms.fAccessSpeed = WIN_SPEED_USE_WAIT;
WinParms.hSocket = pCardInfo->hCardSock;
pCardInfo->hCardWindow = CallCardServices(CardRequestWindow) (pCardInfo->hCardClient, &WinParms);
if (pCardInfo->hCardWindow == NULL)
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("WendySer : CardRequestWindow failed %d\n"),
GetLastError()));
CallCardServices(CardDeregisterClient) (pCardInfo->hCardClient);
return FALSE;
}
CallCardServices(CardResetFunction) (pCardInfo->hCardClient, pCardInfo->hCardSock);
if (FindComConfig(pCardInfo, &ConfigNum, &IOAddress, &IOLen) == FALSE) {
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("WendySer : No valid PC card configuration found\n")));
CallCardServices(CardDeregisterClient) (pCardInfo->hCardClient);
return FALSE;
}
DEBUGMSG (ZONE_INIT,
(TEXT("WendySer : Using Configuration %d (IOAddr 0x%X, len %d)\n"),
ConfigNum, IOAddress, IOLen ));
DEBUGMSG (ZONE_INIT, (TEXT("head @ 2 = 0x%X\r\n"), pCardInfo));
DEBUGMSG (ZONE_INIT,
(TEXT("WendySer : Mapping Window 0x%X at 0x%X, len %d, Granularity %d\n"),
pCardInfo->hCardWindow, IOAddress, IOLen, pCardInfo->IO_Granularity ));
// Now we know all the attributes, lets map the IO space
pCardInfo->pCardIOWin = CallCardServices(CardMapWindow) (pCardInfo->hCardWindow, IOAddress, IOLen, &(pCardInfo->IO_Granularity) );
if (pCardInfo->pCardIOWin == NULL)
{
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("WendySer : CardMapWindow failed %d\n"),
GetLastError()));
CallCardServices(CardDeregisterClient) (pCardInfo->hCardClient);
return FALSE;
}
else
{
DEBUGMSG (ZONE_INIT,
(TEXT("WendySer : CardMapWindow pCardIOWin = 0x%X\n"),
pCardInfo->pCardIOWin));
}
// And then use CardRequestConfig to power this baby up
ConfigInfo.hSocket = pCardInfo->hCardSock;
ConfigInfo.fAttributes = CFG_ATTR_VALID_CLIENT | CFG_ATTR_IRQ_STEERING;
//CFG_ATTR_IRQ_WAKEUP | CFG_ATTR_KEEP_POWERED;
//RETAILMSG(-1, TEXT("fAttributes=%08x\n\r"), ConfigInfo.fAttributes);
ConfigInfo.uVcc = 50;
ConfigInfo.uVpp1 = 0;
ConfigInfo.uVpp2 = 0;
ConfigInfo.fInterfaceType = CFG_IFACE_MEMORY_IO;
ConfigInfo.fRegisters = CFG_REGISTER_STATUS | CFG_REGISTER_CONFIG | CFG_REGISTER_PIN;
ConfigInfo.uStatusReg = FCR_FCSR_REQUIRED_BITS | FCR_FCSR_AUDIO;
ConfigInfo.uPinReg = 0;
ConfigInfo.uCopyReg = 0;
ConfigInfo.uConfigReg = ConfigNum;
ConfigInfo.uExtendedStatus = 0;
if (CallCardServices(CardRequestConfiguration) (pCardInfo->hCardClient, &ConfigInfo))
{
#if 0
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("WendySer : CardRequestConfiguration returned %d\n"),
status) );
#endif
CallCardServices(CardDeregisterClient) (pCardInfo->hCardClient);
return FALSE;
}
else
DEBUGMSG (ZONE_INIT,
(TEXT("WendySer : CardRequestConfiguration completed \n")));
return TRUE;
}
//
// @doc OEM
// @func PVOID | CF_Init | Initializes device identified by argument.
// This routine allocates any memory required by the driver, and
// initializes a few of the fields. For PCMCIA cards, that is all
// we can do this early. Nearly everything else is done at open
// time in order to ensure that we do not power the PCMCIA card
// up any sooner than required.
//
// @rdesc The return value is a PVOID to be passed back into the other
// I_??? entrypoints as a device handle.
//
PVOID
CF_Init(
ULONG Identifier, // @parm pointer to card-socket handle for PCMCIA
PVOID pMddHead // @parm First argument to mdd callbacks.
)
{
PWENDY_CARD_SER_INFO pCardInfo;
CARD_SOCKET_HANDLE hCardSock;
WORD wCardIndex;
int i;
DEBUGMSG (ZONE_FUNCTION, (TEXT("+CF_INIT\r\n") ));
DEBUGMSG (ZONE_INIT, (TEXT("Initializing Wendy\r\n") ));
// First, make sure this card is valid
if( !GetCardHandle( Identifier, &hCardSock ) )
{
return (UINT32)NULL;
}
// Next, make sure we can load the PCMCIA DLL
if( !InitCardServicesTable() )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -