www.pudn.com > PPPOE.rar > miniport.cpp
//********************************************************************
// ÈÕÆÚ: 2004/08/25 - 25:8:2004 1:44
// Ãûǰ: tiamo
// ÃèÊö: miniport
//*********************************************************************
#include "Stdafx.h"
#pragma alloc_text(PAGE,miniportInitialize)
#pragma alloc_text(PAGE,miniportHalt)
// miniport init
NDIS_STATUS miniportInitialize(PNDIS_STATUS pOpenErrorStatus,PUINT puSelectedMediumIndex,PNDIS_MEDIUM pMediumArray,
UINT uMediumArraySize,NDIS_HANDLE hAdapterHandle,NDIS_HANDLE hConfigurationContext)
{
PAGED_CODE();
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
__try
{
// select cowan medium
UINT i;
for(i = 0; i < uMediumArraySize; i ++)
{
if(pMediumArray[i] == NdisMediumCoWan)
{
*puSelectedMediumIndex = i;
break;
}
}
// check
if(i == uMediumArraySize)
{
DebugError(("unable to select cowan medium.\n"));
ExRaiseStatus(status = NDIS_STATUS_UNSUPPORTED_MEDIA);
}
// allocate adapter
g_pAdapter = CreateAdapter();
// init adapter
status = InitializeAdapter(g_pAdapter,hAdapterHandle,hConfigurationContext);
if(status != NDIS_STATUS_SUCCESS)
{
DebugError(("unable to init adapter.\n"));
ExRaiseStatus(status);
}
// register address family
CO_ADDRESS_FAMILY mcmAf;
mcmAf.AddressFamily = CO_ADDRESS_FAMILY_TAPI_PROXY;
mcmAf.MajorVersion = NDIS_MAJOR_VERSION;
mcmAf.MinorVersion = NDIS_MINOR_VERSION;
NDIS_CALL_MANAGER_CHARACTERISTICS mcmChar;
NdisZeroMemory(&mcmChar,sizeof(mcmChar));
mcmChar.MajorVersion = NDIS_MAJOR_VERSION;
mcmChar.MinorVersion = NDIS_MINOR_VERSION;
mcmChar.CmActivateVcCompleteHandler = (CM_ACTIVATE_VC_COMPLETE_HANDLER)mcmActivateVcComplete;
mcmChar.CmCloseAfHandler = (CM_CLOSE_AF_HANDLER)mcmCloseAf;
mcmChar.CmCloseCallHandler = (CM_CLOSE_CALL_HANDLER)mcmCloseCall;
mcmChar.CmCreateVcHandler = (CO_CREATE_VC_HANDLER)mcmCreateVc;
mcmChar.CmDeactivateVcCompleteHandler = (CM_DEACTIVATE_VC_COMPLETE_HANDLER)mcmDeactivateVcComplete;
mcmChar.CmDeleteVcHandler = (CO_DELETE_VC_HANDLER)mcmDeleteVc;
mcmChar.CmDeregisterSapHandler = (CM_DEREG_SAP_HANDLER)mcmDeregisterSap;
mcmChar.CmIncomingCallCompleteHandler = (CM_INCOMING_CALL_COMPLETE_HANDLER)mcmIncomingCallComplete;
mcmChar.CmMakeCallHandler = (CM_MAKE_CALL_HANDLER)mcmMakeCall;
mcmChar.CmModifyCallQoSHandler = (CM_MODIFY_CALL_QOS_HANDLER)mcmModifyCallQos;
mcmChar.CmOpenAfHandler = (CM_OPEN_AF_HANDLER)mcmOpenAf;
mcmChar.CmRegisterSapHandler = (CM_REG_SAP_HANDLER)mcmRegisterSap;
mcmChar.CmRequestCompleteHandler = (CO_REQUEST_COMPLETE_HANDLER)mcmRequestComplete;
mcmChar.CmRequestHandler= (CO_REQUEST_HANDLER)mcmRequest;
status = NdisMCmRegisterAddressFamily(hAdapterHandle,&mcmAf,&mcmChar,sizeof(mcmChar));
if(status != NDIS_STATUS_SUCCESS)
{
DebugError(("register af error 0x%x.\n",status));
ExRaiseStatus(status);
}
NdisMSetAttributesEx(hAdapterHandle,g_pAdapter,0,
NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |
NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT |
NDIS_ATTRIBUTE_DESERIALIZE |
NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
NdisInterfaceInternal);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
miniportHalt(g_pAdapter);
if(status == NDIS_STATUS_SUCCESS)
status = NDIS_STATUS_FAILURE;
}
return status;
}
// miniport halt
VOID miniportHalt(PADAPTER pAdapter)
{
PAGED_CODE();
ASSERT(pAdapter == g_pAdapter);
ShutdownAdapter(pAdapter);
}
// reset
NDIS_STATUS miniportReset(PBOOLEAN pbAddressingReset,PADAPTER pAdapter)
{
return NDIS_STATUS_NOT_RESETTABLE;
}
// send packet
VOID miniportCoSendPackets(PCHANNEL pChannel,PPNDIS_PACKET pPacketArray,UINT uNumberOfPackets)
{
UINT i = 0;
__try
{
for(; i < uNumberOfPackets; i ++)
{
// build packet
PPACKET pPacket = BuildPacketForSend(pChannel,pPacketArray[i]);
// reference the packet,ref = 2
ReferencePacket(pPacket);
// ref bind,protocol's send complete will deref the bind
ReferenceBind(pChannel->m_pBindContext,TRUE);
// send it
SendPacket(pChannel->m_pBindContext,pPacket);
// deref packet,ref = 1, the protocol's send complete routine will deref the packet
DereferencePacket(pPacket);
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// ndis say that we must call send complete for every packet
for( ;i < uNumberOfPackets; i ++)
{
NdisMCoSendComplete(NDIS_STATUS_FAILURE,pChannel->m_hNdisVcHandle,pPacketArray[i]);
}
}
}
// return packet,which we indicate to upper,just ref the packet
VOID miniportReturnPacket(PADAPTER pAdapter,PNDIS_PACKET pNdisPacket)
{
ASSERT(pAdapter && pAdapter == g_pAdapter && pAdapter->m_ulSig == ADAPTER_SIG);
PMINIPORT_RESERVED pResv = reinterpret_cast(pNdisPacket->MiniportReservedEx);
ASSERT(pResv && pResv->m_pChannel && pResv->m_pPacket && pResv->m_pChannel->m_ulSig == CHANNEL_SIG);
NdisInterlockedDecrement(&pResv->m_pChannel->m_lPendingReturnPackets);
DereferencePacket(pResv->m_pPacket);
}
// miniport corequest
NDIS_STATUS miniportCoRequest(PADAPTER pAdapter,PCHANNEL pChannel,PNDIS_REQUEST pNdisRequest)
{
ASSERT(pAdapter && pAdapter == g_pAdapter && pAdapter->m_ulSig == ADAPTER_SIG);
NDIS_STATUS status;
switch(pNdisRequest->RequestType)
{
case NdisRequestQueryInformation:
case NdisRequestQueryStatistics:
status = QueryRequest(pChannel,pNdisRequest->DATA.QUERY_INFORMATION.Oid,
pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
&pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
&pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
break;
case NdisRequestSetInformation:
status = SetRequest(pChannel,pNdisRequest->DATA.QUERY_INFORMATION.Oid,
pNdisRequest->DATA.SET_INFORMATION.InformationBuffer,
pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength,
&pNdisRequest->DATA.SET_INFORMATION.BytesRead,
&pNdisRequest->DATA.SET_INFORMATION.BytesNeeded);
break;
default:
status = NDIS_STATUS_NOT_SUPPORTED;
break;
}
return status;
}
// miniport coactivate vc
NDIS_STATUS miniportCoActivateVc(PCHANNEL pChannel,PCO_CALL_PARAMETERS pCallParameters)
{
return NDIS_STATUS_SUCCESS;
}
// miniport codeactivate vc
NDIS_STATUS miniportCoDeactivateVc(PCHANNEL pChannel)
{
return NDIS_STATUS_SUCCESS;
}
namespace
{
NDIS_OID _s_supported[] =
{
OID_GEN_CO_SUPPORTED_LIST,
OID_GEN_CO_HARDWARE_STATUS,
OID_GEN_CO_MEDIA_SUPPORTED,
OID_GEN_CO_MEDIA_IN_USE,
OID_GEN_CO_LINK_SPEED,
OID_GEN_CO_VENDOR_ID,
OID_GEN_CO_VENDOR_DESCRIPTION,
OID_GEN_CO_DRIVER_VERSION,
OID_GEN_CO_PROTOCOL_OPTIONS,
OID_GEN_CO_MAC_OPTIONS,
OID_GEN_CO_MEDIA_CONNECT_STATUS,
OID_GEN_CO_VENDOR_DRIVER_VERSION,
OID_GEN_CO_SUPPORTED_GUIDS,
OID_CO_TAPI_CM_CAPS,
OID_CO_TAPI_LINE_CAPS,
OID_CO_TAPI_ADDRESS_CAPS,
OID_802_3_PERMANENT_ADDRESS,
OID_802_3_CURRENT_ADDRESS,
OID_WAN_PERMANENT_ADDRESS,
OID_WAN_CURRENT_ADDRESS,
OID_WAN_MEDIUM_SUBTYPE,
OID_WAN_CO_GET_INFO,
OID_WAN_CO_SET_LINK_INFO,
OID_WAN_CO_GET_LINK_INFO,
OID_WAN_LINE_COUNT,
OID_PNP_CAPABILITIES,
OID_PNP_SET_POWER,
OID_PNP_QUERY_POWER,
};
WCHAR _s_address_name[] = L" Address 00";
WCHAR _s_vendor_desc[] = L"tiamo PPPoE Miniport Driver CoNdis edition for windows";
UCHAR _s_vendor_id[4] = {0x00,0x40,0x46,0x0};
UCHAR _s_address[ETH_ADDR_LEN] = {0x00,0x40,0x46,0x00,0x00,0x01};
}
// query request
NDIS_STATUS QueryRequest(PCHANNEL pChannel,NDIS_OID oid,PVOID pBuffer,UINT uBufferLen,PUINT puWritten,PUINT puNeeded)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
UINT uNeeded = 0;
PVOID pTempBuffer = NULL;
ULONG ulValue = 0;
NDIS_CO_LINK_SPEED linkSpeed;
NDIS_PNP_CAPABILITIES PnpCapabilities;
switch(oid)
{
case OID_GEN_CO_SUPPORTED_LIST:
pTempBuffer = _s_supported;
uNeeded = sizeof(_s_supported);
break;
case OID_GEN_CO_SUPPORTED_GUIDS:
uNeeded = 0;
break;
case OID_GEN_CO_HARDWARE_STATUS:
ulValue = NdisHardwareStatusReady;
pTempBuffer = &ulValue;
uNeeded = sizeof(ulValue);
break;
case OID_GEN_CO_MEDIA_SUPPORTED:
case OID_GEN_CO_MEDIA_IN_USE:
ulValue = NdisMediumCoWan;
pTempBuffer = &ulValue;
uNeeded = sizeof(ulValue);
break;
case OID_GEN_CO_LINK_SPEED:
if(pChannel)
linkSpeed.Inbound = linkSpeed.Outbound = pChannel->m_ulLinkSpeed;
else
linkSpeed.Inbound = linkSpeed.Outbound = 1000000;
pTempBuffer = &linkSpeed;
uNeeded = sizeof(linkSpeed);
DebugInfo(("get link speed %d,pChannel = 0x%x\n",linkSpeed.Inbound,pChannel));
break;
case OID_GEN_CO_VENDOR_ID:
pTempBuffer = _s_vendor_id;
uNeeded = sizeof(_s_vendor_id);
break;
case OID_GEN_CO_VENDOR_DESCRIPTION:
pTempBuffer = _s_vendor_desc;
uNeeded = sizeof(_s_vendor_desc);
break;
case OID_GEN_CO_DRIVER_VERSION:
ulValue = (NDIS_MAJOR_VERSION << 8) | NDIS_MINOR_VERSION;
pTempBuffer = &ulValue;
uNeeded = sizeof(ulValue);
break;
case OID_GEN_CO_MAC_OPTIONS:
ulValue = 0;
pTempBuffer = &ulValue;
uNeeded = sizeof(ulValue);
break;
case OID_GEN_CO_MEDIA_CONNECT_STATUS:
ulValue = NdisMediaStateConnected;
pTempBuffer = &ulValue;
uNeeded = sizeof(ulValue);
break;
case OID_GEN_CO_VENDOR_DRIVER_VERSION:
ulValue = 1 << 8;
pTempBuffer = &ulValue;
uNeeded = sizeof(ulValue);
break;
case OID_CO_TAPI_CM_CAPS:
{
PCO_TAPI_CM_CAPS pCallManagerCaps = static_cast(pBuffer);
uNeeded = sizeof(CO_TAPI_CM_CAPS);
if(uNeeded <= uBufferLen)
{
pCallManagerCaps->ulCoTapiVersion = CO_TAPI_VERSION;
pCallManagerCaps->ulFlags = 0;
pCallManagerCaps->ulNumLines = g_pAdapter->m_ulNumChannels;
}
DebugInfo(("get call manager caps len = %d,version = 0x%x,lines = 0x%x\n",uBufferLen,CO_TAPI_VERSION,
g_pAdapter->m_ulNumChannels));
}
break;
case OID_CO_TAPI_LINE_CAPS:
{
PCO_TAPI_LINE_CAPS pLineCaps = static_cast(pBuffer);
uNeeded = sizeof(CO_TAPI_LINE_CAPS);
if(uNeeded <= uBufferLen && pLineCaps->ulLineID < g_pAdapter->m_ulNumChannels)
{
*puWritten = uNeeded;
NdisZeroMemory(pLineCaps, uNeeded);
pLineCaps->LineDevCaps.ulTotalSize = uBufferLen - sizeof(CO_TAPI_LINE_CAPS) + sizeof(LINE_DEV_CAPS);;
pLineCaps->ulFlags = 0;
PCHANNEL pChannel = g_pAdapter->m_ppChannels[pLineCaps->ulLineID];
pLineCaps->LineDevCaps.ulNeededSize = pLineCaps->LineDevCaps.ulUsedSize = sizeof(LINE_DEV_CAPS);
pLineCaps->LineDevCaps.ulPermanentLineID = pChannel->m_ulLineId; // id
pLineCaps->LineDevCaps.ulStringFormat = STRINGFORMAT_UNICODE; // unicode string
pLineCaps->LineDevCaps.ulAddressModes = LINEADDRESSMODE_ADDRESSID; // address id
pLineCaps->LineDevCaps.ulNumAddresses = 1; // only one address per channel
pLineCaps->LineDevCaps.ulBearerModes = pChannel->m_ulBearerMode; // bearer mode
pLineCaps->LineDevCaps.ulMaxRate = pChannel->m_ulLinkSpeed; // link speed
pLineCaps->LineDevCaps.ulMediaModes = pChannel->m_ulMediaMode; // media mode
pLineCaps->LineDevCaps.ulDevCapFlags = LINEDEVCAPFLAGS_CLOSEDROP; // dev cap
pLineCaps->LineDevCaps.ulMaxNumActiveCalls = 1; // only one call
pLineCaps->LineDevCaps.ulAnswerMode = LINEANSWERMODE_DROP; // drop this when answer another
pLineCaps->LineDevCaps.ulRingModes = 1; // one ring
pLineCaps->LineDevCaps.ulLineStates = LINEDEVSTATE_RINGING | LINEDEVSTATE_CONNECTED | LINEDEVSTATE_DISCONNECTED |
LINEDEVSTATE_OPEN | LINEDEVSTATE_CLOSE;
pLineCaps->LineDevCaps.ulLineFeatures = LINEFEATURE_MAKECALL; // can make call
UINT uInfoOffset = sizeof(pLineCaps->LineDevCaps);
UINT uInfoLength = sizeof(_s_vendor_desc);
pLineCaps->LineDevCaps.ulNeededSize += uInfoLength;
uNeeded += uInfoOffset;
if(pLineCaps->LineDevCaps.ulNeededSize <= pLineCaps->LineDevCaps.ulTotalSize)
{
pLineCaps->LineDevCaps.ulProviderInfoSize = uInfoLength; // provider info
pLineCaps->LineDevCaps.ulProviderInfoOffset = uInfoOffset;
NdisMoveMemory(reinterpret_cast(&pLineCaps->LineDevCaps) + uInfoOffset, _s_vendor_desc,uInfoLength);
pLineCaps->LineDevCaps.ulUsedSize += uInfoLength;
uInfoOffset += uInfoLength;
}
}
DebugInfo(("get line caps,len = %d,line id = %d,bearer mode = 0x%x,media mode = 0x%x,speed = %d\n",
uBufferLen,pLineCaps->ulLineID,pLineCaps->LineDevCaps.ulBearerModes,pLineCaps->LineDevCaps.ulMediaModes,
pLineCaps->LineDevCaps.ulMaxRate));
}
break;
case OID_CO_TAPI_ADDRESS_CAPS:
{
PCO_TAPI_ADDRESS_CAPS pAddressCaps = static_cast(pBuffer);
uNeeded = sizeof(CO_TAPI_ADDRESS_CAPS);
if(uNeeded <= uBufferLen && pAddressCaps->ulLineID < g_pAdapter->m_ulNumChannels)
{
NdisZeroMemory(pAddressCaps,uNeeded);
pAddressCaps->LineAddressCaps.ulTotalSize = uBufferLen - sizeof(CO_TAPI_ADDRESS_CAPS) + sizeof(LINE_ADDRESS_CAPS);
pAddressCaps->ulFlags = 0;
PCHANNEL pChannel = g_pAdapter->m_ppChannels[pAddressCaps->ulLineID];
*puWritten = uNeeded;
pAddressCaps->LineAddressCaps.ulNeededSize = pAddressCaps->LineAddressCaps.ulUsedSize = sizeof(LINE_ADDRESS_CAPS);
pAddressCaps->LineAddressCaps.ulLineDeviceID = pChannel->m_ulLineId;
pAddressCaps->LineAddressCaps.ulAddressSharing = LINEADDRESSSHARING_PRIVATE;
pAddressCaps->LineAddressCaps.ulAddressStates = 0;
pAddressCaps->LineAddressCaps.ulCallStates = LINECALLSTATE_IDLE | LINECALLSTATE_DIALING | LINECALLSTATE_OFFERING |
LINECALLSTATE_CONNECTED | LINECALLSTATE_DISCONNECTED;
pAddressCaps->LineAddressCaps.ulDialToneModes = LINEDIALTONEMODE_NORMAL;
pAddressCaps->LineAddressCaps.ulDisconnectModes = LINEDISCONNECTMODE_NORMAL | LINEDISCONNECTMODE_UNKNOWN |
LINEDISCONNECTMODE_BUSY | LINEDISCONNECTMODE_NOANSWER;
pAddressCaps->LineAddressCaps.ulMaxNumActiveCalls = 1;
pAddressCaps->LineAddressCaps.ulAddrCapFlags = LINEADDRCAPFLAGS_DIALED;
pAddressCaps->LineAddressCaps.ulCallFeatures = LINECALLFEATURE_ACCEPT | LINECALLFEATURE_ANSWER |
LINECALLFEATURE_DROP;
pAddressCaps->LineAddressCaps.ulAddressFeatures = LINEADDRFEATURE_MAKECALL;
UINT InfoOffset = sizeof(pAddressCaps->LineAddressCaps);
UINT InfoLength = sizeof(_s_address_name);
pAddressCaps->LineAddressCaps.ulNeededSize += InfoLength;
uNeeded += InfoLength;
if(pAddressCaps->LineAddressCaps.ulNeededSize <= pAddressCaps->LineAddressCaps.ulTotalSize)
{
pAddressCaps->LineAddressCaps.ulAddressSize = InfoLength;
pAddressCaps->LineAddressCaps.ulAddressOffset = InfoOffset;
PWCHAR pBuffer = reinterpret_cast(&pAddressCaps->LineAddressCaps) + InfoOffset / 2;
NdisMoveMemory(pBuffer,_s_address_name,InfoLength);
pBuffer[(InfoLength - 4) / 2] = static_cast(pAddressCaps->ulAddressID) + L'0';
pAddressCaps->LineAddressCaps.ulUsedSize += InfoLength;
InfoOffset += InfoLength;
DebugInfo(("get addr caps,len = %d,line id = %d,addr id = %d,name = %ls\n",
uBufferLen,pAddressCaps->ulLineID,pAddressCaps->ulAddressID,pBuffer));
}
}
}
break;
case OID_802_3_PERMANENT_ADDRESS:
case OID_802_3_CURRENT_ADDRESS:
case OID_WAN_PERMANENT_ADDRESS:
case OID_WAN_CURRENT_ADDRESS:
pTempBuffer = _s_address;
uNeeded = sizeof(_s_address);
DebugInfo(("get eth address 0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x\n",
_s_address[0],_s_address[1],_s_address[2],_s_address[3],_s_address[4],_s_address[5]));
break;
case OID_WAN_MEDIUM_SUBTYPE:
//ulValue = NdisWanMediumIsdn;
ulValue = NdisWanMediumPppoe;
pTempBuffer = &ulValue;
uNeeded = sizeof(ulValue);
break;
case OID_WAN_CO_GET_INFO:
{
PNDIS_WAN_CO_INFO pInfo = &g_pAdapter->m_wanCoInfo;
pTempBuffer = pInfo;
uNeeded = sizeof(g_pAdapter->m_wanCoInfo);
DebugInfo(("wan co get info len = %d,DesiredACCM = %d,FramingBits = %d,MaxFrameSize = %d,MaxSendWindow = %d\n",
uBufferLen,pInfo->DesiredACCM,pInfo->FramingBits,pInfo->MaxFrameSize,pInfo->MaxSendWindow));
}
break;
case OID_WAN_CO_GET_LINK_INFO:
if(!pChannel)
{
uNeeded = 0;
status = NDIS_STATUS_INVALID_DATA;
}
else
{
PNDIS_WAN_CO_GET_LINK_INFO pInfo = &pChannel->m_wanCoLinkInfo;
pTempBuffer = pInfo;
uNeeded = sizeof(NDIS_WAN_CO_GET_LINK_INFO);
DebugInfo(( "get link info size = %d,MaxRecvFrame = %d,MaxSendFrame = %d,RecvACCM = %d,RecvCompressionBits = %d,"
"RecvFramingBits = %d,SendACCM= %d,SendCompressionBits = %d,SendFramingBits = %d,pChannel = 0x%x\n",
uBufferLen,pInfo->MaxRecvFrameSize,pInfo->MaxSendFrameSize,
pInfo->RecvACCM,pInfo->RecvCompressionBits,pInfo->RecvFramingBits,pInfo->SendACCM,
pInfo->SendCompressionBits,pInfo->SendFramingBits,pChannel));
}
break;
case OID_WAN_LINE_COUNT:
ulValue = g_pAdapter->m_ulNumChannels;
pTempBuffer = &ulValue;
uNeeded = sizeof(ulValue);
break;
case OID_PNP_CAPABILITIES:
PnpCapabilities.WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
PnpCapabilities.WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
PnpCapabilities.WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
pTempBuffer = &PnpCapabilities;
uNeeded = sizeof(PnpCapabilities);
break;
case OID_PNP_QUERY_POWER:
break;
default:
status = NDIS_STATUS_INVALID_OID;
break;
}
if(uNeeded > uBufferLen)
{
*puNeeded = uNeeded;
*puWritten = 0;
status = NDIS_STATUS_INVALID_LENGTH;
}
else
{
if(pTempBuffer)
{
NdisMoveMemory(pBuffer,pTempBuffer,uNeeded);
}
*puNeeded = *puWritten = uNeeded;
}
return status;
}
// set quest DISPATCH_LEVEL
NDIS_STATUS SetRequest(PCHANNEL pChannel,NDIS_OID oid,PVOID pBuffer,UINT uBufferLen,PUINT puRead,PUINT puNeeded)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
*puRead = *puNeeded = 0;
switch(oid)
{
case OID_GEN_CURRENT_LOOKAHEAD:
DebugInfo(("set current lookahead.do nothing,total packet is lookahead buffer.\n"));
*puRead = *puNeeded = sizeof(ULONG);
break;
case OID_WAN_CO_SET_LINK_INFO:
{
PNDIS_WAN_CO_SET_LINK_INFO pInfo = static_cast(pBuffer);
DebugInfo(( "set link info size = %d,MaxRecvFrame = %d,MaxSendFrame = %d,RecvACCM = %d,RecvCompressionBits = %d,"
"RecvFramingBits = %d,SendACCM= %d,SendCompressionBits = %d,SendFramingBits = %d,pChannel = 0x%x\n",
uBufferLen,pInfo->MaxRecvFrameSize,pInfo->MaxSendFrameSize,
pInfo->RecvACCM,pInfo->RecvCompressionBits,pInfo->RecvFramingBits,pInfo->SendACCM,
pInfo->SendCompressionBits,pInfo->SendFramingBits,pChannel));
if(uBufferLen >= sizeof(NDIS_WAN_CO_SET_LINK_INFO))
{
if(pChannel)
{
NdisMoveMemory(&pChannel->m_wanCoLinkInfo,pBuffer,sizeof(NDIS_WAN_CO_SET_LINK_INFO));
*puRead = sizeof(NDIS_WAN_CO_SET_LINK_INFO);
}
}
}
*puNeeded = sizeof(NDIS_WAN_CO_SET_LINK_INFO);
break;
case OID_PNP_SET_POWER:
case OID_GEN_CO_PROTOCOL_OPTIONS:
break;
default:
status = NDIS_STATUS_INVALID_OID;
break;
}
return status;
}
// send packet
NDIS_STATUS SendPacket(PBIND_CONTEXT pBind,PPACKET pPacket)
{
NDIS_STATUS status;
pPacket->m_pBindContext = pBind;
NdisSend(&status,pBind->m_pOpenBlock,pPacket->m_pNdisPacket);
if(status != NDIS_STATUS_PENDING)
{
protocolSendComplete(pBind,pPacket->m_pNdisPacket,status);
}
return status;
}
// broadcast packet
BOOLEAN BroadcastPacket(PPACKET pPacket)
{
BOOLEAN bRet = FALSE;
NdisAcquireSpinLock(&g_lockBind);
PLIST_ENTRY pEntry = g_ltBindsHead.Flink;
for(; pEntry != &g_ltBindsHead; pEntry = pEntry->Flink)
{
bRet = TRUE;
PBIND_CONTEXT pBind = CONTAINING_RECORD(pEntry,BIND_CONTEXT,m_ltBindAnchor);
PPACKET pPacketClone = ClonePacket(pPacket);
if(pPacketClone)
{
NdisMoveMemory(pPacketClone->m_pFrame->m_srcMac,pBind->m_macAddress,ETH_ADDR_LEN);
ReferenceBind(pBind,TRUE);
ReferencePacket(pPacketClone);
SendPacket(pBind,pPacketClone);
DereferencePacket(pPacketClone);
}
}
NdisReleaseSpinLock(&g_lockBind);
return bRet;
}