123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716 |
- /*
- * TAP-Windows -- A kernel driver to provide virtual tap
- * device functionality on Windows.
- *
- * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
- *
- * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc.,
- * and is released under the GPL version 2 (see below).
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program (see the file COPYING included with this
- * distribution); if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
- //
- // Include files.
- //
- #include "tap.h"
- NDIS_OID TAPSupportedOids[] =
- {
- OID_GEN_HARDWARE_STATUS,
- OID_GEN_TRANSMIT_BUFFER_SPACE,
- OID_GEN_RECEIVE_BUFFER_SPACE,
- OID_GEN_TRANSMIT_BLOCK_SIZE,
- OID_GEN_RECEIVE_BLOCK_SIZE,
- OID_GEN_VENDOR_ID,
- OID_GEN_VENDOR_DESCRIPTION,
- OID_GEN_VENDOR_DRIVER_VERSION,
- OID_GEN_CURRENT_PACKET_FILTER,
- OID_GEN_CURRENT_LOOKAHEAD,
- OID_GEN_DRIVER_VERSION,
- OID_GEN_MAXIMUM_TOTAL_SIZE,
- OID_GEN_XMIT_OK,
- OID_GEN_RCV_OK,
- OID_GEN_STATISTICS,
- #ifdef IMPLEMENT_OPTIONAL_OIDS
- OID_GEN_TRANSMIT_QUEUE_LENGTH, // Optional
- #endif // IMPLEMENT_OPTIONAL_OIDS
- OID_GEN_LINK_PARAMETERS,
- OID_GEN_INTERRUPT_MODERATION,
- OID_GEN_MEDIA_SUPPORTED,
- OID_GEN_MEDIA_IN_USE,
- OID_GEN_MAXIMUM_SEND_PACKETS,
- OID_GEN_XMIT_ERROR,
- OID_GEN_RCV_ERROR,
- OID_GEN_RCV_NO_BUFFER,
- OID_802_3_PERMANENT_ADDRESS,
- OID_802_3_CURRENT_ADDRESS,
- OID_802_3_MULTICAST_LIST,
- OID_802_3_MAXIMUM_LIST_SIZE,
- OID_802_3_RCV_ERROR_ALIGNMENT,
- OID_802_3_XMIT_ONE_COLLISION,
- OID_802_3_XMIT_MORE_COLLISIONS,
- #ifdef IMPLEMENT_OPTIONAL_OIDS
- OID_802_3_XMIT_DEFERRED, // Optional
- OID_802_3_XMIT_MAX_COLLISIONS, // Optional
- OID_802_3_RCV_OVERRUN, // Optional
- OID_802_3_XMIT_UNDERRUN, // Optional
- OID_802_3_XMIT_HEARTBEAT_FAILURE, // Optional
- OID_802_3_XMIT_TIMES_CRS_LOST, // Optional
- OID_802_3_XMIT_LATE_COLLISIONS, // Optional
- OID_PNP_CAPABILITIES, // Optional
- #endif // IMPLEMENT_OPTIONAL_OIDS
- };
- //======================================================================
- // TAP NDIS 6 Miniport Callbacks
- //======================================================================
- // Returns with reference count initialized to one.
- PTAP_ADAPTER_CONTEXT
- tapAdapterContextAllocate(
- __in NDIS_HANDLE MiniportAdapterHandle
- )
- {
- PTAP_ADAPTER_CONTEXT adapter = NULL;
- adapter = (PTAP_ADAPTER_CONTEXT )NdisAllocateMemoryWithTagPriority(
- GlobalData.NdisDriverHandle,
- sizeof(TAP_ADAPTER_CONTEXT),
- TAP_ADAPTER_TAG,
- NormalPoolPriority
- );
- if(adapter)
- {
- NET_BUFFER_LIST_POOL_PARAMETERS nblPoolParameters = {0};
- NdisZeroMemory(adapter,sizeof(TAP_ADAPTER_CONTEXT));
- adapter->MiniportAdapterHandle = MiniportAdapterHandle;
- // Initialize cancel-safe IRP queue
- tapIrpCsqInitialize(&adapter->PendingReadIrpQueue);
- // Initialize TAP send packet queue.
- tapPacketQueueInitialize(&adapter->SendPacketQueue);
- // Allocate the adapter lock.
- NdisAllocateSpinLock(&adapter->AdapterLock);
- // NBL pool for making TAP receive indications.
- NdisZeroMemory(&nblPoolParameters, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));
- // Initialize event used to determine when all receive NBLs have been returned.
- NdisInitializeEvent(&adapter->ReceiveNblInFlightCountZeroEvent);
- nblPoolParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
- nblPoolParameters.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
- nblPoolParameters.Header.Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
- nblPoolParameters.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
- nblPoolParameters.ContextSize = 0;
- //nblPoolParameters.ContextSize = sizeof(RX_NETBUFLIST_RSVD);
- nblPoolParameters.fAllocateNetBuffer = TRUE;
- nblPoolParameters.PoolTag = TAP_RX_NBL_TAG;
- #pragma warning( suppress : 28197 )
- adapter->ReceiveNblPool = NdisAllocateNetBufferListPool(
- adapter->MiniportAdapterHandle,
- &nblPoolParameters);
- if (adapter->ReceiveNblPool == NULL)
- {
- DEBUGP (("[TAP] Couldn't allocate adapter receive NBL pool\n"));
- NdisFreeMemory(adapter,0,0);
- }
- // Add initial reference. Normally removed in AdapterHalt.
- adapter->RefCount = 1;
- // Safe for multiple removes.
- NdisInitializeListHead(&adapter->AdapterListLink);
- //
- // The miniport adapter is initially powered up
- //
- adapter->CurrentPowerState = NdisDeviceStateD0;
- }
- return adapter;
- }
- VOID
- tapReadPermanentAddress(
- __in PTAP_ADAPTER_CONTEXT Adapter,
- __in NDIS_HANDLE ConfigurationHandle,
- __out MACADDR PermanentAddress
- )
- {
- NDIS_STATUS status;
- NDIS_CONFIGURATION_PARAMETER *configParameter;
- NDIS_STRING macKey = NDIS_STRING_CONST("MAC");
- ANSI_STRING macString;
- BOOLEAN macFromRegistry = FALSE;
- // Read MAC parameter from registry.
- NdisReadConfiguration(
- &status,
- &configParameter,
- ConfigurationHandle,
- &macKey,
- NdisParameterString
- );
- if (status == NDIS_STATUS_SUCCESS)
- {
- if( (configParameter->ParameterType == NdisParameterString)
- && (configParameter->ParameterData.StringData.Length >= 12)
- )
- {
- if (RtlUnicodeStringToAnsiString(
- &macString,
- &configParameter->ParameterData.StringData,
- TRUE) == STATUS_SUCCESS
- )
- {
- macFromRegistry = ParseMAC (PermanentAddress, macString.Buffer);
- RtlFreeAnsiString (&macString);
- }
- }
- }
- if(!macFromRegistry)
- {
- //
- // There is no (valid) address stashed in the registry parameter.
- //
- // Make up a dummy mac address based on the ANSI representation of the
- // NetCfgInstanceId GUID.
- //
- GenerateRandomMac(PermanentAddress, MINIPORT_INSTANCE_ID(Adapter));
- }
- }
- NDIS_STATUS
- tapReadConfiguration(
- __in PTAP_ADAPTER_CONTEXT Adapter
- )
- {
- NDIS_STATUS status = NDIS_STATUS_SUCCESS;
- NDIS_CONFIGURATION_OBJECT configObject;
- NDIS_HANDLE configHandle;
- DEBUGP (("[TAP] --> tapReadConfiguration\n"));
- //
- // Setup defaults in case configuration cannot be opened.
- //
- Adapter->MtuSize = ETHERNET_MTU;
- Adapter->MediaStateAlwaysConnected = FALSE;
- Adapter->LogicalMediaState = FALSE;
- Adapter->AllowNonAdmin = FALSE;
- //
- // Open the registry for this adapter to read advanced
- // configuration parameters stored by the INF file.
- //
- NdisZeroMemory(&configObject, sizeof(configObject));
- {C_ASSERT(sizeof(configObject) >= NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1);}
- configObject.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
- configObject.Header.Size = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
- configObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
- configObject.NdisHandle = Adapter->MiniportAdapterHandle;
- configObject.Flags = 0;
- status = NdisOpenConfigurationEx(
- &configObject,
- &configHandle
- );
- // Read on the opened configuration handle.
- if(status == NDIS_STATUS_SUCCESS)
- {
- NDIS_CONFIGURATION_PARAMETER *configParameter;
- NDIS_STRING mkey = NDIS_STRING_CONST("NetCfgInstanceId");
- //
- // Read NetCfgInstanceId from the registry.
- // ------------------------------------
- // NetCfgInstanceId is required to create device and associated
- // symbolic link for the adapter device.
- //
- // NetCfgInstanceId is a GUID string provided by NDIS that identifies
- // the adapter instance. An example is:
- //
- // NetCfgInstanceId={410EB49D-2381-4FE7-9B36-498E22619DF0}
- //
- // Other names are derived from NetCfgInstanceId. For example, MiniportName:
- //
- // MiniportName=\DEVICE\{410EB49D-2381-4FE7-9B36-498E22619DF0}
- //
- NdisReadConfiguration (
- &status,
- &configParameter,
- configHandle,
- &mkey,
- NdisParameterString
- );
- if (status == NDIS_STATUS_SUCCESS)
- {
- if (configParameter->ParameterType == NdisParameterString)
- {
- DEBUGP (("[TAP] NdisReadConfiguration (NetCfgInstanceId=%wZ)\n",
- &configParameter->ParameterData.StringData ));
- // Save NetCfgInstanceId as UNICODE_STRING.
- Adapter->NetCfgInstanceId.Length = Adapter->NetCfgInstanceId.MaximumLength
- = configParameter->ParameterData.StringData.Length;
- Adapter->NetCfgInstanceId.Buffer = Adapter->NetCfgInstanceIdBuffer;
- NdisMoveMemory(
- Adapter->NetCfgInstanceId.Buffer,
- configParameter->ParameterData.StringData.Buffer,
- Adapter->NetCfgInstanceId.Length
- );
- // Save NetCfgInstanceId as ANSI_STRING as well.
- if (RtlUnicodeStringToAnsiString (
- &Adapter->NetCfgInstanceIdAnsi,
- &configParameter->ParameterData.StringData,
- TRUE) != STATUS_SUCCESS
- )
- {
- DEBUGP (("[TAP] NetCfgInstanceId ANSI name conversion failed\n"));
- status = NDIS_STATUS_RESOURCES;
- }
- }
- else
- {
- DEBUGP (("[TAP] NetCfgInstanceId has invalid type\n"));
- status = NDIS_STATUS_INVALID_DATA;
- }
- }
- else
- {
- DEBUGP (("[TAP] NetCfgInstanceId failed\n"));
- status = NDIS_STATUS_INVALID_DATA;
- }
- if (status == NDIS_STATUS_SUCCESS)
- {
- NDIS_STATUS localStatus; // Use default if these fail.
- NDIS_CONFIGURATION_PARAMETER *configParameter;
- NDIS_STRING mtuKey = NDIS_STRING_CONST("MTU");
- NDIS_STRING mediaStatusKey = NDIS_STRING_CONST("MediaStatus");
- #if ENABLE_NONADMIN
- NDIS_STRING allowNonAdminKey = NDIS_STRING_CONST("AllowNonAdmin");
- #endif
- // Read MTU from the registry.
- NdisReadConfiguration (
- &localStatus,
- &configParameter,
- configHandle,
- &mtuKey,
- NdisParameterInteger
- );
- if (localStatus == NDIS_STATUS_SUCCESS)
- {
- if (configParameter->ParameterType == NdisParameterInteger)
- {
- int mtu = configParameter->ParameterData.IntegerData;
- if(mtu == 0)
- {
- mtu = ETHERNET_MTU;
- }
- // Sanity check
- if (mtu < MINIMUM_MTU)
- {
- mtu = MINIMUM_MTU;
- }
- else if (mtu > MAXIMUM_MTU)
- {
- mtu = MAXIMUM_MTU;
- }
- Adapter->MtuSize = mtu;
- }
- }
- DEBUGP (("[%s] Using MTU %d\n",
- MINIPORT_INSTANCE_ID (Adapter),
- Adapter->MtuSize
- ));
- // Read MediaStatus setting from registry.
- NdisReadConfiguration (
- &localStatus,
- &configParameter,
- configHandle,
- &mediaStatusKey,
- NdisParameterInteger
- );
- if (localStatus == NDIS_STATUS_SUCCESS)
- {
- if (configParameter->ParameterType == NdisParameterInteger)
- {
- if(configParameter->ParameterData.IntegerData == 0)
- {
- // Connect state is appplication controlled.
- DEBUGP(("[%s] Initial MediaConnectState: Application Controlled\n",
- MINIPORT_INSTANCE_ID (Adapter)));
- Adapter->MediaStateAlwaysConnected = FALSE;
- Adapter->LogicalMediaState = FALSE;
- }
- else
- {
- // Connect state is always connected.
- DEBUGP(("[%s] Initial MediaConnectState: Always Connected\n",
- MINIPORT_INSTANCE_ID (Adapter)));
- Adapter->MediaStateAlwaysConnected = TRUE;
- Adapter->LogicalMediaState = TRUE;
- }
- }
- }
- // Read MAC PermanentAddress setting from registry.
- tapReadPermanentAddress(
- Adapter,
- configHandle,
- Adapter->PermanentAddress
- );
- DEBUGP (("[%s] Using MAC PermanentAddress %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
- MINIPORT_INSTANCE_ID (Adapter),
- Adapter->PermanentAddress[0],
- Adapter->PermanentAddress[1],
- Adapter->PermanentAddress[2],
- Adapter->PermanentAddress[3],
- Adapter->PermanentAddress[4],
- Adapter->PermanentAddress[5])
- );
- // Now seed the current MAC address with the permanent address.
- ETH_COPY_NETWORK_ADDRESS(Adapter->CurrentAddress, Adapter->PermanentAddress);
- DEBUGP (("[%s] Using MAC CurrentAddress %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
- MINIPORT_INSTANCE_ID (Adapter),
- Adapter->CurrentAddress[0],
- Adapter->CurrentAddress[1],
- Adapter->CurrentAddress[2],
- Adapter->CurrentAddress[3],
- Adapter->CurrentAddress[4],
- Adapter->CurrentAddress[5])
- );
- // Read optional AllowNonAdmin setting from registry.
- #if ENABLE_NONADMIN
- NdisReadConfiguration (
- &localStatus,
- &configParameter,
- configHandle,
- &allowNonAdminKey,
- NdisParameterInteger
- );
- if (localStatus == NDIS_STATUS_SUCCESS)
- {
- if (configParameter->ParameterType == NdisParameterInteger)
- {
- Adapter->AllowNonAdmin = TRUE;
- }
- }
- #endif
- }
- // Close the configuration handle.
- NdisCloseConfiguration(configHandle);
- }
- else
- {
- DEBUGP (("[TAP] Couldn't open adapter registry\n"));
- }
- DEBUGP (("[TAP] <-- tapReadConfiguration; status = %8.8X\n",status));
- return status;
- }
- VOID
- tapAdapterContextAddToGlobalList(
- __in PTAP_ADAPTER_CONTEXT Adapter
- )
- {
- LOCK_STATE lockState;
- PLIST_ENTRY listEntry = &Adapter->AdapterListLink;
- // Acquire global adapter list lock.
- NdisAcquireReadWriteLock(
- &GlobalData.Lock,
- TRUE, // Acquire for write
- &lockState
- );
- // Adapter context should NOT be in any list.
- ASSERT( (listEntry->Flink == listEntry) && (listEntry->Blink == listEntry ) );
- // Add reference to persist until after removal.
- tapAdapterContextReference(Adapter);
- // Add the adapter context to the global list.
- InsertTailList(&GlobalData.AdapterList,&Adapter->AdapterListLink);
- // Release global adapter list lock.
- NdisReleaseReadWriteLock(&GlobalData.Lock,&lockState);
- }
- VOID
- tapAdapterContextRemoveFromGlobalList(
- __in PTAP_ADAPTER_CONTEXT Adapter
- )
- {
- LOCK_STATE lockState;
- // Acquire global adapter list lock.
- NdisAcquireReadWriteLock(
- &GlobalData.Lock,
- TRUE, // Acquire for write
- &lockState
- );
- // Remove the adapter context from the global list.
- RemoveEntryList(&Adapter->AdapterListLink);
- // Safe for multiple removes.
- NdisInitializeListHead(&Adapter->AdapterListLink);
- // Remove reference added in tapAdapterContextAddToGlobalList.
- tapAdapterContextDereference(Adapter);
- // Release global adapter list lock.
- NdisReleaseReadWriteLock(&GlobalData.Lock,&lockState);
- }
- // Returns with added reference on adapter context.
- PTAP_ADAPTER_CONTEXT
- tapAdapterContextFromDeviceObject(
- __in PDEVICE_OBJECT DeviceObject
- )
- {
- LOCK_STATE lockState;
- // Acquire global adapter list lock.
- NdisAcquireReadWriteLock(
- &GlobalData.Lock,
- FALSE, // Acquire for read
- &lockState
- );
- if (!IsListEmpty(&GlobalData.AdapterList))
- {
- PLIST_ENTRY entry = GlobalData.AdapterList.Flink;
- PTAP_ADAPTER_CONTEXT adapter;
- while (entry != &GlobalData.AdapterList)
- {
- adapter = CONTAINING_RECORD(entry, TAP_ADAPTER_CONTEXT, AdapterListLink);
- // Match on DeviceObject
- if(adapter->DeviceObject == DeviceObject )
- {
- // Add reference to adapter context.
- tapAdapterContextReference(adapter);
- // Release global adapter list lock.
- NdisReleaseReadWriteLock(&GlobalData.Lock,&lockState);
- return adapter;
- }
- // Move to next entry
- entry = entry->Flink;
- }
- }
- // Release global adapter list lock.
- NdisReleaseReadWriteLock(&GlobalData.Lock,&lockState);
- return (PTAP_ADAPTER_CONTEXT )NULL;
- }
- NDIS_STATUS
- AdapterSetOptions(
- __in NDIS_HANDLE NdisDriverHandle,
- __in NDIS_HANDLE DriverContext
- )
- /*++
- Routine Description:
- The MiniportSetOptions function registers optional handlers. For each
- optional handler that should be registered, this function makes a call
- to NdisSetOptionalHandlers.
- MiniportSetOptions runs at IRQL = PASSIVE_LEVEL.
- Arguments:
- DriverContext The context handle
- Return Value:
- NDIS_STATUS_xxx code
- --*/
- {
- NDIS_STATUS status;
- DEBUGP (("[TAP] --> AdapterSetOptions\n"));
- //
- // Set any optional handlers by filling out the appropriate struct and
- // calling NdisSetOptionalHandlers here.
- //
- status = NDIS_STATUS_SUCCESS;
- DEBUGP (("[TAP] <-- AdapterSetOptions; status = %8.8X\n",status));
- return status;
- }
- NDIS_STATUS
- AdapterCreate(
- __in NDIS_HANDLE MiniportAdapterHandle,
- __in NDIS_HANDLE MiniportDriverContext,
- __in PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters
- )
- {
- PTAP_ADAPTER_CONTEXT adapter = NULL;
- NDIS_STATUS status;
- UNREFERENCED_PARAMETER(MiniportDriverContext);
- UNREFERENCED_PARAMETER(MiniportInitParameters);
- DEBUGP (("[TAP] --> AdapterCreate\n"));
- do
- {
- NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES regAttributes = {0};
- NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES genAttributes = {0};
- NDIS_PNP_CAPABILITIES pnpCapabilities = {0};
- //
- // Allocate adapter context structure and initialize all the
- // memory resources for sending and receiving packets.
- //
- // Returns with reference count initialized to one.
- //
- adapter = tapAdapterContextAllocate(MiniportAdapterHandle);
- if(adapter == NULL)
- {
- DEBUGP (("[TAP] Couldn't allocate adapter memory\n"));
- status = NDIS_STATUS_RESOURCES;
- break;
- }
- // Enter the Initializing state.
- DEBUGP (("[TAP] Miniport State: Initializing\n"));
- tapAdapterAcquireLock(adapter,FALSE);
- adapter->Locked.AdapterState = MiniportInitializingState;
- tapAdapterReleaseLock(adapter,FALSE);
- //
- // First read adapter configuration from registry.
- // -----------------------------------------------
- // Subsequent device registration will fail if NetCfgInstanceId
- // has not been successfully read.
- //
- status = tapReadConfiguration(adapter);
- //
- // Set the registration attributes.
- //
- {C_ASSERT(sizeof(regAttributes) >= NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1);}
- regAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
- regAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
- regAttributes.Header.Revision = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
- regAttributes.MiniportAdapterContext = adapter;
- regAttributes.AttributeFlags = TAP_ADAPTER_ATTRIBUTES_FLAGS;
- regAttributes.CheckForHangTimeInSeconds = TAP_ADAPTER_CHECK_FOR_HANG_TIME_IN_SECONDS;
- regAttributes.InterfaceType = TAP_INTERFACE_TYPE;
- //NDIS_DECLARE_MINIPORT_ADAPTER_CONTEXT(TAP_ADAPTER_CONTEXT);
- status = NdisMSetMiniportAttributes(
- MiniportAdapterHandle,
- (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)®Attributes
- );
- if (status != NDIS_STATUS_SUCCESS)
- {
- DEBUGP (("[TAP] NdisSetOptionalHandlers failed; Status 0x%08x\n",status));
- break;
- }
- //
- // Next, set the general attributes.
- //
- {C_ASSERT(sizeof(genAttributes) >= NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1);}
- genAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
- genAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
- genAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
- //
- // Specify the medium type that the NIC can support but not
- // necessarily the medium type that the NIC currently uses.
- //
- genAttributes.MediaType = TAP_MEDIUM_TYPE;
- //
- // Specifiy medium type that the NIC currently uses.
- //
- genAttributes.PhysicalMediumType = TAP_PHYSICAL_MEDIUM;
- //
- // Specifiy the maximum network frame size, in bytes, that the NIC
- // supports excluding the header.
- //
- genAttributes.MtuSize = TAP_FRAME_MAX_DATA_SIZE;
- genAttributes.MaxXmitLinkSpeed = TAP_XMIT_SPEED;
- genAttributes.XmitLinkSpeed = TAP_XMIT_SPEED;
- genAttributes.MaxRcvLinkSpeed = TAP_RECV_SPEED;
- genAttributes.RcvLinkSpeed = TAP_RECV_SPEED;
- if(adapter->MediaStateAlwaysConnected)
- {
- DEBUGP(("[%s] Initial MediaConnectState: Connected\n",
- MINIPORT_INSTANCE_ID (adapter)));
- genAttributes.MediaConnectState = MediaConnectStateConnected;
- }
- else
- {
- DEBUGP(("[%s] Initial MediaConnectState: Disconnected\n",
- MINIPORT_INSTANCE_ID (adapter)));
- genAttributes.MediaConnectState = MediaConnectStateDisconnected;
- }
- genAttributes.MediaDuplexState = MediaDuplexStateFull;
- //
- // The maximum number of bytes the NIC can provide as lookahead data.
- // If that value is different from the size of the lookahead buffer
- // supported by bound protocols, NDIS will call MiniportOidRequest to
- // set the size of the lookahead buffer provided by the miniport driver
- // to the minimum of the miniport driver and protocol(s) values. If the
- // driver always indicates up full packets with
- // NdisMIndicateReceiveNetBufferLists, it should set this value to the
- // maximum total frame size, which excludes the header.
- //
- // Upper-layer drivers examine lookahead data to determine whether a
- // packet that is associated with the lookahead data is intended for
- // one or more of their clients. If the underlying driver supports
- // multipacket receive indications, bound protocols are given full net
- // packets on every indication. Consequently, this value is identical
- // to that returned for OID_GEN_RECEIVE_BLOCK_SIZE.
- //
- genAttributes.LookaheadSize = TAP_MAX_LOOKAHEAD;
- genAttributes.MacOptions = TAP_MAC_OPTIONS;
- genAttributes.SupportedPacketFilters = TAP_SUPPORTED_FILTERS;
- //
- // The maximum number of multicast addresses the NIC driver can manage.
- // This list is global for all protocols bound to (or above) the NIC.
- // Consequently, a protocol can receive NDIS_STATUS_MULTICAST_FULL from
- // the NIC driver when attempting to set the multicast address list,
- // even if the number of elements in the given list is less than the
- // number originally returned for this query.
- //
- genAttributes.MaxMulticastListSize = TAP_MAX_MCAST_LIST;
- genAttributes.MacAddressLength = MACADDR_SIZE;
- //
- // Return the MAC address of the NIC burnt in the hardware.
- //
- ETH_COPY_NETWORK_ADDRESS(genAttributes.PermanentMacAddress, adapter->PermanentAddress);
- //
- // Return the MAC address the NIC is currently programmed to use. Note
- // that this address could be different from the permananent address as
- // the user can override using registry. Read NdisReadNetworkAddress
- // doc for more info.
- //
- ETH_COPY_NETWORK_ADDRESS(genAttributes.CurrentMacAddress, adapter->CurrentAddress);
- genAttributes.RecvScaleCapabilities = NULL;
- genAttributes.AccessType = TAP_ACCESS_TYPE;
- genAttributes.DirectionType = TAP_DIRECTION_TYPE;
- genAttributes.ConnectionType = TAP_CONNECTION_TYPE;
- genAttributes.IfType = TAP_IFTYPE;
- genAttributes.IfConnectorPresent = TAP_HAS_PHYSICAL_CONNECTOR;
- genAttributes.SupportedStatistics = TAP_SUPPORTED_STATISTICS;
- genAttributes.SupportedPauseFunctions = NdisPauseFunctionsUnsupported; // IEEE 802.3 pause frames
- genAttributes.DataBackFillSize = 0;
- genAttributes.ContextBackFillSize = 0;
- //
- // The SupportedOidList is an array of OIDs for objects that the
- // underlying driver or its NIC supports. Objects include general,
- // media-specific, and implementation-specific objects. NDIS forwards a
- // subset of the returned list to protocols that make this query. That
- // is, NDIS filters any supported statistics OIDs out of the list
- // because protocols never make statistics queries.
- //
- genAttributes.SupportedOidList = TAPSupportedOids;
- genAttributes.SupportedOidListLength = sizeof(TAPSupportedOids);
- genAttributes.AutoNegotiationFlags = NDIS_LINK_STATE_DUPLEX_AUTO_NEGOTIATED;
- //
- // Set power management capabilities
- //
- NdisZeroMemory(&pnpCapabilities, sizeof(pnpCapabilities));
- pnpCapabilities.WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
- pnpCapabilities.WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
- genAttributes.PowerManagementCapabilities = &pnpCapabilities;
- status = NdisMSetMiniportAttributes(
- MiniportAdapterHandle,
- (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&genAttributes
- );
- if (status != NDIS_STATUS_SUCCESS)
- {
- DEBUGP (("[TAP] NdisMSetMiniportAttributes failed; Status 0x%08x\n",status));
- break;
- }
- //
- // Create the Win32 device I/O interface.
- //
- status = CreateTapDevice(adapter);
- if (status == NDIS_STATUS_SUCCESS)
- {
- // Add this adapter to the global adapter list.
- tapAdapterContextAddToGlobalList(adapter);
- }
- else
- {
- DEBUGP (("[TAP] CreateTapDevice failed; Status 0x%08x\n",status));
- break;
- }
- } while(FALSE);
- if(status == NDIS_STATUS_SUCCESS)
- {
- // Enter the Paused state if initialization is complete.
- DEBUGP (("[TAP] Miniport State: Paused\n"));
- tapAdapterAcquireLock(adapter,FALSE);
- adapter->Locked.AdapterState = MiniportPausedState;
- tapAdapterReleaseLock(adapter,FALSE);
- }
- else
- {
- if(adapter != NULL)
- {
- DEBUGP (("[TAP] Miniport State: Halted\n"));
- //
- // Remove reference when adapter context was allocated
- // ---------------------------------------------------
- // This should result in freeing adapter context memory
- // and assiciated resources.
- //
- tapAdapterContextDereference(adapter);
- adapter = NULL;
- }
- }
- DEBUGP (("[TAP] <-- AdapterCreate; status = %8.8X\n",status));
- return status;
- }
- VOID
- AdapterHalt(
- __in NDIS_HANDLE MiniportAdapterContext,
- __in NDIS_HALT_ACTION HaltAction
- )
- /*++
- Routine Description:
- Halt handler is called when NDIS receives IRP_MN_STOP_DEVICE,
- IRP_MN_SUPRISE_REMOVE or IRP_MN_REMOVE_DEVICE requests from the PNP
- manager. Here, the driver should free all the resources acquired in
- MiniportInitialize and stop access to the hardware. NDIS will not submit
- any further request once this handler is invoked.
- 1) Free and unmap all I/O resources.
- 2) Disable interrupt and deregister interrupt handler.
- 3) Deregister shutdown handler regsitered by
- NdisMRegisterAdapterShutdownHandler .
- 4) Cancel all queued up timer callbacks.
- 5) Finally wait indefinitely for all the outstanding receive
- packets indicated to the protocol to return.
- MiniportHalt runs at IRQL = PASSIVE_LEVEL.
- Arguments:
- MiniportAdapterContext Pointer to the Adapter
- HaltAction The reason for halting the adapter
- Return Value:
- None.
- --*/
- {
- PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext;
- UNREFERENCED_PARAMETER(HaltAction);
- DEBUGP (("[TAP] --> AdapterHalt\n"));
- // Enter the Halted state.
- DEBUGP (("[TAP] Miniport State: Halted\n"));
- tapAdapterAcquireLock(adapter,FALSE);
- adapter->Locked.AdapterState = MiniportHaltedState;
- tapAdapterReleaseLock(adapter,FALSE);
- // Remove this adapter from the global adapter list.
- tapAdapterContextRemoveFromGlobalList(adapter);
- // BUGBUG!!! Call AdapterShutdownEx to do some of the work of stopping.
- // TODO!!! More...
- //
- // Destroy the TAP Win32 device.
- //
- DestroyTapDevice(adapter);
- //
- // Remove initial reference added in AdapterCreate.
- // ------------------------------------------------
- // This should result in freeing adapter context memory
- // and resources allocated in AdapterCreate.
- //
- tapAdapterContextDereference(adapter);
- adapter = NULL;
- DEBUGP (("[TAP] <-- AdapterHalt\n"));
- }
- VOID
- tapWaitForReceiveNblInFlightCountZeroEvent(
- __in PTAP_ADAPTER_CONTEXT Adapter
- )
- {
- LONG nblCount;
- //
- // Wait until higher-level protocol has returned all NBLs
- // to the driver.
- //
- // Add one NBL "bias" to insure allow event to be reset safely.
- nblCount = NdisInterlockedIncrement(&Adapter->ReceiveNblInFlightCount);
- ASSERT(nblCount > 0 );
- NdisResetEvent(&Adapter->ReceiveNblInFlightCountZeroEvent);
- //
- // Now remove the bias and wait for the ReceiveNblInFlightCountZeroEvent
- // if the count returned is not zero.
- //
- nblCount = NdisInterlockedDecrement(&Adapter->ReceiveNblInFlightCount);
- ASSERT(nblCount >= 0);
- if(nblCount)
- {
- LARGE_INTEGER startTime, currentTime;
- NdisGetSystemUpTimeEx(&startTime);
- for (;;)
- {
- BOOLEAN waitResult = NdisWaitEvent(
- &Adapter->ReceiveNblInFlightCountZeroEvent,
- TAP_WAIT_POLL_LOOP_TIMEOUT
- );
- NdisGetSystemUpTimeEx(¤tTime);
- if (waitResult)
- {
- break;
- }
- DEBUGP (("[%s] Waiting for %d in-flight receive NBLs to be returned.\n",
- MINIPORT_INSTANCE_ID (Adapter),
- Adapter->ReceiveNblInFlightCount
- ));
- }
- DEBUGP (("[%s] Waited %d ms for all in-flight NBLs to be returned.\n",
- MINIPORT_INSTANCE_ID (Adapter),
- (currentTime.LowPart - startTime.LowPart)
- ));
- }
- }
- NDIS_STATUS
- AdapterPause(
- __in NDIS_HANDLE MiniportAdapterContext,
- __in PNDIS_MINIPORT_PAUSE_PARAMETERS PauseParameters
- )
- /*++
- Routine Description:
- When a miniport receives a pause request, it enters into a Pausing state.
- The miniport should not indicate up any more network data. Any pending
- send requests must be completed, and new requests must be rejected with
- NDIS_STATUS_PAUSED.
- Once all sends have been completed and all recieve NBLs have returned to
- the miniport, the miniport enters the Paused state.
- While paused, the miniport can still service interrupts from the hardware
- (to, for example, continue to indicate NDIS_STATUS_MEDIA_CONNECT
- notifications).
- The miniport must continue to be able to handle status indications and OID
- requests. MiniportPause is different from MiniportHalt because, in
- general, the MiniportPause operation won't release any resources.
- MiniportPause must not attempt to acquire any resources where allocation
- can fail, since MiniportPause itself must not fail.
- MiniportPause runs at IRQL = PASSIVE_LEVEL.
- Arguments:
- MiniportAdapterContext Pointer to the Adapter
- MiniportPauseParameters Additional information about the pause operation
- Return Value:
- If the miniport is able to immediately enter the Paused state, it should
- return NDIS_STATUS_SUCCESS.
- If the miniport must wait for send completions or pending receive NBLs, it
- should return NDIS_STATUS_PENDING now, and call NDISMPauseComplete when the
- miniport has entered the Paused state.
- No other return value is permitted. The pause operation must not fail.
- --*/
- {
- PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext;
- NDIS_STATUS status;
- UNREFERENCED_PARAMETER(PauseParameters);
- DEBUGP (("[TAP] --> AdapterPause\n"));
- // Enter the Pausing state.
- DEBUGP (("[TAP] Miniport State: Pausing\n"));
- tapAdapterAcquireLock(adapter,FALSE);
- adapter->Locked.AdapterState = MiniportPausingState;
- tapAdapterReleaseLock(adapter,FALSE);
- //
- // Stop the flow of network data through the receive path
- // ------------------------------------------------------
- // In the Pausing and Paused state tapAdapterSendAndReceiveReady
- // will prevent new calls to NdisMIndicateReceiveNetBufferLists
- // to indicate additional receive NBLs to the host.
- //
- // However, there may be some in-flight NBLs owned by the driver
- // that have been indicated to the host but have not yet been
- // returned.
- //
- // Wait here for all in-flight receive indications to be returned.
- //
- tapWaitForReceiveNblInFlightCountZeroEvent(adapter);
- //
- // Stop the flow of network data through the send path
- // ---------------------------------------------------
- // The initial implementation of the NDIS 6 send path follows the
- // NDIS 5 pattern. Under this approach every send packet is copied
- // into a driver-owned TAP_PACKET structure and the NBL owned by
- // higher-level protocol is immediatly completed.
- //
- // With this deep-copy approach the driver never claims ownership
- // of any send NBL.
- //
- // A future implementation may queue send NBLs and thereby eliminate
- // the need for the unnecessary allocation and deep copy of each packet.
- //
- // So, nothing to do here for the send path for now...
- status = NDIS_STATUS_SUCCESS;
- // Enter the Paused state.
- DEBUGP (("[TAP] Miniport State: Paused\n"));
- tapAdapterAcquireLock(adapter,FALSE);
- adapter->Locked.AdapterState = MiniportPausedState;
- tapAdapterReleaseLock(adapter,FALSE);
- DEBUGP (("[TAP] <-- AdapterPause; status = %8.8X\n",status));
- return status;
- }
- NDIS_STATUS
- AdapterRestart(
- __in NDIS_HANDLE MiniportAdapterContext,
- __in PNDIS_MINIPORT_RESTART_PARAMETERS RestartParameters
- )
- /*++
- Routine Description:
- When a miniport receives a restart request, it enters into a Restarting
- state. The miniport may begin indicating received data (e.g., using
- NdisMIndicateReceiveNetBufferLists), handling status indications, and
- processing OID requests in the Restarting state. However, no sends will be
- requested while the miniport is in the Restarting state.
- Once the miniport is ready to send data, it has entered the Running state.
- The miniport informs NDIS that it is in the Running state by returning
- NDIS_STATUS_SUCCESS from this MiniportRestart function; or if this function
- has already returned NDIS_STATUS_PENDING, by calling NdisMRestartComplete.
- MiniportRestart runs at IRQL = PASSIVE_LEVEL.
- Arguments:
- MiniportAdapterContext Pointer to the Adapter
- RestartParameters Additional information about the restart operation
- Return Value:
- If the miniport is able to immediately enter the Running state, it should
- return NDIS_STATUS_SUCCESS.
- If the miniport is still in the Restarting state, it should return
- NDIS_STATUS_PENDING now, and call NdisMRestartComplete when the miniport
- has entered the Running state.
- Other NDIS_STATUS codes indicate errors. If an error is encountered, the
- miniport must return to the Paused state (i.e., stop indicating receives).
- --*/
- {
- PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext;
- NDIS_STATUS status;
- UNREFERENCED_PARAMETER(RestartParameters);
- DEBUGP (("[TAP] --> AdapterRestart\n"));
- // Enter the Restarting state.
- DEBUGP (("[TAP] Miniport State: Restarting\n"));
- tapAdapterAcquireLock(adapter,FALSE);
- adapter->Locked.AdapterState = MiniportRestartingState;
- tapAdapterReleaseLock(adapter,FALSE);
- status = NDIS_STATUS_SUCCESS;
- if(status == NDIS_STATUS_SUCCESS)
- {
- // Enter the Running state.
- DEBUGP (("[TAP] Miniport State: Running\n"));
- tapAdapterAcquireLock(adapter,FALSE);
- adapter->Locked.AdapterState = MiniportRunning;
- tapAdapterReleaseLock(adapter,FALSE);
- }
- else
- {
- // Enter the Paused state if restart failed.
- DEBUGP (("[TAP] Miniport State: Paused\n"));
- tapAdapterAcquireLock(adapter,FALSE);
- adapter->Locked.AdapterState = MiniportPausedState;
- tapAdapterReleaseLock(adapter,FALSE);
- }
- DEBUGP (("[TAP] <-- AdapterRestart; status = %8.8X\n",status));
- return status;
- }
- BOOLEAN
- tapAdapterReadAndWriteReady(
- __in PTAP_ADAPTER_CONTEXT Adapter
- )
- /*++
- Routine Description:
- This routine determines whether the adapter device interface can
- accept read and write operations.
- Arguments:
- Adapter Pointer to our adapter context
- Return Value:
- Returns TRUE if the adapter state allows it to queue IRPs passed to
- the device read and write callbacks.
- --*/
- {
- if(!Adapter->TapDeviceCreated)
- {
- // TAP device not created or is being destroyed.
- return FALSE;
- }
- if(Adapter->TapFileObject == NULL)
- {
- // TAP application file object not open.
- return FALSE;
- }
- if(!Adapter->TapFileIsOpen)
- {
- // TAP application file object may be closing.
- return FALSE;
- }
- if(!Adapter->LogicalMediaState)
- {
- // Don't handle read/write if media not connected.
- return FALSE;
- }
- if(Adapter->CurrentPowerState != NdisDeviceStateD0)
- {
- // Don't handle read/write if device is not fully powered.
- return FALSE;
- }
- return TRUE;
- }
- NDIS_STATUS
- tapAdapterSendAndReceiveReady(
- __in PTAP_ADAPTER_CONTEXT Adapter
- )
- /*++
- Routine Description:
- This routine determines whether the adapter NDIS send and receive
- paths are ready.
- This routine examines various adapter state variables and returns
- a value that indicates whether the adapter NDIS interfaces can
- accept send packets or indicate receive packets.
- In normal operation the adapter may temporarily enter and then exit
- a not-ready condition. In particular, the adapter becomes not-ready
- when in the Pausing/Paused states, but may become ready again when
- Restarted.
- Runs at IRQL <= DISPATCH_LEVEL
- Arguments:
- Adapter Pointer to our adapter context
- Return Value:
- Returns NDIS_STATUS_SUCCESS if the adapter state allows it to
- accept send packets and indicate receive packets.
- Otherwise it returns a NDIS_STATUS value other than NDIS_STATUS_SUCCESS.
- These status values can be used directly as the completion status for
- packets that must be completed immediatly in the send path.
- --*/
- {
- NDIS_STATUS status = NDIS_STATUS_SUCCESS;
- //
- // Check various state variables to insure adapter is ready.
- //
- tapAdapterAcquireLock(Adapter,FALSE);
- if(!Adapter->LogicalMediaState)
- {
- status = NDIS_STATUS_MEDIA_DISCONNECTED;
- }
- else if(Adapter->CurrentPowerState != NdisDeviceStateD0)
- {
- status = NDIS_STATUS_LOW_POWER_STATE;
- }
- else if(Adapter->ResetInProgress)
- {
- status = NDIS_STATUS_RESET_IN_PROGRESS;
- }
- else
- {
- switch(Adapter->Locked.AdapterState)
- {
- case MiniportPausingState:
- case MiniportPausedState:
- status = NDIS_STATUS_PAUSED;
- break;
- case MiniportHaltedState:
- status = NDIS_STATUS_INVALID_STATE;
- break;
- default:
- status = NDIS_STATUS_SUCCESS;
- break;
- }
- }
- tapAdapterReleaseLock(Adapter,FALSE);
- return status;
- }
- BOOLEAN
- AdapterCheckForHangEx(
- __in NDIS_HANDLE MiniportAdapterContext
- )
- /*++
- Routine Description:
- The MiniportCheckForHangEx handler is called to report the state of the
- NIC, or to monitor the responsiveness of an underlying device driver.
- This is an optional function. If this handler is not specified, NDIS
- judges the driver unresponsive when the driver holds
- MiniportQueryInformation or MiniportSetInformation requests for a
- time-out interval (deafult 4 sec), and then calls the driver's
- MiniportReset function. A NIC driver's MiniportInitialize function can
- extend NDIS's time-out interval by calling NdisMSetAttributesEx to
- avoid unnecessary resets.
- MiniportCheckForHangEx runs at IRQL <= DISPATCH_LEVEL.
- Arguments:
- MiniportAdapterContext Pointer to our adapter
- Return Value:
- TRUE NDIS calls the driver's MiniportReset function.
- FALSE Everything is fine
- --*/
- {
- PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext;
- //DEBUGP (("[TAP] --> AdapterCheckForHangEx\n"));
- //DEBUGP (("[TAP] <-- AdapterCheckForHangEx; status = FALSE\n"));
- return FALSE; // Everything is fine
- }
- NDIS_STATUS
- AdapterReset(
- __in NDIS_HANDLE MiniportAdapterContext,
- __out PBOOLEAN AddressingReset
- )
- /*++
- Routine Description:
- MiniportResetEx is a required to issue a hardware reset to the NIC
- and/or to reset the driver's software state.
- 1) The miniport driver can optionally complete any pending
- OID requests. NDIS will submit no further OID requests
- to the miniport driver for the NIC being reset until
- the reset operation has finished. After the reset,
- NDIS will resubmit to the miniport driver any OID requests
- that were pending but not completed by the miniport driver
- before the reset.
- 2) A deserialized miniport driver must complete any pending send
- operations. NDIS will not requeue pending send packets for
- a deserialized driver since NDIS does not maintain the send
- queue for such a driver.
- 3) If MiniportReset returns NDIS_STATUS_PENDING, the driver must
- complete the original request subsequently with a call to
- NdisMResetComplete.
- MiniportReset runs at IRQL <= DISPATCH_LEVEL.
- Arguments:
- AddressingReset - If multicast or functional addressing information
- or the lookahead size, is changed by a reset,
- MiniportReset must set the variable at AddressingReset
- to TRUE before it returns control. This causes NDIS to
- call the MiniportSetInformation function to restore
- the information.
- MiniportAdapterContext - Pointer to our adapter
- Return Value:
- NDIS_STATUS
- --*/
- {
- PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext;
- NDIS_STATUS status;
- UNREFERENCED_PARAMETER(MiniportAdapterContext);
- UNREFERENCED_PARAMETER(AddressingReset);
- DEBUGP (("[TAP] --> AdapterReset\n"));
- // Indicate that adapter reset is in progress.
- adapter->ResetInProgress = TRUE;
- // See note above...
- *AddressingReset = FALSE;
- // BUGBUG!!! TODO!!! Lots of work here...
- // Indicate that adapter reset has completed.
- adapter->ResetInProgress = FALSE;
- status = NDIS_STATUS_SUCCESS;
- DEBUGP (("[TAP] <-- AdapterReset; status = %8.8X\n",status));
- return status;
- }
- VOID
- AdapterDevicePnpEventNotify(
- __in NDIS_HANDLE MiniportAdapterContext,
- __in PNET_DEVICE_PNP_EVENT NetDevicePnPEvent
- )
- {
- PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext;
- DEBUGP (("[TAP] --> AdapterDevicePnpEventNotify\n"));
- /*
- switch (NetDevicePnPEvent->DevicePnPEvent)
- {
- case NdisDevicePnPEventSurpriseRemoved:
- //
- // Called when NDIS receives IRP_MN_SUPRISE_REMOVAL.
- // NDIS calls MiniportHalt function after this call returns.
- //
- MP_SET_FLAG(Adapter, fMP_ADAPTER_SURPRISE_REMOVED);
- DEBUGP(MP_INFO, "[%p] MPDevicePnpEventNotify: NdisDevicePnPEventSurpriseRemoved\n", Adapter);
- break;
- case NdisDevicePnPEventPowerProfileChanged:
- //
- // After initializing a miniport driver and after miniport driver
- // receives an OID_PNP_SET_POWER notification that specifies
- // a device power state of NdisDeviceStateD0 (the powered-on state),
- // NDIS calls the miniport's MiniportPnPEventNotify function with
- // PnPEvent set to NdisDevicePnPEventPowerProfileChanged.
- //
- DEBUGP(MP_INFO, "[%p] MPDevicePnpEventNotify: NdisDevicePnPEventPowerProfileChanged\n", Adapter);
- if (NetDevicePnPEvent->InformationBufferLength == sizeof(ULONG))
- {
- ULONG NdisPowerProfile = *((PULONG)NetDevicePnPEvent->InformationBuffer);
- if (NdisPowerProfile == NdisPowerProfileBattery)
- {
- DEBUGP(MP_INFO, "[%p] The host system is running on battery power\n", Adapter);
- }
- if (NdisPowerProfile == NdisPowerProfileAcOnLine)
- {
- DEBUGP(MP_INFO, "[%p] The host system is running on AC power\n", Adapter);
- }
- }
- break;
- default:
- DEBUGP(MP_ERROR, "[%p] MPDevicePnpEventNotify: unknown PnP event 0x%x\n", Adapter, NetDevicePnPEvent->DevicePnPEvent);
- }
- */
- DEBUGP (("[TAP] <-- AdapterDevicePnpEventNotify\n"));
- }
- VOID
- AdapterShutdownEx(
- __in NDIS_HANDLE MiniportAdapterContext,
- __in NDIS_SHUTDOWN_ACTION ShutdownAction
- )
- /*++
- Routine Description:
- The MiniportShutdownEx handler restores hardware to its initial state when
- the system is shut down, whether by the user or because an unrecoverable
- system error occurred. This is to ensure that the NIC is in a known
- state and ready to be reinitialized when the machine is rebooted after
- a system shutdown occurs for any reason, including a crash dump.
- Here just disable the interrupt and stop the DMA engine. Do not free
- memory resources or wait for any packet transfers to complete. Do not call
- into NDIS at this time.
- This can be called at aribitrary IRQL, including in the context of a
- bugcheck.
- Arguments:
- MiniportAdapterContext Pointer to our adapter
- ShutdownAction The reason why NDIS called the shutdown function
- Return Value:
- None.
- --*/
- {
- PTAP_ADAPTER_CONTEXT adapter = (PTAP_ADAPTER_CONTEXT )MiniportAdapterContext;
- UNREFERENCED_PARAMETER(ShutdownAction);
- UNREFERENCED_PARAMETER(MiniportAdapterContext);
- DEBUGP (("[TAP] --> AdapterShutdownEx\n"));
- // Enter the Shutdown state.
- DEBUGP (("[TAP] Miniport State: Shutdown\n"));
- tapAdapterAcquireLock(adapter,FALSE);
- adapter->Locked.AdapterState = MiniportShutdownState;
- tapAdapterReleaseLock(adapter,FALSE);
- //
- // BUGBUG!!! FlushIrpQueues???
- //
- DEBUGP (("[TAP] <-- AdapterShutdownEx\n"));
- }
- // Free adapter context memory and associated resources.
- VOID
- tapAdapterContextFree(
- __in PTAP_ADAPTER_CONTEXT Adapter
- )
- {
- PLIST_ENTRY listEntry = &Adapter->AdapterListLink;
- DEBUGP (("[TAP] --> tapAdapterContextFree\n"));
- // Adapter context should already be removed.
- ASSERT( (listEntry->Flink == listEntry) && (listEntry->Blink == listEntry ) );
- // Insure that adapter context has been removed from global adapter list.
- RemoveEntryList(&Adapter->AdapterListLink);
- // Free the adapter lock.
- NdisFreeSpinLock(&Adapter->AdapterLock);
- // Free the ANSI NetCfgInstanceId buffer.
- if(Adapter->NetCfgInstanceIdAnsi.Buffer != NULL)
- {
- RtlFreeAnsiString(&Adapter->NetCfgInstanceIdAnsi);
- }
- Adapter->NetCfgInstanceIdAnsi.Buffer = NULL;
- // Free the receive NBL pool.
- if(Adapter->ReceiveNblPool != NULL )
- {
- NdisFreeNetBufferListPool(Adapter->ReceiveNblPool);
- }
- Adapter->ReceiveNblPool = NULL;
- NdisFreeMemory(Adapter,0,0);
- DEBUGP (("[TAP] <-- tapAdapterContextFree\n"));
- }
- ULONG
- tapGetNetBufferFrameType(
- __in PNET_BUFFER NetBuffer
- )
- /*++
- Routine Description:
- Reads the network frame's destination address to determine the type
- (broadcast, multicast, etc)
- Runs at IRQL <= DISPATCH_LEVEL.
- Arguments:
- NetBuffer The NB to examine
- Return Value:
- NDIS_PACKET_TYPE_BROADCAST
- NDIS_PACKET_TYPE_MULTICAST
- NDIS_PACKET_TYPE_DIRECTED
- --*/
- {
- PETH_HEADER ethernetHeader;
- ethernetHeader = (PETH_HEADER )NdisGetDataBuffer(
- NetBuffer,
- sizeof(ETH_HEADER),
- NULL,
- 1,
- 0
- );
- ASSERT(ethernetHeader);
- if (ETH_IS_BROADCAST(ethernetHeader->dest))
- {
- return NDIS_PACKET_TYPE_BROADCAST;
- }
- else if(ETH_IS_MULTICAST(ethernetHeader->dest))
- {
- return NDIS_PACKET_TYPE_MULTICAST;
- }
- else
- {
- return NDIS_PACKET_TYPE_DIRECTED;
- }
- }
- ULONG
- tapGetNetBufferCountsFromNetBufferList(
- __in PNET_BUFFER_LIST NetBufferList,
- __inout_opt PULONG TotalByteCount // Of all linked NBs
- )
- /*++
- Routine Description:
- Returns the number of net buffers linked to the net buffer list.
- Optionally retuens the total byte count of all net buffers linked
- to the net buffer list
- Runs at IRQL <= DISPATCH_LEVEL.
- Arguments:
- NetBufferList The NBL to examine
- Return Value:
- The number of net buffers linked to the net buffer list.
- --*/
- {
- ULONG netBufferCount = 0;
- PNET_BUFFER currentNb;
- if(TotalByteCount)
- {
- *TotalByteCount = 0;
- }
- currentNb = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
- while(currentNb)
- {
- ++netBufferCount;
- if(TotalByteCount)
- {
- *TotalByteCount += NET_BUFFER_DATA_LENGTH(currentNb);
- }
- // Move to next NB
- currentNb = NET_BUFFER_NEXT_NB(currentNb);
- }
- return netBufferCount;
- }
- VOID
- tapAdapterAcquireLock(
- __in PTAP_ADAPTER_CONTEXT Adapter,
- __in BOOLEAN DispatchLevel
- )
- {
- ASSERT(!DispatchLevel || (DISPATCH_LEVEL == KeGetCurrentIrql()));
-
- if (DispatchLevel)
- {
- NdisDprAcquireSpinLock(&Adapter->AdapterLock);
- }
- else
- {
- NdisAcquireSpinLock(&Adapter->AdapterLock);
- }
- }
- VOID
- tapAdapterReleaseLock(
- __in PTAP_ADAPTER_CONTEXT Adapter,
- __in BOOLEAN DispatchLevel
- )
- {
- ASSERT(!DispatchLevel || (DISPATCH_LEVEL == KeGetCurrentIrql()));
-
- if (DispatchLevel)
- {
- NdisDprReleaseSpinLock(&Adapter->AdapterLock);
- }
- else
- {
- NdisReleaseSpinLock(&Adapter->AdapterLock);
- }
- }
|