1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717 |
- /*
- * 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);
- }
- }
|