Leaked source code of windows server 2003
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.

3519 lines
102 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 = PrStatusComplete;
  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. VOID
  804. PrStatusComplete(
  805. IN NDIS_HANDLE ProtocolBindingContext
  806. )
  807. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  808. Functional Description:
  809. This function is a required driver function that completes a status-change
  810. operation initiated when the underlying driver calls NdisMIndicateStatus.
  811. Parameters:
  812. ProtocolBindingContext:
  813. A pointer ot our binding information structure.
  814. Return Values:
  815. None
  816. ---------------------------------------------------------------------------*/
  817. {
  818. BINDING *pBinding = (BINDING *) ProtocolBindingContext;
  819. }
  820. BOOLEAN
  821. PrQueryAdapterForCurrentAddress(
  822. IN BINDING* pBinding
  823. )
  824. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  825. Functional Description:
  826. This function is called to query the underlying adapter for current MAC
  827. address oid.
  828. The underlying adapter must have been opened succesfully prior to calling
  829. this function.
  830. We save the result of the request in the binding context and set the
  831. RequestCompleted member of the binding context to resume the thread
  832. waiting for this to complete.
  833. CAUTION: It must be called from PASSIVE_LEVEL.
  834. Parameters:
  835. pBinding:
  836. A pointer ot our binding information structure.
  837. Return Values:
  838. TRUE:
  839. If the request was completed succesfully.
  840. FALSE:
  841. If the request was not completed succesfully.
  842. ---------------------------------------------------------------------------*/
  843. {
  844. NDIS_STATUS status;
  845. PNDIS_REQUEST pRequest = &pBinding->Request;
  846. TRACE( TL_N, TM_Pr, ("+PrQueryAdapterForCurrentAddress") );
  847. //
  848. // Generate an NDIS_REQUEST for querying current address oid
  849. //
  850. NdisZeroMemory( pRequest, sizeof( NDIS_REQUEST ) );
  851. pRequest->RequestType = NdisRequestQueryInformation ;
  852. pRequest->DATA.QUERY_INFORMATION.Oid = OID_802_3_CURRENT_ADDRESS;
  853. pRequest->DATA.QUERY_INFORMATION.InformationBuffer = pBinding->LocalAddress;
  854. pRequest->DATA.QUERY_INFORMATION.InformationBufferLength = sizeof( CHAR ) * 6;
  855. //
  856. // Request information from the adapter
  857. //
  858. NdisRequest( &status,
  859. pBinding->NdisBindingHandle,
  860. pRequest );
  861. if ( status != NDIS_STATUS_PENDING )
  862. {
  863. //
  864. // NdisRequest() completed synchronously, call PrRequestComplete()
  865. // manually.
  866. //
  867. PrRequestComplete( pBinding,
  868. pRequest,
  869. status );
  870. }
  871. NdisWaitEvent( &pBinding->RequestCompleted, 0 );
  872. NdisResetEvent( &pBinding->RequestCompleted );
  873. TRACE( TL_N, TM_Pr, ("-PrQueryAdapterForCurrentAddress") );
  874. return pBinding->RequestStatus == NDIS_STATUS_SUCCESS;
  875. }
  876. BOOLEAN
  877. PrQueryAdapterForLinkSpeed(
  878. IN BINDING* pBinding
  879. )
  880. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  881. Functional Description:
  882. This function is called to query the underlying adapter for link speed oid.
  883. The underlying adapter must have been opened succesfully prior to calling
  884. this function.
  885. We save the result of the request in the binding context and set the
  886. RequestCompleted member of the binding context to resume the thread
  887. waiting for this to complete.
  888. CAUTION: It must be called from PASSIVE_LEVEL.
  889. Parameters:
  890. pBinding:
  891. A pointer ot our binding information structure.
  892. Return Values:
  893. TRUE:
  894. If the request was completed succesfully.
  895. FALSE:
  896. If the request was not completed succesfully.
  897. ---------------------------------------------------------------------------*/
  898. {
  899. NDIS_STATUS status;
  900. PNDIS_REQUEST pRequest = &pBinding->Request;
  901. TRACE( TL_N, TM_Pr, ("+PrQueryAdapterForLinkSpeed") );
  902. //
  903. // Generate an NDIS_REQUEST for querying link speed oid
  904. //
  905. NdisZeroMemory( pRequest, sizeof( NDIS_REQUEST ) );
  906. pRequest->RequestType = NdisRequestQueryInformation ;
  907. pRequest->DATA.QUERY_INFORMATION.Oid = OID_GEN_LINK_SPEED;
  908. pRequest->DATA.QUERY_INFORMATION.InformationBuffer = &pBinding->ulSpeed;
  909. pRequest->DATA.QUERY_INFORMATION.InformationBufferLength = sizeof( pBinding->ulSpeed );
  910. //
  911. // Request information from the adapter
  912. //
  913. NdisRequest( &status,
  914. pBinding->NdisBindingHandle,
  915. pRequest );
  916. if ( status != NDIS_STATUS_PENDING )
  917. {
  918. //
  919. // NdisRequest() completed synchronously, call PrRequestComplete()
  920. // manually.
  921. //
  922. PrRequestComplete( pBinding,
  923. pRequest,
  924. status );
  925. }
  926. NdisWaitEvent( &pBinding->RequestCompleted, 0 );
  927. NdisResetEvent( &pBinding->RequestCompleted );
  928. TRACE( TL_N, TM_Pr, ("-PrQueryAdapterForLinkSpeed") );
  929. return pBinding->RequestStatus == NDIS_STATUS_SUCCESS;
  930. }
  931. BOOLEAN
  932. PrQueryAdapterForMaxFrameSize(
  933. IN BINDING* pBinding
  934. )
  935. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  936. Functional Description:
  937. This function is called to query the underlying adapter for max frame size
  938. oid.
  939. The underlying adapter must have been opened succesfully prior to calling
  940. this function.
  941. We save the result of the request in the binding context and set the
  942. RequestCompleted member of the binding context to resume the thread
  943. waiting for this to complete.
  944. CAUTION: It must be called from PASSIVE_LEVEL.
  945. Parameters:
  946. pBinding:
  947. A pointer ot our binding information structure.
  948. Return Values:
  949. TRUE:
  950. If the request was completed succesfully.
  951. FALSE:
  952. If the request was not completed succesfully.
  953. ---------------------------------------------------------------------------*/
  954. {
  955. NDIS_STATUS status;
  956. PNDIS_REQUEST pRequest = &pBinding->Request;
  957. TRACE( TL_N, TM_Pr, ("+PrQueryAdapterForMaxFrameSize") );
  958. //
  959. // Generate an NDIS_REQUEST for querying link speed oid
  960. //
  961. NdisZeroMemory( pRequest, sizeof( NDIS_REQUEST ) );
  962. pRequest->RequestType = NdisRequestQueryInformation ;
  963. pRequest->DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_FRAME_SIZE;
  964. pRequest->DATA.QUERY_INFORMATION.InformationBuffer = &pBinding->ulMaxFrameSize;
  965. pRequest->DATA.QUERY_INFORMATION.InformationBufferLength = sizeof( pBinding->ulMaxFrameSize );
  966. //
  967. // Request information from the adapter
  968. //
  969. NdisRequest( &status,
  970. pBinding->NdisBindingHandle,
  971. pRequest );
  972. if ( status != NDIS_STATUS_PENDING )
  973. {
  974. //
  975. // NdisRequest() completed synchronously, call PrRequestComplete()
  976. // manually.
  977. //
  978. PrRequestComplete( pBinding,
  979. pRequest,
  980. status );
  981. }
  982. NdisWaitEvent( &pBinding->RequestCompleted, 0 );
  983. NdisResetEvent( &pBinding->RequestCompleted );
  984. TRACE( TL_N, TM_Pr, ("-PrQueryAdapterForMaxFrameSize") );
  985. return pBinding->RequestStatus == NDIS_STATUS_SUCCESS;
  986. }
  987. BOOLEAN
  988. PrSetPacketFilterForAdapter(
  989. IN BINDING* pBinding,
  990. IN BOOLEAN fSet
  991. )
  992. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  993. Functional Description:
  994. This function is called to set the current generic packet filter for our
  995. protocol.
  996. The underlying adapter must have been opened succesfully prior to calling
  997. this function.
  998. We save the result of the request in the binding context and set the
  999. RequestCompleted member of the binding context to resume the thread
  1000. waiting for this to complete.
  1001. CAUTION: It must be called from PASSIVE_LEVEL.
  1002. Parameters:
  1003. pBinding:
  1004. A pointer ot our binding information structure.
  1005. fSet:
  1006. Indicates what the filters will be set to.
  1007. TRUE means receive packets, FALSE means set it to 0.
  1008. Return Values:
  1009. TRUE:
  1010. If the request was completed succesfully.
  1011. FALSE:
  1012. If the request was not completed succesfully.
  1013. ---------------------------------------------------------------------------*/
  1014. {
  1015. NDIS_STATUS status;
  1016. PNDIS_REQUEST pRequest = &pBinding->Request;
  1017. BOOLEAN fPacketFilterAlreadySet = (BOOLEAN) ( pBinding->ulBindingFlags & BNBF_PacketFilterSet );
  1018. TRACE( TL_N, TM_Pr, ("+PrSetPacketFilterForAdapter") );
  1019. //
  1020. // See if we already are in the state the request wants us to be in
  1021. //
  1022. if ( ( fPacketFilterAlreadySet && fSet ) ||
  1023. ( !fPacketFilterAlreadySet && !fSet ) )
  1024. {
  1025. pBinding->RequestStatus = NDIS_STATUS_SUCCESS;
  1026. TRACE( TL_N, TM_Pr, ("PrSetPacketFilterForAdapter: Already in the requested state") );
  1027. TRACE( TL_N, TM_Pr, ("-PrSetPacketFilterForAdapter") );
  1028. return TRUE;
  1029. }
  1030. pBinding->ulPacketFilter = ( fSet ) ? (NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_DIRECTED) : 0;
  1031. //
  1032. // Generate an NDIS_REQUEST for setting current packet filter
  1033. //
  1034. NdisZeroMemory( pRequest, sizeof( NDIS_REQUEST ) );
  1035. pRequest->RequestType = NdisRequestSetInformation;
  1036. pRequest->DATA.SET_INFORMATION.Oid = OID_GEN_CURRENT_PACKET_FILTER;
  1037. pRequest->DATA.SET_INFORMATION.InformationBuffer = &pBinding->ulPacketFilter;
  1038. pRequest->DATA.SET_INFORMATION.InformationBufferLength = sizeof( ULONG );
  1039. //
  1040. // Request set info on the adapter
  1041. //
  1042. NdisRequest( &status,
  1043. pBinding->NdisBindingHandle,
  1044. pRequest );
  1045. if ( status != NDIS_STATUS_PENDING )
  1046. {
  1047. //
  1048. // NdisRequest() completed synchronously, call PrRequestComplete()
  1049. // manually.
  1050. //
  1051. PrRequestComplete( pBinding,
  1052. pRequest,
  1053. status );
  1054. }
  1055. NdisWaitEvent( &pBinding->RequestCompleted, 0 );
  1056. NdisResetEvent( &pBinding->RequestCompleted );
  1057. TRACE( TL_N, TM_Pr, ("-PrSetPacketFilterForAdapter") );
  1058. return pBinding->RequestStatus == NDIS_STATUS_SUCCESS;
  1059. }
  1060. VOID
  1061. PrRequestComplete(
  1062. IN NDIS_HANDLE ProtocolBindingContext,
  1063. IN PNDIS_REQUEST pRequest,
  1064. IN NDIS_STATUS status
  1065. )
  1066. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1067. Functional Description:
  1068. This function will be called to indicate that an NDIS request submitted
  1069. previously has completed.
  1070. We submit 2 requests:
  1071. - OID_802_3_CURRENT_ADDRESS: This is submitted from PrQueryAdapterForCurrentAddress()
  1072. to obtain the current MAC address for the underlying
  1073. adapter.
  1074. - OID_GEN_LINK_SPEED: This is submitted from PrQueryAdapterForLinkSpeed() to obtain
  1075. the current link speed of the underlying adapter.
  1076. - OID_GEN_CURRENT_PACKET_FILTER: This is submitted from PrSetPacketFilterForAdapter()
  1077. to set the packet types we are interested in to NDIS.
  1078. If the request for MAC address fail, we clean up the binding context and notify
  1079. NDIS that bind adapter failed, otherwise we go ahead and query the adapter for link
  1080. speed.
  1081. Regardless of the status of request for link speed, we notify NDIS about succesful
  1082. completion of the bind operation as this is not a fatal error.
  1083. Before calling this function, the underlying adapter must have been opened
  1084. succesfully.
  1085. Parameters:
  1086. ProtocolBindingContext:
  1087. A pointer ot our binding information structure.
  1088. pRequest:
  1089. A pointer to the request submitted previously.
  1090. Status:
  1091. Completion status of the request.
  1092. Return Values:
  1093. None
  1094. ---------------------------------------------------------------------------*/
  1095. {
  1096. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  1097. BOOLEAN fUnknownOid = FALSE;
  1098. ASSERT( VALIDATE_BINDING( pBinding ) );
  1099. TRACE( TL_I, TM_Pr, ("+PrRequestComplete") );
  1100. switch ( pRequest->RequestType )
  1101. {
  1102. case NdisRequestQueryInformation:
  1103. {
  1104. switch ( pRequest->DATA.QUERY_INFORMATION.Oid )
  1105. {
  1106. case OID_802_3_CURRENT_ADDRESS:
  1107. TRACE( TL_N, TM_Pr, ("PrRequestComplete: OID_802_3_CURRENT_ADDRESS=$%x",status) );
  1108. pBinding->ulBindingFlags |= BNBF_CurrentAddressQueryCompleted;
  1109. break;
  1110. case OID_GEN_LINK_SPEED:
  1111. TRACE( TL_N, TM_Pr, ("PrRequestComplete: OID_GEN_LINK_SPEED=$%x",status) );
  1112. pBinding->ulBindingFlags |= BNBF_LinkSpeedQueryCompleted;
  1113. break;
  1114. case OID_GEN_MAXIMUM_FRAME_SIZE:
  1115. TRACE( TL_N, TM_Pr, ("PrRequestComplete: OID_GEN_MAXIMUM_FRAME_SIZE=$%x",status) );
  1116. pBinding->ulBindingFlags |= BNBF_MaxFrameSizeQueryCompleted;
  1117. break;
  1118. default:
  1119. TRACE( TL_N, TM_Pr, ("PrRequestComplete: UNKNOWN OID=$%x",pRequest->DATA.QUERY_INFORMATION.Oid) );
  1120. fUnknownOid = TRUE;
  1121. break;
  1122. }
  1123. }
  1124. break;
  1125. case NdisRequestSetInformation:
  1126. {
  1127. switch ( pRequest->DATA.SET_INFORMATION.Oid )
  1128. {
  1129. case OID_GEN_CURRENT_PACKET_FILTER:
  1130. TRACE( TL_N, TM_Pr, ("PrRequestComplete: OID_GEN_CURRENT_PACKET_FILTER=$%x",status) );
  1131. if ( status == NDIS_STATUS_SUCCESS )
  1132. {
  1133. if ( pBinding->ulBindingFlags & BNBF_PacketFilterSet )
  1134. {
  1135. //
  1136. // Packet filter was set, so reset it
  1137. //
  1138. pBinding->ulBindingFlags &= ~BNBF_PacketFilterSet;
  1139. }
  1140. else
  1141. {
  1142. //
  1143. // Packet filter was reset, so set it
  1144. //
  1145. pBinding->ulBindingFlags |= BNBF_PacketFilterSet;
  1146. }
  1147. }
  1148. break;
  1149. default:
  1150. TRACE( TL_N, TM_Pr, ("PrRequestComplete: UNKNOWN OID=$%x",pRequest->DATA.SET_INFORMATION.Oid) );
  1151. fUnknownOid = TRUE;
  1152. break;
  1153. }
  1154. }
  1155. break;
  1156. default:
  1157. TRACE( TL_N, TM_Pr, ("PrRequestComplete: Unknown RequestType=$%x",pRequest->RequestType) );
  1158. fUnknownOid = TRUE;
  1159. break;
  1160. }
  1161. if ( !fUnknownOid )
  1162. {
  1163. pBinding->RequestStatus = status;
  1164. NdisSetEvent( &pBinding->RequestCompleted );
  1165. }
  1166. TRACE( TL_I, TM_Pr, ("-PrRequestComplete") );
  1167. }
  1168. VOID
  1169. PrUnbindAdapter(
  1170. OUT PNDIS_STATUS Status,
  1171. IN NDIS_HANDLE ProtocolBindingContext,
  1172. IN NDIS_HANDLE UnbindContext
  1173. )
  1174. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1175. Functional Description:
  1176. This function will be called by NDIS when an underlying adapter wants to
  1177. unbind from us.
  1178. ArvindM says PrBindAdapter() and PrUnbindAdapter() will be serialized
  1179. by NDIS.
  1180. This function will not be called if PrBindAdapter() did not succeed.
  1181. Also this function will not be called as long as there are outstanding
  1182. PrReceivePacket() calls active.
  1183. However this function may be called while there are outstanding
  1184. PrSend(), PrSendPayload() or PrBroadcast() calls, that's why we keep
  1185. track of such calls with pBinding->nSendPending and wait on the completion
  1186. of these requests. And as we set the state to BN_stateUnbinding, no such
  1187. new requests will be accepted, and pBinding->nSendPending will reach 0
  1188. at some point which will trigger the pBinding->eventSendCompleted.
  1189. This function is called at IRQL_PASSIVE level by default so we can
  1190. safely wait on events.
  1191. Parameters:
  1192. Status
  1193. Points to a variable in which ProtocolBindAdapter returns the status of its
  1194. operation(s), as one of the following:
  1195. NDIS_STATUS_SUCCESS
  1196. The driver completed the unbind operation and deallocated the resources.
  1197. NDIS_STATUS_PENDING
  1198. The protocol will complete the unbind operation asynchronously with a call to
  1199. NdisCompleteUnbindAdapter when ProtocolCloseAdapterComplete() is called.
  1200. ProtocolBindingContext
  1201. A pointer to our binding context.
  1202. UnbindContext:
  1203. This handle is supplied by NDIS and should be used if NdisCloseAdapter() pends.
  1204. Then we will get a call to ProtocolCloseAdapterComplete() which will use this
  1205. handle to notify NDIS about the completion of the initial PrUnbindAdapter()
  1206. request.
  1207. Return Values:
  1208. None
  1209. ---------------------------------------------------------------------------*/
  1210. {
  1211. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  1212. ASSERT( VALIDATE_BINDING( pBinding ) );
  1213. TRACE( TL_I, TM_Pr, ("+PrUnbindAdapter") );
  1214. NdisAcquireSpinLock( &pBinding->lockBinding );
  1215. //
  1216. // If there is a sleep request pending, wait for it to complete
  1217. //
  1218. while ( pBinding->stateBinding == BN_stateSleepPending )
  1219. {
  1220. NdisReleaseSpinLock( &pBinding->lockBinding );
  1221. NdisMSleep( 10000 );
  1222. NdisAcquireSpinLock( &pBinding->lockBinding );
  1223. }
  1224. //
  1225. // Mark binding as unbind pending
  1226. //
  1227. ASSERT( pBinding->stateBinding == BN_stateSleeping ||
  1228. pBinding->stateBinding == BN_stateBound );
  1229. pBinding->stateBinding = BN_stateUnbindPending;
  1230. NdisReleaseSpinLock( &pBinding->lockBinding );
  1231. //
  1232. // Unbind all the active sessions on this binding
  1233. //
  1234. MpNotifyBindingRemoval( pBinding );
  1235. //
  1236. // Remove Binding from protocols binding table
  1237. //
  1238. RemoveBindingFromProtocol( pBinding );
  1239. //
  1240. // Wait for all references to be deleted
  1241. //
  1242. NdisWaitEvent( &pBinding->eventFreeBinding, 0 );
  1243. TRACE( TL_N, TM_Pr, ("PrUnbindAdapter: All references are deleted") );
  1244. //
  1245. // All references have been removed, now wait for all packets owned by NDIS
  1246. // to be returned.
  1247. //
  1248. // Note that no synchronization is necesarry for reading the value of numPacketsOwnedByNdis
  1249. // at this point since it can only be incremented when there is at least 1 reference on the
  1250. // binding - at this point ref count is 0 -, and because it can not be incremented, it can
  1251. // only reach 0 once.
  1252. //
  1253. while ( pBinding->NumPacketsOwnedByNdis )
  1254. {
  1255. NdisMSleep( 10000 );
  1256. }
  1257. TRACE( TL_N, TM_Pr, ("PrUnbindAdapter: All NDIS owned packets have been returned") );
  1258. //
  1259. // Since all references have been deleted, we can close the underlying adapter.
  1260. //
  1261. PrCloseAdapter( pBinding );
  1262. //
  1263. // Change the binding state to unbound
  1264. //
  1265. pBinding->stateBinding = BN_stateUnbound;
  1266. //
  1267. // Clean up the binding context
  1268. //
  1269. BindingCleanup( pBinding );
  1270. *Status = NDIS_STATUS_SUCCESS;
  1271. TRACE( TL_I, TM_Pr, ("-PrUnbindAdapter") );
  1272. }
  1273. VOID
  1274. PrCloseAdapter(
  1275. IN BINDING* pBinding
  1276. )
  1277. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1278. Functional Description:
  1279. This function is called to close the underlying adapter. It must be called
  1280. either from PrBindAdapter() or PrUnbindAdapter().
  1281. CAUTION: It must be called from PASSIVE_LEVEL.
  1282. Parameters:
  1283. pBinding:
  1284. Binding context that owns the adapter to close.
  1285. Return Values:
  1286. None
  1287. ---------------------------------------------------------------------------*/
  1288. {
  1289. NDIS_STATUS status;
  1290. TRACE( TL_N, TM_Pr, ("+PrCloseAdapter") );
  1291. NdisCloseAdapter( &status, pBinding->NdisBindingHandle );
  1292. if ( status != NDIS_STATUS_PENDING )
  1293. {
  1294. //
  1295. // NdisCloseAdapter() completed synchronously,
  1296. // complete the request manually
  1297. //
  1298. PrCloseAdapterComplete( pBinding, status );
  1299. }
  1300. NdisWaitEvent( &pBinding->RequestCompleted, 0 );
  1301. NdisResetEvent( &pBinding->RequestCompleted );
  1302. TRACE( TL_N, TM_Pr, ("-PrCloseAdapter") );
  1303. }
  1304. VOID
  1305. PrCloseAdapterComplete(
  1306. IN NDIS_HANDLE ProtocolBindingContext,
  1307. IN NDIS_STATUS Status
  1308. )
  1309. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1310. Functional Description:
  1311. This function can be called from PrCloseAdapter() if NdisCloseAdapter()
  1312. completes synchronously, or it will be called by NDIS at DISPATCH_LEVEL.
  1313. It sets the BNBF_CloseAdapterCompleted flag and sets the RequestCompleted
  1314. member of the binding context to resume the thread waiting on this event.
  1315. CAUTION: It can be called from PASSIVE_LEVEL or DISPATCH_LEVEL.
  1316. Parameters:
  1317. ProtocolBindingContext:
  1318. Specifies the handle to a protocol-allocated context area in which the
  1319. protocol driver maintains per-binding runtime state. The driver supplied this
  1320. handle when it called NdisOpenAdapter.
  1321. Status:
  1322. Indicates the final status of the close operation in the underlying driver.
  1323. Return Values:
  1324. None
  1325. ---------------------------------------------------------------------------*/
  1326. {
  1327. BINDING* pBinding = ProtocolBindingContext;
  1328. ASSERT( VALIDATE_BINDING( pBinding ) );
  1329. TRACE( TL_I, TM_Pr, ("+PrCloseAdapterComplete") );
  1330. TRACE( TL_N, TM_Pr, ("PrCloseAdapterComplete: NdisCloseAdapter() completed=$%x", Status ) );
  1331. pBinding->ulBindingFlags |= BNBF_CloseAdapterCompleted;
  1332. NdisSetEvent( &pBinding->RequestCompleted );
  1333. TRACE( TL_I, TM_Pr, ("-PrCloseAdapterComplete") );
  1334. }
  1335. BOOLEAN
  1336. PrAddCallToBinding(
  1337. IN BINDING* pBinding,
  1338. IN PCALL pCall
  1339. )
  1340. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1341. Functional Description:
  1342. This function will put a reference on the binding which will be removed
  1343. when PrRemoveCallFromBinding() is called.
  1344. It will return TRUE if reference is added succesfully, and FALSE if reference
  1345. could not be added.
  1346. Reference will not be added if binding is not in bound state.
  1347. CAUTION: Caller must make sure that the binding is not freed before calling this
  1348. function.
  1349. Parameters:
  1350. pBinding:
  1351. A pointer ot our binding information structure.
  1352. pCall:
  1353. A pointer to our call information structure.
  1354. Return Values:
  1355. TRUE:
  1356. Binding referenced for the call
  1357. FALSE:
  1358. Binding not reference for the call
  1359. ---------------------------------------------------------------------------*/
  1360. {
  1361. BOOLEAN fResult;
  1362. TRACE( TL_N, TM_Pr, ("+PrAddCallToBinding") );
  1363. //
  1364. // We have to acquire lock of call first to avoid dead locks
  1365. //
  1366. NdisAcquireSpinLock( &pCall->lockCall );
  1367. if ( pCall->ulClFlags & CLBF_CallDropped ||
  1368. pCall->ulClFlags & CLBF_CallClosePending )
  1369. {
  1370. NdisReleaseSpinLock( &pCall->lockCall );
  1371. TRACE( TL_A, TM_Pr, ("PrAddCallToBinding: Call already dropped or close pending") );
  1372. TRACE( TL_N, TM_Pr, ("-PrAddCallToBinding") );
  1373. return FALSE;
  1374. }
  1375. NdisAcquireSpinLock( &pBinding->lockBinding );
  1376. //
  1377. // Check the state of the binding, if it is not bound
  1378. // we can not add the call
  1379. //
  1380. if ( pBinding->stateBinding != BN_stateBound )
  1381. {
  1382. NdisReleaseSpinLock( &pBinding->lockBinding );
  1383. NdisReleaseSpinLock( &pCall->lockCall );
  1384. TRACE( TL_A, TM_Pr, ("PrAddCallToBinding: Binding state not bound") );
  1385. TRACE( TL_N, TM_Pr, ("-PrAddCallToBinding") );
  1386. return FALSE;
  1387. }
  1388. //
  1389. // Both binding and call are ready to be bound
  1390. // Go ahead and add the call
  1391. //
  1392. //
  1393. // Set call's binding context ptr to binding
  1394. //
  1395. pCall->pBinding = pBinding;
  1396. //
  1397. // Copy the local address of the binding
  1398. //
  1399. NdisMoveMemory( pCall->SrcAddr, pBinding->LocalAddress, 6 * sizeof( CHAR ) );
  1400. //
  1401. // Set call's link speed
  1402. //
  1403. pCall->ulSpeed = pBinding->ulSpeed;
  1404. //
  1405. // Pass the MaxFrameSize to call context
  1406. //
  1407. pCall->ulMaxFrameSize = pBinding->ulMaxFrameSize - PPPOE_PACKET_HEADER_LENGTH;
  1408. //
  1409. // Make a reference on the binding which will be removed when PrRemoveCallFromBinding()
  1410. // is called
  1411. //
  1412. ReferenceBinding( pBinding, FALSE );
  1413. //
  1414. // Release the locks, and return
  1415. //
  1416. NdisReleaseSpinLock( &pBinding->lockBinding );
  1417. NdisReleaseSpinLock( &pCall->lockCall );
  1418. TRACE( TL_N, TM_Pr, ("-PrAddCallToBinding") );
  1419. return TRUE;
  1420. }
  1421. VOID
  1422. PrRemoveCallFromBinding(
  1423. IN BINDING* pBinding,
  1424. IN CALL* pCall
  1425. )
  1426. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1427. Functional Description:
  1428. This function will be called to remove a reference added by a PrAddCallToBinding()
  1429. for a call on this binding.
  1430. Parameters:
  1431. pBinding:
  1432. Pointer to the binding context that the will be dereferenced.
  1433. pCall:
  1434. Pointer to the call context being unbound fromthe binding.
  1435. Return Values:
  1436. None
  1437. ---------------------------------------------------------------------------*/
  1438. {
  1439. ASSERT( VALIDATE_BINDING( pBinding ) );
  1440. TRACE( TL_N, TM_Pr, ("+PrRemoveCallFromBinding") );
  1441. NdisAcquireSpinLock( &pCall->lockCall );
  1442. pCall->pBinding = NULL;
  1443. pCall->ulSpeed = 0;
  1444. NdisReleaseSpinLock( &pCall->lockCall );
  1445. DereferenceBinding( pBinding );
  1446. TRACE( TL_N, TM_Pr, ("-PrRemoveCallFromBinding") );
  1447. }
  1448. VOID
  1449. PrSendComplete(
  1450. IN NDIS_HANDLE ProtocolBindingContext,
  1451. IN PNDIS_PACKET pNdisPacket,
  1452. IN NDIS_STATUS Status
  1453. )
  1454. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1455. Functional Description:
  1456. This function will be called by NDIS to notify that a previously send operation
  1457. on this packet has been completed.
  1458. It will notify NDISWAN, if packet was a payload packet.
  1459. It will remove the references on the packet and binding added by the PrSendXXX()
  1460. functions.
  1461. Parameters:
  1462. ProtocolBindingContext:
  1463. A pointer to our binding context.
  1464. pNdisPacket:
  1465. Ndis Packet that was send previously.
  1466. Status:
  1467. Status of the send operation.
  1468. Return Values:
  1469. None
  1470. ---------------------------------------------------------------------------*/
  1471. {
  1472. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  1473. PPPOE_PACKET* pPacket = NULL;
  1474. USHORT usCode;
  1475. ASSERT( VALIDATE_BINDING( pBinding ) );
  1476. TRACE( TL_V, TM_Pr, ("+PrSendComplete($%x,$%x,$%x)",pBinding,pNdisPacket,Status) );
  1477. //
  1478. // Retrieve the related PPPoE packet context from the NDIS packet
  1479. //
  1480. pPacket = PacketGetRelatedPppoePacket( pNdisPacket );
  1481. ASSERT( pPacket != NULL );
  1482. //
  1483. // Set the completion status for the send to be passed back to
  1484. // NDISWAN when the packet is freed (only for Payload packets)
  1485. //
  1486. PacketSetSendCompletionStatus( pPacket, Status );
  1487. //
  1488. // Remove the reference on the packet added by the sending function
  1489. //
  1490. DereferencePacket( pPacket );
  1491. //
  1492. // Remove the reference on the binding
  1493. //
  1494. DereferenceBinding( pBinding );
  1495. TRACE( TL_V, TM_Pr, ("-PrSendComplete($%x,$%x,$%x)",pBinding,pNdisPacket,Status) );
  1496. }
  1497. INT
  1498. PrReceivePacket(
  1499. IN NDIS_HANDLE ProtocolBindingContext,
  1500. IN PNDIS_PACKET Packet
  1501. )
  1502. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1503. Functional Description:
  1504. This function is called by NDIS when a packet is received over this binding.
  1505. Packet is converted into a PPPoE packet and notified to Miniport so that miniport
  1506. processes it.
  1507. Parameters:
  1508. ProtocolBindingContext:
  1509. A pointer to our binding context.
  1510. Packet:
  1511. An Ndis packet received over this binding.
  1512. Return Values:
  1513. The return value represents the number of references NDIS should wait for
  1514. before freeing his copy of the packet, but we will be done by the NDIS packet
  1515. at the end of the function, we always return 0.
  1516. ---------------------------------------------------------------------------*/
  1517. {
  1518. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  1519. PPPOE_PACKET* pPacket = NULL;
  1520. INT nRefCount = 0;
  1521. ASSERT( VALIDATE_BINDING( pBinding ) );
  1522. TRACE( TL_V, TM_Pr, ("+PrReceivePacket($%x,$%x)",pBinding,Packet) );
  1523. do
  1524. {
  1525. pPacket = PacketNdis2Pppoe( (PVOID) pBinding,
  1526. Packet,
  1527. &nRefCount );
  1528. if ( pPacket )
  1529. {
  1530. TRACE( TL_V, TM_Pr, ("PrReceivePacket: Received PPPoE packet=$%x",pPacket) );
  1531. //
  1532. // We have a copy of the packet, insert it into our queue of received packets,
  1533. // so that it will be consumed by a call to our PrReceiveComplete() function.
  1534. //
  1535. // It will be freed when it is consumed in PrReceiveComplete().
  1536. //
  1537. NdisInterlockedInsertTailList( &pBinding->linkPackets,
  1538. &pPacket->linkPackets,
  1539. &pBinding->lockBinding );
  1540. }
  1541. } while ( FALSE );
  1542. TRACE( TL_V, TM_Pr, ("-PrReceivePacket($%x,$%x)",pBinding,Packet) );
  1543. return nRefCount;
  1544. }
  1545. NDIS_STATUS
  1546. PrBroadcast(
  1547. IN PPPOE_PACKET* pPacket
  1548. )
  1549. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1550. Functional Description:
  1551. This function is called by an adapter to broadcast a PADI packet.
  1552. It clones the packet and schedules a send over each binding that's currrently
  1553. active.
  1554. The caller can destroy the packet after return from this function.
  1555. Parameters:
  1556. pPacket:
  1557. A PPPoE PADI packet ready to be broadcast.
  1558. Return Values:
  1559. NDIS_STATUS_SUCCESS:
  1560. At least 1 send operation was scheduled over a binding.
  1561. NDIS_STATUS_FAILURE:
  1562. No sends could be scheduled.
  1563. ---------------------------------------------------------------------------*/
  1564. {
  1565. NDIS_STATUS status = NDIS_STATUS_FAILURE;
  1566. TRACE( TL_N, TM_Pr, ("+PrBroadcast($%x)",pPacket) );
  1567. //
  1568. // Check if we have any bindings
  1569. //
  1570. if ( gl_ulNumBindings == 0 )
  1571. {
  1572. TRACE( TL_N, TM_Pr, ("PrBroadcast($%x): No bindings available",pPacket) );
  1573. TRACE( TL_N, TM_Pr, ("-PrBroadcast($%x)=$%x",pPacket,status) );
  1574. return status;
  1575. }
  1576. NdisAcquireSpinLock( &gl_lockProtocol );
  1577. do
  1578. {
  1579. LIST_ENTRY* pHead = NULL;
  1580. //
  1581. // We have to do the same check again, as the first one is to make sure
  1582. // we have allocated the spin lock, and this one is to make sure after we acquired
  1583. // it, we still have some bindings
  1584. //
  1585. if ( gl_ulNumBindings == 0 )
  1586. {
  1587. TRACE( TL_N, TM_Pr, ("PrBroadcast($%x): No bindings available",pPacket) );
  1588. break;
  1589. }
  1590. //
  1591. // Get the head of the bindings list
  1592. //
  1593. pHead = gl_linkBindings.Flink;
  1594. //
  1595. // Traverse the bindings list and schedule a PrSend() with a clone of pNdisPacket
  1596. //
  1597. while ( pHead != &gl_linkBindings )
  1598. {
  1599. PPPOE_PACKET* pClone = NULL;
  1600. BINDING* pBinding = (BINDING*) CONTAINING_RECORD( pHead,
  1601. BINDING,
  1602. linkBindings );
  1603. //
  1604. // Do not schedule a send if binding is not bound
  1605. //
  1606. if ( pBinding->stateBinding != BN_stateBound )
  1607. {
  1608. pHead = pHead->Flink;
  1609. continue;
  1610. }
  1611. //
  1612. // Make a clone of the actual packet
  1613. //
  1614. pClone = PacketMakeClone( pPacket );
  1615. if ( pClone != NULL )
  1616. {
  1617. WORKITEM* pWorkItem = NULL;
  1618. PVOID Args[4];
  1619. //
  1620. // Set the source address on the packet to be sent
  1621. //
  1622. PacketSetSrcAddr( pClone, pBinding->LocalAddress );
  1623. //
  1624. // Set the arguements array
  1625. //
  1626. Args[0] = (PVOID) pBinding;
  1627. Args[1] = (PVOID) pClone;
  1628. //
  1629. // Allocate work item
  1630. //
  1631. pWorkItem = AllocWorkItem( &gl_llistWorkItems,
  1632. ExecBindingWorkItem,
  1633. NULL,
  1634. Args,
  1635. BWT_workPrSend );
  1636. if ( pWorkItem != NULL )
  1637. {
  1638. ReferenceBinding( pBinding, TRUE );
  1639. ReferencePacket( pClone );
  1640. //
  1641. // Schedule the send operation
  1642. //
  1643. ScheduleWorkItem( pWorkItem );
  1644. status = NDIS_STATUS_SUCCESS;
  1645. }
  1646. //
  1647. // We can free the packet since we have put a reference for scheduling it
  1648. //
  1649. PacketFree( pClone );
  1650. }
  1651. pHead = pHead->Flink;
  1652. }
  1653. } while ( FALSE );
  1654. NdisReleaseSpinLock( &gl_lockProtocol );
  1655. TRACE( TL_N, TM_Pr, ("-PrBroadcast($%x)=$%x",pPacket,status) );
  1656. return status;
  1657. }
  1658. VOID
  1659. ExecBindingWorkItem(
  1660. IN PVOID Args[4],
  1661. IN UINT workType
  1662. )
  1663. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1664. Functional Description:
  1665. This function executes the scheduled work items for the binding.
  1666. Parameters:
  1667. Args:
  1668. An array of length 4 keeping PVOIDs
  1669. workType:
  1670. Indicates the type of the work to be executed.
  1671. We use this to understand what we should do in this function.
  1672. Return Values:
  1673. None
  1674. ---------------------------------------------------------------------------*/
  1675. {
  1676. TRACE( TL_V, TM_Pr, ("+ExecBindingWorkItem") );
  1677. switch( workType )
  1678. {
  1679. case BWT_workPrStartBinds:
  1680. //
  1681. // Tell NDIS to bind our protocol to any interested miniports.
  1682. // If we need to start an outgoing call then kick that off too.
  1683. //
  1684. {
  1685. ULONG_PTR FilterChangeRequest = (ULONG_PTR) Args[0];
  1686. BOOLEAN fSetFilters = (BOOLEAN) ( FilterChangeRequest != BN_ResetFiltersForCloseLine );
  1687. switch ( FilterChangeRequest )
  1688. {
  1689. case BN_SetFiltersForMediaDetection:
  1690. {
  1691. //
  1692. // This is a set default media detection request so complete it
  1693. //
  1694. LINE* pLine = (LINE*) Args[1];
  1695. PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION pRequest = (PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION) Args[2];
  1696. PrReEnumerateBindings();
  1697. ChangePacketFiltersForAdapters( fSetFilters );
  1698. TpSetDefaultMediaDetectionComplete( pLine, pRequest );
  1699. }
  1700. break;
  1701. case BN_SetFiltersForMakeCall:
  1702. {
  1703. //
  1704. // This is a make call request so schedule the real work item and complete it
  1705. //
  1706. CALL* pCall = (CALL*) Args[1];
  1707. PNDIS_TAPI_MAKE_CALL pRequest = (PNDIS_TAPI_MAKE_CALL) Args[2];
  1708. WORKITEM* pWorkItem = (WORKITEM*) Args[3];
  1709. PrReEnumerateBindings();
  1710. ChangePacketFiltersForAdapters( fSetFilters );
  1711. TpMakeCallComplete( pCall, pRequest );
  1712. ScheduleWorkItem( pWorkItem );
  1713. }
  1714. break;
  1715. case BN_ResetFiltersForCloseLine:
  1716. {
  1717. //
  1718. // This is a close line request so dereference it
  1719. //
  1720. LINE* pLine = (LINE*) Args[1];
  1721. ChangePacketFiltersForAdapters( fSetFilters );
  1722. DereferenceLine( pLine );
  1723. }
  1724. break;
  1725. default:
  1726. {
  1727. //
  1728. // Unknown request
  1729. //
  1730. ASSERT( FALSE );
  1731. }
  1732. break;
  1733. }
  1734. }
  1735. break;
  1736. case BWT_workPrSend:
  1737. //
  1738. // Scheduled from PrBroadcast() to send PADI packets
  1739. //
  1740. {
  1741. NDIS_STATUS status;
  1742. status = PrSend( ( BINDING*) Args[0], (PPPOE_PACKET*) Args[1] );
  1743. TRACE( TL_N, TM_Pr, ("ExecBindingWorkItem: BWT_workSend=$%x",status) );
  1744. }
  1745. break;
  1746. case BWT_workPrReceiveComplete:
  1747. //
  1748. // Scheduled from PrReceivePacket() if receive loop on the specific binding is not running
  1749. //
  1750. {
  1751. BINDING* pBinding = ( ( BINDING*) Args[0] );
  1752. PrReceiveComplete( pBinding );
  1753. DereferenceBinding( pBinding );
  1754. }
  1755. break;
  1756. default:
  1757. break;
  1758. }
  1759. TRACE( TL_V, TM_Pr, ("-ExecBindingWorkItem") );
  1760. }
  1761. NDIS_STATUS
  1762. PrReceive(
  1763. IN NDIS_HANDLE ProtocolBindingContext,
  1764. IN NDIS_HANDLE MacReceiveContext,
  1765. IN PVOID HeaderBuffer,
  1766. IN UINT HeaderBufferSize,
  1767. IN PVOID LookaheadBuffer,
  1768. IN UINT LookaheadBufferSize,
  1769. IN UINT PacketSize
  1770. )
  1771. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1772. Functional Description:
  1773. This function will be called by NDIS to indicate the receipt of a new packet.
  1774. We check if packet is a PPPoE frame, and if it is not, we just return.
  1775. However if it is then we determine if we have received the whole packet or
  1776. not. If we have received the whole packet, we call PrTransferDataComplete()
  1777. manually, otherwise we initiate the data transfer and return. When transfer
  1778. is completed PrDataTransferComplete() will be called by NDIS.
  1779. Parameters:
  1780. ProtocolBindingContext:
  1781. Specifies the handle to a protocol-allocated context area in which the
  1782. protocol driver maintains per-binding runtime state. The driver supplied this
  1783. handle when it called NdisOpenAdapter.
  1784. MacReceiveContext:
  1785. Specifies a context handle that the underlying NIC driver associates with the
  1786. packet received from the network. This handle is opaque to the protocol,
  1787. reserved for use by the underlying driver that made the indication, and a
  1788. required parameter to NdisTransferData.
  1789. HeaderBuffer:
  1790. Points to the base virtual address of a range containing the buffered packet
  1791. header. The address is valid only within the current call to ProtocolReceive.
  1792. HeaderBufferSize:
  1793. Specifies the number of bytes in the packet header.
  1794. LookAheadBuffer:
  1795. Points to the base virtual address of a range that contains
  1796. LookaheadBufferSize bytes of buffered network packet data. This address is
  1797. valid only within the current call to ProtocolReceive.
  1798. LookaheadBufferSize:
  1799. Specifies the number of bytes of network packet data in the lookahead buffer.
  1800. The indicating driver ensures this number is at least as large as the size it
  1801. returned for the protocol's preceding call to NdisRequest with
  1802. OID_GEN_CURRENT_LOOKAHEAD or the size of the packet, whichever is less.
  1803. If PacketSize is less than or equal to the given LookaheadBufferSize, the
  1804. kahead buffer contains the entire packet. If the underlying driver made
  1805. the indication with NdisMIndicateReceivePacket, the lookahead buffer always
  1806. contains a full network packet.
  1807. PacketSize:
  1808. Specifies the size, in bytes, of the network packet data. The length of the
  1809. packet does not include the length of the header.
  1810. ProtocolReceive determines whether the protocol must call NdisTransferData by
  1811. comparing this parameter to the given LookaheadBufferSize.
  1812. Return Values:
  1813. NDIS_STATUS_NOT_ACCEPTED:
  1814. The protocol has no use for the indicated packet, that is, it has no current
  1815. clients interested in the indicated network data.
  1816. Returning this status quickly for rejected packets yields higher performance
  1817. for the protocol and the highest possible network I/O throughput for the
  1818. system as a whole.
  1819. NDIS_STATUS_SUCCESS:
  1820. ProtocolReceive has processed the header information and accepted the packet,
  1821. that is, it has copied the indicated network data from the header and
  1822. lookahead buffers and, possibly, called NdisTransferData to retrieve the
  1823. remaining data if less than a full network packet was indicated.
  1824. ---------------------------------------------------------------------------*/
  1825. {
  1826. NDIS_STATUS status = NDIS_STATUS_NOT_ACCEPTED;
  1827. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  1828. PPPOE_PACKET *pPacket = NULL;
  1829. ASSERT( VALIDATE_BINDING( pBinding ) );
  1830. TRACE( TL_V, TM_Pr, ("+PrReceive") );
  1831. //
  1832. // Check if the packet is a PPPoE frame or not
  1833. //
  1834. if ( !PacketFastIsPPPoE( (CHAR*) HeaderBuffer, HeaderBufferSize ) )
  1835. {
  1836. TRACE( TL_V, TM_Pr, ("-PrReceive=$%x",status) );
  1837. return status;
  1838. }
  1839. //
  1840. // Make sure packet is not too large
  1841. //
  1842. if ( HeaderBufferSize + PacketSize > PPPOE_PACKET_BUFFER_SIZE )
  1843. {
  1844. TRACE( TL_A, TM_Pr, ("PrReceive: Packet too large" ) );
  1845. TRACE( TL_V, TM_Pr, ("-PrReceive=$%x",status) );
  1846. return status;
  1847. }
  1848. //
  1849. // Let's create our PPPoE packet to keep the copy of the received packet
  1850. //
  1851. pPacket = PacketCreateSimple();
  1852. if ( pPacket == NULL )
  1853. {
  1854. TRACE( TL_A, TM_Pr, ("PrReceive: Could not allocate context to copy the packet") );
  1855. TRACE( TL_V, TM_Pr, ("-PrReceive=$%x",status) );
  1856. return status;
  1857. }
  1858. //
  1859. // See if the packet indicated is complete, or not.
  1860. // If it is not the complete packet then we should call NdisTransferData(),
  1861. // otherwise we can do the copy here
  1862. //
  1863. if ( LookaheadBufferSize >= PacketSize )
  1864. {
  1865. TRACE( TL_V, TM_Pr, ("PrReceive: Complete packet indicated, transferring data") );
  1866. //
  1867. // First copy the header portion
  1868. //
  1869. NdisMoveMemory( pPacket->pHeader,
  1870. HeaderBuffer,
  1871. HeaderBufferSize );
  1872. //
  1873. // Packet is complete, so let's copy whole data to our own copy
  1874. //
  1875. TdiCopyLookaheadData( pPacket->pHeader + HeaderBufferSize,
  1876. (CHAR*) LookaheadBuffer,
  1877. (ULONG) PacketSize,
  1878. (ULONG) 0 );
  1879. //
  1880. // Let's call PrTransferDataComplete() manually now.
  1881. //
  1882. PrTransferDataComplete( pBinding,
  1883. pPacket->pNdisPacket,
  1884. NDIS_STATUS_SUCCESS,
  1885. PacketSize );
  1886. }
  1887. else
  1888. {
  1889. UINT nBytesTransferred = 0;
  1890. TRACE( TL_V, TM_Pr, ("PrReceive: Partial packet indicated, transferring data") );
  1891. //
  1892. // Mark the packet for incomplete indication
  1893. //
  1894. pPacket->ulFlags |= PCBF_PacketIndicatedIncomplete;
  1895. //
  1896. // First copy the header to the end of the packet
  1897. //
  1898. // Note that HeaderBufferSize MUST be equal to ETHERNET_HEADER_LENGTH and
  1899. // this is ensured in PacketIsFastPPPoE().
  1900. //
  1901. NdisMoveMemory( pPacket->pHeader + (PPPOE_PACKET_BUFFER_SIZE - ETHERNET_HEADER_LENGTH),
  1902. HeaderBuffer,
  1903. HeaderBufferSize );
  1904. //
  1905. // Lookahead buffer does not contain all the packet, we should call NdisTransferData()
  1906. // to receive the full packet
  1907. //
  1908. NdisTransferData( &status,
  1909. pBinding->NdisBindingHandle,
  1910. MacReceiveContext,
  1911. 0,
  1912. PacketSize,
  1913. pPacket->pNdisPacket,
  1914. &nBytesTransferred );
  1915. if ( status != NDIS_STATUS_PENDING )
  1916. {
  1917. //
  1918. // Call PrTransferDataComplete() manually if transfer data completed
  1919. // synchronously
  1920. //
  1921. PrTransferDataComplete( pBinding,
  1922. pPacket->pNdisPacket,
  1923. status,
  1924. nBytesTransferred );
  1925. }
  1926. }
  1927. TRACE( TL_V, TM_Pr, ("-PrReceive=$%x",status) );
  1928. return NDIS_STATUS_SUCCESS;
  1929. }
  1930. VOID
  1931. PrTransferDataComplete(
  1932. IN NDIS_HANDLE ProtocolBindingContext,
  1933. IN PNDIS_PACKET Packet,
  1934. IN NDIS_STATUS Status,
  1935. IN UINT BytesTransferred
  1936. )
  1937. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1938. Functional Description:
  1939. This function is called to post process a received packet when whole data
  1940. is copied into the packet context.
  1941. It can be called by NDIS, or it can be called manually from inside PrReceive()
  1942. if the indicated packet is a whole packet.
  1943. If the status is succesfull, it will insert the packet to the end of the
  1944. bindings received packets queue, otherwise it will clean up our copy of
  1945. NDIS packet and return.
  1946. Parameters:
  1947. ProtocolBindingContext
  1948. Specifies the handle to a protocol-allocated context area in which the
  1949. protocol driver maintains per-binding runtime state. The driver supplied this
  1950. handle when it called NdisOpenAdapter.
  1951. Packet
  1952. Points to the protocol-allocated packet descriptor the driver originally
  1953. passed to NdisTransferData.
  1954. Status
  1955. Specifies the final status of the transfer-data operation.
  1956. BytesTransferred
  1957. Specifies the number of bytes of data that the NIC driver transferred into
  1958. the buffers mapped by buffer descriptors chained to the packet descriptor at
  1959. Packet. The protocol uses this value to determine whether the miniport
  1960. supplied all the requested data for the originally indicated network packet.
  1961. Return Values:
  1962. None
  1963. ---------------------------------------------------------------------------*/
  1964. {
  1965. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  1966. PPPOE_PACKET* pPacket = NULL;
  1967. ASSERT( VALIDATE_BINDING( pBinding ) );
  1968. TRACE( TL_V, TM_Pr, ("+PrTransferDataComplete") );
  1969. do
  1970. {
  1971. //
  1972. // Retrieve the related PPPoE packet first
  1973. //
  1974. pPacket = PacketGetRelatedPppoePacket( Packet );
  1975. //
  1976. // Make sure the data transfer suceeded
  1977. //
  1978. if ( Status != NDIS_STATUS_SUCCESS )
  1979. {
  1980. //
  1981. // Transfer of data to our copy of packet failed, so clean up our packet
  1982. //
  1983. PacketFree( pPacket );
  1984. break;
  1985. }
  1986. //
  1987. // Rearrange the data in the packet if the packet was indicated incomplete
  1988. //
  1989. if ( pPacket->ulFlags & PCBF_PacketIndicatedIncomplete )
  1990. {
  1991. CHAR tempHeader[ ETHERNET_HEADER_LENGTH ];
  1992. CHAR* srcPos = pPacket->pHeader + BytesTransferred;
  1993. //
  1994. // Make a copy of the header stored at the end of the packet
  1995. //
  1996. NdisMoveMemory( tempHeader,
  1997. pPacket->pHeader + (PPPOE_PACKET_BUFFER_SIZE - ETHERNET_HEADER_LENGTH),
  1998. ETHERNET_HEADER_LENGTH );
  1999. //
  2000. // Move the contents of the packet appropriately to make room
  2001. // for the header (slip contents by ETHERNET_HEADER_LENGTH)
  2002. //
  2003. while ( BytesTransferred > 0 )
  2004. {
  2005. #define TEMP_BUFFER_SIZE 100
  2006. CHAR tempBuffer[ TEMP_BUFFER_SIZE ];
  2007. UINT size = (BytesTransferred < TEMP_BUFFER_SIZE) ?
  2008. BytesTransferred :
  2009. TEMP_BUFFER_SIZE;
  2010. srcPos -= size;
  2011. NdisMoveMemory( tempBuffer,
  2012. srcPos,
  2013. size );
  2014. NdisMoveMemory( srcPos + ETHERNET_HEADER_LENGTH,
  2015. tempBuffer,
  2016. size );
  2017. BytesTransferred -= size;
  2018. }
  2019. //
  2020. // Copy the header to the correct position in the packet
  2021. //
  2022. NdisMoveMemory( pPacket->pHeader,
  2023. tempHeader,
  2024. ETHERNET_HEADER_LENGTH );
  2025. //
  2026. // Clear the incomplete indication flag
  2027. //
  2028. pPacket->ulFlags &= ~PCBF_PacketIndicatedIncomplete;
  2029. }
  2030. //
  2031. // Data transfer succeeded, insert into our queue of received packets, so that it will
  2032. // be consumed by a call to our PrReceiveComplete() function
  2033. //
  2034. NdisInterlockedInsertTailList( &pBinding->linkPackets,
  2035. &pPacket->linkPackets,
  2036. &pBinding->lockBinding );
  2037. } while ( FALSE );
  2038. TRACE( TL_V, TM_Pr, ("-PrTransferDataComplete=$%x",Status) );
  2039. }
  2040. VOID
  2041. PrReceiveComplete(
  2042. IN NDIS_HANDLE ProtocolBindingContext
  2043. )
  2044. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2045. Functional Description:
  2046. This function will be called to perform post processing of received packets
  2047. indicated previously. Underlying NIC will call it when it is not busy.
  2048. We need to serialize the indication of packets to the miniport, since this
  2049. is of vital importance for PPP frames. To achieve this, we use the lock
  2050. protected flag of binding (fRecvLoopRunning).
  2051. When this function is called, it will return immediately if this flag is
  2052. already set.
  2053. If flag is not set, then it will set this flag and start processing packets
  2054. from the received queue, and indicate all packets to miniport one by one
  2055. untill all the queue is drained. Then it will reset the flag and return.
  2056. Parameters:
  2057. ProtocolBindingContext
  2058. Specifies the handle to a protocol-allocated context area in which the
  2059. protocol driver maintains per-binding runtime state. The driver supplied this
  2060. handle when it called NdisOpenAdapter.
  2061. Return Values:
  2062. None
  2063. ---------------------------------------------------------------------------*/
  2064. {
  2065. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  2066. LIST_ENTRY* pLink = NULL;
  2067. PPPOE_PACKET* pPacket = NULL;
  2068. BOOLEAN fStartRecvLoop = FALSE;
  2069. ASSERT( VALIDATE_BINDING( pBinding ) );
  2070. TRACE( TL_V, TM_Pr, ("+PrReceiveComplete") );
  2071. NdisAcquireSpinLock( &pBinding->lockBinding );
  2072. //
  2073. // See if recv loop is already running
  2074. //
  2075. if ( !pBinding->fRecvLoopRunning )
  2076. {
  2077. //
  2078. // Indicate the recv loop has started to run
  2079. //
  2080. pBinding->fRecvLoopRunning = TRUE;
  2081. //
  2082. // Now consume these packet's
  2083. //
  2084. while ( !IsListEmpty( &pBinding->linkPackets ) )
  2085. {
  2086. pLink = RemoveHeadList( &pBinding->linkPackets );
  2087. NdisReleaseSpinLock( &pBinding->lockBinding );
  2088. pPacket = (PPPOE_PACKET*) CONTAINING_RECORD( pLink, PPPOE_PACKET, linkPackets );
  2089. InitializeListHead( &pPacket->linkPackets );
  2090. if ( PacketInitializeFromReceived( pPacket ) == NDIS_STATUS_SUCCESS )
  2091. {
  2092. //
  2093. // Indicate the packet to miniport
  2094. //
  2095. MpRecvPacket( pBinding, pPacket );
  2096. }
  2097. //
  2098. // Free the packet since we are done with it
  2099. //
  2100. PacketFree( pPacket );
  2101. //
  2102. // Acquire the lock again
  2103. //
  2104. NdisAcquireSpinLock( &pBinding->lockBinding );
  2105. }
  2106. //
  2107. // The queue is drained, so stop the recv loop
  2108. //
  2109. pBinding->fRecvLoopRunning = FALSE;
  2110. }
  2111. NdisReleaseSpinLock( &pBinding->lockBinding );
  2112. TRACE( TL_V, TM_Pr, ("-PrReceiveComplete") );
  2113. }
  2114. ULONG
  2115. PrQueryMaxFrameSize()
  2116. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2117. Functional Description:
  2118. This function will be called by the miniport to retrieve the current minimum
  2119. of max frame sizes of the bindings, since this is the value passed to
  2120. NDISWAN in an OID_WAN_GET_INFO query as the MaxFrameSize.
  2121. We adjust the max frame size considering the PPPoE and Ethernet headers.
  2122. Parameters:
  2123. None
  2124. Return Values:
  2125. Minimum of max frame sizes
  2126. ---------------------------------------------------------------------------*/
  2127. {
  2128. ULONG ulMaxFrameSize = gl_ulMaxFrameSize;
  2129. if ( ulMaxFrameSize == 0 )
  2130. {
  2131. ulMaxFrameSize = PACKET_PPP_PAYLOAD_MAX_LENGTH;
  2132. }
  2133. else
  2134. {
  2135. ulMaxFrameSize = ulMaxFrameSize - PPPOE_PACKET_HEADER_LENGTH;
  2136. }
  2137. return ulMaxFrameSize;
  2138. }
  2139. NDIS_STATUS
  2140. PrSend(
  2141. IN BINDING* pBinding,
  2142. IN PPPOE_PACKET* pPacket
  2143. )
  2144. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2145. Functional Description:
  2146. This function will be called to transmit a PPPoE packet.
  2147. The caller must have referenced the packet and binding before calling this
  2148. function. Then the caller can forget about the references, everything will
  2149. be handled by the protocol. If send operation complets synchrnously then
  2150. the references are removed in the function, otherwise PrSendComplete()
  2151. will be called and references will be removed then.
  2152. Parameters:
  2153. pBinding _ Binding to send the packet over.
  2154. pPacket _ PPPoE packet to be transmitted.
  2155. Return Values:
  2156. NDIS_STATUS_SUCCESS
  2157. NDIS_STATUS_PENDING
  2158. NDIS_STATUS_FAILURE
  2159. NDIS_STATUS_XXXXXXX
  2160. ---------------------------------------------------------------------------*/
  2161. {
  2162. NDIS_STATUS status = NDIS_STATUS_FAILURE;
  2163. ASSERT( VALIDATE_BINDING( pBinding ) );
  2164. TRACE( TL_V, TM_Pr, ("+PrSend") );
  2165. //
  2166. // Make sure we are bound before sending the packet.
  2167. //
  2168. // Note: We do not need to acquire the lock here since NDIS should prevent
  2169. // a crash even if we are unbound, and we already have a reference
  2170. // on the binding, so this is not a really strict check..
  2171. //
  2172. if ( pBinding->stateBinding == BN_stateBound )
  2173. {
  2174. //
  2175. // Make sure we are sending a packet not exceeding the max frame size
  2176. // of the underlying NIC
  2177. //
  2178. if ( pBinding->ulMaxFrameSize + ETHERNET_HEADER_LENGTH >=
  2179. (ULONG) ( PacketGetLength( pPacket ) + PPPOE_PACKET_HEADER_LENGTH ) )
  2180. {
  2181. NdisSend( &status,
  2182. pBinding->NdisBindingHandle,
  2183. PacketGetNdisPacket( pPacket ) );
  2184. }
  2185. }
  2186. if ( status != NDIS_STATUS_PENDING )
  2187. {
  2188. //
  2189. // NdisSend() completed synchronously so call PrSendComplete()
  2190. // manually here.
  2191. //
  2192. PrSendComplete( pBinding, PacketGetNdisPacket( pPacket ), status );
  2193. }
  2194. TRACE( TL_V, TM_Pr, ("-PrSend=$%x",status) );
  2195. return status;
  2196. }
  2197. VOID
  2198. PrStatus(
  2199. IN NDIS_HANDLE ProtocolBindingContext,
  2200. IN NDIS_STATUS GeneralStatus,
  2201. IN PVOID StatusBuffer,
  2202. IN UINT StatusBufferSize
  2203. )
  2204. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2205. Functional Description:
  2206. ProtocolStatus is a required driver function that handles status-change
  2207. notifications raised by an underlying connectionless NIC driver or by NDIS.
  2208. In this driver, we only use this function to receive Media disconnect
  2209. notifications to disconnect the active calls on that NIC.
  2210. Parameters:
  2211. ProtocolBindingContext:
  2212. Specifies the handle to a protocol-allocated context area in which the
  2213. protocol driver maintains per-binding runtime state. The driver supplied this
  2214. handle when it called NdisOpenAdapter.
  2215. GeneralStatus:
  2216. Indicates the general status code, either raised by NDIS or propagated from
  2217. the underlying driver's call to NdisMIndicateStatus.
  2218. StatusBuffer:
  2219. Points to a buffer containing medium-specific data that depends on the value
  2220. of GeneralStatus.
  2221. For example, if the GeneralStatus argument is NDIS_STATUS_RING_STATUS, this
  2222. parameter points to a ULONG-sized bitmask and StatusBufferSize is four. As
  2223. another example, if GeneralStatus is NDIS_STATUS_WAN_LINE_UP, this parameter
  2224. points to an NDIS_WAN_LINE_UP structure and StatusBufferSize is sizeof(
  2225. NDIS_STATUS_WAN_LINE_UP).
  2226. For some NDIS_STATUS_XXX values, this pointer is NULL and StatusBufferSize is
  2227. set to zero.
  2228. StatusBufferSize:
  2229. Specifies the number of bytes at StatusBuffer.
  2230. Return Values:
  2231. None
  2232. ---------------------------------------------------------------------------*/
  2233. {
  2234. BINDING* pBinding = (BINDING*) ProtocolBindingContext;
  2235. ASSERT( VALIDATE_BINDING( pBinding ) );
  2236. TRACE( TL_N, TM_Pr, ("+PrStatus") );
  2237. switch ( GeneralStatus )
  2238. {
  2239. case NDIS_STATUS_MEDIA_DISCONNECT:
  2240. //
  2241. // If the underlying media is disconnected, notify miniport of this event.
  2242. // It will appear to the miniport as if the NIC is removed, so it will drop all the
  2243. // active calls
  2244. //
  2245. TRACE( TL_N, TM_Pr, ("PrStatus: Notifying miniport of media disconnect event") );
  2246. MpNotifyBindingRemoval( pBinding );
  2247. break;
  2248. }
  2249. TRACE( TL_N, TM_Pr, ("-PrStatus") );
  2250. }
  2251. NDIS_STATUS
  2252. PrPnPEvent(
  2253. IN NDIS_HANDLE hProtocolBindingContext,
  2254. IN PNET_PNP_EVENT pNetPnPEvent
  2255. )
  2256. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2257. Functional Description:
  2258. ProtocolPnPEvent is a required function in any protocol driver to support
  2259. Plug and Play and/or Power Management. NDIS calls ProtocolPnPEvent to
  2260. indicate a Plug and Play event or a Power Management event to a protocol
  2261. bound to a NIC.
  2262. NDIS calls ProtocolPnPEvent to notify a protocol bound to a network NIC that
  2263. the operating system has issued a Plug and Play or Power Management event to
  2264. the device object representing the NIC. NDIS calls the ProtocolPnPEvent
  2265. function of each protocol bound to the NIC.
  2266. The NET_PNP_EVENT structure passed to ProtocolPnPEvent describes the Plug and
  2267. Play or Power Management event. ProtocolPnPEvent interprets two basic pieces
  2268. of information in the NET_PNP_EVENT structure:
  2269. A NetEvent code that describes the Plug and Play or Power Management event.
  2270. Event-specific information (for example, for a NetEventSetPower, the device
  2271. power state to which the device is transitioning).
  2272. The protocol should save the NetPnPEvent pointer. This pointer is a required
  2273. input parameter to NdisCompletePnPEvent, which the protocol must subsequently
  2274. call if ProtocolPnPEvent returns NDIS_STATUS_PENDING.
  2275. Parameters
  2276. hProtocolBindingContext:
  2277. Specifies the handle to a protocol-allocated context area in which this
  2278. driver maintains per-binding runtime state. The protocol supplied this handle
  2279. when it called NdisOpenAdapter. A NetEventXxx indicated on a NULL
  2280. ProtocolBindingContext pertains to all network bindings. NetEventBindList and
  2281. NetEventBindsComplete are always indicated on a NULL ProtocolBindingContext.
  2282. NetEventReconfigure can be indicated on a particular ProtocolBindingContext
  2283. or a NULL ProtocolBindingContext.
  2284. pNetPnPEvent:
  2285. Points to a NET_PNP_EVENT structure, which describes the Plug and Play event
  2286. or Power Management event being indicated to the protocol driver.
  2287. Return Value
  2288. NDIS_STATUS_SUCCESS:
  2289. The protocol successfully handled the indicated Plug and Play or Power
  2290. Management event. The meaning of this status code depends on the NetEvent
  2291. code in the buffered NET_PNP_EVENT structure at NetPnPEvent.
  2292. NDIS_STATUS_PENDING
  2293. The protocol will return its response to the indicated event asynchronously
  2294. with a call to NdisCompletePnPEvent.
  2295. NDIS_STATUS_RESOURCES
  2296. The protocol could not obtain the necessary system resources to satisfy the
  2297. indicated Plug and Play or Power Management event.
  2298. NDIS_STATUS_NOT_SUPPORTED
  2299. A legacy (non-PnP-aware) protocol can return this status in response to a
  2300. NetEventSetPower to indicate that NDIS should unbind the it from the NIC.
  2301. NDIS_STATUS_FAILURE
  2302. The protocol failed the indicated Plug and Play or Power Management event.
  2303. The meaning of this status code depends on the NetEvent code in the buffered
  2304. NET_PNP_EVENT structure at NetPnPEvent.
  2305. ---------------------------------------------------------------------------*/
  2306. {
  2307. NDIS_STATUS status = NDIS_STATUS_NOT_SUPPORTED;
  2308. BINDING *pBinding = (BINDING*) hProtocolBindingContext;
  2309. TRACE( TL_N, TM_Pr, ("+PrPnpEvent") );
  2310. switch ( pNetPnPEvent->NetEvent )
  2311. {
  2312. case NetEventQueryPower:
  2313. {
  2314. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventQueryPower") );
  2315. status = NDIS_STATUS_SUCCESS;
  2316. break;
  2317. }
  2318. case NetEventQueryRemoveDevice:
  2319. {
  2320. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventQueryRemoveDevice") );
  2321. status = NDIS_STATUS_SUCCESS;
  2322. break;
  2323. }
  2324. case NetEventCancelRemoveDevice:
  2325. {
  2326. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventCancelRemoveDevice") );
  2327. status = NDIS_STATUS_SUCCESS;
  2328. break;
  2329. }
  2330. case NetEventReconfigure:
  2331. {
  2332. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventReconfigure") );
  2333. status = NDIS_STATUS_SUCCESS;
  2334. break;
  2335. }
  2336. case NetEventBindsComplete:
  2337. {
  2338. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventBindsComplete") );
  2339. status = NDIS_STATUS_SUCCESS;
  2340. break;
  2341. }
  2342. case NetEventPnPCapabilities:
  2343. {
  2344. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventPnPCapabilities") );
  2345. status = NDIS_STATUS_SUCCESS;
  2346. break;
  2347. }
  2348. case NetEventBindList:
  2349. {
  2350. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventBindList") );
  2351. status = NDIS_STATUS_SUCCESS;
  2352. break;
  2353. }
  2354. case NetEventSetPower:
  2355. {
  2356. BOOLEAN fWakeUp = FALSE;
  2357. BOOLEAN fSleep = FALSE;
  2358. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventSetPower") );
  2359. NdisAcquireSpinLock( &pBinding->lockBinding );
  2360. if ( *( (NDIS_DEVICE_POWER_STATE*) pNetPnPEvent->Buffer ) == NdisDeviceStateD0 )
  2361. {
  2362. if ( pBinding->stateBinding == BN_stateSleeping )
  2363. {
  2364. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventSetPower - Wake up request") );
  2365. fWakeUp = TRUE;
  2366. pBinding->stateBinding = BN_stateBound;
  2367. }
  2368. }
  2369. else if ( *( (NDIS_DEVICE_POWER_STATE*) pNetPnPEvent->Buffer ) > NdisDeviceStateD0 )
  2370. {
  2371. if ( pBinding->stateBinding == BN_stateBound )
  2372. {
  2373. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventSetPower - Sleep request") );
  2374. fSleep = TRUE;
  2375. pBinding->stateBinding = BN_stateSleepPending;
  2376. }
  2377. }
  2378. NdisReleaseSpinLock( &pBinding->lockBinding );
  2379. if ( fSleep )
  2380. {
  2381. //
  2382. // Since this NIC is going to sleep, drop all the calls on it
  2383. //
  2384. MpNotifyBindingRemoval( pBinding );
  2385. //
  2386. // Wait for pending operations to be completed
  2387. //
  2388. TRACE( TL_N, TM_Pr, ("PrPnpEvent: NetEventSetPower - Waiting for pending operations to be completed") );
  2389. NdisAcquireSpinLock( &pBinding->lockBinding );
  2390. while ( pBinding->lRef > 1 )
  2391. {
  2392. NdisReleaseSpinLock( &pBinding->lockBinding );
  2393. NdisMSleep( 10000 );
  2394. NdisAcquireSpinLock( &pBinding->lockBinding );
  2395. }
  2396. pBinding->stateBinding = BN_stateSleeping;
  2397. NdisReleaseSpinLock( &pBinding->lockBinding );
  2398. }
  2399. status = NDIS_STATUS_SUCCESS;
  2400. break;
  2401. }
  2402. default:
  2403. {
  2404. TRACE( TL_N, TM_Pr, ("PrPnpEvent: Unknown Event - %x", pNetPnPEvent->NetEvent) );
  2405. status = NDIS_STATUS_NOT_SUPPORTED;
  2406. break;
  2407. }
  2408. }
  2409. TRACE( TL_N, TM_Pr, ("-PrPnpEvent=$%x", status) );
  2410. return status;
  2411. }
  2412. VOID
  2413. PrReEnumerateBindings(
  2414. VOID
  2415. )
  2416. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2417. Functional Description:
  2418. PrReEnumerateBindings causes NDIS to send bind notifications to the pppoe
  2419. protocol section for each miniport that it needs to bind to. It is called
  2420. when a tapi client is interested in either making an outgoing call or
  2421. listening for an incoming call. It is expected that when this function
  2422. returns all of the bindings between the protocol and underlying miniports
  2423. will be finished!
  2424. Parameters
  2425. None
  2426. Return Value
  2427. None
  2428. ---------------------------------------------------------------------------*/
  2429. {
  2430. TRACE( TL_N, TM_Pr, ("+PrReEnumerateBindings") );
  2431. NdisAcquireSpinLock( &gl_lockProtocol );
  2432. gl_fBindProtocol = TRUE;
  2433. NdisReleaseSpinLock( &gl_lockProtocol );
  2434. NdisReEnumerateProtocolBindings(gl_hNdisProtocolHandle);
  2435. TRACE( TL_N, TM_Pr, ("-PrReEnumerateBindings") );
  2436. }
  2437. VOID
  2438. ChangePacketFiltersForAdapters(
  2439. BOOLEAN fSet
  2440. )
  2441. {
  2442. LIST_ENTRY* pLink = NULL;
  2443. TRACE( TL_N, TM_Pr, ("+ChangePacketFiltersForAdapters") );
  2444. NdisAcquireSpinLock( &gl_lockProtocol );
  2445. gl_fSetPacketFiltersAtBind = fSet;
  2446. pLink = gl_linkBindings.Flink;
  2447. //
  2448. // See if we have any bindings
  2449. //
  2450. if ( pLink != &gl_linkBindings )
  2451. {
  2452. BINDING* pBinding = NULL;
  2453. TRACE( TL_N, TM_Pr, ("ChangePacketFiltersForAdapters: %s packet filters", ( fSet ) ? "Setting" : "Resetting") );
  2454. //
  2455. // First reference the bindings in the list and mark their
  2456. // BNBF_ChangePacketFilterInProgress bit
  2457. //
  2458. while ( pLink != &gl_linkBindings )
  2459. {
  2460. //
  2461. // We have at least one binding, so walk thru the list
  2462. // and reference them
  2463. //
  2464. pBinding = ((BINDING*) CONTAINING_RECORD( pLink, BINDING, linkBindings ));
  2465. NdisAcquireSpinLock( &pBinding->lockBinding );
  2466. if ( pBinding->stateBinding == BN_stateBound )
  2467. {
  2468. //
  2469. // If the state of the binding is BN_stateBound then
  2470. // set the BNBF_PacketFilterChangeInProgress bit,
  2471. // reference
  2472. // the binding.
  2473. //
  2474. pBinding->ulBindingFlags |= BNBF_PacketFilterChangeInProgress;
  2475. ReferenceBinding( pBinding, FALSE );
  2476. }
  2477. NdisReleaseSpinLock( &pBinding->lockBinding );
  2478. //
  2479. // Iterate to the next binding
  2480. //
  2481. pLink = pLink->Flink;
  2482. }
  2483. //
  2484. // Now make a second pass and shoot the SetPacket filter request for
  2485. // all the marked items
  2486. //
  2487. pLink = gl_linkBindings.Flink;
  2488. while ( pLink != &gl_linkBindings )
  2489. {
  2490. //
  2491. // We have at least one binding, so walk thru the list
  2492. // and reference them
  2493. //
  2494. pBinding = ((BINDING*) CONTAINING_RECORD( pLink, BINDING, linkBindings ));
  2495. //
  2496. // Advance to the next item
  2497. //
  2498. pLink = pLink->Flink;
  2499. NdisReleaseSpinLock( &gl_lockProtocol );
  2500. //
  2501. // If we are just marking, check the state of the binding and mark it
  2502. // by setting the BNBF_SetPacketFilterInProgress bit
  2503. //
  2504. if ( pBinding->ulBindingFlags & BNBF_PacketFilterChangeInProgress )
  2505. {
  2506. //
  2507. // This binding is marked by the previous loop so change the filter
  2508. // for this binding
  2509. //
  2510. PrSetPacketFilterForAdapter( pBinding, fSet );
  2511. //
  2512. // Reset what was done in the first pass
  2513. //
  2514. pBinding->ulBindingFlags &= ~BNBF_PacketFilterChangeInProgress;
  2515. DereferenceBinding( pBinding );
  2516. }
  2517. NdisAcquireSpinLock( &gl_lockProtocol );
  2518. }
  2519. }
  2520. NdisReleaseSpinLock( &gl_lockProtocol );
  2521. TRACE( TL_N, TM_Pr, ("-ChangePacketFiltersForAdapters") );
  2522. }