| ..back |
/* Copyright (c) 1999-2000 Microsoft Corporation. All rights reserved. */
#include "windows.h"
#include "tapi.h"
#include "ndis.h"
#include "ndiswan.h"
#include "ndistapi.h"
#include "asyncmac.h"
#include "frame.h"
#include "cclib.h"
#define DEV_CLASS_COMM_DATAMODEM TEXT("comm/datamodem")
#ifdef DEBUG
DBGPARAM dpCurSettings = {
TEXT("AsyncMac"), {
TEXT("Init"), TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined"),
TEXT("Undefined"),TEXT("Send"), TEXT("Undefined"),TEXT("Undefined"),
TEXT("Tapi"), TEXT("Recv"), TEXT("Interface"),TEXT("Misc"),
TEXT("Alloc"), TEXT("Function"), TEXT("Warning"), TEXT("Error") },
0x0000C000
};
#endif // DEBUG
HINSTANCE v_hInstance;
NDIS_HANDLE v_hNdisWrapper;
PDRIVER_OBJECT v_AsyncDriverObject;
DWORD v_GlobalAdapterCount;
// Because this driver only supports a single adapter, it is unnecessary to have
// a list of active adapters. Instead, a single pointer to the active adapter (NULL
// if none active) is sufficient.
PASYNCMAC_ADAPTER v_pAdapter;
CRITICAL_SECTION v_AdapterCS;
NDIS_OID SupportedOids[] = {
OID_GEN_MAC_OPTIONS,
OID_GEN_SUPPORTED_LIST,
OID_GEN_MEDIA_SUPPORTED,
OID_GEN_MEDIA_IN_USE,
OID_GEN_VENDOR_DESCRIPTION,
OID_GEN_VENDOR_ID,
OID_GEN_DRIVER_VERSION,
OID_GEN_HARDWARE_STATUS,
OID_GEN_LINK_SPEED,
OID_GEN_MAXIMUM_LOOKAHEAD,
OID_GEN_CURRENT_LOOKAHEAD,
OID_GEN_MAXIMUM_FRAME_SIZE,
OID_GEN_TRANSMIT_BLOCK_SIZE,
OID_GEN_RECEIVE_BLOCK_SIZE,
OID_GEN_MAXIMUM_TOTAL_SIZE,
OID_GEN_RECEIVE_BUFFER_SPACE,
OID_GEN_TRANSMIT_BUFFER_SPACE,
OID_WAN_CURRENT_ADDRESS,
OID_WAN_PERMANENT_ADDRESS,
OID_WAN_GET_INFO,
OID_WAN_GET_LINK_INFO,
OID_WAN_SET_LINK_INFO,
OID_WAN_MEDIUM_SUBTYPE,
OID_WAN_HEADER_FORMAT,
/* NOT Supported yet
OID_TAPI_GET_ADDRESS_CAPS,
OID_TAPI_GET_EXTENSION_ID,
OID_TAPI_NEGOTIATE_EXT_VERSION,
*/
OID_TAPI_GET_DEV_CAPS,
OID_TAPI_PROVIDER_INITIALIZE,
OID_TAPI_TRANSLATE_ADDRESS,
OID_TAPI_OPEN,
OID_TAPI_MAKE_CALL,
OID_TAPI_DROP,
OID_TAPI_CLOSE_CALL,
OID_TAPI_CLOSE,
/*
OID_WAN_GET_BRIDGE_INFO,
OID_WAN_GET_COMP_INFO,
OID_WAN_GET_STATS_INFO,
OID_WAN_LINE_COUNT,
OID_WAN_PROTOCOL_TYPE,
OID_WAN_QUALITY_OF_SERVICE,
OID_WAN_SET_BRIDGE_INFO,
OID_WAN_SET_COMP_INFO,
*/
};
#if DEBUG
PUCHAR
GetOidString(
NDIS_OID Oid
)
{
PUCHAR OidName = NULL;
#define OID_CASE(oid) case (oid): OidName = #oid; break
switch (Oid)
{
OID_CASE(OID_GEN_CURRENT_LOOKAHEAD);
OID_CASE(OID_GEN_DRIVER_VERSION);
OID_CASE(OID_GEN_HARDWARE_STATUS);
OID_CASE(OID_GEN_LINK_SPEED);
OID_CASE(OID_GEN_MAC_OPTIONS);
OID_CASE(OID_GEN_MAXIMUM_LOOKAHEAD);
OID_CASE(OID_GEN_MAXIMUM_FRAME_SIZE);
OID_CASE(OID_GEN_MAXIMUM_TOTAL_SIZE);
OID_CASE(OID_GEN_MEDIA_SUPPORTED);
OID_CASE(OID_GEN_MEDIA_IN_USE);
OID_CASE(OID_GEN_RECEIVE_BLOCK_SIZE);
OID_CASE(OID_GEN_RECEIVE_BUFFER_SPACE);
OID_CASE(OID_GEN_SUPPORTED_LIST);
OID_CASE(OID_GEN_TRANSMIT_BLOCK_SIZE);
OID_CASE(OID_GEN_TRANSMIT_BUFFER_SPACE);
OID_CASE(OID_GEN_VENDOR_DESCRIPTION);
OID_CASE(OID_GEN_VENDOR_ID);
OID_CASE(OID_802_3_CURRENT_ADDRESS);
OID_CASE(OID_TAPI_ACCEPT);
OID_CASE(OID_TAPI_ANSWER);
OID_CASE(OID_TAPI_CLOSE);
OID_CASE(OID_TAPI_CLOSE_CALL);
OID_CASE(OID_TAPI_CONDITIONAL_MEDIA_DETECTION);
OID_CASE(OID_TAPI_CONFIG_DIALOG);
OID_CASE(OID_TAPI_DEV_SPECIFIC);
OID_CASE(OID_TAPI_DIAL);
OID_CASE(OID_TAPI_DROP);
OID_CASE(OID_TAPI_GET_ADDRESS_CAPS);
OID_CASE(OID_TAPI_GET_ADDRESS_ID);
OID_CASE(OID_TAPI_GET_ADDRESS_STATUS);
OID_CASE(OID_TAPI_GET_CALL_ADDRESS_ID);
OID_CASE(OID_TAPI_GET_CALL_INFO);
OID_CASE(OID_TAPI_GET_CALL_STATUS);
OID_CASE(OID_TAPI_GET_DEV_CAPS);
OID_CASE(OID_TAPI_GET_DEV_CONFIG);
OID_CASE(OID_TAPI_GET_EXTENSION_ID);
OID_CASE(OID_TAPI_GET_ID);
OID_CASE(OID_TAPI_GET_LINE_DEV_STATUS);
OID_CASE(OID_TAPI_MAKE_CALL);
OID_CASE(OID_TAPI_NEGOTIATE_EXT_VERSION);
OID_CASE(OID_TAPI_OPEN);
OID_CASE(OID_TAPI_PROVIDER_INITIALIZE);
OID_CASE(OID_TAPI_PROVIDER_SHUTDOWN);
OID_CASE(OID_TAPI_SECURE_CALL);
OID_CASE(OID_TAPI_SELECT_EXT_VERSION);
OID_CASE(OID_TAPI_SEND_USER_USER_INFO);
OID_CASE(OID_TAPI_SET_APP_SPECIFIC);
OID_CASE(OID_TAPI_SET_CALL_PARAMS);
OID_CASE(OID_TAPI_SET_DEFAULT_MEDIA_DETECTION);
OID_CASE(OID_TAPI_SET_DEV_CONFIG);
OID_CASE(OID_TAPI_SET_MEDIA_MODE);
OID_CASE(OID_TAPI_SET_STATUS_MESSAGES);
OID_CASE(OID_TAPI_TRANSLATE_ADDRESS);
OID_CASE(OID_WAN_CURRENT_ADDRESS);
OID_CASE(OID_WAN_GET_BRIDGE_INFO);
OID_CASE(OID_WAN_GET_COMP_INFO);
OID_CASE(OID_WAN_GET_INFO);
OID_CASE(OID_WAN_GET_LINK_INFO);
OID_CASE(OID_WAN_GET_STATS_INFO);
OID_CASE(OID_WAN_HEADER_FORMAT);
OID_CASE(OID_WAN_LINE_COUNT);
OID_CASE(OID_WAN_MEDIUM_SUBTYPE);
OID_CASE(OID_WAN_PERMANENT_ADDRESS);
OID_CASE(OID_WAN_PROTOCOL_TYPE);
OID_CASE(OID_WAN_QUALITY_OF_SERVICE);
OID_CASE(OID_WAN_SET_BRIDGE_INFO);
OID_CASE(OID_WAN_SET_COMP_INFO);
OID_CASE(OID_WAN_SET_LINK_INFO);
default:
OidName = "Unknown OID";
break;
}
return OidName;
}
#endif
//
// This constant is used for places where NdisAllocateMemory
// needs to be called and the HighestAcceptableAddress does
// not matter.
//
NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
// Number of bytes to allocate before and after each block to look for corruption
#define GUARD_REGION_SIZE 32
#define GUARD_BYTE_VALUE (BYTE)'a'
#ifdef DEBUG
BOOL
memchk(
BYTE *pMem,
BYTE bValue,
UINT nBytes)
//
// Return true if the bytes at pMem are all set to bValue.
//
{
BYTE *pStartMem = pMem;
UINT nOrigBytes = nBytes;
//DEBUGMSG (1, (TEXT("Check %x bytes at %x\n"), nBytes, pMem));
while (nBytes--)
if (*pMem++ != bValue)
{
DumpMem(pStartMem, nOrigBytes);
DebugBreak();
return FALSE;
}
return TRUE;
}
BOOL
AsyncMacGuardRegionOk(
IN void *pMem,
IN UINT nBytes)
//
// Validate the guard regions at the start and end of a block of allocated memory.
//
{
BOOL bResult;
pMem = (BYTE *)pMem - GUARD_REGION_SIZE;
bResult = memchk(pMem, GUARD_BYTE_VALUE, GUARD_REGION_SIZE)
&& memchk((BYTE *)pMem + nBytes + GUARD_REGION_SIZE, GUARD_BYTE_VALUE, GUARD_REGION_SIZE);
if (bResult == FALSE)
DEBUGMSG(1, (TEXT("MemCorrupted: pMem=%x size=%x\n"), pMem, nBytes));
return bResult;
}
#endif
void *
AsyncMacAllocateMemory(
IN UINT nBytes)
//
// Call NdisAllocateMemory to allocate a block of the requested size.
// In DEBUG mode, allocate leading and trailing guard regions to look for memory corruption.
//
{
void *pMem;
NDIS_STATUS Status;
#ifdef DEBUG
nBytes += 2 * GUARD_REGION_SIZE;
#endif
Status = NdisAllocateMemory( (PVOID *)&pMem, nBytes, 0, HighestAcceptableMax);
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGMSG (ZONE_ERROR, (TEXT("+ASYNCMAC: AllocMem %d bytes failed\n")));
pMem = NULL;
}
#ifdef DEBUG
else
{
memset(pMem, GUARD_BYTE_VALUE, GUARD_REGION_SIZE);
memset((BYTE *)pMem + nBytes - GUARD_REGION_SIZE, GUARD_BYTE_VALUE, GUARD_REGION_SIZE);
pMem = (BYTE *)pMem + GUARD_REGION_SIZE;
ASSERT(AsyncMacGuardRegionOk(pMem, nBytes - 2 * GUARD_REGION_SIZE));
}
#endif
return pMem;
}
void
AsyncMacFreeMemory(
IN void *pMem,
IN UINT nBytes)
{
#ifdef DEBUG
ASSERT(AsyncMacGuardRegionOk(pMem, nBytes));
pMem = (BYTE *)pMem - GUARD_REGION_SIZE;
nBytes += 2 * GUARD_REGION_SIZE;
#endif
NdisFreeMemory(pMem, nBytes, 0);
}
//
// ZZZ Portable interface.
//
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
/*++
Routine Description:
This is the primary initialization routine for the async driver.
It is simply responsible for the intializing the wrapper and registering
the MAC. It then calls a system and architecture specific routine that
will initialize and register each adapter.
Arguments:
DriverObject - Pointer to driver object created by the system.
Return Value:
The status of the operation.
--*/
{
NDIS_STATUS InitStatus;
NDIS_MINIPORT_CHARACTERISTICS AsyncChar;
DEBUGMSG (ZONE_INIT|ZONE_INTERFACE,
(TEXT("+ASYNCMAC:DriverEntry(0x%X, 0x%X)\r\n"),
DriverObject, RegistryPath));
v_AsyncDriverObject = DriverObject;
v_pAdapter = NULL;
//
// Initialize the wrapper.
//
NdisMInitializeWrapper(&v_hNdisWrapper, DriverObject,
RegistryPath, NULL);
//
// Initialize the MAC characteristics for the call to NdisRegisterMac.
//
NdisZeroMemory(&AsyncChar, sizeof(AsyncChar));
AsyncChar.MajorNdisVersion = ASYNC_NDIS_MAJOR_VERSION;
AsyncChar.MinorNdisVersion = ASYNC_NDIS_MINOR_VERSION;
AsyncChar.Reserved = NDIS_USE_WAN_WRAPPER;
//
// We do not need the following handlers:
// CheckForHang
// DisableInterrupt
// EnableInterrupt
// HandleInterrupt
// ISR
// Send
// TransferData
//
AsyncChar.HaltHandler = MpHalt;
AsyncChar.InitializeHandler = MpInit;
AsyncChar.QueryInformationHandler = MpQueryInfo;
AsyncChar.ReconfigureHandler = MpReconfigure;
AsyncChar.ResetHandler = MpReset;
AsyncChar.WanSendHandler = MpSend;
AsyncChar.SetInformationHandler = MpSetInfo;
InitStatus = NdisMRegisterMiniport(v_hNdisWrapper,
&AsyncChar,
sizeof(AsyncChar));
if ( InitStatus == NDIS_STATUS_SUCCESS ) {
DEBUGMSG (ZONE_INIT|ZONE_INTERFACE,
(TEXT("-ASYNCMAC:DriverEntry: Returning STATUS_SUCCESS\r\n"),
DriverObject, RegistryPath));
return NDIS_STATUS_SUCCESS;
}
NdisTerminateWrapper(v_hNdisWrapper, DriverObject);
DEBUGMSG (ZONE_INIT|ZONE_INTERFACE|ZONE_ERROR,
(TEXT("-ASYNCMAC:DriverEntry: Returning STATUS_FAILURE\r\n"),
DriverObject, RegistryPath));
return NDIS_STATUS_FAILURE;
}
//
// Standard Windows DLL entrypoint.
// Since Windows CE NDIS miniports are implemented as DLLs, a DLL entrypoint is
// needed.
//
BOOL __stdcall
DllEntry(
HANDLE hDLL,
DWORD dwReason,
LPVOID lpReserved
)
{
switch (dwReason) {
case DLL_PROCESS_ATTACH:
v_hInstance = (HINSTANCE) hDLL;
DEBUGREGISTER(hDLL);
InitializeCriticalSection(&v_AdapterCS);
DEBUGMSG(ZONE_INIT, (TEXT("ASYNCMAC: DLL_PROCESS_ATTACH\n")));
break;
case DLL_PROCESS_DETACH:
DEBUGMSG(ZONE_INIT, (TEXT("ASYNCMAC: DLL_PROCESS_DETACH\n")));
DeleteCriticalSection(&v_AdapterCS);
break;
}
return TRUE;
}
VOID
MpHalt(
IN NDIS_HANDLE MiniportAdapterContext
)
{
DEBUGMSG (ZONE_INIT|ZONE_INTERFACE, (TEXT("+ASYNCMAC:MpHalt(0x%X)\n"), MiniportAdapterContext));
EnterCriticalSection(&v_AdapterCS);
AsyncMacFreeMemory(MiniportAdapterContext, sizeof(ASYNCMAC_ADAPTER));
v_pAdapter = NULL;
v_GlobalAdapterCount--;
LeaveCriticalSection(&v_AdapterCS);
DEBUGMSG (ZONE_INIT|ZONE_INTERFACE, (TEXT("-ASYNCMAC:MpHalt\n")));
}
NDIS_STATUS
MpInit(
OUT PNDIS_STATUS OpenErrorStatus,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE MiniportAdapterHandle,
IN NDIS_HANDLE WrapperConfigurationContext
)
{
NDIS_STATUS Status;
UINT i; // counter
PASYNCMAC_ADAPTER pAdapter;
NDIS_HANDLE ConfigHandle;
PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
NDIS_STRING MaxFrameSizeStr = NDIS_STRING_CONST("MaxFrameSize");
NDIS_STRING MaxSendFrameSizeStr = NDIS_STRING_CONST("MaxSendFrameSize");
NDIS_STRING MaxRecvFrameSizeStr = NDIS_STRING_CONST("MaxRecvFrameSize");
NDIS_STRING RecvBufSizeStr = NDIS_STRING_CONST("ReceiveBufferSize");
NDIS_STRING RecvThreadPrioStr = NDIS_STRING_CONST("ReceiveThreadPriority256");
DEBUGMSG (ZONE_INIT|ZONE_INTERFACE,
(TEXT("+ASYNCMAC:MpInit(0x%X, 0x%X, 0x%X, %d, 0x%X, 0x%X)\r\n"),
OpenErrorStatus, SelectedMediumIndex, MediumArray,
MediumArraySize, MiniportAdapterHandle,
WrapperConfigurationContext));
//
// We only support a single instance of AsyncMac
//
if (v_GlobalAdapterCount != 0) {
return NDIS_STATUS_FAILURE;
}
for (i = 0; TRUE; i++)
{
if (i >= MediumArraySize)
return NDIS_STATUS_UNSUPPORTED_MEDIA;
if (MediumArray[i] == NdisMediumWan)
{
*SelectedMediumIndex = i;
break;
}
}
//
// Let's allocate an AsyncMac adapter structure.
//
pAdapter = AsyncMacAllocateMemory(sizeof(ASYNCMAC_ADAPTER));
if (pAdapter == NULL)
{
return NDIS_STATUS_RESOURCES;
}
ASSERT(AsyncMacGuardRegionOk(pAdapter, sizeof(ASYNCMAC_ADAPTER)));
#ifdef DEBUG
pAdapter->dwDebugSigStart = AA_SIG_START;
pAdapter->dwDebugSigEnd = AA_SIG_END;
DEBUGMSG (ZONE_ALLOC, (TEXT(" ASYNCMAC:MpInit: Allocated pAdapter 0x%X(%d)\r\n"),
pAdapter, sizeof(ASYNCMAC_ADAPTER)));
#endif
pAdapter->hMiniportAdapter = MiniportAdapterHandle;
//
// Open the configuration space.
//
NdisOpenConfiguration(&Status, &ConfigHandle, WrapperConfigurationContext);
if (Status != NDIS_STATUS_SUCCESS)
{
AsyncMacFreeMemory(pAdapter, sizeof(ASYNCMAC_ADAPTER));
DEBUGMSG(ZONE_INIT,
(TEXT("NE2000:Initialize: NdisOpenConfiguration failed 0x%x\n"),
Status));
return Status;
}
pAdapter->Info.MaxFrameSize = MAX_FRAME_SIZE;
NdisReadConfiguration(&Status, &ReturnedValue, ConfigHandle, &MaxFrameSizeStr, NdisParameterInteger);
if (Status == NDIS_STATUS_SUCCESS)
{
pAdapter->Info.MaxFrameSize = ReturnedValue->ParameterData.IntegerData;
DEBUGMSG(ZONE_INIT,(TEXT("ASYNCMAC: MaxFrameSize=%d.\n"), pAdapter->Info.MaxFrameSize));
}
pAdapter->MaxSendFrameSize = pAdapter->Info.MaxFrameSize;
NdisReadConfiguration(&Status, &ReturnedValue, ConfigHandle, &MaxSendFrameSizeStr, NdisParameterInteger);
if (Status == NDIS_STATUS_SUCCESS)
{
pAdapter->MaxSendFrameSize = ReturnedValue->ParameterData.IntegerData;
DEBUGMSG(ZONE_INIT,(TEXT("ASYNCMAC: MaxSendFrameSize=%d.\n"), pAdapter->MaxSendFrameSize));
}
pAdapter->MaxRecvFrameSize = pAdapter->Info.MaxFrameSize;
NdisReadConfiguration(&Status, &ReturnedValue, ConfigHandle, &MaxRecvFrameSizeStr, NdisParameterInteger);
if (Status == NDIS_STATUS_SUCCESS)
{
pAdapter->MaxRecvFrameSize = ReturnedValue->ParameterData.IntegerData;
DEBUGMSG(ZONE_INIT,(TEXT("ASYNCMAC: MaxRecvFrameSize=%d.\n"), pAdapter->MaxRecvFrameSize));
}
pAdapter->dwRecvBufSize = DEFAULT_RX_BUF_SIZE;
NdisReadConfiguration(&Status, &ReturnedValue, ConfigHandle, &RecvBufSizeStr, NdisParameterInteger);
if (Status == NDIS_STATUS_SUCCESS)
{
pAdapter->dwRecvBufSize = ReturnedValue->ParameterData.IntegerData;
DEBUGMSG(ZONE_INIT,(TEXT("ASYNCMAC: RecvBufferSize=%d.\n"), pAdapter->dwRecvBufSize));
}
pAdapter->dwRecvThreadPrio = DEFAULT_RX_THREAD_PRIORITY;
NdisReadConfiguration(&Status, &ReturnedValue, ConfigHandle, &RecvThreadPrioStr, NdisParameterInteger);
if (Status == NDIS_STATUS_SUCCESS)
{
pAdapter->dwRecvThreadPrio = ReturnedValue->ParameterData.IntegerData;
}
DEBUGMSG(ZONE_INIT,(TEXT("ASYNCMAC: RecvThreadPrio=%d.\n"), pAdapter->dwRecvThreadPrio));
// Just close the config handle
NdisCloseConfiguration (ConfigHandle);
// Initialize our structure.
pAdapter->Info.MaxTransmit = 2;
#define ROUND_UP_TO_MULTIPLE_OF_N(value, N) ((value + N - 1) & ~(N - 1))
// For more info on HeaderPadding and TailPadding sizes see AssemblePPPFrame.
// HeaderPadding = 1 byte for opening flag (7e) + MaxFrameSize bytes to allow for insertion of escape bytes
// TailPadding = 4 bytes for escaped 16 bit CRC + 1 byte for closing flag
//
// The header padding must be rounded up because the PPP code that builds a packet expects that
// PacketStartAddress + HeaderPadding will be DWORD aligned.
pAdapter->Info.HeaderPadding = ROUND_UP_TO_MULTIPLE_OF_N(1 + pAdapter->Info.MaxFrameSize, 4);
pAdapter->Info.TailPadding = 4 + 1;
pAdapter->Info.Endpoints = 1;
pAdapter->Info.MemoryFlags = 0;
// pAdapter->Info.HighestAcceptableAddress = NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
pAdapter->Info.FramingBits = PPP_FRAMING|SLIP_FRAMING;
pAdapter->Info.DesiredACCM = DEFAULT_ACCM;
// Tell NDIS about our handle
NdisMSetAttributesEx(MiniportAdapterHandle, (NDIS_HANDLE)pAdapter, 1000,
0, NdisInterfaceInternal);
// Initialize TAPI
#ifdef TODO
// Once we change the load order so that miniports get loaded after the
// system is initialized we can do the lineInitialize here. In the meantime
// we'll use a lame function to sleep for awhile until we think the system
// might be happy.
{
long lReturn;
lReturn = lineInitialize (&(pAdapter->hLineApp),
v_hInstance, lineCallbackFunc,
TEXT("ASYNCMAC"), &(pAdapter->dwNumDevs));
DEBUGMSG (1, (TEXT("lineInitialize returned %d\r\n"),
lReturn));
DEBUGMSG (1, (TEXT("lineInitialize say's there's %d devices\r\n"),
pAdapter->dwNumDevs));
}
#else
{
NdisMInitializeTimer (&(pAdapter->ntLineInit),
pAdapter->hMiniportAdapter,
DoLineInitialize, pAdapter);
NdisMSetTimer (&(pAdapter->ntLineInit), 1000);
}
#endif
// Lot's more stuff.
EnterCriticalSection(&v_AdapterCS);
v_pAdapter = pAdapter;
v_GlobalAdapterCount++;
LeaveCriticalSection(&v_AdapterCS);
ASSERT(AsyncMacGuardRegionOk(pAdapter, sizeof(ASYNCMAC_ADAPTER)));
DEBUGMSG (ZONE_INIT|ZONE_INTERFACE, (TEXT("-ASYNCMAC:MpInit\r\n")));
return NDIS_STATUS_SUCCESS;
}
NDIS_STATUS
MapTapiErrorToNdisStatus(
IN DWORD dwTapiErrorCode)
//
// Translate a TAPI error code to an NDIS status.
//
{
NDIS_STATUS NdisStatus;
switch(dwTapiErrorCode)
{
case 0:
NdisStatus = NDIS_STATUS_SUCCESS;
break;
case LINEERR_BADDEVICEID:
case LINEERR_INVALADDRESS:
case LINEERR_INVALAPPHANDLE:
case LINEERR_INVALPARAM:
case LINEERR_INVALPOINTER:
case LINEERR_INVALDEVICECLASS:
case LINEERR_STRUCTURETOOSMALL:
NdisStatus = NDIS_STATUS_TAPI_INVALPARAM;
break;
case LINEERR_CALLUNAVAIL:
NdisStatus = NDIS_STATUS_TAPI_CALLUNAVAIL;
break;
case LINEERR_INCOMPATIBLEEXTVERSION:
NdisStatus = NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION;
break;
case LINEERR_INVALLINESTATE:
NdisStatus = NDIS_STATUS_TAPI_INVALLINESTATE;
break;
case LINEERR_INVALCARD:
case LINEERR_NODEVICE:
case LINEERR_UNINITIALIZED:
NdisStatus = NDIS_STATUS_TAPI_NODEVICE;
break;
case LINEERR_NODRIVER:
NdisStatus = NDIS_STATUS_TAPI_NODRIVER;
break;
case LINEERR_NOMEM:
NdisStatus = NDIS_STATUS_RESOURCES;
break;
case LINEERR_OPERATIONUNAVAIL:
NdisStatus = NDIS_STATUS_TAPI_OPERATIONUNAVAIL;
break;
case LINEERR_RESOURCEUNAVAIL:
NdisStatus = NDIS_STATUS_TAPI_RESOURCEUNAVAIL;
break;
case LINEERR_INCOMPATIBLEAPIVERSION:
case LINEERR_OPERATIONFAILED:
NdisStatus = NDIS_STATUS_FAILURE;
break;
default:
//
// All TAPI codes should be covered explicitly, if
// they are not we can catch them with the assert and
// add them.
//
ASSERT(FALSE);
NdisStatus = NDIS_STATUS_FAILURE;
break;
}
return NdisStatus;
}
DWORD WINAPI
LineConfigDialogEditThread(
LPVOID pVArg)
{
PNDIS_TAPI_LINE_CONFIG_DIALOG_EDIT pConfigDlgEdit = (PNDIS_TAPI_LINE_CONFIG_DIALOG_EDIT)pVArg;
long lResult;
LPTSTR szDeviceClass;
//
// In case any of the data is on the application stack or heap...
//
SetProcPermissions(-1);
if (pConfigDlgEdit->ulDeviceClassLen) {
szDeviceClass = (LPTSTR)pConfigDlgEdit->DataBuf;
} else {
szDeviceClass = NULL;
}
lResult = lineConfigDialogEdit (pConfigDlgEdit->ulDeviceID,
pConfigDlgEdit->hwndOwner,
szDeviceClass,
pConfigDlgEdit->DataBuf + pConfigDlgEdit->ulConfigInOffset,
pConfigDlgEdit->ulConfigInSize,
(LPVARSTRING)(pConfigDlgEdit->DataBuf + pConfigDlgEdit->ulConfigOutOffset));
return (DWORD)lResult;
}
NDIS_STATUS
MpQueryInfo(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesWritten,
OUT PULONG BytesNeeded
)
/*++
Routine Description:
The MpQueryProtocolInformation process a Query request for
NDIS_OIDs that are specific to a binding about the MAC. Note that
some of the OIDs that are specific to bindings are also queryable
on a global basis. Rather than recreate this code to handle the
global queries, I use a flag to indicate if this is a query for the
global data or the binding specific data.
Arguments:
Adapter - a pointer to the adapter.
Oid - the NDIS_OID to process.
Return Value:
The function value is the status of the operation.
--*/
{
NDIS_MEDIUM Medium = NdisMediumWan;
PASYNCMAC_ADAPTER pAdapter = (PASYNCMAC_ADAPTER)MiniportAdapterContext;
NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
PVOID MoveSource;
ULONG MoveBytes;
ULONG GenericULong = 0;
USHORT GenericUShort = 0;
INT fDoCommonMove = TRUE;
UCHAR WanAddress[6] = {' ','A','S','Y','N',0xFF}; // This is the address returned by OID_WAN_*_ADDRESS.
DEBUGMSG (ZONE_INIT|ZONE_INTERFACE,
(TEXT("+ASYNCMAC:MpQueryInfo(0x%X, 0x%X(%hs), 0x%X, %d, 0x%X, 0x%X)\r\n"),
MiniportAdapterContext, Oid, GetOidString(Oid),
InformationBuffer, InformationBufferLength,
BytesWritten, BytesNeeded));
ASSERT(CHK_AA(pAdapter));
MoveSource = &GenericULong;
MoveBytes = sizeof(GenericULong);
switch ( Oid ) {
case OID_GEN_SUPPORTED_LIST:
MoveSource = (PVOID) SupportedOids;
MoveBytes = sizeof(SupportedOids);
break;
case OID_GEN_MEDIA_SUPPORTED :
case OID_GEN_MEDIA_IN_USE:
MoveSource = (PVOID)&Medium;
MoveBytes = sizeof(Medium);
break;
case OID_GEN_VENDOR_ID:
GenericULong = 0xFFFFFFFF;
MoveBytes = 3;
break;
case OID_GEN_VENDOR_DESCRIPTION:
MoveSource = (PVOID)"AsyncMac Adapter";
MoveBytes = 16;
break;
case OID_GEN_DRIVER_VERSION:
GenericUShort = 0x0300;
MoveSource = (PVOID)&GenericUShort;
MoveBytes = sizeof(USHORT);
break;
case OID_GEN_HARDWARE_STATUS:
MoveSource = (PVOID)&HardwareStatus;
MoveBytes = sizeof(HardwareStatus);
break;
case OID_GEN_LINK_SPEED:
//
// Who knows what the initial link speed is?
// This should not be called, right?
//
GenericULong = (ULONG)288;
break;
case OID_TAPI_PROVIDER_INITIALIZE:
fDoCommonMove = FALSE;
if (InformationBufferLength < sizeof(NDIS_TAPI_PROVIDER_INITIALIZE)) {
StatusToReturn = NDIS_STATUS_BUFFER_TOO_SHORT;
*BytesNeeded = sizeof(NDIS_TAPI_PROVIDER_INITIALIZE);
} else {
PNDIS_TAPI_PROVIDER_INITIALIZE pProvInit = (PNDIS_TAPI_PROVIDER_INITIALIZE)InformationBuffer;
pProvInit->ulNumLineDevs = pAdapter->dwNumDevs;
*BytesWritten = sizeof(NDIS_TAPI_PROVIDER_INITIALIZE);
}
break;
case OID_TAPI_GET_DEV_CAPS :
fDoCommonMove = FALSE;
if (InformationBufferLength < sizeof(NDIS_TAPI_GET_DEV_CAPS))
{
StatusToReturn = NDIS_STATUS_BUFFER_TOO_SHORT;
*BytesNeeded = sizeof(NDIS_TAPI_GET_DEV_CAPS);
} else
{
LONG lResult;
PNDIS_TAPI_GET_DEV_CAPS pGetDevCaps = (PNDIS_TAPI_GET_DEV_CAPS)InformationBuffer;
lResult = lineGetDevCaps(pAdapter->hLineApp, pGetDevCaps->ulDeviceID, pAdapter->dwAPIVersion,
0, (LPLINEDEVCAPS)&(pGetDevCaps->LineDevCaps));
if (lResult != 0)
{
DEBUGMSG (ZONE_TAPI|ZONE_ERROR, (TEXT("lineGetDevCaps failed (%d)\n"), lResult));
StatusToReturn = MapTapiErrorToNdisStatus(lResult);
}
}
break;
case OID_TAPI_GET_DEV_CONFIG :
fDoCommonMove = FALSE;
if (InformationBufferLength < sizeof(NDIS_TAPI_GET_DEV_CONFIG))
{
DEBUGMSG (ZONE_TAPI, (TEXT("ASYNCMAC: Buffer too short (%d < %d)\n"), InformationBufferLength, sizeof(NDIS_TAPI_GET_DEV_CONFIG)));
StatusToReturn = NDIS_STATUS_BUFFER_TOO_SHORT;
*BytesNeeded = sizeof(NDIS_TAPI_GET_DEV_CONFIG);
break;
}
else
{
PNDIS_TAPI_GET_DEV_CONFIG pTapiDevConfig = (PNDIS_TAPI_GET_DEV_CONFIG)InformationBuffer;
LPVARSTRING pDevConfig = (LPVARSTRING)&pTapiDevConfig->DeviceConfig;
LONG lResult;
DEBUGMSG (ZONE_TAPI, (TEXT("ASYNCMAC: Calling lineGetDevConfig\n")));
lResult = lineGetDevConfig(
pTapiDevConfig->ulDeviceID,
pDevConfig,
DEV_CLASS_COMM_DATAMODEM);
if (lResult != 0)
{
DEBUGMSG (ZONE_TAPI|ZONE_ERROR, (TEXT("lineGetDevConfig failed (%d)\n"), lResult));
StatusToReturn = MapTapiErrorToNdisStatus(lResult);
}
}
break;
case OID_TAPI_TRANSLATE_ADDRESS :
fDoCommonMove = FALSE;
if (InformationBufferLength < sizeof(NDIS_TAPI_LINE_TRANSLATE)) {
StatusToReturn = NDIS_STATUS_BUFFER_TOO_SHORT;
*BytesNeeded = sizeof(NDIS_TAPI_LINE_TRANSLATE);
DEBUGMSG (ZONE_ERROR, (TEXT(" ASYNCMAC:MpQueryInfo length too short for lineTranslateAddress, new length=%d\r\n"),
*BytesNeeded));
} else {
PNDIS_TAPI_LINE_TRANSLATE pLineTranslate = (PNDIS_TAPI_LINE_TRANSLATE)InformationBuffer;
long lResult;
// Lame check to see if the structures are the same size
ASSERT (sizeof(LINETRANSLATEOUTPUT) == sizeof(LINE_TRANSLATE_OUTPUT));
lResult = lineTranslateAddress (pAdapter->hLineApp, pLineTranslate->ulDeviceID,
pAdapter->dwAPIVersion, (LPTSTR)pLineTranslate->DataBuf,
0, pLineTranslate->ulTranslateOptions,
(LPLINETRANSLATEOUTPUT)(pLineTranslate->DataBuf+pLineTranslate->ulLineTranslateOutputOffset));
if (lResult != 0) {
DEBUGMSG (ZONE_ERROR, (TEXT(" ASYNCMAC:MpQueryInfo Error %d from lineTranslateAddress\r\n"),
lResult));
StatusToReturn = MapTapiErrorToNdisStatus(lResult);
}
}
break;
case OID_TAPI_OPEN :
fDoCommonMove = FALSE;
if (InformationBufferLength < sizeof(NDIS_TAPI_OPEN)) {
StatusToReturn = NDIS_STATUS_BUFFER_TOO_SHORT;
*BytesNeeded = sizeof(NDIS_TAPI_OPEN);
break;
} else {
PNDIS_TAPI_OPEN pTapiOpen = (PNDIS_TAPI_OPEN)InformationBuffer;
PASYNCMAC_OPEN_LINE pOpenLine;
long lResult;
pOpenLine = AsyncMacAllocateMemory(sizeof(ASYNCMAC_OPEN_LINE));
if (pOpenLine == NULL)
{
StatusToReturn = NDIS_STATUS_RESOURCES;
break;
}
ASSERT(AsyncMacGuardRegionOk(pOpenLine, sizeof(ASYNCMAC_OPEN_LINE)));
#ifdef DEBUG
pOpenLine->dwDebugSigStart = AOL_SIG_START;
pOpenLine->dwDebugSigEnd = AOL_SIG_END;
DEBUGMSG (ZONE_ALLOC, (TEXT(" ASYNCMAC:MpQueryInfo: Allocated pOpenLine 0x%X(%d)\r\n"),
pOpenLine, sizeof(ASYNCMAC_OPEN_LINE)));
#endif
DEBUGMSG (ZONE_TAPI, (TEXT("***Allocated pOpenLine at 0x%X\r\n"),
pOpenLine));
pOpenLine->dwRefCnt = 1; // InitializeRefCnt
pOpenLine->pAdapter = pAdapter;
pOpenLine->dwDeviceID = pTapiOpen->ulDeviceID;
pOpenLine->htLine = pTapiOpen->htLine;
pOpenLine->dwBaudRate = AOL_DEF_BAUD_RATE; // Default baud rate.
// Initialize the GET_LINK_INFO struct
pOpenLine->WanLinkInfo.MaxSendFrameSize = pAdapter->MaxSendFrameSize;
pOpenLine->WanLinkInfo.MaxRecvFrameSize = pAdapter->MaxRecvFrameSize;
pOpenLine->WanLinkInfo.HeaderPadding = pAdapter->Info.HeaderPadding;
pOpenLine->WanLinkInfo.TailPadding = pAdapter->Info.TailPadding;
pOpenLine->WanLinkInfo.SendFramingBits = PPP_FRAMING; // For SLIP, we will have to be told to turn this off.
pOpenLine->WanLinkInfo.RecvFramingBits = PPP_FRAMING;
pOpenLine->WanLinkInfo.SendCompressionBits = 0;
pOpenLine->WanLinkInfo.RecvCompressionBits = 0;
pOpenLine->WanLinkInfo.SendACCM = (ULONG) -1;
pOpenLine->WanLinkInfo.RecvACCM = (ULONG) -1;
lResult = lineOpen(pAdapter->hLineApp, pTapiOpen->ulDeviceID,
&pOpenLine->hLine,
pAdapter->dwAPIVersion, 0,
(DWORD)pOpenLine, LINECALLPRIVILEGE_OWNER,
LINEMEDIAMODE_DATAMODEM, NULL);
if (lResult != 0) {
DEBUGMSG (ZONE_TAPI|ZONE_ERROR,
(TEXT("lineOpen failed (%x)\r\n"), lResult));
AsyncMacFreeMemory (pOpenLine, sizeof(ASYNCMAC_OPEN_LINE));
StatusToReturn = MapTapiErrorToNdisStatus(lResult);
} else {
DEBUGMSG (ZONE_TAPI, (TEXT("lineOpen success\r\n")));
pTapiOpen->hdLine = (HDRV_LINE)pOpenLine;
// Add ourselves to the list of open lines for this adapter
pOpenLine->pNext = pAdapter->pHead;
pAdapter->pHead = pOpenLine;
DEBUGMSG(ZONE_TAPI, (TEXT(" Add pOpenLine=%x to pAdapter=%x (v_pAdapter=%x)\n"), pOpenLine, pAdapter, v_pAdapter));
}
}
break;
case OID_TAPI_MAKE_CALL :
fDoCommonMove = FALSE;
if (InformationBufferLength < sizeof(NDIS_TAPI_MAKE_CALL)) {
StatusToReturn = NDIS_STATUS_BUFFER_TOO_SHORT;
*BytesNeeded = sizeof(NDIS_TAPI_MAKE_CALL);
break;
} else {
PNDIS_TAPI_MAKE_CALL pTapiMakeCall = (PNDIS_TAPI_MAKE_CALL)InformationBuffer;
long lResult;
PASYNCMAC_OPEN_LINE pOpenLine;
LINECALLPARAMS CallParams;
LPTSTR szDialStr;
pOpenLine = (PASYNCMAC_OPEN_LINE)pTapiMakeCall->hdLine;
ASSERT(CHK_AOL(pOpenLine));
pOpenLine->htCall = pTapiMakeCall->htCall;
#ifdef TODO
// For now I'll assume that the bUserDefaultCallParams has been
// specified
#endif
szDialStr = (LPTSTR)((PBYTE)pTapiMakeCall+pTapiMakeCall->ulDestAddressOffset);
RETAILMSG (1, (TEXT("ASYNCMAC: Dialing '%s'\r\n"), szDialStr));
memset ((char *)&CallParams, 0, sizeof(LINECALLPARAMS));
CallParams.dwTotalSize = sizeof(LINECALLPARAMS);
CallParams.dwBearerMode = LINEBEARERMODE_DATA;
CallParams.dwMinRate = 0; // Any rate
CallParams.dwMaxRate = 0; // This should mean any max rate
CallParams.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
CallParams.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
CallParams.dwAddressMode = LINEADDRESSMODE_ADDRESSID;
CallParams.dwAddressID = 0; // there's only one address...
lResult = lineMakeCall (pOpenLine->hLine, &(pOpenLine->hCall),
szDialStr, 0,
&CallParams);
if (lResult < 0) {
DEBUGMSG (ZONE_TAPI|ZONE_ERROR,
(TEXT("Error %x from lineMakeCall\r\n"), lResult));
StatusToReturn = MapTapiErrorToNdisStatus(lResult);
} else {
DEBUGMSG (ZONE_TAPI, (TEXT("lineMakeCall Success. RequestID=%d, hCall=0x%X\r\n"),
lResult, pOpenLine->hCall));
pTapiMakeCall->hdCall = (HDRV_CALL)pOpenLine;
pOpenLine->TapiReqID = lResult;
}
ASSERT(CHK_AOL(pOpenLine));
}
break;
case OID_TAPI_CONFIG_DIALOG_EDIT :
fDoCommonMove = FALSE;
if (InformationBufferLength < sizeof(NDIS_TAPI_LINE_CONFIG_DIALOG_EDIT)) {
StatusToReturn = NDIS_STATUS_BUFFER_TOO_SHORT;
*BytesNeeded = sizeof(NDIS_TAPI_LINE_CONFIG_DIALOG_EDIT);
DEBUGMSG (ZONE_ERROR, (TEXT(" ASYNCMAC:MpQueryInfo length too short for lineTranslateAddress, new length=%d\r\n"),
*BytesNeeded));
} else {
long lResult;
HANDLE hEditThread;
DWORD dwID;
//
// Spin a thread to do the edit.
// That way, when the edit thread goes away GWE will release any "hidden" window
// from the system. Otherwise the hidden window would persist as long as the INdisDriverThread
// for asyncmac was around and cause problems as there is no message pump for it.
//
hEditThread = CreateThread(NULL, 0, LineConfigDialogEditThread, InformationBuffer, 0, &dwID);
if (hEditThread == INVALID_HANDLE_VALUE)
{
StatusToReturn = NDIS_STATUS_RESOURCES;
}
else
{
WaitForSingleObject(hEditThread, INFINITE);
GetExitCodeThread(hEditThread, (PDWORD)&lResult);
CloseHandle(hEditThread);
DEBUGMSG (lResult && ZONE_ERROR, (TEXT(" ASYNCMAC:MpQueryInfo Error 0x%X(%d) from lineConfigDialogEdit\r\n"), lResult, lResult));
}
}
break;
case OID_WAN_CURRENT_ADDRESS:
case OID_WAN_PERMANENT_ADDRESS:
MoveSource = WanAddress;
MoveBytes = sizeof(WanAddress);
break;
case OID_WAN_GET_INFO:
MoveSource = &pAdapter->Info;
MoveBytes = sizeof(pAdapter->Info);
break;
case OID_WAN_MEDIUM_SUBTYPE:
GenericULong = NdisWanMediumSerial;
break;
case OID_WAN_HEADER_FORMAT:
GenericULong = NdisWanHeaderEthernet;
break;
case OID_GEN_MAC_OPTIONS:
GenericULong = (ULONG)(NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
NDIS_MAC_OPTION_FULL_DUPLEX |
NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA);
break;
case OID_GEN_MAXIMUM_LOOKAHEAD :
case OID_GEN_CURRENT_LOOKAHEAD:
case OID_GEN_MAXIMUM_FRAME_SIZE:
case OID_GEN_TRANSMIT_BLOCK_SIZE:
case OID_GEN_RECEIVE_BLOCK_SIZE:
case OID_GEN_MAXIMUM_TOTAL_SIZE:
GenericULong = pAdapter->Info.MaxFrameSize;
break;
case OID_GEN_TRANSMIT_BUFFER_SPACE:
case OID_GEN_RECEIVE_BUFFER_SPACE:
// TODO: Get real buffer space numbers
GenericULong = (ULONG)(pAdapter->Info.MaxFrameSize * 2);
break;
case OID_WAN_GET_LINK_INFO :
if (InformationBufferLength < sizeof (NDIS_WAN_GET_LINK_INFO)) {
StatusToReturn = NDIS_STATUS_BUFFER_TOO_SHORT;
*BytesNeeded = sizeof(NDIS_WAN_GET_LINK_INFO);
break;
} else {
PNDIS_WAN_GET_LINK_INFO pLinkInfo = (PNDIS_WAN_GET_LINK_INFO)InformationBuffer;
PASYNCMAC_OPEN_LINE pOpenLine;
pOpenLine = (PASYNCMAC_OPEN_LINE)pLinkInfo->NdisLinkHandle;
ASSERT(CHK_AOL(pOpenLine));
// Let's move this just in case...
pOpenLine->WanLinkInfo.NdisLinkHandle = pLinkInfo->NdisLinkHandle;
MoveSource = &pOpenLine->WanLinkInfo;
MoveBytes = sizeof(pOpenLine->WanLinkInfo);
}
break;
default:
DEBUGMSG (ZONE_ERROR,
(TEXT(" ASYNCMAC:MpQueryInfo: OID 0x%X/%hs not supported\r\n"),
Oid, GetOidString(Oid)));
StatusToReturn = NDIS_STATUS_NOT_SUPPORTED;
break;
}
if ( StatusToReturn == NDIS_STATUS_SUCCESS ) {
if (fDoCommonMove) {
//
// If there is enough room then we can copy the data and
// return the number of bytes copied, otherwise we must
// fail and return the number of bytes needed.
//
if ( MoveBytes <= InformationBufferLength ) {
memcpy (InformationBuffer, MoveSource, MoveBytes);
*BytesWritten = MoveBytes;
} else {
*BytesNeeded = MoveBytes;
StatusToReturn = NDIS_STATUS_BUFFER_TOO_SHORT;
}
}
}
DEBUGMSG (ZONE_INIT|ZONE_INTERFACE,
(TEXT("-ASYNCMAC:MpQueryInfo: Returning 0x%X\r\n"),
StatusToReturn));
return StatusToReturn;
}
NDIS_STATUS
MpSetInfo(
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN ULONG InformationBufferLength,
OUT PULONG BytesRead,
OUT PULONG BytesNeeded
)
/*++
Routine Description:
The AsyncSetInformation is used by AsyncRequest to set information
about the MAC.
Note: Assumes it is called with the lock held. Any calls are made down
to the serial driver from this routine may return pending. If this happens
the completion routine for the call needs to complete this request by
calling NdisMSetInformationComplete.
Arguments:
MiniportAdapterContext - A pointer to the adapter.
Return Value:
The function value is the status of the operation.
--*/
{
PASYNCMAC_ADAPTER pAdapter = (PASYNCMAC_ADAPTER)MiniportAdapterContext;
NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
DEBUGMSG (ZONE_INIT|ZONE_INTERFACE,
(TEXT("+ASYNCMAC:MpSetInfo(0x%X, 0x%X, 0x%X, %d, 0x%X, 0x%X)\r\n"),
MiniportAdapterContext, Oid, InformationBuffer,
InformationBufferLength, BytesRead, BytesNeeded));
ASSERT(CHK_AA(pAdapter));
switch ( Oid ) {
case OID_WAN_SET_LINK_INFO :
if (InformationBufferLength < sizeof (NDIS_WAN_GET_LINK_INFO)) {
StatusToReturn = NDIS_STATUS_BUFFER_TOO_SHORT;
*BytesNeeded = sizeof(NDIS_WAN_GET_LINK_INFO);
break;
} else {
PNDIS_WAN_GET_LINK_INFO pLinkInfo = (PNDIS_WAN_GET_LINK_INFO)InformationBuffer;
PASYNCMAC_OPEN_LINE pOpenLine;
pOpenLine = (PASYNCMAC_OPEN_LINE)pLinkInfo->NdisLinkHandle;
ASSERT(CHK_AOL(pOpenLine));
DEBUGMSG (1, (TEXT("MpSetInfo: Orig ACCM=0x%X\r\n"), pOpenLine->WanLinkInfo.SendACCM));
// Let's just save this away.
memcpy ((char *)&(pOpenLine->WanLinkInfo),
(char *)pLinkInfo,
sizeof (pOpenLine->WanLinkInfo));
DEBUGMSG (1, (TEXT("MpSetInfo: New ACCM=0x%X\r\n"), pOpenLine->WanLinkInfo.SendACCM));
}
break;
case OID_TAPI_SET_DEV_CONFIG :
if (InformationBufferLength < sizeof(NDIS_TAPI_SET_DEV_CONFIG))
{
DEBUGMSG (ZONE_TAPI, (TEXT("ASYNCMAC: Buffer too short (%d < %d)\n"), InformationBufferLength, sizeof(NDIS_TAPI_SET_DEV_CONFIG)));
StatusToReturn = NDIS_STATUS_BUFFER_TOO_SHORT;
*BytesNeeded = sizeof(NDIS_TAPI_SET_DEV_CONFIG);
break;
}
else
{
PNDIS_TAPI_SET_DEV_CONFIG pTapiDevConfig = (PNDIS_TAPI_SET_DEV_CONFIG)InformationBuffer;
LONG lResult;
if (pTapiDevConfig->ulDeviceConfigSize > 0)
{
DEBUGMSG (ZONE_TAPI, (TEXT("ASYNCMAC: Calling lineSetDevConfig\n")));
lResult = lineSetDevConfig (
pTapiDevConfig->ulDeviceID,
&pTapiDevConfig->DeviceConfig[0],
pTapiDevConfig->ulDeviceConfigSize,
DEV_CLASS_COMM_DATAMODEM);
if (lResult != 0)
{
DEBUGMSG (ZONE_TAPI|ZONE_ERROR,
(TEXT("lineSetDevConfig failed (%d)\n"), lResult));
StatusToReturn = NDIS_STATUS_TAPI_INVALPARAM;
}
}
}
break;
case OID_TAPI_DROP :
DEBUGMSG(ZONE_INTERFACE, (TEXT("ASYNCMAC: OID_TAPI_DROP\n")));
if (InformationBufferLength < sizeof (NDIS_TAPI_DROP)) {
StatusToReturn = NDIS_STATUS_BUFFER_TOO_SHORT;
*BytesNeeded = sizeof(NDIS_TAPI_DROP);
break;
} else {
PNDIS_TAPI_DROP pTapiDrop = (PNDIS_TAPI_DROP)InformationBuffer;
PASYNCMAC_OPEN_LINE pOpenLine;
long lResult;
// We return the pOpenLine for the hdCall.
pOpenLine = (PASYNCMAC_OPEN_LINE)pTapiDrop->hdCall;
ASSERT(CHK_AOL(pOpenLine));
// Forward on the info.
lResult = lineDrop(pOpenLine->hCall, pTapiDrop->UserUserInfo,
pTapiDrop->ulUserUserInfoSize);
DEBUGMSG( ZONE_TAPI, (TEXT("Return from lineDrop()=%d\r\n"), lResult));
}
break;
case OID_TAPI_CLOSE_CALL :
DEBUGMSG(ZONE_INTERFACE, (TEXT("ASYNCMAC: OID_TAPI_CLOSE_CALL\n")));
if (InformationBufferLength < sizeof (NDIS_TAPI_CLOSE_CALL)) {
StatusToReturn = NDIS_STATUS_BUFFER_TOO_SHORT;
*BytesNeeded = sizeof(NDIS_TAPI_CLOSE_CALL);
break;
} else {
PNDIS_TAPI_CLOSE_CALL pTapiCloseCall = (PNDIS_TAPI_CLOSE_CALL)InformationBuffer;
PASYNCMAC_OPEN_LINE pOpenLine;
long lResult;
// We return the pOpenLine for the hdCall.
pOpenLine = (PASYNCMAC_OPEN_LINE)pTapiCloseCall->hdCall;
ASSERT(CHK_AOL(pOpenLine));
// TAPI docs state that CloseHandle must be done on the hPort before
// calling lineDeallocateCall.
if (pOpenLine->hPort != NULL)
{
CloseHandle(pOpenLine->hPort);
pOpenLine->hPort = NULL;
}
lResult = lineDeallocateCall( pOpenLine->hCall );
pOpenLine->hCall = NULL;
// We don't actually free the pOpenLine until the OID_TAPI_CLOSE.
DEBUGMSG( ZONE_TAPI, (TEXT("Return from lineDeallocateCall()=%d\r\n"),
lResult));
}
break;
case OID_TAPI_CLOSE :
DEBUGMSG(ZONE_INTERFACE, (TEXT("ASYNCMAC: OID_TAPI_CLOSE\n")));
if (InformationBufferLength < sizeof (NDIS_TAPI_CLOSE)) {
StatusToReturn = NDIS_STATUS_BUFFER_TOO_SHORT;
*BytesNeeded = sizeof(NDIS_TAPI_CLOSE);
break;
} else {
PNDIS_TAPI_CLOSE pTapiClose = (PNDIS_TAPI_CLOSE)InformationBuffer;
PASYNCMAC_OPEN_LINE pOpenLine;
long lResult;
// We return the pOpenLine for the hdLine.
pOpenLine = (PASYNCMAC_OPEN_LINE)pTapiClose->hdLine;
ASSERT(CHK_AOL(pOpenLine));
// Ok, now it's removed from the list.
lResult = lineClose (pOpenLine->hLine);
ReleaseOpenLinePtr (pOpenLine);
DEBUGMSG( ZONE_TAPI, (TEXT("Return from lineClose()=%d\r\n"), lResult));
}
break;
default:
StatusToReturn = NDIS_STATUS_INVALID_OID;
*BytesRead = 0;
*BytesNeeded = 0;
break;
}
DEBUGMSG (ZONE_INIT|ZONE_INTERFACE,
(TEXT("-ASYNCMAC:MpSetInfo: Returning 0x%X\r\n"),
StatusToReturn));
return StatusToReturn;
}
NDIS_STATUS
MpReconfigure(
OUT PNDIS_STATUS OpenErrorStatus,
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_HANDLE WrapperConfigurationContext
)
{
DEBUGMSG (ZONE_INIT|ZONE_INTERFACE,
(TEXT("+/-ASYNCMAC:MpReconfigure(0x%X, 0x%X, 0x%X)\r\n"),
OpenErrorStatus, MiniportAdapterContext,
WrapperConfigurationContext));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
MpReset(
OUT PBOOLEAN AddressingReset,
IN NDIS_HANDLE MiniportAdapterContext
)
{
DEBUGMSG (ZONE_INIT|ZONE_INTERFACE,
(TEXT("+/-ASYNCMAC:MpReset(0x%X, 0x%X)\r\n"),
AddressingReset, MiniportAdapterContext));
*AddressingReset = FALSE;
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
MpSend(
IN NDIS_HANDLE MacBindingHandle,
IN NDIS_HANDLE NdisLinkHandle,
IN PNDIS_WAN_PACKET pPacket)
{
PASYNCMAC_OPEN_LINE pOpenLine = (PASYNCMAC_OPEN_LINE) NdisLinkHandle;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
DWORD bytesWritten; // bytes written per WriteFile call
DWORD packetBytesSent; // sum of prior WriteFile bytesWritten
DEBUGMSG (ZONE_INIT|ZONE_INTERFACE,
(TEXT("ASYNCMAC:+MpSend(0x%X, 0x%X, 0x%X)\r\n"),
MacBindingHandle, NdisLinkHandle,
pPacket));
if (pOpenLine == NULL)
{
//
// This can happen if the connection is closed by RAS/PPP just as it is
// sending a packet. In this case, we don't want to send anything.
//
Status = NDIS_STATUS_FAILURE;
}
else
{
ASSERT(CHK_AOL(pOpenLine));
// Let's just send it for now.
if (pOpenLine->hPort == NULL)
{
Status = NDIS_STATUS_FAILURE;
}
else
{
#ifdef DEBUG
if (ZONE_SEND)
{
DEBUGMSG (1, (TEXT("ASYNCMAC: MpSend: About to frame packet (%d):\n"), pPacket->CurrentLength));
DumpMem (pPacket->CurrentBuffer, pPacket->CurrentLength);
}
#endif
if (pOpenLine->WanLinkInfo.SendFramingBits & PPP_FRAMING)
{
// Do CRC generation and escape byte insertion
AssemblePPPFrame (pOpenLine, pPacket);
}
else
{
// Do SLIP escape byte insertion
AssembleSLIPFrame(pOpenLine, pPacket);
}
#ifdef DEBUG
// DEBUGMSG (1, (TEXT("MpSend: After frame packet (%d):\r\n"), pPacket->CurrentLength));
// DumpMem (pPacket->CurrentBuffer, pPacket->CurrentLength);
#endif
for (packetBytesSent = 0;
packetBytesSent < pPacket->CurrentLength;
packetBytesSent += bytesWritten)
{
if (!WriteFile (pOpenLine->hPort, pPacket->CurrentBuffer + packetBytesSent,
pPacket->CurrentLength - packetBytesSent, &bytesWritten, 0)
|| bytesWritten == 0)
{
DEBUGMSG(ZONE_SEND | ZONE_ERROR, (
TEXT( "AsyncMac:WriteFile Error %d Aborting Packet after sending %d of %d bytes\r\n" ),
GetLastError(), packetBytesSent, pPacket->CurrentLength) );
Status = NDIS_STATUS_FAILURE;
break;
}
DEBUGMSG (ZONE_SEND, (TEXT("AsyncMac: MpSend wrote %d bytes\r\n"), bytesWritten));
}
}
}
DEBUGMSG ((ZONE_INIT|ZONE_INTERFACE) || (ZONE_ERROR && Status),
(TEXT("ASYNCMAC:-MpSend: Returning 0x%X\r\n"),
Status));
return Status;
}
BOOL
IsValidOpenLinePtr(PASYNCMAC_OPEN_LINE pOpenLine)
//
// Validate pOpenLine.
// Return TRUE if it is valid, FALSE otherwise.
//
// This function must be called with v_AdapterCS held.
{
BOOL bValid = FALSE;
PASYNCMAC_OPEN_LINE pOLCurrent;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+IsValidOpenLinePtr %x\n"), pOpenLine));
DEBUGMSG(ZONE_MISC, (TEXT(" IsValidOpenLinePtr v_pAdapter=%x\n"), v_pAdapter));
if (v_pAdapter)
{
DEBUGMSG(ZONE_MISC, (TEXT(" IsValidOpenLinePtr pHead=%x\n"), v_pAdapter->pHead));
for (pOLCurrent = v_pAdapter->pHead; pOLCurrent; pOLCurrent = pOLCurrent->pNext)
{
DEBUGMSG(ZONE_MISC, (TEXT(" IsValidOpenLinePtr pOLCurrent=%x\n"), pOLCurrent));
if (pOLCurrent == pOpenLine)
{
bValid = TRUE;
break;
}
}
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("-IsValidOpenLinePtr %x result=%d\n"), pOpenLine, bValid));
return bValid;
}
void
ReleaseOpenLinePtr (PASYNCMAC_OPEN_LINE pOpenLine)
//
// Decrement the refcnt for the OpenLine parameter.
// If the refcnt reaches zero, then no threads are using the OpenLine and so it is freed.
//
{
PASYNCMAC_OPEN_LINE pOLTemp;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+ReleaseOpenLinePtr %x\n"), pOpenLine));
EnterCriticalSection(&v_AdapterCS);
if (IsValidOpenLinePtr(pOpenLine))
{
pOpenLine->dwRefCnt--;
DEBUGMSG(ZONE_MISC, (TEXT(" ReleaseOpenLinePtr refcnt now %d\n"), pOpenLine->dwRefCnt));
if (0 == pOpenLine->dwRefCnt) {
DEBUGMSG(ZONE_MISC, (TEXT(" ReleaseOpenLinePtr removing pOpenLine=%x\n"), pOpenLine));
// Remove this from the adapter list.
if (pOpenLine == pOpenLine->pAdapter->pHead) {
// Trivial case, remove from head.
pOpenLine->pAdapter->pHead = pOpenLine->pNext;
DEBUGMSG(ZONE_MISC, (TEXT(" ReleaseOpenLinePtr trivial remove from head\n")));
} else {
for (pOLTemp = pOpenLine->pAdapter->pHead; pOLTemp; pOLTemp = pOLTemp->pNext) {
if (pOLTemp->pNext == pOpenLine) {
pOLTemp->pNext = pOpenLine->pNext;
break;
}
}
ASSERT (pOLTemp);
}
DEBUGMSG(ZONE_MISC, (TEXT("***ReleaseOpenLinePtr FREEING pOpenLine=%x\n"), pOpenLine));
AsyncMacFreeMemory (pOpenLine, sizeof(ASYNCMAC_OPEN_LINE));
}
}
LeaveCriticalSection(&v_AdapterCS);
DEBUGMSG(ZONE_FUNCTION, (TEXT("-ReleaseOpenLinePtr %x\n"), pOpenLine));
}
PASYNCMAC_OPEN_LINE
GetOpenLinePtr (void *context)
//
// Return an OPEN_LINE ptr if the context is valid, NULL if not.
//
// Increments the refcnt to the OPEN_LINE.
//
// The caller of this function must call ReleaseOpenLinePtr if this
// function returns non-NULL, in order to decrement the refcnt.
//
{
PASYNCMAC_OPEN_LINE pOpenLine = (PASYNCMAC_OPEN_LINE) context;
DEBUGMSG(ZONE_FUNCTION, (TEXT("+GetOpenLinePtr %x\n"), pOpenLine));
EnterCriticalSection(&v_AdapterCS);
if (IsValidOpenLinePtr(pOpenLine))
{
// Increment refcnt to make sure it doesn't go away while in use.
pOpenLine->dwRefCnt++;
DEBUGMSG(ZONE_FUNCTION, (TEXT(" GetOpenLinePtr refcnt now %d\n"), pOpenLine->dwRefCnt));
}
else
pOpenLine = NULL;
LeaveCriticalSection(&v_AdapterCS);
DEBUGMSG(ZONE_FUNCTION, (TEXT("-GetOpenLinePtr result=%x\n"), pOpenLine));
return pOpenLine;
}
Legal Declaration: it is for studying wince(MicroSoft Windows CE) only! : http://www.vxworks6.com