Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3495 lines
98 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Module Name:
  3. protocol.c
  4. Abstract:
  5. This module contains all the protocol interface routines.
  6. Author:
  7. Hakan Berk - Microsoft, Inc. (hakanb@microsoft.com) Feb-2000
  8. Environment:
  9. Windows 2000 kernel mode Miniport driver or equivalent.
  10. Revision History:
  11. ---------------------------------------------------------------------------*/
  12. #include <ntddk.h>
  13. #include <ntddndis.h>
  14. #include <ndis.h>
  15. #include <ndiswan.h>
  16. #include <ndistapi.h>
  17. #include <ntverp.h>
  18. #include <tdikrnl.h> // For TdiCopyLookaheadData()
  19. //
  20. // VOID
  21. // TdiCopyLookaheadData(
  22. // IN PVOID Destination,
  23. // IN PVOID Source,
  24. // IN ULONG Length,
  25. // IN ULONG ReceiveFlags
  26. // );
  27. //
  28. /*
  29. #ifdef _M_IX86
  30. #define TdiCopyLookaheadData(_Destination,_Source,_Length,_ReceiveFlags) \
  31. RtlCopyMemory(_Destination,_Source,_Length)
  32. #else
  33. #define TdiCopyLookaheadData(_Destination,_Source,_Length,_ReceiveFlags) { \
  34. if ((_ReceiveFlags) & TDI_RECEIVE_COPY_LOOKAHEAD) { \
  35. RtlCopyMemory(_Destination,_Source,_Length); \
  36. } else { \
  37. PUCHAR _Src = (PUCHAR)(_Source); \
  38. PUCHAR _Dest = (PUCHAR)(_Destination); \
  39. PUCHAR _End = _Dest + (_Length); \
  40. while (_Dest < _End) { \
  41. *_Dest++ = *_Src++; \
  42. } \
  43. } \
  44. }
  45. #endif
  46. */
  47. #include "debug.h"
  48. #include "timer.h"
  49. #include "bpool.h"
  50. #include "ppool.h"
  51. #include "util.h"
  52. #include "packet.h"
  53. #include "protocol.h"
  54. #include "miniport.h"
  55. #include "tapi.h"
  56. extern NPAGED_LOOKASIDE_LIST gl_llistWorkItems;
  57. /////////////////////////////////////////////////////////////////////////////
  58. //
  59. // Variables local to this module
  60. // They are defined as global only for debugging purposes
  61. //
  62. /////////////////////////////////////////////////////////////////////////////
  63. #define INVALID_HANDLE_VALUE (NDIS_HANDLE) 0
  64. //
  65. // Handle passed to us by NDIS while registering the protocol
  66. //
  67. NDIS_HANDLE gl_hNdisProtocolHandle = INVALID_HANDLE_VALUE;
  68. //
  69. // Controls access for members listed below
  70. //
  71. NDIS_SPIN_LOCK gl_lockProtocol;
  72. //
  73. // List of binding contexts that are bound
  74. //
  75. LIST_ENTRY gl_linkBindings;
  76. //
  77. // Boolean flag to remember if PrUnload() was called previously
  78. //
  79. BOOLEAN gl_fProtocolUnloaded = TRUE;
  80. // Boolean flag to decide if we need to set packet filters at bind time
  81. //
  82. //
  83. BOOLEAN gl_fSetPacketFiltersAtBind = FALSE;
  84. //
  85. // Boolean flag set to tell the protocol it is okay to bind
  86. // This flag is initially FALSE and is only set to true
  87. // when a tapi client either wants to make an outgoing call
  88. // or listen for incoming calls
  89. //
  90. BOOLEAN gl_fBindProtocol = FALSE;
  91. //
  92. // Number of binding contexts in linkBindings
  93. //
  94. ULONG gl_ulNumBindings;
  95. //
  96. // Keeps the minimum of max frame sizes of bindings.
  97. // This value is used by miniport and is passed to NDISWAN
  98. // in OID_WAN_GET_INFO query.
  99. //
  100. ULONG gl_ulMaxFrameSize = 0;
  101. /////////////////////////////////////////////////////////////////////////////
  102. //
  103. //
  104. // Local functions (not exposed) definitions
  105. //
  106. /////////////////////////////////////////////////////////////////////////////
  107. NDIS_STATUS
  108. InitializeProtocol(
  109. IN NDIS_HANDLE NdisProtocolHandle,
  110. IN PUNICODE_STRING RegistryPath
  111. )
  112. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  113. Functional Description:
  114. This function initializes the static protocol members.
  115. NdisRegisterProtocol() must be called before.
  116. Parameters:
  117. DriverObject:
  118. Pointer to the driver object.
  119. RegistryPath:
  120. A unicode string that identifies the registry entry. We can use this this retrieve
  121. value from the registry.
  122. Return Values:
  123. NDIS_STATUS_SUCCESS:
  124. Protocol initialized.
  125. NDIS_STATUS_XXX:
  126. Protocol initialization failed, deregister protocol.
  127. ---------------------------------------------------------------------------*/
  128. {
  129. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  130. TRACE( TL_N, TM_Pr, ("+InitializeProtocol") );
  131. //
  132. // Future: Read values from registry here
  133. //
  134. //
  135. // Initialize the NdisProtocolHandle
  136. //
  137. gl_hNdisProtocolHandle = NdisProtocolHandle;
  138. //
  139. // Allocate the spin lock
  140. //
  141. NdisAllocateSpinLock( &gl_lockProtocol );
  142. //
  143. // Initialize list of bindings
  144. //
  145. NdisInitializeListHead( &gl_linkBindings );
  146. //
  147. // Initialize number of allocated bindings
  148. //
  149. gl_ulNumBindings = 0;
  150. //
  151. // Load the resources
  152. //
  153. PrLoad();
  154. TRACE( TL_N, TM_Pr, ("-InitializeProtocol=$%x",status) );
  155. return status;
  156. }
  157. VOID
  158. PrLoad()
  159. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  160. Functional Description:
  161. This function will allocate the resources for the protocol.
  162. Caller must make sure that PrLoad() and PrUnload() are not called simultaneously,
  163. as well as multiple PrLoad()'s are not called simultanesouly.
  164. It will load the resources if they were unloaded, and do nothing otherwise.
  165. We need this function because the resources freed by PrUnload() must be loaded
  166. somehow, and there is no function called prior to PrBindAdapter() once PrUnload()
  167. is called. So we allocate all the resources for the binding, and once binding is completed,
  168. we call this function to load the resources if necesarry prior to notifying the completion
  169. of binding to NDIS.
  170. Parameters:
  171. None
  172. Return Values:
  173. - Pointer to the newly allocated binding context.
  174. - NULL if allocation fails.
  175. ---------------------------------------------------------------------------*/
  176. {
  177. TRACE( TL_N, TM_Pr, ("+PrLoad") );
  178. //
  179. // Make sure we are not trying to initialize resources,
  180. // unless they are already freed by PrUnload()
  181. //
  182. if ( gl_fProtocolUnloaded )
  183. {
  184. TRACE( TL_N, TM_Pr, ("PrLoad: Loading the resources" ) );
  185. ASSERT( gl_ulNumBindings == 0 );
  186. //
  187. // Allocate packet pool
  188. //
  189. PacketPoolInit();
  190. gl_fProtocolUnloaded = FALSE;
  191. }
  192. TRACE( TL_N, TM_Pr, ("-PrLoad") );
  193. }
  194. BINDING*
  195. AllocBinding()
  196. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  197. Functional Description:
  198. This function will allocate the resources for the binding context.
  199. Parameters:
  200. pBinding _ A pointer to our binding information structure.
  201. fAcquireLock _ Flag that indicates if the function needs to acquire the lock
  202. or not. If the caller already owns the lock for the binding,
  203. then it should be supplied as TRUE, otherwise FALSE.
  204. Return Values:
  205. - Pointer to the newly allocated binding context.
  206. - NULL if allocation fails.
  207. ---------------------------------------------------------------------------*/
  208. {
  209. BINDING* pBinding = NULL;
  210. TRACE( TL_N, TM_Pr, ("+AllocBinding") );
  211. if ( ALLOC_BINDING( &pBinding ) != NDIS_STATUS_SUCCESS )
  212. {
  213. TRACE( TL_A, TM_Pr, ("AllocBinding: Could not allocate context") );
  214. TRACE( TL_N, TM_Pr, ("-AllocBinding") );
  215. return NULL;
  216. }
  217. NdisZeroMemory( pBinding, sizeof(BINDING) );
  218. pBinding->tagBinding = MTAG_BINDING;
  219. pBinding->stateBinding = BN_stateBindPending;
  220. NdisInitializeEvent( &pBinding->RequestCompleted );
  221. pBinding->BindAdapterStatus = NDIS_STATUS_FAILURE;
  222. NdisInitializeEvent( &pBinding->eventFreeBinding );
  223. NdisAllocateSpinLock( &pBinding->lockBinding );
  224. InitializeListHead( &pBinding->linkPackets );
  225. TRACE( TL_N, TM_Pr, ("-AllocBinding") );
  226. return pBinding;
  227. }
  228. VOID
  229. ReferenceBinding(
  230. IN BINDING* pBinding,
  231. IN BOOLEAN fAcquireLock
  232. )
  233. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  234. Functional Description:
  235. This function will increment the reference count on the binding.
  236. Parameters:
  237. pBinding _ A pointer ot our binding information structure.
  238. fAcquireLock _ Flag that indicates if the function needs to acquire the lock
  239. or not. If the caller already owns the lock for the binding,
  240. then it should be supplied as TRUE, otherwise FALSE.
  241. Return Values:
  242. None
  243. ---------------------------------------------------------------------------*/
  244. {
  245. LONG lRef;
  246. ASSERT( VALIDATE_BINDING( pBinding ) );
  247. TRACE( TL_V, TM_Pr, ("+ReferenceBinding") );
  248. if ( fAcquireLock )
  249. NdisAcquireSpinLock( &pBinding->lockBinding );
  250. lRef = ++pBinding->lRef;
  251. if ( fAcquireLock )
  252. NdisReleaseSpinLock( &pBinding->lockBinding );
  253. TRACE( TL_V, TM_Pr, ("-ReferenceBinding=$%d",lRef) );
  254. }
  255. VOID
  256. DereferenceBinding(
  257. IN BINDING* pBinding
  258. )
  259. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  260. Functional Description:
  261. This function will decrement the reference count on the binding.
  262. If the count reaches 0, it will signal pBinding->eventFreeBinding
  263. so that PrUnbindAdapter() function can free the protocol context.
  264. CAUTION: Caller must not be holding any locks.
  265. Parameters:
  266. pBinding _ A pointer to our binding information structure.
  267. Return Values:
  268. None
  269. ---------------------------------------------------------------------------*/
  270. {
  271. BOOLEAN fSignalFreeBindingEvent = FALSE;
  272. LONG lRef;
  273. ASSERT( VALIDATE_BINDING( pBinding ) );
  274. TRACE( TL_V, TM_Pr, ("+DereferenceBinding") );
  275. NdisAcquireSpinLock( &pBinding->lockBinding );
  276. lRef = --pBinding->lRef;
  277. if ( lRef == 0 )
  278. {
  279. fSignalFreeBindingEvent = TRUE;
  280. }
  281. NdisReleaseSpinLock( &pBinding->lockBinding );
  282. if ( fSignalFreeBindingEvent )
  283. NdisSetEvent( &pBinding->eventFreeBinding );
  284. TRACE( TL_V, TM_Pr, ("-DereferenceBinding=$%d",lRef) );
  285. }
  286. VOID
  287. BindingCleanup(
  288. IN BINDING* pBinding
  289. )
  290. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  291. Functional Description:
  292. This function will free the resources allocated for the binding context.
  293. Parameters:
  294. pBinding _ A pointer to our binding information structure.
  295. Return Values:
  296. None
  297. ---------------------------------------------------------------------------*/
  298. {
  299. ASSERT( VALIDATE_BINDING( pBinding ) );
  300. TRACE( TL_N, TM_Pr, ("+BindingCleanup") );
  301. ASSERT( pBinding->lRef == 0 );
  302. NdisFreeSpinLock( &pBinding->lockBinding );
  303. FREE_BINDING( pBinding );
  304. TRACE( TL_N, TM_Pr, ("-BindingCleanup") );
  305. }
  306. VOID
  307. DetermineMaxFrameSize()
  308. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  309. Functional Description:
  310. This function will be called when a new binding is added or removed.
  311. It will walk thru all the bindings and select the minimum of max frame
  312. size values, and set it to gl_ulMaxFrameSize.
  313. It will be called from 2 places:
  314. - PrAddBindingToProtocol()
  315. - PrRemoveBindingFromProtocol()
  316. CAUTION: gl_lockProtocol must be acquired before calling this function.
  317. Parameters:
  318. None
  319. Return Values:
  320. None
  321. ---------------------------------------------------------------------------*/
  322. {
  323. LIST_ENTRY* pLink = NULL;
  324. pLink = gl_linkBindings.Flink;
  325. //
  326. // See if we have any bindings
  327. //
  328. if ( pLink != &gl_linkBindings )
  329. {
  330. ULONG MinOfMaxFrameSizes = 0;
  331. BINDING* pBinding = NULL;
  332. //
  333. // We have at least one binding, so walk thru the list
  334. // and select the minimum of MaxFrameSize values
  335. //
  336. pBinding = ((BINDING*) CONTAINING_RECORD( pLink, BINDING, linkBindings ));
  337. MinOfMaxFrameSizes = pBinding->ulMaxFrameSize;
  338. //
  339. // Iterate to the next binding
  340. //
  341. pLink = pLink->Flink;
  342. while ( pLink != &gl_linkBindings )
  343. {
  344. ULONG MaxFrameSize;
  345. //
  346. // Retrieve the MaxFrameSize value of the next binding and
  347. // select the minimum
  348. //
  349. pBinding = ((BINDING*) CONTAINING_RECORD( pLink, BINDING, linkBindings ));
  350. MaxFrameSize = pBinding->ulMaxFrameSize;
  351. if ( MinOfMaxFrameSizes > MaxFrameSize )
  352. {
  353. MinOfMaxFrameSizes = MaxFrameSize;
  354. }
  355. //
  356. // Iterate to the next binding
  357. //
  358. pLink = pLink->Flink;
  359. }
  360. //
  361. // Set gl_ulMaxFrameSize to the selected minimum value
  362. //
  363. gl_ulMaxFrameSize = MinOfMaxFrameSizes;
  364. }
  365. else
  366. {
  367. //
  368. // Binding list is empty, so set it to 0
  369. //
  370. gl_ulMaxFrameSize = 0;
  371. }
  372. }
  373. VOID
  374. AddBindingToProtocol(
  375. IN BINDING* pBinding
  376. )
  377. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  378. Functional Description:
  379. This function will insert a binding to protocols binding table.
  380. It will also put a reference on the binding which will go away
  381. when the binding is removed from this table with a call to
  382. RemoveBindingFromProtocol().
  383. Parameters:
  384. pBinding:
  385. A pointer ot our binding information structure.
  386. Return Values:
  387. None
  388. ---------------------------------------------------------------------------*/
  389. {
  390. ASSERT( VALIDATE_BINDING( pBinding ) );
  391. TRACE( TL_N, TM_Pr, ("+AddBindingToProtocol") );
  392. NdisAcquireSpinLock( &gl_lockProtocol );
  393. InsertTailList( &gl_linkBindings, &pBinding->linkBindings );
  394. gl_ulNumBindings++;
  395. //
  396. // Determine the new max frame size value
  397. //
  398. DetermineMaxFrameSize();
  399. NdisReleaseSpinLock( &gl_lockProtocol );
  400. ReferenceBinding( pBinding, TRUE );
  401. TRACE( TL_N, TM_Pr, ("-AddBindingToProtocol") );
  402. }
  403. VOID
  404. RemoveBindingFromProtocol(
  405. IN BINDING* pBinding
  406. )
  407. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  408. Functional Description:
  409. This function will remove a binding from protocols binding list.
  410. Binding will be dereferenced after removal from the list.
  411. CAUTION: Caller must not be holding any locks before calling this function.
  412. Parameters:
  413. pBinding:
  414. A pointer ot our binding information structure.
  415. Return Values:
  416. None
  417. ---------------------------------------------------------------------------*/
  418. {
  419. ASSERT( VALIDATE_BINDING( pBinding ) );
  420. TRACE( TL_N, TM_Pr, ("+RemoveBindingFromProtocol") );
  421. NdisAcquireSpinLock( &gl_lockProtocol );
  422. RemoveHeadList( pBinding->linkBindings.Blink );
  423. InitializeListHead( &pBinding->linkBindings );
  424. gl_ulNumBindings--;
  425. //
  426. // Determine the new max frame size value
  427. //
  428. DetermineMaxFrameSize();
  429. NdisReleaseSpinLock( &gl_lockProtocol );
  430. DereferenceBinding( pBinding );
  431. TRACE( TL_N, TM_Pr, ("-RemoveBindingFromProtocol") );
  432. }
  433. /////////////////////////////////////////////////////////////////////////////
  434. //
  435. // Interface functions (exposed) definitions
  436. //
  437. /////////////////////////////////////////////////////////////////////////////
  438. VOID
  439. PrUnload(
  440. VOID
  441. )
  442. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  443. Functional Description:
  444. In response to a user request to uninstall a protocol, NDIS calls a protocol's
  445. ProtocolUnload function if the protocol has registered an entry point for
  446. this function in the NDIS_PROTOCOL_CHARACTERISTICS structure that it passed
  447. to NdisRegisterProtocol. NDIS calls ProtocolUnload after calling the protocol's
  448. ProtocolUnbindAdapter function once for each bound adapter.
  449. ProtocolUnload performs driver-determined cleanup operations. For example,
  450. ProtocolUnload could request clients to close handles that they have opened
  451. to device objects exported by the protocol. Until all such handles are closed,
  452. the I/O Manager will not call the DriverUnload function that the protocol
  453. registered in the driver object passed to its DriverEntry function. After all
  454. the handles are closed, ProtocolUnload could call IoDeleteDevice one or more
  455. times to delete device objects created by the protocol.
  456. ProtocolUnload does not have to close a protocol's open bindings. When a
  457. protocol's DriverUnload function calls NdisDeregisterProtocol, NDIS calls the
  458. protocol's ProtocolUnbindAdapter function once for each binding that the
  459. protocol has open. The ProtocolUnbindAdapter function calls NdisCloseAdapter
  460. to close the binding.
  461. ProtocolUnload must be written so that it can run at IRQL PASSIVE_LEVEL.
  462. Parameters:
  463. None
  464. Return Values:
  465. None
  466. ---------------------------------------------------------------------------*/
  467. {
  468. TRACE( TL_N, TM_Pr, ("+PrUnload") );
  469. if ( !gl_fProtocolUnloaded && gl_ulNumBindings == 0 )
  470. {
  471. TRACE( TL_N, TM_Pr, ("PrUnload: Unloading the resources" ) );
  472. PacketPoolUninit();
  473. gl_fProtocolUnloaded = TRUE;
  474. }
  475. TRACE( TL_N, TM_Pr, ("-PrUnlooad") );
  476. }
  477. NDIS_STATUS
  478. PrRegisterProtocol(
  479. IN PDRIVER_OBJECT DriverObject,
  480. IN PUNICODE_STRING RegistryPath,
  481. OUT NDIS_HANDLE* pNdisProtocolHandle
  482. )
  483. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  484. Functional Description:
  485. This function will register the protocol with NDIS.
  486. It must be called from DriverEntry() function before any other in this module
  487. can be called.
  488. Parameters:
  489. DriverObject:
  490. Pointer to the driver object.
  491. RegistryPath:
  492. A unicode string that identifies the registry entry. We can use this this retrieve
  493. value from the registry.
  494. Return Values:
  495. NDIS_STATUS_SUCCESS :
  496. The NDIS library registered the caller as a protocol driver.
  497. NDIS_STATUS_BAD_CHARACTERISTICS :
  498. The CharacteristicsLength is too small for the MajorNdisVersion specified in
  499. the buffer at ProtocolCharacteristics.
  500. NDIS_STATUS_BAD_VERSION :
  501. The MajorNdisVersion specified in the buffer at ProtocolCharacteristics is
  502. invalid.
  503. NDIS_STATUS_RESOURCES :
  504. A shortage of resources, possibly memory, prevented the NDIS library from
  505. registering the caller.
  506. ---------------------------------------------------------------------------*/
  507. {
  508. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  509. BOOLEAN fProtocolRegistered = FALSE;
  510. NDIS_HANDLE NdisProtocolHandle;
  511. NDIS_PROTOCOL_CHARACTERISTICS npc;
  512. STRING NameString;
  513. UNICODE_STRING UnicodeNameString;
  514. TRACE( TL_I, TM_Pr, ("+PrRegisterProtocol") );
  515. do
  516. {
  517. NdisZeroMemory( &npc, sizeof(npc) );
  518. npc.MajorNdisVersion = PR_NDIS_MajorVersion;
  519. npc.MinorNdisVersion = PR_NDIS_MinorVersion;
  520. npc.Reserved = NDIS_USE_WAN_WRAPPER;
  521. npc.OpenAdapterCompleteHandler = PrOpenAdapterComplete;
  522. npc.CloseAdapterCompleteHandler = PrCloseAdapterComplete;
  523. npc.SendCompleteHandler = PrSendComplete;
  524. npc.TransferDataCompleteHandler = PrTransferDataComplete;
  525. // npc.ResetCompleteHandler = PrResetCompleteHandler;
  526. npc.RequestCompleteHandler = PrRequestComplete;
  527. npc.ReceiveHandler = PrReceive;
  528. npc.ReceiveCompleteHandler = PrReceiveComplete;
  529. npc.StatusHandler = PrStatus;
  530. // npc.StatusCompleteHandler;
  531. RtlInitString( &NameString, PR_CHARACTERISTIC_NAME );
  532. RtlAnsiStringToUnicodeString( &UnicodeNameString,
  533. &NameString,
  534. TRUE );
  535. npc.Name.Length = UnicodeNameString.Length;
  536. npc.Name.Buffer = UnicodeNameString.Buffer;
  537. //
  538. // MajorNdisVersion must be set to 0x04 or 0x05
  539. // with any of the following members.
  540. //
  541. npc.ReceivePacketHandler = PrReceivePacket;
  542. npc.BindAdapterHandler = PrBindAdapter;
  543. npc.UnbindAdapterHandler = PrUnbindAdapter;
  544. npc.PnPEventHandler = PrPnPEvent;
  545. npc.UnloadHandler = PrUnload;
  546. //
  547. // MajorNdisVersion must be set to 0x05
  548. // with any of the following members.
  549. //
  550. // CoSendCompleteHandler;
  551. // CoStatusHandler;
  552. // CoReceivePacketHandler;
  553. // CoAfRegisterNotifyHandler;
  554. NdisRegisterProtocol( &status,
  555. &NdisProtocolHandle,
  556. &npc,
  557. sizeof( NDIS_PROTOCOL_CHARACTERISTICS ) );
  558. if ( status != NDIS_STATUS_SUCCESS )
  559. break;
  560. fProtocolRegistered = TRUE;
  561. status = InitializeProtocol( NdisProtocolHandle, RegistryPath );
  562. if ( status != NDIS_STATUS_SUCCESS )
  563. break;
  564. } while ( FALSE );
  565. if ( status != NDIS_STATUS_SUCCESS )
  566. {
  567. if ( fProtocolRegistered )
  568. {
  569. NDIS_STATUS tempStatus;
  570. NdisDeregisterProtocol( &tempStatus, NdisProtocolHandle );
  571. }
  572. }
  573. else
  574. {
  575. *pNdisProtocolHandle = NdisProtocolHandle;
  576. }
  577. TRACE( TL_I, TM_Pr, ("-PrRegisterProtocol=$%x",status) );
  578. return status;
  579. }
  580. VOID
  581. PrBindAdapter(
  582. OUT PNDIS_STATUS Status,
  583. IN NDIS_HANDLE BindContext,
  584. IN PNDIS_STRING DeviceName,
  585. IN PVOID SystemSpecific1,
  586. IN PVOID SystemSpecific2
  587. )
  588. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  589. Functional Description:
  590. This function will be called by NDIS when an underlying adapter wants to
  591. bind to us.
  592. Parameters:
  593. Status
  594. Points to a variable in which ProtocolBindAdapter returns the status of its
  595. operation(s), as one of the following:
  596. NDIS_STATUS_SUCCESS
  597. The driver completed initialization successfully and bound itself to the
  598. given NIC driver specified at DeviceName.
  599. NDIS_STATUS_PENDING
  600. The protocol will complete the bind operation asynchronously with a call to
  601. NdisCompleteBindAdapter when it is ready to accept receives from the
  602. underlying driver and to send transmit, query, and set requests down to the
  603. underlying driver.
  604. NDIS_STATUS_XXX or NTSTATUS_XXX
  605. The protocol's attempt to set up a binding failed or the protocol could not
  606. allocate the resources it needed to carry out network I/O operations. Usually
  607. , such an error status is propagated from an NdisXxx function or a kernel-
  608. mode support routine.
  609. BindContext
  610. Specifies a handle, supplied by NDIS, that the protocol passes subsequently
  611. to NdisCompleteBindAdapter.
  612. DeviceName
  613. Points to a buffered Unicode string naming an underlying NIC driver or
  614. virtual NIC driver to which ProtocolBindAdapter should bind.
  615. SystemSpecific1
  616. Specifies a registry path pointer that is a required parameter to
  617. NdisOpenProtocolConfiguration. The caller cannot use this pointer for any
  618. other purpose.
  619. SystemSpecific2
  620. Reserved for system use. The caller cannot use this pointer for any purpose.
  621. Return Values:
  622. None
  623. ---------------------------------------------------------------------------*/
  624. {
  625. NDIS_STATUS status = NDIS_STATUS_FAILURE;
  626. BINDING* pBinding = NULL;
  627. TRACE( TL_I, TM_Pr, ("+PrBindAdapter") );
  628. do
  629. {
  630. NdisAcquireSpinLock( &gl_lockProtocol );
  631. if (gl_fBindProtocol == FALSE) {
  632. TRACE( TL_I, TM_Pr, ("PrBindAdapter: Not ready to bind!") );
  633. NdisReleaseSpinLock( &gl_lockProtocol );
  634. status = NDIS_STATUS_FAILURE;
  635. break;
  636. }
  637. NdisReleaseSpinLock( &gl_lockProtocol );
  638. pBinding = AllocBinding();
  639. if ( pBinding == NULL )
  640. {
  641. status = NDIS_STATUS_RESOURCES;
  642. break;
  643. }
  644. //
  645. // Load resources
  646. //
  647. PrLoad();
  648. //
  649. // Open adapter, and query it
  650. //
  651. if ( !PrOpenAdapter( pBinding, DeviceName ) )
  652. {
  653. break;
  654. }
  655. if ( !PrQueryAdapterForCurrentAddress( pBinding ) )
  656. {
  657. break;
  658. }
  659. //
  660. // No need to break if this one fails since it is not critical enough
  661. //
  662. PrQueryAdapterForLinkSpeed( pBinding );
  663. if ( !PrQueryAdapterForMaxFrameSize( pBinding ) )
  664. {
  665. break;
  666. }
  667. //
  668. // Check if we need to set packet filters at bind time
  669. //
  670. if ( gl_fSetPacketFiltersAtBind )
  671. {
  672. PrSetPacketFilterForAdapter( pBinding, TRUE);
  673. }
  674. //
  675. // Change the state to bound
  676. //
  677. pBinding->stateBinding = BN_stateBound;
  678. // AddBindingToProtocol() will insert the new binding to protocols
  679. // binding list, and reference it
  680. //
  681. AddBindingToProtocol( pBinding );
  682. status = NDIS_STATUS_SUCCESS;
  683. } while ( FALSE);
  684. if ( pBinding )
  685. {
  686. pBinding->ulBindingFlags |= BNBF_BindAdapterCompleted;
  687. pBinding->BindAdapterStatus = status;
  688. if ( status != NDIS_STATUS_SUCCESS )
  689. {
  690. //
  691. // We did not call NdisCompleteBindAdapter() because
  692. // somethings went wrong
  693. //
  694. //
  695. // Close the adapter if it was opened succesfully
  696. //
  697. if ( ( pBinding->ulBindingFlags & BNBF_OpenAdapterCompleted ) &&
  698. ( pBinding->OpenAdapterStatus == NDIS_STATUS_SUCCESS ) )
  699. {
  700. PrCloseAdapter( pBinding );
  701. }
  702. //
  703. // Clean up the binding context
  704. //
  705. BindingCleanup( pBinding );
  706. }
  707. }
  708. *Status = status;
  709. TRACE( TL_I, TM_Pr, ("-PrBindAdapter=$%x",status) );
  710. }
  711. BOOLEAN
  712. PrOpenAdapter(
  713. IN BINDING* pBinding,
  714. IN PNDIS_STRING DeviceName
  715. )
  716. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  717. Functional Description:
  718. This function is called to open the underlying adapter.
  719. CAUTION: It must be called from PASSIVE_LEVEL.
  720. Parameters:
  721. pBinding:
  722. A pointer ot our binding information structure.
  723. DeviceName:
  724. Name of the device to be opened. This is passed to PrBindAdapter()
  725. by NDIS.
  726. Return Values:
  727. TRUE:
  728. If underlying adapter could be opened succesfully.
  729. FALSE:
  730. If underlying adapter could not be opened succesfully.
  731. ---------------------------------------------------------------------------*/
  732. {
  733. NDIS_STATUS status;
  734. NDIS_STATUS openErrorStatus;
  735. NDIS_MEDIUM arrayNdisMedium[] = { NdisMedium802_3 };
  736. UINT sizeNdisMediumArray = sizeof( arrayNdisMedium ) / sizeof( NDIS_MEDIUM );
  737. TRACE( TL_N, TM_Pr, ("+PrOpenAdapter") );
  738. NdisOpenAdapter( &status,
  739. &openErrorStatus,
  740. &pBinding->NdisBindingHandle,
  741. &pBinding->uintSelectedMediumIndex,
  742. arrayNdisMedium,
  743. sizeNdisMediumArray,
  744. gl_hNdisProtocolHandle,
  745. pBinding,
  746. DeviceName,
  747. 0,
  748. NULL );
  749. if ( status != NDIS_STATUS_PENDING )
  750. {
  751. //
  752. // NidsOpenAdapter() completed synchronously,
  753. // so call PrOpenAdapterComplete() manually.
  754. //
  755. PrOpenAdapterComplete( pBinding,
  756. status,
  757. openErrorStatus );
  758. }
  759. NdisWaitEvent( &pBinding->RequestCompleted, 0 );
  760. NdisResetEvent( &pBinding->RequestCompleted );
  761. TRACE( TL_N, TM_Pr, ("-PrOpenAdapter") );
  762. return pBinding->OpenAdapterStatus == NDIS_STATUS_SUCCESS;
  763. }
  764. VOID
  765. PrOpenAdapterComplete(
  766. IN NDIS_HANDLE ProtocolBindingContext,
  767. IN NDIS_STATUS Status,
  768. IN NDIS_STATUS OpenErrorStatus
  769. )
  770. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  771. Functional Description:
  772. This function will be called after the underlying adapter is opened.
  773. We save the result of the Open adapter operation and set the RequestCompleted
  774. member of the binding context to resume the thread waiting for this to complete.
  775. CAUTION: It can be called from PASSIVE_LEVEL or at DISPATCH_LEVEL.
  776. Parameters:
  777. ProtocolBindingContext:
  778. A pointer ot our binding information structure.
  779. Status:
  780. NDIS_STATUS_SUCCESS:
  781. Indicates that NdisOpenAdapter() completed succesfully.
  782. NDIS_XXX:
  783. Indicates that NdisOpenAdapter() did not complete succesfully.
  784. OpenErrorStatus:
  785. Specifies additional information about the reason for a failure if the value
  786. at Status is not NDIS_STATUS_SUCCESS and if the underlying driver supplied
  787. this information. For example, the driver of a Token Ring NIC might return a
  788. ring error that NDIS forwards to ProtocolOpenAdapterComplete. This parameter
  789. can be NULL.
  790. Return Values:
  791. None
  792. ---------------------------------------------------------------------------*/
  793. {
  794. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  795. ASSERT( VALIDATE_BINDING( pBinding ) );
  796. TRACE( TL_I, TM_Pr, ("+PrOpenAdapterComplete") );
  797. TRACE( TL_N, TM_Pr, ("PrOpenAdapterComplete: NdisOpenAdapter() completed=$%x", Status ) );
  798. pBinding->ulBindingFlags |= BNBF_OpenAdapterCompleted;
  799. pBinding->OpenAdapterStatus = Status;
  800. NdisSetEvent( &pBinding->RequestCompleted );
  801. TRACE( TL_I, TM_Pr, ("-PrOpenAdapterComplete") );
  802. }
  803. BOOLEAN
  804. PrQueryAdapterForCurrentAddress(
  805. IN BINDING* pBinding
  806. )
  807. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  808. Functional Description:
  809. This function is called to query the underlying adapter for current MAC
  810. address oid.
  811. The underlying adapter must have been opened succesfully prior to calling
  812. this function.
  813. We save the result of the request in the binding context and set the
  814. RequestCompleted member of the binding context to resume the thread
  815. waiting for this to complete.
  816. CAUTION: It must be called from PASSIVE_LEVEL.
  817. Parameters:
  818. pBinding:
  819. A pointer ot our binding information structure.
  820. Return Values:
  821. TRUE:
  822. If the request was completed succesfully.
  823. FALSE:
  824. If the request was not completed succesfully.
  825. ---------------------------------------------------------------------------*/
  826. {
  827. NDIS_STATUS status;
  828. PNDIS_REQUEST pRequest = &pBinding->Request;
  829. TRACE( TL_N, TM_Pr, ("+PrQueryAdapterForCurrentAddress") );
  830. //
  831. // Generate an NDIS_REQUEST for querying current address oid
  832. //
  833. NdisZeroMemory( pRequest, sizeof( NDIS_REQUEST ) );
  834. pRequest->RequestType = NdisRequestQueryInformation ;
  835. pRequest->DATA.QUERY_INFORMATION.Oid = OID_802_3_CURRENT_ADDRESS;
  836. pRequest->DATA.QUERY_INFORMATION.InformationBuffer = pBinding->LocalAddress;
  837. pRequest->DATA.QUERY_INFORMATION.InformationBufferLength = sizeof( CHAR ) * 6;
  838. //
  839. // Request information from the adapter
  840. //
  841. NdisRequest( &status,
  842. pBinding->NdisBindingHandle,
  843. pRequest );
  844. if ( status != NDIS_STATUS_PENDING )
  845. {
  846. //
  847. // NdisRequest() completed synchronously, call PrRequestComplete()
  848. // manually.
  849. //
  850. PrRequestComplete( pBinding,
  851. pRequest,
  852. status );
  853. }
  854. NdisWaitEvent( &pBinding->RequestCompleted, 0 );
  855. NdisResetEvent( &pBinding->RequestCompleted );
  856. TRACE( TL_N, TM_Pr, ("-PrQueryAdapterForCurrentAddress") );
  857. return pBinding->RequestStatus == NDIS_STATUS_SUCCESS;
  858. }
  859. BOOLEAN
  860. PrQueryAdapterForLinkSpeed(
  861. IN BINDING* pBinding
  862. )
  863. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  864. Functional Description:
  865. This function is called to query the underlying adapter for link speed oid.
  866. The underlying adapter must have been opened succesfully prior to calling
  867. this function.
  868. We save the result of the request in the binding context and set the
  869. RequestCompleted member of the binding context to resume the thread
  870. waiting for this to complete.
  871. CAUTION: It must be called from PASSIVE_LEVEL.
  872. Parameters:
  873. pBinding:
  874. A pointer ot our binding information structure.
  875. Return Values:
  876. TRUE:
  877. If the request was completed succesfully.
  878. FALSE:
  879. If the request was not completed succesfully.
  880. ---------------------------------------------------------------------------*/
  881. {
  882. NDIS_STATUS status;
  883. PNDIS_REQUEST pRequest = &pBinding->Request;
  884. TRACE( TL_N, TM_Pr, ("+PrQueryAdapterForLinkSpeed") );
  885. //
  886. // Generate an NDIS_REQUEST for querying link speed oid
  887. //
  888. NdisZeroMemory( pRequest, sizeof( NDIS_REQUEST ) );
  889. pRequest->RequestType = NdisRequestQueryInformation ;
  890. pRequest->DATA.QUERY_INFORMATION.Oid = OID_GEN_LINK_SPEED;
  891. pRequest->DATA.QUERY_INFORMATION.InformationBuffer = &pBinding->ulSpeed;
  892. pRequest->DATA.QUERY_INFORMATION.InformationBufferLength = sizeof( pBinding->ulSpeed );
  893. //
  894. // Request information from the adapter
  895. //
  896. NdisRequest( &status,
  897. pBinding->NdisBindingHandle,
  898. pRequest );
  899. if ( status != NDIS_STATUS_PENDING )
  900. {
  901. //
  902. // NdisRequest() completed synchronously, call PrRequestComplete()
  903. // manually.
  904. //
  905. PrRequestComplete( pBinding,
  906. pRequest,
  907. status );
  908. }
  909. NdisWaitEvent( &pBinding->RequestCompleted, 0 );
  910. NdisResetEvent( &pBinding->RequestCompleted );
  911. TRACE( TL_N, TM_Pr, ("-PrQueryAdapterForLinkSpeed") );
  912. return pBinding->RequestStatus == NDIS_STATUS_SUCCESS;
  913. }
  914. BOOLEAN
  915. PrQueryAdapterForMaxFrameSize(
  916. IN BINDING* pBinding
  917. )
  918. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  919. Functional Description:
  920. This function is called to query the underlying adapter for max frame size
  921. oid.
  922. The underlying adapter must have been opened succesfully prior to calling
  923. this function.
  924. We save the result of the request in the binding context and set the
  925. RequestCompleted member of the binding context to resume the thread
  926. waiting for this to complete.
  927. CAUTION: It must be called from PASSIVE_LEVEL.
  928. Parameters:
  929. pBinding:
  930. A pointer ot our binding information structure.
  931. Return Values:
  932. TRUE:
  933. If the request was completed succesfully.
  934. FALSE:
  935. If the request was not completed succesfully.
  936. ---------------------------------------------------------------------------*/
  937. {
  938. NDIS_STATUS status;
  939. PNDIS_REQUEST pRequest = &pBinding->Request;
  940. TRACE( TL_N, TM_Pr, ("+PrQueryAdapterForMaxFrameSize") );
  941. //
  942. // Generate an NDIS_REQUEST for querying link speed oid
  943. //
  944. NdisZeroMemory( pRequest, sizeof( NDIS_REQUEST ) );
  945. pRequest->RequestType = NdisRequestQueryInformation ;
  946. pRequest->DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_FRAME_SIZE;
  947. pRequest->DATA.QUERY_INFORMATION.InformationBuffer = &pBinding->ulMaxFrameSize;
  948. pRequest->DATA.QUERY_INFORMATION.InformationBufferLength = sizeof( pBinding->ulMaxFrameSize );
  949. //
  950. // Request information from the adapter
  951. //
  952. NdisRequest( &status,
  953. pBinding->NdisBindingHandle,
  954. pRequest );
  955. if ( status != NDIS_STATUS_PENDING )
  956. {
  957. //
  958. // NdisRequest() completed synchronously, call PrRequestComplete()
  959. // manually.
  960. //
  961. PrRequestComplete( pBinding,
  962. pRequest,
  963. status );
  964. }
  965. NdisWaitEvent( &pBinding->RequestCompleted, 0 );
  966. NdisResetEvent( &pBinding->RequestCompleted );
  967. TRACE( TL_N, TM_Pr, ("-PrQueryAdapterForMaxFrameSize") );
  968. return pBinding->RequestStatus == NDIS_STATUS_SUCCESS;
  969. }
  970. BOOLEAN
  971. PrSetPacketFilterForAdapter(
  972. IN BINDING* pBinding,
  973. IN BOOLEAN fSet
  974. )
  975. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  976. Functional Description:
  977. This function is called to set the current generic packet filter for our
  978. protocol.
  979. The underlying adapter must have been opened succesfully prior to calling
  980. this function.
  981. We save the result of the request in the binding context and set the
  982. RequestCompleted member of the binding context to resume the thread
  983. waiting for this to complete.
  984. CAUTION: It must be called from PASSIVE_LEVEL.
  985. Parameters:
  986. pBinding:
  987. A pointer ot our binding information structure.
  988. fSet:
  989. Indicates what the filters will be set to.
  990. TRUE means receive packets, FALSE means set it to 0.
  991. Return Values:
  992. TRUE:
  993. If the request was completed succesfully.
  994. FALSE:
  995. If the request was not completed succesfully.
  996. ---------------------------------------------------------------------------*/
  997. {
  998. NDIS_STATUS status;
  999. PNDIS_REQUEST pRequest = &pBinding->Request;
  1000. BOOLEAN fPacketFilterAlreadySet = (BOOLEAN) ( pBinding->ulBindingFlags & BNBF_PacketFilterSet );
  1001. TRACE( TL_N, TM_Pr, ("+PrSetPacketFilterForAdapter") );
  1002. //
  1003. // See if we already are in the state the request wants us to be in
  1004. //
  1005. if ( ( fPacketFilterAlreadySet && fSet ) ||
  1006. ( !fPacketFilterAlreadySet && !fSet ) )
  1007. {
  1008. pBinding->RequestStatus = NDIS_STATUS_SUCCESS;
  1009. TRACE( TL_N, TM_Pr, ("PrSetPacketFilterForAdapter: Already in the requested state") );
  1010. TRACE( TL_N, TM_Pr, ("-PrSetPacketFilterForAdapter") );
  1011. return TRUE;
  1012. }
  1013. pBinding->ulPacketFilter = ( fSet ) ? (NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_DIRECTED) : 0;
  1014. //
  1015. // Generate an NDIS_REQUEST for setting current packet filter
  1016. //
  1017. NdisZeroMemory( pRequest, sizeof( NDIS_REQUEST ) );
  1018. pRequest->RequestType = NdisRequestSetInformation;
  1019. pRequest->DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
  1020. pRequest->DATA.SET_INFORMATION.InformationBuffer = &pBinding->ulPacketFilter;
  1021. pRequest->DATA.SET_INFORMATION.InformationBufferLength = sizeof( ULONG );
  1022. //
  1023. // Request set info on the adapter
  1024. //
  1025. NdisRequest( &status,
  1026. pBinding->NdisBindingHandle,
  1027. pRequest );
  1028. if ( status != NDIS_STATUS_PENDING )
  1029. {
  1030. //
  1031. // NdisRequest() completed synchronously, call PrRequestComplete()
  1032. // manually.
  1033. //
  1034. PrRequestComplete( pBinding,
  1035. pRequest,
  1036. status );
  1037. }
  1038. NdisWaitEvent( &pBinding->RequestCompleted, 0 );
  1039. NdisResetEvent( &pBinding->RequestCompleted );
  1040. TRACE( TL_N, TM_Pr, ("-PrSetPacketFilterForAdapter") );
  1041. return pBinding->RequestStatus == NDIS_STATUS_SUCCESS;
  1042. }
  1043. VOID
  1044. PrRequestComplete(
  1045. IN NDIS_HANDLE ProtocolBindingContext,
  1046. IN PNDIS_REQUEST pRequest,
  1047. IN NDIS_STATUS status
  1048. )
  1049. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1050. Functional Description:
  1051. This function will be called to indicate that an NDIS request submitted
  1052. previously has completed.
  1053. We submit 2 requests:
  1054. - OID_802_3_CURRENT_ADDRESS: This is submitted from PrQueryAdapterForCurrentAddress()
  1055. to obtain the current MAC address for the underlying
  1056. adapter.
  1057. - OID_GEN_LINK_SPEED: This is submitted from PrQueryAdapterForLinkSpeed() to obtain
  1058. the current link speed of the underlying adapter.
  1059. - OID_GEN_CURRENT_PACKET_FILTER: This is submitted from PrSetPacketFilterForAdapter()
  1060. to set the packet types we are interested in to NDIS.
  1061. If the request for MAC address fail, we clean up the binding context and notify
  1062. NDIS that bind adapter failed, otherwise we go ahead and query the adapter for link
  1063. speed.
  1064. Regardless of the status of request for link speed, we notify NDIS about succesful
  1065. completion of the bind operation as this is not a fatal error.
  1066. Before calling this function, the underlying adapter must have been opened
  1067. succesfully.
  1068. Parameters:
  1069. ProtocolBindingContext:
  1070. A pointer ot our binding information structure.
  1071. pRequest:
  1072. A pointer to the request submitted previously.
  1073. Status:
  1074. Completion status of the request.
  1075. Return Values:
  1076. None
  1077. ---------------------------------------------------------------------------*/
  1078. {
  1079. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  1080. BOOLEAN fUnknownOid = FALSE;
  1081. ASSERT( VALIDATE_BINDING( pBinding ) );
  1082. TRACE( TL_I, TM_Pr, ("+PrRequestComplete") );
  1083. switch ( pRequest->RequestType )
  1084. {
  1085. case NdisRequestQueryInformation:
  1086. {
  1087. switch ( pRequest->DATA.QUERY_INFORMATION.Oid )
  1088. {
  1089. case OID_802_3_CURRENT_ADDRESS:
  1090. TRACE( TL_N, TM_Pr, ("PrRequestComplete: OID_802_3_CURRENT_ADDRESS=$%x",status) );
  1091. pBinding->ulBindingFlags |= BNBF_CurrentAddressQueryCompleted;
  1092. break;
  1093. case OID_GEN_LINK_SPEED:
  1094. TRACE( TL_N, TM_Pr, ("PrRequestComplete: OID_GEN_LINK_SPEED=$%x",status) );
  1095. pBinding->ulBindingFlags |= BNBF_LinkSpeedQueryCompleted;
  1096. break;
  1097. case OID_GEN_MAXIMUM_FRAME_SIZE:
  1098. TRACE( TL_N, TM_Pr, ("PrRequestComplete: OID_GEN_MAXIMUM_FRAME_SIZE=$%x",status) );
  1099. pBinding->ulBindingFlags |= BNBF_MaxFrameSizeQueryCompleted;
  1100. break;
  1101. default:
  1102. TRACE( TL_N, TM_Pr, ("PrRequestComplete: UNKNOWN OID=$%x",pRequest->DATA.QUERY_INFORMATION.Oid) );
  1103. fUnknownOid = TRUE;
  1104. break;
  1105. }
  1106. }
  1107. break;
  1108. case NdisRequestSetInformation:
  1109. {
  1110. switch ( pRequest->DATA.SET_INFORMATION.Oid )
  1111. {
  1112. case OID_GEN_CURRENT_PACKET_FILTER:
  1113. TRACE( TL_N, TM_Pr, ("PrRequestComplete: OID_GEN_CURRENT_PACKET_FILTER=$%x",status) );
  1114. if ( status == NDIS_STATUS_SUCCESS )
  1115. {
  1116. if ( pBinding->ulBindingFlags & BNBF_PacketFilterSet )
  1117. {
  1118. //
  1119. // Packet filter was set, so reset it
  1120. //
  1121. pBinding->ulBindingFlags &= ~BNBF_PacketFilterSet;
  1122. }
  1123. else
  1124. {
  1125. //
  1126. // Packet filter was reset, so set it
  1127. //
  1128. pBinding->ulBindingFlags |= BNBF_PacketFilterSet;
  1129. }
  1130. }
  1131. break;
  1132. default:
  1133. TRACE( TL_N, TM_Pr, ("PrRequestComplete: UNKNOWN OID=$%x",pRequest->DATA.SET_INFORMATION.Oid) );
  1134. fUnknownOid = TRUE;
  1135. break;
  1136. }
  1137. }
  1138. break;
  1139. default:
  1140. TRACE( TL_N, TM_Pr, ("PrRequestComplete: Unknown RequestType=$%x",pRequest->RequestType) );
  1141. fUnknownOid = TRUE;
  1142. break;
  1143. }
  1144. if ( !fUnknownOid )
  1145. {
  1146. pBinding->RequestStatus = status;
  1147. NdisSetEvent( &pBinding->RequestCompleted );
  1148. }
  1149. TRACE( TL_I, TM_Pr, ("-PrRequestComplete") );
  1150. }
  1151. VOID
  1152. PrUnbindAdapter(
  1153. OUT PNDIS_STATUS Status,
  1154. IN NDIS_HANDLE ProtocolBindingContext,
  1155. IN NDIS_HANDLE UnbindContext
  1156. )
  1157. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1158. Functional Description:
  1159. This function will be called by NDIS when an underlying adapter wants to
  1160. unbind from us.
  1161. ArvindM says PrBindAdapter() and PrUnbindAdapter() will be serialized
  1162. by NDIS.
  1163. This function will not be called if PrBindAdapter() did not succeed.
  1164. Also this function will not be called as long as there are outstanding
  1165. PrReceivePacket() calls active.
  1166. However this function may be called while there are outstanding
  1167. PrSend(), PrSendPayload() or PrBroadcast() calls, that's why we keep
  1168. track of such calls with pBinding->nSendPending and wait on the completion
  1169. of these requests. And as we set the state to BN_stateUnbinding, no such
  1170. new requests will be accepted, and pBinding->nSendPending will reach 0
  1171. at some point which will trigger the pBinding->eventSendCompleted.
  1172. This function is called at IRQL_PASSIVE level by default so we can
  1173. safely wait on events.
  1174. Parameters:
  1175. Status
  1176. Points to a variable in which ProtocolBindAdapter returns the status of its
  1177. operation(s), as one of the following:
  1178. NDIS_STATUS_SUCCESS
  1179. The driver completed the unbind operation and deallocated the resources.
  1180. NDIS_STATUS_PENDING
  1181. The protocol will complete the unbind operation asynchronously with a call to
  1182. NdisCompleteUnbindAdapter when ProtocolCloseAdapterComplete() is called.
  1183. ProtocolBindingContext
  1184. A pointer to our binding context.
  1185. UnbindContext:
  1186. This handle is supplied by NDIS and should be used if NdisCloseAdapter() pends.
  1187. Then we will get a call to ProtocolCloseAdapterComplete() which will use this
  1188. handle to notify NDIS about the completion of the initial PrUnbindAdapter()
  1189. request.
  1190. Return Values:
  1191. None
  1192. ---------------------------------------------------------------------------*/
  1193. {
  1194. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  1195. ASSERT( VALIDATE_BINDING( pBinding ) );
  1196. TRACE( TL_I, TM_Pr, ("+PrUnbindAdapter") );
  1197. NdisAcquireSpinLock( &pBinding->lockBinding );
  1198. //
  1199. // If there is a sleep request pending, wait for it to complete
  1200. //
  1201. while ( pBinding->stateBinding == BN_stateSleepPending )
  1202. {
  1203. NdisReleaseSpinLock( &pBinding->lockBinding );
  1204. NdisMSleep( 10000 );
  1205. NdisAcquireSpinLock( &pBinding->lockBinding );
  1206. }
  1207. //
  1208. // Mark binding as unbind pending
  1209. //
  1210. ASSERT( pBinding->stateBinding == BN_stateSleeping ||
  1211. pBinding->stateBinding == BN_stateBound );
  1212. pBinding->stateBinding = BN_stateUnbindPending;
  1213. NdisReleaseSpinLock( &pBinding->lockBinding );
  1214. //
  1215. // Unbind all the active sessions on this binding
  1216. //
  1217. MpNotifyBindingRemoval( pBinding );
  1218. //
  1219. // Remove Binding from protocols binding table
  1220. //
  1221. RemoveBindingFromProtocol( pBinding );
  1222. //
  1223. // Wait for all references to be deleted
  1224. //
  1225. NdisWaitEvent( &pBinding->eventFreeBinding, 0 );
  1226. TRACE( TL_N, TM_Pr, ("PrUnbindAdapter: All references are deleted") );
  1227. //
  1228. // All references have been removed, now wait for all packets owned by NDIS
  1229. // to be returned.
  1230. //
  1231. // Note that no synchronization is necesarry for reading the value of numPacketsOwnedByNdis
  1232. // at this point since it can only be incremented when there is at least 1 reference on the
  1233. // binding - at this point ref count is 0 -, and because it can not be incremented, it can
  1234. // only reach 0 once.
  1235. //
  1236. while ( pBinding->NumPacketsOwnedByNdis )
  1237. {
  1238. NdisMSleep( 10000 );
  1239. }
  1240. TRACE( TL_N, TM_Pr, ("PrUnbindAdapter: All NDIS owned packets have been returned") );
  1241. //
  1242. // Since all references have been deleted, we can close the underlying adapter.
  1243. //
  1244. PrCloseAdapter( pBinding );
  1245. //
  1246. // Change the binding state to unbound
  1247. //
  1248. pBinding->stateBinding = BN_stateUnbound;
  1249. //
  1250. // Clean up the binding context
  1251. //
  1252. BindingCleanup( pBinding );
  1253. *Status = NDIS_STATUS_SUCCESS;
  1254. TRACE( TL_I, TM_Pr, ("-PrUnbindAdapter") );
  1255. }
  1256. VOID
  1257. PrCloseAdapter(
  1258. IN BINDING* pBinding
  1259. )
  1260. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1261. Functional Description:
  1262. This function is called to close the underlying adapter. It must be called
  1263. either from PrBindAdapter() or PrUnbindAdapter().
  1264. CAUTION: It must be called from PASSIVE_LEVEL.
  1265. Parameters:
  1266. pBinding:
  1267. Binding context that owns the adapter to close.
  1268. Return Values:
  1269. None
  1270. ---------------------------------------------------------------------------*/
  1271. {
  1272. NDIS_STATUS status;
  1273. TRACE( TL_N, TM_Pr, ("+PrCloseAdapter") );
  1274. NdisCloseAdapter( &status, pBinding->NdisBindingHandle );
  1275. if ( status != NDIS_STATUS_PENDING )
  1276. {
  1277. //
  1278. // NdisCloseAdapter() completed synchronously,
  1279. // complete the request manually
  1280. //
  1281. PrCloseAdapterComplete( pBinding, status );
  1282. }
  1283. NdisWaitEvent( &pBinding->RequestCompleted, 0 );
  1284. NdisResetEvent( &pBinding->RequestCompleted );
  1285. TRACE( TL_N, TM_Pr, ("-PrCloseAdapter") );
  1286. }
  1287. VOID
  1288. PrCloseAdapterComplete(
  1289. IN NDIS_HANDLE ProtocolBindingContext,
  1290. IN NDIS_STATUS Status
  1291. )
  1292. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1293. Functional Description:
  1294. This function can be called from PrCloseAdapter() if NdisCloseAdapter()
  1295. completes synchronously, or it will be called by NDIS at DISPATCH_LEVEL.
  1296. It sets the BNBF_CloseAdapterCompleted flag and sets the RequestCompleted
  1297. member of the binding context to resume the thread waiting on this event.
  1298. CAUTION: It can be called from PASSIVE_LEVEL or DISPATCH_LEVEL.
  1299. Parameters:
  1300. ProtocolBindingContext:
  1301. Specifies the handle to a protocol-allocated context area in which the
  1302. protocol driver maintains per-binding runtime state. The driver supplied this
  1303. handle when it called NdisOpenAdapter.
  1304. Status:
  1305. Indicates the final status of the close operation in the underlying driver.
  1306. Return Values:
  1307. None
  1308. ---------------------------------------------------------------------------*/
  1309. {
  1310. BINDING* pBinding = ProtocolBindingContext;
  1311. ASSERT( VALIDATE_BINDING( pBinding ) );
  1312. TRACE( TL_I, TM_Pr, ("+PrCloseAdapterComplete") );
  1313. TRACE( TL_N, TM_Pr, ("PrCloseAdapterComplete: NdisCloseAdapter() completed=$%x", Status ) );
  1314. pBinding->ulBindingFlags |= BNBF_CloseAdapterCompleted;
  1315. NdisSetEvent( &pBinding->RequestCompleted );
  1316. TRACE( TL_I, TM_Pr, ("-PrCloseAdapterComplete") );
  1317. }
  1318. BOOLEAN
  1319. PrAddCallToBinding(
  1320. IN BINDING* pBinding,
  1321. IN PCALL pCall
  1322. )
  1323. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1324. Functional Description:
  1325. This function will put a reference on the binding which will be removed
  1326. when PrRemoveCallFromBinding() is called.
  1327. It will return TRUE if reference is added succesfully, and FALSE if reference
  1328. could not be added.
  1329. Reference will not be added if binding is not in bound state.
  1330. CAUTION: Caller must make sure that the binding is not freed before calling this
  1331. function.
  1332. Parameters:
  1333. pBinding:
  1334. A pointer ot our binding information structure.
  1335. pCall:
  1336. A pointer to our call information structure.
  1337. Return Values:
  1338. TRUE:
  1339. Binding referenced for the call
  1340. FALSE:
  1341. Binding not reference for the call
  1342. ---------------------------------------------------------------------------*/
  1343. {
  1344. BOOLEAN fResult;
  1345. TRACE( TL_N, TM_Pr, ("+PrAddCallToBinding") );
  1346. //
  1347. // We have to acquire lock of call first to avoid dead locks
  1348. //
  1349. NdisAcquireSpinLock( &pCall->lockCall );
  1350. if ( pCall->ulClFlags & CLBF_CallDropped ||
  1351. pCall->ulClFlags & CLBF_CallClosePending )
  1352. {
  1353. NdisReleaseSpinLock( &pCall->lockCall );
  1354. TRACE( TL_A, TM_Pr, ("PrAddCallToBinding: Call already dropped or close pending") );
  1355. TRACE( TL_N, TM_Pr, ("-PrAddCallToBinding") );
  1356. return FALSE;
  1357. }
  1358. NdisAcquireSpinLock( &pBinding->lockBinding );
  1359. //
  1360. // Check the state of the binding, if it is not bound
  1361. // we can not add the call
  1362. //
  1363. if ( pBinding->stateBinding != BN_stateBound )
  1364. {
  1365. NdisReleaseSpinLock( &pBinding->lockBinding );
  1366. NdisReleaseSpinLock( &pCall->lockCall );
  1367. TRACE( TL_A, TM_Pr, ("PrAddCallToBinding: Binding state not bound") );
  1368. TRACE( TL_N, TM_Pr, ("-PrAddCallToBinding") );
  1369. return FALSE;
  1370. }
  1371. //
  1372. // Both binding and call are ready to be bound
  1373. // Go ahead and add the call
  1374. //
  1375. //
  1376. // Set call's binding context ptr to binding
  1377. //
  1378. pCall->pBinding = pBinding;
  1379. //
  1380. // Copy the local address of the binding
  1381. //
  1382. NdisMoveMemory( pCall->SrcAddr, pBinding->LocalAddress, 6 * sizeof( CHAR ) );
  1383. //
  1384. // Set call's link speed
  1385. //
  1386. pCall->ulSpeed = pBinding->ulSpeed;
  1387. //
  1388. // Pass the MaxFrameSize to call context
  1389. //
  1390. pCall->ulMaxFrameSize = pBinding->ulMaxFrameSize - ( PPPOE_PACKET_HEADER_LENGTH - ETHERNET_HEADER_LENGTH );
  1391. //
  1392. // Make a reference on the binding which will be removed when PrRemoveCallFromBinding()
  1393. // is called
  1394. //
  1395. ReferenceBinding( pBinding, FALSE );
  1396. //
  1397. // Release the locks, and return
  1398. //
  1399. NdisReleaseSpinLock( &pBinding->lockBinding );
  1400. NdisReleaseSpinLock( &pCall->lockCall );
  1401. TRACE( TL_N, TM_Pr, ("-PrAddCallToBinding") );
  1402. return TRUE;
  1403. }
  1404. VOID
  1405. PrRemoveCallFromBinding(
  1406. IN BINDING* pBinding,
  1407. IN CALL* pCall
  1408. )
  1409. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1410. Functional Description:
  1411. This function will be called to remove a reference added by a PrAddCallToBinding()
  1412. for a call on this binding.
  1413. Parameters:
  1414. pBinding:
  1415. Pointer to the binding context that the will be dereferenced.
  1416. pCall:
  1417. Pointer to the call context being unbound fromthe binding.
  1418. Return Values:
  1419. None
  1420. ---------------------------------------------------------------------------*/
  1421. {
  1422. ASSERT( VALIDATE_BINDING( pBinding ) );
  1423. TRACE( TL_N, TM_Pr, ("+PrRemoveCallFromBinding") );
  1424. NdisAcquireSpinLock( &pCall->lockCall );
  1425. pCall->pBinding = NULL;
  1426. pCall->ulSpeed = 0;
  1427. NdisReleaseSpinLock( &pCall->lockCall );
  1428. DereferenceBinding( pBinding );
  1429. TRACE( TL_N, TM_Pr, ("-PrRemoveCallFromBinding") );
  1430. }
  1431. VOID
  1432. PrSendComplete(
  1433. IN NDIS_HANDLE ProtocolBindingContext,
  1434. IN PNDIS_PACKET pNdisPacket,
  1435. IN NDIS_STATUS Status
  1436. )
  1437. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1438. Functional Description:
  1439. This function will be called by NDIS to notify that a previously send operation
  1440. on this packet has been completed.
  1441. It will notify NDISWAN, if packet was a payload packet.
  1442. It will remove the references on the packet and binding added by the PrSendXXX()
  1443. functions.
  1444. Parameters:
  1445. ProtocolBindingContext:
  1446. A pointer to our binding context.
  1447. pNdisPacket:
  1448. Ndis Packet that was send previously.
  1449. Status:
  1450. Status of the send operation.
  1451. Return Values:
  1452. None
  1453. ---------------------------------------------------------------------------*/
  1454. {
  1455. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  1456. PPPOE_PACKET* pPacket = NULL;
  1457. USHORT usCode;
  1458. ASSERT( VALIDATE_BINDING( pBinding ) );
  1459. TRACE( TL_V, TM_Pr, ("+PrSendComplete($%x,$%x,$%x)",pBinding,pNdisPacket,Status) );
  1460. //
  1461. // Retrieve the related PPPoE packet context from the NDIS packet
  1462. //
  1463. pPacket = PacketGetRelatedPppoePacket( pNdisPacket );
  1464. ASSERT( pPacket != NULL );
  1465. //
  1466. // Set the completion status for the send to be passed back to
  1467. // NDISWAN when the packet is freed (only for Payload packets)
  1468. //
  1469. PacketSetSendCompletionStatus( pPacket, Status );
  1470. //
  1471. // Remove the reference on the packet added by the sending function
  1472. //
  1473. DereferencePacket( pPacket );
  1474. //
  1475. // Remove the reference on the binding
  1476. //
  1477. DereferenceBinding( pBinding );
  1478. TRACE( TL_V, TM_Pr, ("-PrSendComplete($%x,$%x,$%x)",pBinding,pNdisPacket,Status) );
  1479. }
  1480. INT
  1481. PrReceivePacket(
  1482. IN NDIS_HANDLE ProtocolBindingContext,
  1483. IN PNDIS_PACKET Packet
  1484. )
  1485. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1486. Functional Description:
  1487. This function is called by NDIS when a packet is received over this binding.
  1488. Packet is converted into a PPPoE packet and notified to Miniport so that miniport
  1489. processes it.
  1490. Parameters:
  1491. ProtocolBindingContext:
  1492. A pointer to our binding context.
  1493. Packet:
  1494. An Ndis packet received over this binding.
  1495. Return Values:
  1496. The return value represents the number of references NDIS should wait for
  1497. before freeing his copy of the packet, but we will be done by the NDIS packet
  1498. at the end of the function, we always return 0.
  1499. ---------------------------------------------------------------------------*/
  1500. {
  1501. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  1502. PPPOE_PACKET* pPacket = NULL;
  1503. INT nRefCount = 0;
  1504. ASSERT( VALIDATE_BINDING( pBinding ) );
  1505. TRACE( TL_V, TM_Pr, ("+PrReceivePacket($%x,$%x)",pBinding,Packet) );
  1506. do
  1507. {
  1508. pPacket = PacketNdis2Pppoe( (PVOID) pBinding,
  1509. Packet,
  1510. &nRefCount );
  1511. if ( pPacket )
  1512. {
  1513. TRACE( TL_V, TM_Pr, ("PrReceivePacket: Received PPPoE packet=$%x",pPacket) );
  1514. //
  1515. // We have a copy of the packet, insert it into our queue of received packets,
  1516. // so that it will be consumed by a call to our PrReceiveComplete() function.
  1517. //
  1518. // It will be freed when it is consumed in PrReceiveComplete().
  1519. //
  1520. NdisInterlockedInsertTailList( &pBinding->linkPackets,
  1521. &pPacket->linkPackets,
  1522. &pBinding->lockBinding );
  1523. }
  1524. } while ( FALSE );
  1525. TRACE( TL_V, TM_Pr, ("-PrReceivePacket($%x,$%x)",pBinding,Packet) );
  1526. return nRefCount;
  1527. }
  1528. NDIS_STATUS
  1529. PrBroadcast(
  1530. IN PPPOE_PACKET* pPacket
  1531. )
  1532. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1533. Functional Description:
  1534. This function is called by an adapter to broadcast a PADI packet.
  1535. It clones the packet and schedules a send over each binding that's currrently
  1536. active.
  1537. The caller can destroy the packet after return from this function.
  1538. Parameters:
  1539. pPacket:
  1540. A PPPoE PADI packet ready to be broadcast.
  1541. Return Values:
  1542. NDIS_STATUS_SUCCESS:
  1543. At least 1 send operation was scheduled over a binding.
  1544. NDIS_STATUS_FAILURE:
  1545. No sends could be scheduled.
  1546. ---------------------------------------------------------------------------*/
  1547. {
  1548. NDIS_STATUS status = NDIS_STATUS_FAILURE;
  1549. TRACE( TL_N, TM_Pr, ("+PrBroadcast($%x)",pPacket) );
  1550. //
  1551. // Check if we have any bindings
  1552. //
  1553. if ( gl_ulNumBindings == 0 )
  1554. {
  1555. TRACE( TL_N, TM_Pr, ("PrBroadcast($%x): No bindings available",pPacket) );
  1556. TRACE( TL_N, TM_Pr, ("-PrBroadcast($%x)=$%x",pPacket,status) );
  1557. return status;
  1558. }
  1559. NdisAcquireSpinLock( &gl_lockProtocol );
  1560. do
  1561. {
  1562. LIST_ENTRY* pHead = NULL;
  1563. //
  1564. // We have to do the same check again, as the first one is to make sure
  1565. // we have allocated the spin lock, and this one is to make sure after we acquired
  1566. // it, we still have some bindings
  1567. //
  1568. if ( gl_ulNumBindings == 0 )
  1569. {
  1570. TRACE( TL_N, TM_Pr, ("PrBroadcast($%x): No bindings available",pPacket) );
  1571. break;
  1572. }
  1573. //
  1574. // Get the head of the bindings list
  1575. //
  1576. pHead = gl_linkBindings.Flink;
  1577. //
  1578. // Traverse the bindings list and schedule a PrSend() with a clone of pNdisPacket
  1579. //
  1580. while ( pHead != &gl_linkBindings )
  1581. {
  1582. PPPOE_PACKET* pClone = NULL;
  1583. BINDING* pBinding = (BINDING*) CONTAINING_RECORD( pHead,
  1584. BINDING,
  1585. linkBindings );
  1586. //
  1587. // Do not schedule a send if binding is not bound
  1588. //
  1589. if ( pBinding->stateBinding != BN_stateBound )
  1590. {
  1591. pHead = pHead->Flink;
  1592. continue;
  1593. }
  1594. //
  1595. // Make a clone of the actual packet
  1596. //
  1597. pClone = PacketMakeClone( pPacket );
  1598. if ( pClone != NULL )
  1599. {
  1600. WORKITEM* pWorkItem = NULL;
  1601. PVOID Args[4];
  1602. //
  1603. // Set the source address on the packet to be sent
  1604. //
  1605. PacketSetSrcAddr( pClone, pBinding->LocalAddress );
  1606. //
  1607. // Set the arguements array
  1608. //
  1609. Args[0] = (PVOID) pBinding;
  1610. Args[1] = (PVOID) pClone;
  1611. //
  1612. // Allocate work item
  1613. //
  1614. pWorkItem = AllocWorkItem( &gl_llistWorkItems,
  1615. ExecBindingWorkItem,
  1616. NULL,
  1617. Args,
  1618. BWT_workPrSend );
  1619. if ( pWorkItem != NULL )
  1620. {
  1621. ReferenceBinding( pBinding, TRUE );
  1622. ReferencePacket( pClone );
  1623. //
  1624. // Schedule the send operation
  1625. //
  1626. ScheduleWorkItem( pWorkItem );
  1627. status = NDIS_STATUS_SUCCESS;
  1628. }
  1629. //
  1630. // We can free the packet since we have put a reference for scheduling it
  1631. //
  1632. PacketFree( pClone );
  1633. }
  1634. pHead = pHead->Flink;
  1635. }
  1636. } while ( FALSE );
  1637. NdisReleaseSpinLock( &gl_lockProtocol );
  1638. TRACE( TL_N, TM_Pr, ("-PrBroadcast($%x)=$%x",pPacket,status) );
  1639. return status;
  1640. }
  1641. VOID
  1642. ExecBindingWorkItem(
  1643. IN PVOID Args[4],
  1644. IN UINT workType
  1645. )
  1646. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1647. Functional Description:
  1648. This function executes the scheduled work items for the binding.
  1649. Parameters:
  1650. Args:
  1651. An array of length 4 keeping PVOIDs
  1652. workType:
  1653. Indicates the type of the work to be executed.
  1654. We use this to understand what we should do in this function.
  1655. Return Values:
  1656. None
  1657. ---------------------------------------------------------------------------*/
  1658. {
  1659. TRACE( TL_V, TM_Pr, ("+ExecBindingWorkItem") );
  1660. switch( workType )
  1661. {
  1662. case BWT_workPrStartBinds:
  1663. //
  1664. // Tell NDIS to bind our protocol to any interested miniports.
  1665. // If we need to start an outgoing call then kick that off too.
  1666. //
  1667. {
  1668. ULONG_PTR FilterChangeRequest = (ULONG_PTR) Args[0];
  1669. BOOLEAN fSetFilters = (BOOLEAN) ( FilterChangeRequest != BN_ResetFiltersForCloseLine );
  1670. switch ( FilterChangeRequest )
  1671. {
  1672. case BN_SetFiltersForMediaDetection:
  1673. {
  1674. //
  1675. // This is a set default media detection request so complete it
  1676. //
  1677. LINE* pLine = (LINE*) Args[1];
  1678. PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION pRequest = (PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION) Args[2];
  1679. PrReEnumerateBindings();
  1680. ChangePacketFiltersForAdapters( fSetFilters );
  1681. TpSetDefaultMediaDetectionComplete( pLine, pRequest );
  1682. }
  1683. break;
  1684. case BN_SetFiltersForMakeCall:
  1685. {
  1686. //
  1687. // This is a make call request so schedule the real work item and complete it
  1688. //
  1689. CALL* pCall = (CALL*) Args[1];
  1690. PNDIS_TAPI_MAKE_CALL pRequest = (PNDIS_TAPI_MAKE_CALL) Args[2];
  1691. WORKITEM* pWorkItem = (WORKITEM*) Args[3];
  1692. PrReEnumerateBindings();
  1693. ChangePacketFiltersForAdapters( fSetFilters );
  1694. TpMakeCallComplete( pCall, pRequest );
  1695. ScheduleWorkItem( pWorkItem );
  1696. }
  1697. break;
  1698. case BN_ResetFiltersForCloseLine:
  1699. {
  1700. //
  1701. // This is a close line request so dereference it
  1702. //
  1703. LINE* pLine = (LINE*) Args[1];
  1704. ChangePacketFiltersForAdapters( fSetFilters );
  1705. DereferenceLine( pLine );
  1706. }
  1707. break;
  1708. default:
  1709. {
  1710. //
  1711. // Unknown request
  1712. //
  1713. ASSERT( FALSE );
  1714. }
  1715. break;
  1716. }
  1717. }
  1718. break;
  1719. case BWT_workPrSend:
  1720. //
  1721. // Scheduled from PrBroadcast() to send PADI packets
  1722. //
  1723. {
  1724. NDIS_STATUS status;
  1725. status = PrSend( ( BINDING*) Args[0], (PPPOE_PACKET*) Args[1] );
  1726. TRACE( TL_N, TM_Pr, ("ExecBindingWorkItem: BWT_workSend=$%x",status) );
  1727. }
  1728. break;
  1729. case BWT_workPrReceiveComplete:
  1730. //
  1731. // Scheduled from PrReceivePacket() if receive loop on the specific binding is not running
  1732. //
  1733. {
  1734. BINDING* pBinding = ( ( BINDING*) Args[0] );
  1735. PrReceiveComplete( pBinding );
  1736. DereferenceBinding( pBinding );
  1737. }
  1738. break;
  1739. default:
  1740. break;
  1741. }
  1742. TRACE( TL_V, TM_Pr, ("-ExecBindingWorkItem") );
  1743. }
  1744. NDIS_STATUS
  1745. PrReceive(
  1746. IN NDIS_HANDLE ProtocolBindingContext,
  1747. IN NDIS_HANDLE MacReceiveContext,
  1748. IN PVOID HeaderBuffer,
  1749. IN UINT HeaderBufferSize,
  1750. IN PVOID LookaheadBuffer,
  1751. IN UINT LookaheadBufferSize,
  1752. IN UINT PacketSize
  1753. )
  1754. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1755. Functional Description:
  1756. This function will be called by NDIS to indicate the receipt of a new packet.
  1757. We check if packet is a PPPoE frame, and if it is not, we just return.
  1758. However if it is then we determine if we have received the whole packet or
  1759. not. If we have received the whole packet, we call PrTransferDataComplete()
  1760. manually, otherwise we initiate the data transfer and return. When transfer
  1761. is completed PrDataTransferComplete() will be called by NDIS.
  1762. Parameters:
  1763. ProtocolBindingContext:
  1764. Specifies the handle to a protocol-allocated context area in which the
  1765. protocol driver maintains per-binding runtime state. The driver supplied this
  1766. handle when it called NdisOpenAdapter.
  1767. MacReceiveContext:
  1768. Specifies a context handle that the underlying NIC driver associates with the
  1769. packet received from the network. This handle is opaque to the protocol,
  1770. reserved for use by the underlying driver that made the indication, and a
  1771. required parameter to NdisTransferData.
  1772. HeaderBuffer:
  1773. Points to the base virtual address of a range containing the buffered packet
  1774. header. The address is valid only within the current call to ProtocolReceive.
  1775. HeaderBufferSize:
  1776. Specifies the number of bytes in the packet header.
  1777. LookAheadBuffer:
  1778. Points to the base virtual address of a range that contains
  1779. LookaheadBufferSize bytes of buffered network packet data. This address is
  1780. valid only within the current call to ProtocolReceive.
  1781. LookaheadBufferSize:
  1782. Specifies the number of bytes of network packet data in the lookahead buffer.
  1783. The indicating driver ensures this number is at least as large as the size it
  1784. returned for the protocol's preceding call to NdisRequest with
  1785. OID_GEN_CURRENT_LOOKAHEAD or the size of the packet, whichever is less.
  1786. If PacketSize is less than or equal to the given LookaheadBufferSize, the
  1787. kahead buffer contains the entire packet. If the underlying driver made
  1788. the indication with NdisMIndicateReceivePacket, the lookahead buffer always
  1789. contains a full network packet.
  1790. PacketSize:
  1791. Specifies the size, in bytes, of the network packet data. The length of the
  1792. packet does not include the length of the header.
  1793. ProtocolReceive determines whether the protocol must call NdisTransferData by
  1794. comparing this parameter to the given LookaheadBufferSize.
  1795. Return Values:
  1796. NDIS_STATUS_NOT_ACCEPTED:
  1797. The protocol has no use for the indicated packet, that is, it has no current
  1798. clients interested in the indicated network data.
  1799. Returning this status quickly for rejected packets yields higher performance
  1800. for the protocol and the highest possible network I/O throughput for the
  1801. system as a whole.
  1802. NDIS_STATUS_SUCCESS:
  1803. ProtocolReceive has processed the header information and accepted the packet,
  1804. that is, it has copied the indicated network data from the header and
  1805. lookahead buffers and, possibly, called NdisTransferData to retrieve the
  1806. remaining data if less than a full network packet was indicated.
  1807. ---------------------------------------------------------------------------*/
  1808. {
  1809. NDIS_STATUS status = NDIS_STATUS_NOT_ACCEPTED;
  1810. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  1811. PPPOE_PACKET *pPacket = NULL;
  1812. ASSERT( VALIDATE_BINDING( pBinding ) );
  1813. TRACE( TL_V, TM_Pr, ("+PrReceive") );
  1814. //
  1815. // Check if the packet is a PPPoE frame or not
  1816. //
  1817. if ( !PacketFastIsPPPoE( (CHAR*) HeaderBuffer, HeaderBufferSize ) )
  1818. {
  1819. TRACE( TL_V, TM_Pr, ("-PrReceive=$%x",status) );
  1820. return status;
  1821. }
  1822. //
  1823. // Make sure packet is not too large
  1824. //
  1825. if ( HeaderBufferSize + PacketSize > PPPOE_PACKET_BUFFER_SIZE )
  1826. {
  1827. TRACE( TL_A, TM_Pr, ("PrReceive: Packet too large" ) );
  1828. TRACE( TL_V, TM_Pr, ("-PrReceive=$%x",status) );
  1829. return status;
  1830. }
  1831. //
  1832. // Let's create our PPPoE packet to keep the copy of the received packet
  1833. //
  1834. pPacket = PacketCreateSimple();
  1835. if ( pPacket == NULL )
  1836. {
  1837. TRACE( TL_A, TM_Pr, ("PrReceive: Could not allocate context to copy the packet") );
  1838. TRACE( TL_V, TM_Pr, ("-PrReceive=$%x",status) );
  1839. return status;
  1840. }
  1841. //
  1842. // See if the packet indicated is complete, or not.
  1843. // If it is not the complete packet then we should call NdisTransferData(),
  1844. // otherwise we can do the copy here
  1845. //
  1846. if ( LookaheadBufferSize >= PacketSize )
  1847. {
  1848. TRACE( TL_V, TM_Pr, ("PrReceive: Complete packet indicated, transferring data") );
  1849. //
  1850. // First copy the header portion
  1851. //
  1852. NdisMoveMemory( pPacket->pHeader,
  1853. HeaderBuffer,
  1854. HeaderBufferSize );
  1855. //
  1856. // Packet is complete, so let's copy whole data to our own copy
  1857. //
  1858. TdiCopyLookaheadData( pPacket->pHeader + HeaderBufferSize,
  1859. (CHAR*) LookaheadBuffer,
  1860. (ULONG) PacketSize,
  1861. (ULONG) 0 );
  1862. //
  1863. // Let's call PrTransferDataComplete() manually now.
  1864. //
  1865. PrTransferDataComplete( pBinding,
  1866. pPacket->pNdisPacket,
  1867. NDIS_STATUS_SUCCESS,
  1868. PacketSize );
  1869. }
  1870. else
  1871. {
  1872. UINT nBytesTransferred = 0;
  1873. TRACE( TL_V, TM_Pr, ("PrReceive: Partial packet indicated, transferring data") );
  1874. //
  1875. // Mark the packet for incomplete indication
  1876. //
  1877. pPacket->ulFlags |= PCBF_PacketIndicatedIncomplete;
  1878. //
  1879. // First copy the header to the end of the packet
  1880. //
  1881. // Note that HeaderBufferSize MUST be equal to ETHERNET_HEADER_LENGTH and
  1882. // this is ensured in PacketIsFastPPPoE().
  1883. //
  1884. NdisMoveMemory( pPacket->pHeader + (PPPOE_PACKET_BUFFER_SIZE - ETHERNET_HEADER_LENGTH),
  1885. HeaderBuffer,
  1886. HeaderBufferSize );
  1887. //
  1888. // Lookahead buffer does not contain all the packet, we should call NdisTransferData()
  1889. // to receive the full packet
  1890. //
  1891. NdisTransferData( &status,
  1892. pBinding->NdisBindingHandle,
  1893. MacReceiveContext,
  1894. 0,
  1895. PacketSize,
  1896. pPacket->pNdisPacket,
  1897. &nBytesTransferred );
  1898. if ( status != NDIS_STATUS_PENDING )
  1899. {
  1900. //
  1901. // Call PrTransferDataComplete() manually if transfer data completed
  1902. // synchronously
  1903. //
  1904. PrTransferDataComplete( pBinding,
  1905. pPacket->pNdisPacket,
  1906. status,
  1907. nBytesTransferred );
  1908. }
  1909. }
  1910. TRACE( TL_V, TM_Pr, ("-PrReceive=$%x",status) );
  1911. return NDIS_STATUS_SUCCESS;
  1912. }
  1913. VOID
  1914. PrTransferDataComplete(
  1915. IN NDIS_HANDLE ProtocolBindingContext,
  1916. IN PNDIS_PACKET Packet,
  1917. IN NDIS_STATUS Status,
  1918. IN UINT BytesTransferred
  1919. )
  1920. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1921. Functional Description:
  1922. This function is called to post process a received packet when whole data
  1923. is copied into the packet context.
  1924. It can be called by NDIS, or it can be called manually from inside PrReceive()
  1925. if the indicated packet is a whole packet.
  1926. If the status is succesfull, it will insert the packet to the end of the
  1927. bindings received packets queue, otherwise it will clean up our copy of
  1928. NDIS packet and return.
  1929. Parameters:
  1930. ProtocolBindingContext
  1931. Specifies the handle to a protocol-allocated context area in which the
  1932. protocol driver maintains per-binding runtime state. The driver supplied this
  1933. handle when it called NdisOpenAdapter.
  1934. Packet
  1935. Points to the protocol-allocated packet descriptor the driver originally
  1936. passed to NdisTransferData.
  1937. Status
  1938. Specifies the final status of the transfer-data operation.
  1939. BytesTransferred
  1940. Specifies the number of bytes of data that the NIC driver transferred into
  1941. the buffers mapped by buffer descriptors chained to the packet descriptor at
  1942. Packet. The protocol uses this value to determine whether the miniport
  1943. supplied all the requested data for the originally indicated network packet.
  1944. Return Values:
  1945. None
  1946. ---------------------------------------------------------------------------*/
  1947. {
  1948. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  1949. PPPOE_PACKET* pPacket = NULL;
  1950. ASSERT( VALIDATE_BINDING( pBinding ) );
  1951. TRACE( TL_V, TM_Pr, ("+PrTransferDataComplete") );
  1952. do
  1953. {
  1954. //
  1955. // Retrieve the related PPPoE packet first
  1956. //
  1957. pPacket = PacketGetRelatedPppoePacket( Packet );
  1958. //
  1959. // Make sure the data transfer suceeded
  1960. //
  1961. if ( Status != NDIS_STATUS_SUCCESS )
  1962. {
  1963. //
  1964. // Transfer of data to our copy of packet failed, so clean up our packet
  1965. //
  1966. PacketFree( pPacket );
  1967. break;
  1968. }
  1969. //
  1970. // Rearrange the data in the packet if the packet was indicated incomplete
  1971. //
  1972. if ( pPacket->ulFlags & PCBF_PacketIndicatedIncomplete )
  1973. {
  1974. CHAR tempHeader[ ETHERNET_HEADER_LENGTH ];
  1975. CHAR* srcPos = pPacket->pHeader + BytesTransferred;
  1976. //
  1977. // Make a copy of the header stored at the end of the packet
  1978. //
  1979. NdisMoveMemory( tempHeader,
  1980. pPacket->pHeader + (PPPOE_PACKET_BUFFER_SIZE - ETHERNET_HEADER_LENGTH),
  1981. ETHERNET_HEADER_LENGTH );
  1982. //
  1983. // Move the contents of the packet appropriately to make room
  1984. // for the header (slip contents by ETHERNET_HEADER_LENGTH)
  1985. //
  1986. while ( BytesTransferred > 0 )
  1987. {
  1988. #define TEMP_BUFFER_SIZE 100
  1989. CHAR tempBuffer[ TEMP_BUFFER_SIZE ];
  1990. UINT size = (BytesTransferred < TEMP_BUFFER_SIZE) ?
  1991. BytesTransferred :
  1992. TEMP_BUFFER_SIZE;
  1993. srcPos -= size;
  1994. NdisMoveMemory( tempBuffer,
  1995. srcPos,
  1996. size );
  1997. NdisMoveMemory( srcPos + ETHERNET_HEADER_LENGTH,
  1998. tempBuffer,
  1999. size );
  2000. BytesTransferred -= size;
  2001. }
  2002. //
  2003. // Copy the header to the correct position in the packet
  2004. //
  2005. NdisMoveMemory( pPacket->pHeader,
  2006. tempHeader,
  2007. ETHERNET_HEADER_LENGTH );
  2008. //
  2009. // Clear the incomplete indication flag
  2010. //
  2011. pPacket->ulFlags &= ~PCBF_PacketIndicatedIncomplete;
  2012. }
  2013. //
  2014. // Data transfer succeeded, insert into our queue of received packets, so that it will
  2015. // be consumed by a call to our PrReceiveComplete() function
  2016. //
  2017. NdisInterlockedInsertTailList( &pBinding->linkPackets,
  2018. &pPacket->linkPackets,
  2019. &pBinding->lockBinding );
  2020. } while ( FALSE );
  2021. TRACE( TL_V, TM_Pr, ("-PrTransferDataComplete=$%x",Status) );
  2022. }
  2023. VOID
  2024. PrReceiveComplete(
  2025. IN NDIS_HANDLE ProtocolBindingContext
  2026. )
  2027. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2028. Functional Description:
  2029. This function will be called to perform post processing of received packets
  2030. indicated previously. Underlying NIC will call it when it is not busy.
  2031. We need to serialize the indication of packets to the miniport, since this
  2032. is of vital importance for PPP frames. To achieve this, we use the lock
  2033. protected flag of binding (fRecvLoopRunning).
  2034. When this function is called, it will return immediately if this flag is
  2035. already set.
  2036. If flag is not set, then it will set this flag and start processing packets
  2037. from the received queue, and indicate all packets to miniport one by one
  2038. untill all the queue is drained. Then it will reset the flag and return.
  2039. Parameters:
  2040. ProtocolBindingContext
  2041. Specifies the handle to a protocol-allocated context area in which the
  2042. protocol driver maintains per-binding runtime state. The driver supplied this
  2043. handle when it called NdisOpenAdapter.
  2044. Return Values:
  2045. None
  2046. ---------------------------------------------------------------------------*/
  2047. {
  2048. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  2049. LIST_ENTRY* pLink = NULL;
  2050. PPPOE_PACKET* pPacket = NULL;
  2051. BOOLEAN fStartRecvLoop = FALSE;
  2052. ASSERT( VALIDATE_BINDING( pBinding ) );
  2053. TRACE( TL_V, TM_Pr, ("+PrReceiveComplete") );
  2054. NdisAcquireSpinLock( &pBinding->lockBinding );
  2055. //
  2056. // See if recv loop is already running
  2057. //
  2058. if ( !pBinding->fRecvLoopRunning )
  2059. {
  2060. //
  2061. // Indicate the recv loop has started to run
  2062. //
  2063. pBinding->fRecvLoopRunning = TRUE;
  2064. //
  2065. // Now consume these packet's
  2066. //
  2067. while ( !IsListEmpty( &pBinding->linkPackets ) )
  2068. {
  2069. pLink = RemoveHeadList( &pBinding->linkPackets );
  2070. NdisReleaseSpinLock( &pBinding->lockBinding );
  2071. pPacket = (PPPOE_PACKET*) CONTAINING_RECORD( pLink, PPPOE_PACKET, linkPackets );
  2072. InitializeListHead( &pPacket->linkPackets );
  2073. if ( PacketInitializeFromReceived( pPacket ) == NDIS_STATUS_SUCCESS )
  2074. {
  2075. //
  2076. // Indicate the packet to miniport
  2077. //
  2078. MpRecvPacket( pBinding, pPacket );
  2079. }
  2080. //
  2081. // Free the packet since we are done with it
  2082. //
  2083. PacketFree( pPacket );
  2084. //
  2085. // Acquire the lock again
  2086. //
  2087. NdisAcquireSpinLock( &pBinding->lockBinding );
  2088. }
  2089. //
  2090. // The queue is drained, so stop the recv loop
  2091. //
  2092. pBinding->fRecvLoopRunning = FALSE;
  2093. }
  2094. NdisReleaseSpinLock( &pBinding->lockBinding );
  2095. TRACE( TL_V, TM_Pr, ("-PrReceiveComplete") );
  2096. }
  2097. ULONG
  2098. PrQueryMaxFrameSize()
  2099. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2100. Functional Description:
  2101. This function will be called by the miniport to retrieve the current minimum
  2102. of max frame sizes of the bindings, since this is the value passed to
  2103. NDISWAN in an OID_WAN_GET_INFO query as the MaxFrameSize.
  2104. We adjust the max frame size considering the PPPoE and Ethernet headers.
  2105. Parameters:
  2106. None
  2107. Return Values:
  2108. Minimum of max frame sizes
  2109. ---------------------------------------------------------------------------*/
  2110. {
  2111. ULONG ulMaxFrameSize = gl_ulMaxFrameSize;
  2112. if ( ulMaxFrameSize == 0 )
  2113. {
  2114. ulMaxFrameSize = PACKET_PPP_PAYLOAD_MAX_LENGTH;
  2115. }
  2116. else
  2117. {
  2118. ulMaxFrameSize = ulMaxFrameSize - ( PPPOE_PACKET_HEADER_LENGTH + PPP_MAX_HEADER_LENGTH);
  2119. }
  2120. return ulMaxFrameSize;
  2121. }
  2122. NDIS_STATUS
  2123. PrSend(
  2124. IN BINDING* pBinding,
  2125. IN PPPOE_PACKET* pPacket
  2126. )
  2127. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2128. Functional Description:
  2129. This function will be called to transmit a PPPoE packet.
  2130. The caller must have referenced the packet and binding before calling this
  2131. function. Then the caller can forget about the references, everything will
  2132. be handled by the protocol. If send operation complets synchrnously then
  2133. the references are removed in the function, otherwise PrSendComplete()
  2134. will be called and references will be removed then.
  2135. Parameters:
  2136. pBinding _ Binding to send the packet over.
  2137. pPacket _ PPPoE packet to be transmitted.
  2138. Return Values:
  2139. NDIS_STATUS_SUCCESS
  2140. NDIS_STATUS_PENDING
  2141. NDIS_STATUS_FAILURE
  2142. NDIS_STATUS_XXXXXXX
  2143. ---------------------------------------------------------------------------*/
  2144. {
  2145. NDIS_STATUS status = NDIS_STATUS_FAILURE;
  2146. ASSERT( VALIDATE_BINDING( pBinding ) );
  2147. TRACE( TL_V, TM_Pr, ("+PrSend") );
  2148. //
  2149. // Make sure we are bound before sending the packet.
  2150. //
  2151. // Note: We do not need to acquire the lock here since NDIS should prevent
  2152. // a crash even if we are unbound, and we already have a reference
  2153. // on the binding, so this is not a really strict check..
  2154. //
  2155. if ( pBinding->stateBinding == BN_stateBound )
  2156. {
  2157. //
  2158. // Make sure we are sending a packet not exceeding the max frame size
  2159. // of the underlying NIC
  2160. //
  2161. if ( pBinding->ulMaxFrameSize + ETHERNET_HEADER_LENGTH >=
  2162. (ULONG) ( PacketGetLength( pPacket ) + PPPOE_PACKET_HEADER_LENGTH ) )
  2163. {
  2164. NdisSend( &status,
  2165. pBinding->NdisBindingHandle,
  2166. PacketGetNdisPacket( pPacket ) );
  2167. }
  2168. }
  2169. if ( status != NDIS_STATUS_PENDING )
  2170. {
  2171. //
  2172. // NdisSend() completed synchronously so call PrSendComplete()
  2173. // manually here.
  2174. //
  2175. PrSendComplete( pBinding, PacketGetNdisPacket( pPacket ), status );
  2176. }
  2177. TRACE( TL_V, TM_Pr, ("-PrSend=$%x",status) );
  2178. return status;
  2179. }
  2180. VOID
  2181. PrStatus(
  2182. IN NDIS_HANDLE ProtocolBindingContext,
  2183. IN NDIS_STATUS GeneralStatus,
  2184. IN PVOID StatusBuffer,
  2185. IN UINT StatusBufferSize
  2186. )
  2187. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2188. Functional Description:
  2189. ProtocolStatus is a required driver function that handles status-change
  2190. notifications raised by an underlying connectionless NIC driver or by NDIS.
  2191. In this driver, we only use this function to receive Media disconnect
  2192. notifications to disconnect the active calls on that NIC.
  2193. Parameters:
  2194. ProtocolBindingContext:
  2195. Specifies the handle to a protocol-allocated context area in which the
  2196. protocol driver maintains per-binding runtime state. The driver supplied this
  2197. handle when it called NdisOpenAdapter.
  2198. GeneralStatus:
  2199. Indicates the general status code, either raised by NDIS or propagated from
  2200. the underlying driver's call to NdisMIndicateStatus.
  2201. StatusBuffer:
  2202. Points to a buffer containing medium-specific data that depends on the value
  2203. of GeneralStatus.
  2204. For example, if the GeneralStatus argument is NDIS_STATUS_RING_STATUS, this
  2205. parameter points to a ULONG-sized bitmask and StatusBufferSize is four. As
  2206. another example, if GeneralStatus is NDIS_STATUS_WAN_LINE_UP, this parameter
  2207. points to an NDIS_WAN_LINE_UP structure and StatusBufferSize is sizeof(
  2208. NDIS_STATUS_WAN_LINE_UP).
  2209. For some NDIS_STATUS_XXX values, this pointer is NULL and StatusBufferSize is
  2210. set to zero.
  2211. StatusBufferSize:
  2212. Specifies the number of bytes at StatusBuffer.
  2213. Return Values:
  2214. None
  2215. ---------------------------------------------------------------------------*/
  2216. {
  2217. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  2218. ASSERT( VALIDATE_BINDING( pBinding ) );
  2219. TRACE( TL_N, TM_Pr, ("+PrStatus") );
  2220. switch ( GeneralStatus )
  2221. {
  2222. case NDIS_STATUS_MEDIA_DISCONNECT:
  2223. //
  2224. // If the underlying media is disconnected, notify miniport of this event.
  2225. // It will appear to the miniport as if the NIC is removed, so it will drop all the
  2226. // active calls
  2227. //
  2228. TRACE( TL_N, TM_Pr, ("PrStatus: Notifying miniport of media disconnect event") );
  2229. MpNotifyBindingRemoval( pBinding );
  2230. break;
  2231. }
  2232. TRACE( TL_N, TM_Pr, ("-PrStatus") );
  2233. }
  2234. NDIS_STATUS
  2235. PrPnPEvent(
  2236. IN NDIS_HANDLE hProtocolBindingContext,
  2237. IN PNET_PNP_EVENT pNetPnPEvent
  2238. )
  2239. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2240. Functional Description:
  2241. ProtocolPnPEvent is a required function in any protocol driver to support
  2242. Plug and Play and/or Power Management. NDIS calls ProtocolPnPEvent to
  2243. indicate a Plug and Play event or a Power Management event to a protocol
  2244. bound to a NIC.
  2245. NDIS calls ProtocolPnPEvent to notify a protocol bound to a network NIC that
  2246. the operating system has issued a Plug and Play or Power Management event to
  2247. the device object representing the NIC. NDIS calls the ProtocolPnPEvent
  2248. function of each protocol bound to the NIC.
  2249. The NET_PNP_EVENT structure passed to ProtocolPnPEvent describes the Plug and
  2250. Play or Power Management event. ProtocolPnPEvent interprets two basic pieces
  2251. of information in the NET_PNP_EVENT structure:
  2252. A NetEvent code that describes the Plug and Play or Power Management event.
  2253. Event-specific information (for example, for a NetEventSetPower, the device
  2254. power state to which the device is transitioning).
  2255. The protocol should save the NetPnPEvent pointer. This pointer is a required
  2256. input parameter to NdisCompletePnPEvent, which the protocol must subsequently
  2257. call if ProtocolPnPEvent returns NDIS_STATUS_PENDING.
  2258. Parameters
  2259. hProtocolBindingContext:
  2260. Specifies the handle to a protocol-allocated context area in which this
  2261. driver maintains per-binding runtime state. The protocol supplied this handle
  2262. when it called NdisOpenAdapter. A NetEventXxx indicated on a NULL
  2263. ProtocolBindingContext pertains to all network bindings. NetEventBindList and
  2264. NetEventBindsComplete are always indicated on a NULL ProtocolBindingContext.
  2265. NetEventReconfigure can be indicated on a particular ProtocolBindingContext
  2266. or a NULL ProtocolBindingContext.
  2267. pNetPnPEvent:
  2268. Points to a NET_PNP_EVENT structure, which describes the Plug and Play event
  2269. or Power Management event being indicated to the protocol driver.
  2270. Return Value
  2271. NDIS_STATUS_SUCCESS:
  2272. The protocol successfully handled the indicated Plug and Play or Power
  2273. Management event. The meaning of this status code depends on the NetEvent
  2274. code in the buffered NET_PNP_EVENT structure at NetPnPEvent.
  2275. NDIS_STATUS_PENDING
  2276. The protocol will return its response to the indicated event asynchronously
  2277. with a call to NdisCompletePnPEvent.
  2278. NDIS_STATUS_RESOURCES
  2279. The protocol could not obtain the necessary system resources to satisfy the
  2280. indicated Plug and Play or Power Management event.
  2281. NDIS_STATUS_NOT_SUPPORTED
  2282. A legacy (non-PnP-aware) protocol can return this status in response to a
  2283. NetEventSetPower to indicate that NDIS should unbind the it from the NIC.
  2284. NDIS_STATUS_FAILURE
  2285. The protocol failed the indicated Plug and Play or Power Management event.
  2286. The meaning of this status code depends on the NetEvent code in the buffered
  2287. NET_PNP_EVENT structure at NetPnPEvent.
  2288. ---------------------------------------------------------------------------*/
  2289. {
  2290. NDIS_STATUS status = NDIS_STATUS_NOT_SUPPORTED;
  2291. BINDING *pBinding = (BINDING*) hProtocolBindingContext;
  2292. TRACE( TL_N, TM_Pr, ("+PrPnpEvent") );
  2293. switch ( pNetPnPEvent->NetEvent )
  2294. {
  2295. case NetEventQueryPower:
  2296. {
  2297. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventQueryPower") );
  2298. status = NDIS_STATUS_SUCCESS;
  2299. break;
  2300. }
  2301. case NetEventQueryRemoveDevice:
  2302. {
  2303. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventQueryRemoveDevice") );
  2304. status = NDIS_STATUS_SUCCESS;
  2305. break;
  2306. }
  2307. case NetEventCancelRemoveDevice:
  2308. {
  2309. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventCancelRemoveDevice") );
  2310. status = NDIS_STATUS_SUCCESS;
  2311. break;
  2312. }
  2313. case NetEventReconfigure:
  2314. {
  2315. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventReconfigure") );
  2316. status = NDIS_STATUS_SUCCESS;
  2317. break;
  2318. }
  2319. case NetEventBindsComplete:
  2320. {
  2321. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventBindsComplete") );
  2322. status = NDIS_STATUS_SUCCESS;
  2323. break;
  2324. }
  2325. case NetEventPnPCapabilities:
  2326. {
  2327. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventPnPCapabilities") );
  2328. status = NDIS_STATUS_SUCCESS;
  2329. break;
  2330. }
  2331. case NetEventBindList:
  2332. {
  2333. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventBindList") );
  2334. status = NDIS_STATUS_SUCCESS;
  2335. break;
  2336. }
  2337. case NetEventSetPower:
  2338. {
  2339. BOOLEAN fWakeUp = FALSE;
  2340. BOOLEAN fSleep = FALSE;
  2341. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventSetPower") );
  2342. NdisAcquireSpinLock( &pBinding->lockBinding );
  2343. if ( *( (NDIS_DEVICE_POWER_STATE*) pNetPnPEvent->Buffer ) == NdisDeviceStateD0 )
  2344. {
  2345. if ( pBinding->stateBinding == BN_stateSleeping )
  2346. {
  2347. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventSetPower - Wake up request") );
  2348. fWakeUp = TRUE;
  2349. pBinding->stateBinding = BN_stateBound;
  2350. }
  2351. }
  2352. else if ( *( (NDIS_DEVICE_POWER_STATE*) pNetPnPEvent->Buffer ) > NdisDeviceStateD0 )
  2353. {
  2354. if ( pBinding->stateBinding == BN_stateBound )
  2355. {
  2356. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventSetPower - Sleep request") );
  2357. fSleep = TRUE;
  2358. pBinding->stateBinding = BN_stateSleepPending;
  2359. }
  2360. }
  2361. NdisReleaseSpinLock( &pBinding->lockBinding );
  2362. if ( fSleep )
  2363. {
  2364. //
  2365. // Since this NIC is going to sleep, drop all the calls on it
  2366. //
  2367. MpNotifyBindingRemoval( pBinding );
  2368. //
  2369. // Wait for pending operations to be completed
  2370. //
  2371. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventSetPower - Waiting for pending operations to be completed") );
  2372. NdisAcquireSpinLock( &pBinding->lockBinding );
  2373. while ( pBinding->lRef > 1 )
  2374. {
  2375. NdisReleaseSpinLock( &pBinding->lockBinding );
  2376. NdisMSleep( 10000 );
  2377. NdisAcquireSpinLock( &pBinding->lockBinding );
  2378. }
  2379. pBinding->stateBinding = BN_stateSleeping;
  2380. NdisReleaseSpinLock( &pBinding->lockBinding );
  2381. }
  2382. status = NDIS_STATUS_SUCCESS;
  2383. break;
  2384. }
  2385. default:
  2386. {
  2387. TRACE( TL_N, TM_Pr, ("PrPnpEvent: Unknown Event - %x", pNetPnPEvent->NetEvent) );
  2388. status = NDIS_STATUS_NOT_SUPPORTED;
  2389. break;
  2390. }
  2391. }
  2392. TRACE( TL_N, TM_Pr, ("-PrPnpEvent=$%x", status) );
  2393. return status;
  2394. }
  2395. VOID
  2396. PrReEnumerateBindings(
  2397. VOID
  2398. )
  2399. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2400. Functional Description:
  2401. PrReEnumerateBindings causes NDIS to send bind notifications to the pppoe
  2402. protocol section for each miniport that it needs to bind to. It is called
  2403. when a tapi client is interested in either making an outgoing call or
  2404. listening for an incoming call. It is expected that when this function
  2405. returns all of the bindings between the protocol and underlying miniports
  2406. will be finished!
  2407. Parameters
  2408. None
  2409. Return Value
  2410. None
  2411. ---------------------------------------------------------------------------*/
  2412. {
  2413. TRACE( TL_N, TM_Pr, ("+PrReEnumerateBindings") );
  2414. NdisAcquireSpinLock( &gl_lockProtocol );
  2415. gl_fBindProtocol = TRUE;
  2416. NdisReleaseSpinLock( &gl_lockProtocol );
  2417. NdisReEnumerateProtocolBindings(gl_hNdisProtocolHandle);
  2418. TRACE( TL_N, TM_Pr, ("-PrReEnumerateBindings") );
  2419. }
  2420. VOID
  2421. ChangePacketFiltersForAdapters(
  2422. BOOLEAN fSet
  2423. )
  2424. {
  2425. LIST_ENTRY* pLink = NULL;
  2426. TRACE( TL_N, TM_Pr, ("+ChangePacketFiltersForAdapters") );
  2427. NdisAcquireSpinLock( &gl_lockProtocol );
  2428. gl_fSetPacketFiltersAtBind = fSet;
  2429. pLink = gl_linkBindings.Flink;
  2430. //
  2431. // See if we have any bindings
  2432. //
  2433. if ( pLink != &gl_linkBindings )
  2434. {
  2435. BINDING* pBinding = NULL;
  2436. TRACE( TL_N, TM_Pr, ("ChangePacketFiltersForAdapters: %s packet filters", ( fSet ) ? "Setting" : "Resetting") );
  2437. //
  2438. // First reference the bindings in the list and mark their
  2439. // BNBF_ChangePacketFilterInProgress bit
  2440. //
  2441. while ( pLink != &gl_linkBindings )
  2442. {
  2443. //
  2444. // We have at least one binding, so walk thru the list
  2445. // and reference them
  2446. //
  2447. pBinding = ((BINDING*) CONTAINING_RECORD( pLink, BINDING, linkBindings ));
  2448. NdisAcquireSpinLock( &pBinding->lockBinding );
  2449. if ( pBinding->stateBinding == BN_stateBound )
  2450. {
  2451. //
  2452. // If the state of the binding is BN_stateBound then
  2453. // set the BNBF_PacketFilterChangeInProgress bit,
  2454. // reference
  2455. // the binding.
  2456. //
  2457. pBinding->ulBindingFlags |= BNBF_PacketFilterChangeInProgress;
  2458. ReferenceBinding( pBinding, FALSE );
  2459. }
  2460. NdisReleaseSpinLock( &pBinding->lockBinding );
  2461. //
  2462. // Iterate to the next binding
  2463. //
  2464. pLink = pLink->Flink;
  2465. }
  2466. //
  2467. // Now make a second pass and shoot the SetPacket filter request for
  2468. // all the marked items
  2469. //
  2470. pLink = gl_linkBindings.Flink;
  2471. while ( pLink != &gl_linkBindings )
  2472. {
  2473. //
  2474. // We have at least one binding, so walk thru the list
  2475. // and reference them
  2476. //
  2477. pBinding = ((BINDING*) CONTAINING_RECORD( pLink, BINDING, linkBindings ));
  2478. //
  2479. // Advance to the next item
  2480. //
  2481. pLink = pLink->Flink;
  2482. NdisReleaseSpinLock( &gl_lockProtocol );
  2483. //
  2484. // If we are just marking, check the state of the binding and mark it
  2485. // by setting the BNBF_SetPacketFilterInProgress bit
  2486. //
  2487. if ( pBinding->ulBindingFlags & BNBF_PacketFilterChangeInProgress )
  2488. {
  2489. //
  2490. // This binding is marked by the previous loop so change the filter
  2491. // for this binding
  2492. //
  2493. PrSetPacketFilterForAdapter( pBinding, fSet );
  2494. //
  2495. // Reset what was done in the first pass
  2496. //
  2497. pBinding->ulBindingFlags &= ~BNBF_PacketFilterChangeInProgress;
  2498. DereferenceBinding( pBinding );
  2499. }
  2500. NdisAcquireSpinLock( &gl_lockProtocol );
  2501. }
  2502. }
  2503. NdisReleaseSpinLock( &gl_lockProtocol );
  2504. TRACE( TL_N, TM_Pr, ("-ChangePacketFiltersForAdapters") );
  2505. }