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.

3427 lines
96 KiB

  1. /*++
  2. Copyright(c) 1992-2000 Microsoft Corporation
  3. Module Name:
  4. protocol.c
  5. Abstract:
  6. NDIS Protocol Entry points and utility functions for the NDIS
  7. MUX Intermediate Miniport sample.
  8. The protocol edge binds to Ethernet (NdisMedium802_3) adapters,
  9. and initiates creation of zero or more Virtual Ethernet LAN (VELAN)
  10. miniport instances by calling NdisIMInitializeDeviceInstanceEx once
  11. for each VELAN configured over a lower binding.
  12. Environment:
  13. Kernel mode.
  14. Revision History:
  15. --*/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. #define MODULE_NUMBER MODULE_PROT
  19. VOID
  20. PtBindAdapter(
  21. OUT PNDIS_STATUS Status,
  22. IN NDIS_HANDLE BindContext,
  23. IN PNDIS_STRING DeviceName,
  24. IN PVOID SystemSpecific1,
  25. IN PVOID SystemSpecific2
  26. )
  27. /*++
  28. Routine Description:
  29. Called by NDIS to bind to a miniport below. This routine
  30. creates a binding by calling NdisOpenAdapter, and then
  31. initiates creation of all configured VELANs on this binding.
  32. Arguments:
  33. Status - Return status of bind here.
  34. BindContext - Can be passed to NdisCompleteBindAdapter if this
  35. call is pended.
  36. DeviceName - Device name to bind to. This is passed to
  37. NdisOpenAdapter.
  38. SystemSpecific1 - Can be passed to NdisOpenProtocolConfiguration to
  39. read per-binding information
  40. SystemSpecific2 - Unused
  41. Return Value:
  42. *Status is set to NDIS_STATUS_SUCCESS if no failure occurred
  43. while handling this call, otherwise an error code.
  44. --*/
  45. {
  46. PADAPT pAdapt = NULL;
  47. NDIS_STATUS OpenErrorStatus;
  48. UINT MediumIndex;
  49. PNDIS_STRING pConfigString;
  50. ULONG Length;
  51. UNREFERENCED_PARAMETER(BindContext);
  52. UNREFERENCED_PARAMETER(SystemSpecific2);
  53. pConfigString = (PNDIS_STRING)SystemSpecific1;
  54. DBGPRINT(MUX_LOUD, ("==> Protocol BindAdapter: %ws\n", pConfigString->Buffer));
  55. do
  56. {
  57. //
  58. // Allocate memory for Adapter struct plus the config
  59. // string with two extra WCHARs for NULL termination.
  60. //
  61. Length = sizeof(ADAPT) +
  62. pConfigString->MaximumLength + sizeof(WCHAR);
  63. NdisAllocateMemoryWithTag(&pAdapt, Length , TAG);
  64. if (pAdapt == NULL)
  65. {
  66. *Status = NDIS_STATUS_RESOURCES;
  67. break;
  68. }
  69. //
  70. // Initialize the adapter structure
  71. //
  72. NdisZeroMemory(pAdapt, sizeof(ADAPT));
  73. (VOID)PtReferenceAdapter(pAdapt, (PUCHAR)"openadapter");
  74. //
  75. // Copy in the Config string - we will use this to open the
  76. // registry section for this adapter at a later point.
  77. //
  78. pAdapt->ConfigString.MaximumLength = pConfigString->MaximumLength;
  79. pAdapt->ConfigString.Length = pConfigString->Length;
  80. pAdapt->ConfigString.Buffer = (PWCHAR)((PUCHAR)pAdapt +
  81. sizeof(ADAPT));
  82. NdisMoveMemory(pAdapt->ConfigString.Buffer,
  83. pConfigString->Buffer,
  84. pConfigString->Length);
  85. pAdapt->ConfigString.Buffer[pConfigString->Length/sizeof(WCHAR)] =
  86. ((WCHAR)0);
  87. NdisInitializeEvent(&pAdapt->Event);
  88. NdisInitializeListHead(&pAdapt->VElanList);
  89. pAdapt->PtDevicePowerState = NdisDeviceStateD0;
  90. MUX_INIT_ADAPT_RW_LOCK(pAdapt);
  91. //
  92. // TODO: Allocate a packet pool and buffers for send & receive.
  93. //
  94. // Now open the adapter below and complete the initialization
  95. //
  96. NdisOpenAdapter(Status,
  97. &OpenErrorStatus,
  98. &pAdapt->BindingHandle,
  99. &MediumIndex,
  100. MediumArray,
  101. sizeof(MediumArray)/sizeof(NDIS_MEDIUM),
  102. ProtHandle,
  103. pAdapt,
  104. DeviceName,
  105. 0,
  106. NULL);
  107. if (*Status == NDIS_STATUS_PENDING)
  108. {
  109. NdisWaitEvent(&pAdapt->Event, 0);
  110. *Status = pAdapt->Status;
  111. }
  112. if (*Status != NDIS_STATUS_SUCCESS)
  113. {
  114. pAdapt->BindingHandle = NULL;
  115. break;
  116. }
  117. pAdapt->Medium = MediumArray[MediumIndex];
  118. //
  119. // Add this adapter to the global AdapterList
  120. //
  121. MUX_ACQUIRE_MUTEX(&GlobalMutex);
  122. InsertTailList(&AdapterList, &pAdapt->Link);
  123. MUX_RELEASE_MUTEX(&GlobalMutex);
  124. //
  125. // Get some information from the adapter below.
  126. //
  127. PtQueryAdapterInfo(pAdapt);
  128. //
  129. // Start all VELANS configured on this adapter.
  130. //
  131. *Status = PtBootStrapVElans(pAdapt);
  132. } while(FALSE);
  133. if (*Status != NDIS_STATUS_SUCCESS)
  134. {
  135. if (pAdapt != NULL)
  136. {
  137. //
  138. // For some reason, the driver cannot create velan for the binding
  139. //
  140. if (pAdapt->BindingHandle != NULL)
  141. {
  142. NDIS_STATUS LocalStatus;
  143. //
  144. // Close the binding the driver opened above
  145. //
  146. NdisResetEvent(&pAdapt->Event);
  147. NdisCloseAdapter(&LocalStatus, pAdapt->BindingHandle);
  148. pAdapt->BindingHandle = NULL;
  149. if (LocalStatus == NDIS_STATUS_PENDING)
  150. {
  151. NdisWaitEvent(&pAdapt->Event, 0);
  152. }
  153. MUX_ACQUIRE_MUTEX(&GlobalMutex);
  154. RemoveEntryList(&pAdapt->Link);
  155. MUX_RELEASE_MUTEX(&GlobalMutex);
  156. }
  157. PtDereferenceAdapter(pAdapt, (PUCHAR)"openadapter");
  158. pAdapt = NULL;
  159. }
  160. }
  161. DBGPRINT(MUX_INFO, ("<== Protocol BindAdapter: pAdapt %p, Status %x\n", pAdapt, *Status));
  162. }
  163. VOID
  164. PtOpenAdapterComplete(
  165. IN NDIS_HANDLE ProtocolBindingContext,
  166. IN NDIS_STATUS Status,
  167. IN NDIS_STATUS OpenErrorStatus
  168. )
  169. /*++
  170. Routine Description:
  171. Completion routine for NdisOpenAdapter issued from within the
  172. PtBindAdapter. Simply unblock the caller.
  173. Arguments:
  174. ProtocolBindingContext Pointer to the adapter
  175. Status Status of the NdisOpenAdapter call
  176. OpenErrorStatus Secondary status(ignored by us).
  177. Return Value:
  178. None
  179. --*/
  180. {
  181. PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
  182. UNREFERENCED_PARAMETER(OpenErrorStatus);
  183. DBGPRINT(MUX_LOUD, ("==> PtOpenAdapterComplete: Adapt %p, Status %x\n", pAdapt, Status));
  184. pAdapt->Status = Status;
  185. NdisSetEvent(&pAdapt->Event);
  186. }
  187. VOID
  188. PtQueryAdapterInfo(
  189. IN PADAPT pAdapt
  190. )
  191. /*++
  192. Routine Description:
  193. Query the adapter we are bound to for some standard OID values
  194. which we cache.
  195. Arguments:
  196. pAdapt Pointer to the adapter
  197. Return Value:
  198. None
  199. --*/
  200. {
  201. //
  202. // Get the link speed.
  203. //
  204. pAdapt->LinkSpeed = MUX_DEFAULT_LINK_SPEED;
  205. PtQueryAdapterSync(pAdapt,
  206. OID_GEN_LINK_SPEED,
  207. &pAdapt->LinkSpeed,
  208. sizeof(pAdapt->LinkSpeed));
  209. //
  210. // Get the max lookahead size.
  211. //
  212. pAdapt->MaxLookAhead = MUX_DEFAULT_LOOKAHEAD_SIZE;
  213. PtQueryAdapterSync(pAdapt,
  214. OID_GEN_MAXIMUM_LOOKAHEAD,
  215. &pAdapt->MaxLookAhead,
  216. sizeof(pAdapt->MaxLookAhead));
  217. //
  218. // Get the Ethernet MAC address.
  219. //
  220. PtQueryAdapterSync(pAdapt,
  221. OID_802_3_CURRENT_ADDRESS,
  222. &pAdapt->CurrentAddress,
  223. sizeof(pAdapt->CurrentAddress));
  224. }
  225. VOID
  226. PtQueryAdapterSync(
  227. IN PADAPT pAdapt,
  228. IN NDIS_OID Oid,
  229. IN PVOID InformationBuffer,
  230. IN ULONG InformationBufferLength
  231. )
  232. /*++
  233. Routine Description:
  234. Utility routine to query the adapter for a single OID value. This
  235. blocks for the query to complete.
  236. Arguments:
  237. pAdapt Pointer to the adapter
  238. Oid OID to query for
  239. InformationBuffer Place for the result
  240. InformationBufferLength Length of the above
  241. Return Value:
  242. None.
  243. --*/
  244. {
  245. PMUX_NDIS_REQUEST pMuxNdisRequest = NULL;
  246. NDIS_STATUS Status;
  247. do
  248. {
  249. NdisAllocateMemoryWithTag(&pMuxNdisRequest, sizeof(MUX_NDIS_REQUEST), TAG);
  250. if (pMuxNdisRequest == NULL)
  251. {
  252. break;
  253. }
  254. pMuxNdisRequest->pVElan = NULL; // internal request
  255. //
  256. // Set up completion routine.
  257. //
  258. pMuxNdisRequest->pCallback = PtCompleteBlockingRequest;
  259. NdisInitializeEvent(&pMuxNdisRequest->Event);
  260. pMuxNdisRequest->Request.RequestType = NdisRequestQueryInformation;
  261. pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.Oid = Oid;
  262. pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer =
  263. InformationBuffer;
  264. pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength =
  265. InformationBufferLength;
  266. NdisRequest(&Status,
  267. pAdapt->BindingHandle,
  268. &pMuxNdisRequest->Request);
  269. if (Status == NDIS_STATUS_PENDING)
  270. {
  271. NdisWaitEvent(&pMuxNdisRequest->Event, 0);
  272. Status = pMuxNdisRequest->Status;
  273. }
  274. }
  275. while (FALSE);
  276. if (NULL != pMuxNdisRequest)
  277. {
  278. NdisFreeMemory(pMuxNdisRequest, sizeof(MUX_NDIS_REQUEST), 0);
  279. }
  280. }
  281. VOID
  282. PtRequestAdapterAsync(
  283. IN PADAPT pAdapt,
  284. IN NDIS_REQUEST_TYPE RequestType,
  285. IN NDIS_OID Oid,
  286. IN PVOID InformationBuffer,
  287. IN ULONG InformationBufferLength,
  288. IN PMUX_REQ_COMPLETE_HANDLER pCallback
  289. )
  290. /*++
  291. Routine Description:
  292. Utility routine to query the adapter for a single OID value.
  293. This completes asynchronously, i.e. the calling thread is
  294. not blocked until the request completes.
  295. Arguments:
  296. pAdapt Pointer to the adapter
  297. RequestType NDIS request type
  298. Oid OID to set/query
  299. InformationBuffer Input/output buffer
  300. InformationBufferLength Length of the above
  301. pCallback Function to call on request completion
  302. Return Value:
  303. None.
  304. --*/
  305. {
  306. PMUX_NDIS_REQUEST pMuxNdisRequest = NULL;
  307. PNDIS_REQUEST pNdisRequest;
  308. NDIS_STATUS Status;
  309. do
  310. {
  311. NdisAllocateMemoryWithTag(&pMuxNdisRequest, sizeof(MUX_NDIS_REQUEST), TAG);
  312. if (pMuxNdisRequest == NULL)
  313. {
  314. break;
  315. }
  316. pMuxNdisRequest->pVElan = NULL; // internal request
  317. //
  318. // Set up completion routine.
  319. //
  320. pMuxNdisRequest->pCallback = pCallback;
  321. pNdisRequest = &pMuxNdisRequest->Request;
  322. pNdisRequest->RequestType = RequestType;
  323. switch (RequestType)
  324. {
  325. case NdisRequestQueryInformation:
  326. pNdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
  327. pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
  328. InformationBuffer;
  329. pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
  330. InformationBufferLength;
  331. break;
  332. case NdisRequestSetInformation:
  333. pNdisRequest->DATA.SET_INFORMATION.Oid = Oid;
  334. pNdisRequest->DATA.SET_INFORMATION.InformationBuffer =
  335. InformationBuffer;
  336. pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength =
  337. InformationBufferLength;
  338. break;
  339. default:
  340. ASSERT(FALSE);
  341. break;
  342. }
  343. NdisRequest(&Status,
  344. pAdapt->BindingHandle,
  345. pNdisRequest);
  346. if (Status != NDIS_STATUS_PENDING)
  347. {
  348. PtRequestComplete(
  349. (NDIS_HANDLE)pAdapt,
  350. pNdisRequest,
  351. Status);
  352. }
  353. }
  354. while (FALSE);
  355. }
  356. VOID
  357. PtUnbindAdapter(
  358. OUT PNDIS_STATUS Status,
  359. IN NDIS_HANDLE ProtocolBindingContext,
  360. IN NDIS_HANDLE UnbindContext
  361. )
  362. /*++
  363. Routine Description:
  364. Called by NDIS when we are required to unbind to the adapter below.
  365. Go through all VELANs on the adapter and shut them down.
  366. Arguments:
  367. Status Placeholder for return status
  368. ProtocolBindingContext Pointer to the adapter structure
  369. UnbindContext Context for NdisUnbindComplete() if this pends
  370. Return Value:
  371. Status from closing the binding.
  372. --*/
  373. {
  374. PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
  375. PLIST_ENTRY p;
  376. PVELAN pVElan = NULL;
  377. LOCK_STATE LockState;
  378. UNREFERENCED_PARAMETER(UnbindContext);
  379. DBGPRINT(MUX_LOUD, ("==> PtUnbindAdapter: Adapt %p\n", pAdapt));
  380. //
  381. // Stop all VELANs associated with the adapter.
  382. // Repeatedly find the first unprocessed VELAN on
  383. // the adapter, mark it, and stop it.
  384. //
  385. MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
  386. do
  387. {
  388. for (p = pAdapt->VElanList.Flink;
  389. p != &pAdapt->VElanList;
  390. p = p->Flink)
  391. {
  392. pVElan = CONTAINING_RECORD(p, VELAN, Link);
  393. if (!pVElan->DeInitializing)
  394. {
  395. pVElan->DeInitializing = TRUE;
  396. break;
  397. }
  398. }
  399. if (p != &pAdapt->VElanList)
  400. {
  401. ASSERT(pVElan == CONTAINING_RECORD(p, VELAN, Link));
  402. //
  403. // Got a VELAN to stop. Add a temp ref
  404. // so that the VELAN won't go away when
  405. // we release the ADAPT lock below.
  406. //
  407. PtReferenceVElan(pVElan, (PUCHAR)"UnbindTemp");
  408. //
  409. // Release the read lock because we want to
  410. // run StopVElan at passive IRQL.
  411. //
  412. MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
  413. PtStopVElan(pVElan);
  414. PtDereferenceVElan(pVElan, (PUCHAR)"UnbindTemp");
  415. MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
  416. }
  417. else
  418. {
  419. //
  420. // No unmarked VELAN, so exit.
  421. //
  422. break;
  423. }
  424. }
  425. while (TRUE);
  426. //
  427. // Wait until all VELANs are unlinked from the adapter.
  428. // This is so that we don't attempt to forward down packets
  429. // and/or requests from VELANs after calling NdisCloseAdapter.
  430. //
  431. while (!IsListEmpty(&pAdapt->VElanList))
  432. {
  433. MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
  434. DBGPRINT(MUX_INFO, ("PtUnbindAdapter: pAdapt %p, VELANlist not yet empty\n",
  435. pAdapt));
  436. NdisMSleep(2000);
  437. MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
  438. }
  439. MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
  440. //
  441. // Close the binding to the lower adapter.
  442. //
  443. if (pAdapt->BindingHandle != NULL)
  444. {
  445. NdisResetEvent(&pAdapt->Event);
  446. NdisCloseAdapter(Status, pAdapt->BindingHandle);
  447. //
  448. // Wait for it to complete.
  449. //
  450. if (*Status == NDIS_STATUS_PENDING)
  451. {
  452. NdisWaitEvent(&pAdapt->Event, 0);
  453. *Status = pAdapt->Status;
  454. }
  455. }
  456. else
  457. {
  458. //
  459. // Binding Handle should not be NULL.
  460. //
  461. *Status = NDIS_STATUS_FAILURE;
  462. ASSERT(0);
  463. }
  464. //
  465. // Remove the adapter from the global AdapterList
  466. //
  467. MUX_ACQUIRE_MUTEX(&GlobalMutex);
  468. RemoveEntryList(&pAdapt->Link);
  469. MUX_RELEASE_MUTEX(&GlobalMutex);
  470. //
  471. // Free all the resources associated with this Adapter except the
  472. // ADAPT struct itself, because that will be freed by
  473. // PtDereferenceAdapter call when the reference drops to zero.
  474. // Note: Every VELAN associated with this Adapter takes a ref count
  475. // on it. So the adapter memory wouldn't be freed until all the VELANs
  476. // are shutdown.
  477. //
  478. PtDereferenceAdapter(pAdapt, (PUCHAR)"Unbind");
  479. DBGPRINT(MUX_INFO, ("<== PtUnbindAdapter: Adapt %p\n", pAdapt));
  480. }
  481. VOID
  482. PtCloseAdapterComplete(
  483. IN NDIS_HANDLE ProtocolBindingContext,
  484. IN NDIS_STATUS Status
  485. )
  486. /*++
  487. Routine Description:
  488. Completion for the CloseAdapter call.
  489. Arguments:
  490. ProtocolBindingContext Pointer to the adapter structure
  491. Status Completion status
  492. Return Value:
  493. None.
  494. --*/
  495. {
  496. PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
  497. DBGPRINT(MUX_INFO, ("==> PtCloseAdapterComplete: Adapt %p, Status %x\n",
  498. pAdapt, Status));
  499. pAdapt->Status = Status;
  500. NdisSetEvent(&pAdapt->Event);
  501. }
  502. VOID
  503. PtResetComplete(
  504. IN NDIS_HANDLE ProtocolBindingContext,
  505. IN NDIS_STATUS Status
  506. )
  507. /*++
  508. Routine Description:
  509. Completion for the reset.
  510. Arguments:
  511. ProtocolBindingContext Pointer to the adapter structure
  512. Status Completion status
  513. Return Value:
  514. None.
  515. --*/
  516. {
  517. #if DBG
  518. PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
  519. #endif
  520. #if !DBG
  521. UNREFERENCED_PARAMETER(ProtocolBindingContext);
  522. UNREFERENCED_PARAMETER(Status);
  523. #endif
  524. DBGPRINT(MUX_ERROR, ("==> PtResetComplete: Adapt %p, Status %x\n",
  525. pAdapt, Status));
  526. //
  527. // We never issue a reset, so we should not be here.
  528. //
  529. ASSERT(0);
  530. }
  531. VOID
  532. PtRequestComplete(
  533. IN NDIS_HANDLE ProtocolBindingContext,
  534. IN PNDIS_REQUEST NdisRequest,
  535. IN NDIS_STATUS Status
  536. )
  537. /*++
  538. Routine Description:
  539. Completion handler for an NDIS request sent to a lower
  540. miniport.
  541. Arguments:
  542. ProtocolBindingContext Pointer to the adapter structure
  543. NdisRequest The completed request
  544. Status Completion status
  545. Return Value:
  546. None
  547. --*/
  548. {
  549. PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
  550. PMUX_NDIS_REQUEST pMuxNdisRequest;
  551. pMuxNdisRequest = CONTAINING_RECORD(NdisRequest, MUX_NDIS_REQUEST, Request);
  552. ASSERT(pMuxNdisRequest->pCallback != NULL);
  553. //
  554. // Completion is handled by the callback routine:
  555. //
  556. (*pMuxNdisRequest->pCallback)(pAdapt,
  557. pMuxNdisRequest,
  558. Status);
  559. }
  560. VOID
  561. PtCompleteForwardedRequest(
  562. IN PADAPT pAdapt,
  563. IN PMUX_NDIS_REQUEST pMuxNdisRequest,
  564. IN NDIS_STATUS Status
  565. )
  566. /*++
  567. Routine Description:
  568. Handle completion of an NDIS request that was originally
  569. submitted to our VELAN miniport and was forwarded down
  570. to the lower binding.
  571. We do some postprocessing, to cache the results of
  572. certain queries.
  573. Arguments:
  574. pAdapt - Adapter on which the request was forwarded
  575. pMuxNdisRequest - super-struct for request
  576. Status - request completion status
  577. Return Value:
  578. None
  579. --*/
  580. {
  581. PVELAN pVElan = NULL;
  582. PNDIS_REQUEST pNdisRequest = &pMuxNdisRequest->Request;
  583. NDIS_OID Oid = pNdisRequest->DATA.SET_INFORMATION.Oid;
  584. UNREFERENCED_PARAMETER(pAdapt);
  585. //
  586. // Get the originating VELAN. The VELAN will not be dereferenced
  587. // away until the pended request is completed.
  588. //
  589. pVElan = pMuxNdisRequest->pVElan;
  590. ASSERT(pVElan != NULL);
  591. ASSERT(pMuxNdisRequest == &pVElan->Request);
  592. if (Status != NDIS_STATUS_SUCCESS)
  593. {
  594. DBGPRINT(MUX_WARN, ("PtCompleteForwardedReq: pVElan %p, OID %x, Status %x\n",
  595. pVElan,
  596. pMuxNdisRequest->Request.DATA.QUERY_INFORMATION.Oid,
  597. Status));
  598. }
  599. //
  600. // Complete the original request.
  601. //
  602. switch (pNdisRequest->RequestType)
  603. {
  604. case NdisRequestQueryInformation:
  605. *pVElan->BytesReadOrWritten =
  606. pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
  607. *pVElan->BytesNeeded =
  608. pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;
  609. //
  610. // Before completing the request, do any necessary
  611. // post-processing.
  612. //
  613. Oid = pNdisRequest->DATA.QUERY_INFORMATION.Oid;
  614. if (Status == NDIS_STATUS_SUCCESS)
  615. {
  616. if (Oid == OID_GEN_LINK_SPEED)
  617. {
  618. NdisMoveMemory (&pVElan->LinkSpeed,
  619. pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
  620. sizeof(ULONG));
  621. }
  622. else if (Oid == OID_PNP_CAPABILITIES)
  623. {
  624. PtPostProcessPnPCapabilities(pVElan,
  625. pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
  626. pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength);
  627. }
  628. }
  629. NdisMQueryInformationComplete(pVElan->MiniportAdapterHandle, Status);
  630. break;
  631. case NdisRequestSetInformation:
  632. *pVElan->BytesReadOrWritten =
  633. pNdisRequest->DATA.SET_INFORMATION.BytesRead;
  634. *pVElan->BytesNeeded =
  635. pNdisRequest->DATA.SET_INFORMATION.BytesNeeded;
  636. //
  637. // Before completing the request, cache relevant information
  638. // in our structure.
  639. //
  640. if (Status == NDIS_STATUS_SUCCESS)
  641. {
  642. Oid = pNdisRequest->DATA.SET_INFORMATION.Oid;
  643. switch (Oid)
  644. {
  645. case OID_GEN_CURRENT_LOOKAHEAD:
  646. NdisMoveMemory(&pVElan->LookAhead,
  647. pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
  648. sizeof(ULONG));
  649. break;
  650. default:
  651. break;
  652. }
  653. }
  654. NdisMSetInformationComplete(pVElan->MiniportAdapterHandle, Status);
  655. break;
  656. default:
  657. ASSERT(FALSE);
  658. break;
  659. }
  660. MUX_DECR_PENDING_SENDS(pVElan);
  661. }
  662. VOID
  663. PtPostProcessPnPCapabilities(
  664. IN PVELAN pVElan,
  665. IN PVOID InformationBuffer,
  666. IN ULONG InformationBufferLength
  667. )
  668. /*++
  669. Routine Description:
  670. Postprocess a successfully completed query for OID_PNP_CAPABILITIES.
  671. We modify the returned information slightly before completing
  672. it to the VELAN above.
  673. Arguments:
  674. pVElan - Pointer to VELAN
  675. InformationBuffer - points to buffer for the OID
  676. InformationBufferLength - byte length of the above.
  677. Return Value:
  678. None
  679. --*/
  680. {
  681. PNDIS_PNP_CAPABILITIES pPNPCapabilities;
  682. PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct;
  683. UNREFERENCED_PARAMETER(pVElan);
  684. if (InformationBufferLength >= sizeof(NDIS_PNP_CAPABILITIES))
  685. {
  686. pPNPCapabilities = (PNDIS_PNP_CAPABILITIES)InformationBuffer;
  687. //
  688. // The following fields must be overwritten by an IM driver.
  689. //
  690. pPMstruct= &pPNPCapabilities->WakeUpCapabilities;
  691. pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
  692. pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified;
  693. pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
  694. }
  695. }
  696. VOID
  697. PtCompleteBlockingRequest(
  698. IN PADAPT pAdapt,
  699. IN PMUX_NDIS_REQUEST pMuxNdisRequest,
  700. IN NDIS_STATUS Status
  701. )
  702. /*++
  703. Routine Description:
  704. Handle completion of an NDIS request that was originated
  705. by this driver and the calling thread is blocked waiting
  706. for completion.
  707. Arguments:
  708. pAdapt - Adapter on which the request was forwarded
  709. pMuxNdisRequest - super-struct for request
  710. Status - request completion status
  711. Return Value:
  712. None
  713. --*/
  714. {
  715. UNREFERENCED_PARAMETER(pAdapt);
  716. pMuxNdisRequest->Status = Status;
  717. //
  718. // The request was originated from this driver. Wake up the
  719. // thread blocked for its completion.
  720. //
  721. pMuxNdisRequest->Status = Status;
  722. NdisSetEvent(&pMuxNdisRequest->Event);
  723. }
  724. VOID
  725. PtDiscardCompletedRequest(
  726. IN PADAPT pAdapt,
  727. IN PMUX_NDIS_REQUEST pMuxNdisRequest,
  728. IN NDIS_STATUS Status
  729. )
  730. /*++
  731. Routine Description:
  732. Handle completion of an NDIS request that was originated
  733. by this driver - the request is to be discarded.
  734. Arguments:
  735. pAdapt - Adapter on which the request was forwarded
  736. pMuxNdisRequest - super-struct for request
  737. Status - request completion status
  738. Return Value:
  739. None
  740. --*/
  741. {
  742. UNREFERENCED_PARAMETER(pAdapt);
  743. UNREFERENCED_PARAMETER(Status);
  744. NdisFreeMemory(pMuxNdisRequest, sizeof(MUX_NDIS_REQUEST), 0);
  745. }
  746. VOID
  747. PtStatus(
  748. IN NDIS_HANDLE ProtocolBindingContext,
  749. IN NDIS_STATUS GeneralStatus,
  750. IN PVOID StatusBuffer,
  751. IN UINT StatusBufferSize
  752. )
  753. /*++
  754. Routine Description:
  755. Handle a status indication on the lower binding (ADAPT).
  756. If this is a media status indication, we also pass this
  757. on to all associated VELANs.
  758. Arguments:
  759. ProtocolBindingContext Pointer to the adapter structure
  760. GeneralStatus Status code
  761. StatusBuffer Status buffer
  762. StatusBufferSize Size of the status buffer
  763. Return Value:
  764. None
  765. --*/
  766. {
  767. PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
  768. PLIST_ENTRY p;
  769. PVELAN pVElan;
  770. LOCK_STATE LockState;
  771. DBGPRINT(MUX_LOUD, ("PtStatus: Adapt %p, Status %x\n", pAdapt, GeneralStatus));
  772. do
  773. {
  774. //
  775. // Ignore status indications that we aren't going
  776. // to pass up.
  777. //
  778. if ((GeneralStatus != NDIS_STATUS_MEDIA_CONNECT) &&
  779. (GeneralStatus != NDIS_STATUS_MEDIA_DISCONNECT))
  780. {
  781. break;
  782. }
  783. MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
  784. for (p = pAdapt->VElanList.Flink;
  785. p != &pAdapt->VElanList;
  786. p = p->Flink)
  787. {
  788. pVElan = CONTAINING_RECORD(p, VELAN, Link);
  789. MUX_INCR_PENDING_RECEIVES(pVElan);
  790. //
  791. // Should the indication be sent on this VELAN?
  792. //
  793. if ((pVElan->MiniportHalting) ||
  794. (pVElan->MiniportAdapterHandle == NULL) ||
  795. MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState))
  796. {
  797. MUX_DECR_PENDING_RECEIVES(pVElan);
  798. if (MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState))
  799. {
  800. //
  801. // Keep track of the lastest status to indicated when VELAN power is on
  802. //
  803. ASSERT((GeneralStatus == NDIS_STATUS_MEDIA_CONNECT) || (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT));
  804. pVElan->LatestUnIndicateStatus = GeneralStatus;
  805. }
  806. continue;
  807. }
  808. //
  809. // Save the last indicated status when
  810. pVElan->LastIndicatedStatus = GeneralStatus;
  811. NdisMIndicateStatus(pVElan->MiniportAdapterHandle,
  812. GeneralStatus,
  813. StatusBuffer,
  814. StatusBufferSize);
  815. //
  816. // Mark this so that we forward a status complete
  817. // indication as well.
  818. //
  819. pVElan->IndicateStatusComplete = TRUE;
  820. MUX_DECR_PENDING_RECEIVES(pVElan);
  821. }
  822. MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
  823. }
  824. while (FALSE);
  825. }
  826. VOID
  827. PtStatusComplete(
  828. IN NDIS_HANDLE ProtocolBindingContext
  829. )
  830. /*++
  831. Routine Description:
  832. Marks the end of a status indication. Pass it on to
  833. associated VELANs if necessary.
  834. Arguments:
  835. ProtocolBindingContext - pointer to ADAPT
  836. Return Value:
  837. None.
  838. --*/
  839. {
  840. PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
  841. PLIST_ENTRY p;
  842. PVELAN pVElan;
  843. LOCK_STATE LockState;
  844. MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
  845. for (p = pAdapt->VElanList.Flink;
  846. p != &pAdapt->VElanList;
  847. p = p->Flink)
  848. {
  849. pVElan = CONTAINING_RECORD(p, VELAN, Link);
  850. MUX_INCR_PENDING_RECEIVES(pVElan);
  851. //
  852. // Should this indication be sent on this VELAN?
  853. //
  854. if ((pVElan->MiniportHalting) ||
  855. (pVElan->MiniportAdapterHandle == NULL) ||
  856. (!pVElan->IndicateStatusComplete) ||
  857. (MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState)))
  858. {
  859. MUX_DECR_PENDING_RECEIVES(pVElan);
  860. continue;
  861. }
  862. pVElan->IndicateStatusComplete = FALSE;
  863. NdisMIndicateStatusComplete(pVElan->MiniportAdapterHandle);
  864. MUX_DECR_PENDING_RECEIVES(pVElan);
  865. }
  866. MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
  867. }
  868. VOID
  869. PtSendComplete(
  870. IN NDIS_HANDLE ProtocolBindingContext,
  871. IN PNDIS_PACKET Packet,
  872. IN NDIS_STATUS Status
  873. )
  874. /*++
  875. Routine Description:
  876. Called by NDIS when the miniport below had completed a send.
  877. We complete the corresponding upper-edge send this represents.
  878. The packet being completed belongs to our send packet pool,
  879. however we store a pointer to the original packet this represents,
  880. in the packet's reserved field.
  881. Arguments:
  882. ProtocolBindingContext - Points to ADAPT structure
  883. Packet - Packet being completed by the lower miniport
  884. Status - status of send
  885. Return Value:
  886. None
  887. --*/
  888. {
  889. PVELAN pVElan;
  890. PMUX_SEND_RSVD pSendReserved;
  891. PNDIS_PACKET OriginalPacket;
  892. #if IEEE_VLAN_SUPPORT
  893. NDIS_PACKET_8021Q_INFO NdisPacket8021qInfo;
  894. BOOLEAN IsTagInsert;
  895. PNDIS_BUFFER pNdisBuffer;
  896. PVOID pVa;
  897. ULONG BufferLength;
  898. #endif
  899. UNREFERENCED_PARAMETER(ProtocolBindingContext);
  900. pSendReserved = MUX_RSVD_FROM_SEND_PACKET(Packet);
  901. OriginalPacket = pSendReserved->pOriginalPacket;
  902. pVElan = pSendReserved->pVElan;
  903. #if IEEE_VLAN_SUPPORT
  904. //
  905. // Check if we had inserted a tag header
  906. //
  907. IsTagInsert = FALSE;
  908. NdisPacket8021qInfo.Value = NDIS_PER_PACKET_INFO_FROM_PACKET(
  909. OriginalPacket,
  910. Ieee8021QInfo);
  911. if ((pVElan->VlanId != 0) || (NdisPacket8021qInfo.Value != NULL))
  912. {
  913. IsTagInsert = TRUE;
  914. }
  915. #endif
  916. #ifndef WIN9X
  917. NdisIMCopySendCompletePerPacketInfo(OriginalPacket, Packet);
  918. #endif
  919. //
  920. // Update statistics.
  921. //
  922. if (Status == NDIS_STATUS_SUCCESS)
  923. {
  924. MUX_INCR_STATISTICS64(&pVElan->GoodTransmits);
  925. }
  926. else
  927. {
  928. MUX_INCR_STATISTICS(&pVElan->TransmitFailuresOther);
  929. }
  930. //
  931. // Complete the original send.
  932. //
  933. NdisMSendComplete(pVElan->MiniportAdapterHandle,
  934. OriginalPacket,
  935. Status);
  936. #if IEEE_VLAN_SUPPORT
  937. //
  938. // If we had inserted a tag header, then remove the header
  939. // buffer and free it. We would also have created a new
  940. // NDIS buffer to map part of the original packet's header;
  941. // free that, too.
  942. //
  943. if (IsTagInsert)
  944. {
  945. pNdisBuffer = Packet->Private.Head;
  946. #ifdef NDIS51_MINIPORT
  947. NdisQueryBufferSafe(pNdisBuffer, &pVa, (PUINT)&BufferLength, NormalPagePriority);
  948. #else
  949. NdisQueryBuffer(pNdisBuffer, &pVa, &BufferLength);
  950. #endif
  951. if (pVa != NULL)
  952. {
  953. NdisFreeToNPagedLookasideList(&pVElan->TagLookaside, pVa);
  954. }
  955. NdisFreeBuffer(NDIS_BUFFER_LINKAGE(pNdisBuffer));
  956. NdisFreeBuffer (pNdisBuffer);
  957. }
  958. #endif
  959. //
  960. // Free our packet.
  961. //
  962. NdisFreePacket(Packet);
  963. //
  964. // Note down send-completion.
  965. //
  966. MUX_DECR_PENDING_SENDS(pVElan);
  967. }
  968. VOID
  969. PtTransferDataComplete(
  970. IN NDIS_HANDLE ProtocolBindingContext,
  971. IN PNDIS_PACKET Packet,
  972. IN NDIS_STATUS Status,
  973. IN UINT BytesTransferred
  974. )
  975. /*++
  976. Routine Description:
  977. Entry point called by NDIS to indicate completion of a call by us
  978. to NdisTransferData. We locate the original packet and VELAN on
  979. which our TransferData function (see MPTransferData) was called,
  980. and complete the original request.
  981. Arguments:
  982. ProtocolBindingContext - lower binding context, pointer to ADAPT
  983. Packet - Packet allocated by us
  984. Status - Completion status
  985. BytesTransferred - Number of bytes copied in
  986. Return Value:
  987. None
  988. --*/
  989. {
  990. PVELAN pVElan;
  991. PNDIS_PACKET pOriginalPacket;
  992. PMUX_TD_RSVD pTDReserved;
  993. UNREFERENCED_PARAMETER(ProtocolBindingContext);
  994. pTDReserved = MUX_RSVD_FROM_TD_PACKET(Packet);
  995. pOriginalPacket = pTDReserved->pOriginalPacket;
  996. pVElan = pTDReserved->pVElan;
  997. //
  998. // Complete the original TransferData request.
  999. //
  1000. NdisMTransferDataComplete(pVElan->MiniportAdapterHandle,
  1001. pOriginalPacket,
  1002. Status,
  1003. BytesTransferred);
  1004. //
  1005. // Free our packet.
  1006. //
  1007. NdisFreePacket(Packet);
  1008. }
  1009. BOOLEAN
  1010. PtMulticastMatch(
  1011. IN PVELAN pVElan,
  1012. IN PUCHAR pDstMac
  1013. )
  1014. /*++
  1015. Routine Description:
  1016. Check if the given multicast destination MAC address matches
  1017. any of the multicast address entries set on the VELAN.
  1018. NOTE: the caller is assumed to hold a READ/WRITE lock
  1019. to the parent ADAPT structure. This is so that the multicast
  1020. list on the VELAN is invariant for the duration of this call.
  1021. Arguments:
  1022. pVElan - VELAN to look in
  1023. pDstMac - Destination MAC address to compare
  1024. Return Value:
  1025. TRUE iff the address matches an entry in the VELAN
  1026. --*/
  1027. {
  1028. ULONG i;
  1029. UINT AddrCompareResult;
  1030. for (i = 0; i < pVElan->McastAddrCount; i++)
  1031. {
  1032. ETH_COMPARE_NETWORK_ADDRESSES_EQ(pVElan->McastAddrs[i],
  1033. pDstMac,
  1034. &AddrCompareResult);
  1035. if (AddrCompareResult == 0)
  1036. {
  1037. break;
  1038. }
  1039. }
  1040. return (i != pVElan->McastAddrCount);
  1041. }
  1042. BOOLEAN
  1043. PtMatchPacketToVElan(
  1044. IN PVELAN pVElan,
  1045. IN PUCHAR pDstMac,
  1046. IN BOOLEAN bIsMulticast,
  1047. IN BOOLEAN bIsBroadcast
  1048. )
  1049. /*++
  1050. Routine Description:
  1051. Check if the destination address of a received packet
  1052. matches the receive criteria on the specified VELAN.
  1053. NOTE: the caller is assumed to hold a READ/WRITE lock
  1054. to the parent ADAPT structure.
  1055. Arguments:
  1056. pVElan - VELAN to check on
  1057. pDstMac - Destination MAC address in received packet
  1058. bIsMulticast - is this a multicast address
  1059. bIsBroadcast - is this a broadcast address
  1060. Return Value:
  1061. TRUE iff this packet should be received on the VELAN
  1062. --*/
  1063. {
  1064. UINT AddrCompareResult;
  1065. ULONG PacketFilter;
  1066. BOOLEAN bPacketMatch;
  1067. PacketFilter = pVElan->PacketFilter;
  1068. //
  1069. // Handle the directed packet case first.
  1070. //
  1071. if (!bIsMulticast)
  1072. {
  1073. //
  1074. // If the VELAN is not in promisc. mode, check if
  1075. // the destination MAC address matches the local
  1076. // address.
  1077. //
  1078. if ((PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) == 0)
  1079. {
  1080. ETH_COMPARE_NETWORK_ADDRESSES_EQ(pVElan->CurrentAddress,
  1081. pDstMac,
  1082. &AddrCompareResult);
  1083. bPacketMatch = ((AddrCompareResult == 0) &&
  1084. ((PacketFilter & NDIS_PACKET_TYPE_DIRECTED) != 0));
  1085. }
  1086. else
  1087. {
  1088. bPacketMatch = TRUE;
  1089. }
  1090. }
  1091. else
  1092. {
  1093. //
  1094. // Multicast or broadcast packet.
  1095. //
  1096. //
  1097. // Indicate if the filter is set to promisc mode ...
  1098. //
  1099. if ((PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
  1100. ||
  1101. //
  1102. // or if this is a broadcast packet and the filter
  1103. // is set to receive all broadcast packets...
  1104. //
  1105. (bIsBroadcast &&
  1106. (PacketFilter & NDIS_PACKET_TYPE_BROADCAST))
  1107. ||
  1108. //
  1109. // or if this is a multicast packet, and the filter is
  1110. // either set to receive all multicast packets, or
  1111. // set to receive specific multicast packets. In the
  1112. // latter case, indicate receive only if the destn
  1113. // MAC address is present in the list of multicast
  1114. // addresses set on the VELAN.
  1115. //
  1116. (!bIsBroadcast &&
  1117. ((PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST) ||
  1118. ((PacketFilter & NDIS_PACKET_TYPE_MULTICAST) &&
  1119. PtMulticastMatch(pVElan, pDstMac))))
  1120. )
  1121. {
  1122. bPacketMatch = TRUE;
  1123. }
  1124. else
  1125. {
  1126. //
  1127. // No protocols above are interested in this
  1128. // multicast/broadcast packet.
  1129. //
  1130. bPacketMatch = FALSE;
  1131. }
  1132. }
  1133. return (bPacketMatch);
  1134. }
  1135. NDIS_STATUS
  1136. PtReceive(
  1137. IN NDIS_HANDLE ProtocolBindingContext,
  1138. IN NDIS_HANDLE MacReceiveContext,
  1139. IN PVOID HeaderBuffer,
  1140. IN UINT HeaderBufferSize,
  1141. IN PVOID LookAheadBuffer,
  1142. IN UINT LookAheadBufferSize,
  1143. IN UINT PacketSize
  1144. )
  1145. /*++
  1146. Routine Description:
  1147. Handle receive data indicated up by the miniport below.
  1148. We forward this up to all VELANs that are eligible to
  1149. receive this packet:
  1150. - If this is directed to a broadcast/multicast address,
  1151. indicate up on all VELANs that have multicast or broadcast
  1152. or promisc. bits set in their packet filters.
  1153. - If this is a directed packet, indicate it up on all VELANs
  1154. that have the a matching MAC address or have the promisc.
  1155. bit set in their packet filters.
  1156. We acquire a read lock on the ADAPT structure to ensure
  1157. that the VELAN list on the adapter is undisturbed.
  1158. If the miniport below indicates packets, NDIS would more
  1159. likely call us at our ReceivePacket handler. However we
  1160. might be called here in certain situations even though
  1161. the miniport below has indicated a receive packet, e.g.
  1162. if the miniport had set packet status to NDIS_STATUS_RESOURCES.
  1163. Arguments:
  1164. <see DDK ref page for ProtocolReceive>
  1165. Return Value:
  1166. NDIS_STATUS_SUCCESS if we processed the receive successfully,
  1167. NDIS_STATUS_XXX error code if we discarded it.
  1168. --*/
  1169. {
  1170. PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
  1171. PLIST_ENTRY p;
  1172. PVELAN pVElan;
  1173. PNDIS_PACKET MyPacket, Packet;
  1174. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1175. PUCHAR pData;
  1176. PUCHAR pDstMac;
  1177. BOOLEAN bIsMulticast, bIsBroadcast;
  1178. PMUX_RECV_RSVD pRecvReserved;
  1179. LOCK_STATE LockState;
  1180. #if IEEE_VLAN_SUPPORT
  1181. VLAN_TAG_HEADER UNALIGNED * pTagHeader;
  1182. USHORT UNALIGNED * pTpid;
  1183. MUX_RCV_CONTEXT MuxRcvContext;
  1184. #endif
  1185. do
  1186. {
  1187. if (HeaderBufferSize != ETH_HEADER_SIZE)
  1188. {
  1189. Status = NDIS_STATUS_NOT_ACCEPTED;
  1190. break;
  1191. }
  1192. if (pAdapt->PacketFilter == 0)
  1193. {
  1194. //
  1195. // We could get receives in the interval between
  1196. // initiating a request to set the packet filter on
  1197. // the binding to 0 and completion of that request.
  1198. // Drop such packets.
  1199. //
  1200. Status = NDIS_STATUS_NOT_ACCEPTED;
  1201. break;
  1202. }
  1203. //
  1204. // Collect some information from the packet.
  1205. //
  1206. pData = (PUCHAR)HeaderBuffer;
  1207. pDstMac = pData;
  1208. bIsMulticast = ETH_IS_MULTICAST(pDstMac);
  1209. bIsBroadcast = ETH_IS_BROADCAST(pDstMac);
  1210. //
  1211. // Get at the packet, if any, indicated up by the miniport below.
  1212. //
  1213. Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);
  1214. //
  1215. // Lock down the VELAN list on the adapter so that
  1216. // no insertions/deletions to this list happen while
  1217. // we loop through it. The packet filter will also not
  1218. // change during the time we hold the read lock.
  1219. //
  1220. MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
  1221. for (p = pAdapt->VElanList.Flink;
  1222. p != &pAdapt->VElanList;
  1223. p = p->Flink)
  1224. {
  1225. BOOLEAN bIndicateReceive;
  1226. pVElan = CONTAINING_RECORD(p, VELAN, Link);
  1227. //
  1228. // Should the packet be indicated up on this VELAN?
  1229. //
  1230. bIndicateReceive = PtMatchPacketToVElan(pVElan,
  1231. pDstMac,
  1232. bIsMulticast,
  1233. bIsBroadcast);
  1234. if (!bIndicateReceive)
  1235. {
  1236. continue;
  1237. }
  1238. //
  1239. // Make sure we don't Halt the VELAN miniport while
  1240. // we are accessing it here. See MPHalt.
  1241. //
  1242. // Also don't indicate receives if the virtual miniport
  1243. // has been set to a low power state. A specific case
  1244. // is when the system is resuming from "Stand-by", if
  1245. // the lower adapter is restored to D0 before the upper
  1246. // miniports are.
  1247. //
  1248. //
  1249. MUX_INCR_PENDING_RECEIVES(pVElan);
  1250. if ((pVElan->MiniportHalting) ||
  1251. (MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState)))
  1252. {
  1253. MUX_DECR_PENDING_RECEIVES(pVElan);
  1254. continue;
  1255. }
  1256. if (Packet != NULL)
  1257. {
  1258. //
  1259. // The miniport below did indicate up a packet. Use information
  1260. // from that packet to construct a new packet to indicate up.
  1261. //
  1262. //
  1263. // Get a packet off our receive pool and indicate that up.
  1264. //
  1265. NdisDprAllocatePacket(&Status,
  1266. &MyPacket,
  1267. pVElan->RecvPacketPoolHandle);
  1268. if (Status == NDIS_STATUS_SUCCESS)
  1269. {
  1270. //
  1271. // Make our packet point to data from the original
  1272. // packet. NOTE: this works only because we are
  1273. // indicating a receive directly from the context of
  1274. // our receive indication. If we need to queue this
  1275. // packet and indicate it from another thread context,
  1276. // we will also have to allocate a new buffer and copy
  1277. // over the packet contents, OOB data and per-packet
  1278. // information. This is because the packet data
  1279. // is available only for the duration of this
  1280. // receive indication call.
  1281. //
  1282. MyPacket->Private.Head = Packet->Private.Head;
  1283. MyPacket->Private.Tail = Packet->Private.Tail;
  1284. #if IEEE_VLAN_SUPPORT
  1285. Status = PtHandleRcvTagging(pVElan, Packet, MyPacket);
  1286. if (Status != NDIS_STATUS_SUCCESS)
  1287. {
  1288. NdisFreePacket(MyPacket);
  1289. MUX_DECR_PENDING_RECEIVES(pVElan);
  1290. continue;
  1291. }
  1292. #endif
  1293. //
  1294. // Get the original packet (it could be the same packet
  1295. // as the one received or a different one based on the
  1296. // number of layered miniports below) and set it on the
  1297. // indicated packet so the OOB data is visible correctly
  1298. // at protocols above.
  1299. //
  1300. NDIS_SET_ORIGINAL_PACKET(MyPacket,
  1301. NDIS_GET_ORIGINAL_PACKET(Packet));
  1302. NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);
  1303. //
  1304. // Copy packet flags.
  1305. //
  1306. NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
  1307. //
  1308. // Force protocols above to make a copy if they want to hang
  1309. // on to data in this packet. This is because we are in our
  1310. // Receive handler (not ReceivePacket), and the original
  1311. // packet can't be accessed after we return from here.
  1312. //
  1313. NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);
  1314. //
  1315. // Set our context information in the packet. Since
  1316. // the original packet from the miniport below is not being
  1317. // queued up, set this to NULL:
  1318. //
  1319. pRecvReserved = MUX_RSVD_FROM_RECV_PACKET(MyPacket);
  1320. pRecvReserved->pOriginalPacket = NULL;
  1321. MUX_INCR_STATISTICS64(&pVElan->GoodReceives);
  1322. //
  1323. // By setting NDIS_STATUS_RESOURCES, we also know that
  1324. // we can reclaim this packet as soon as the call to
  1325. // NdisMIndicateReceivePacket returns.
  1326. //
  1327. NdisMIndicateReceivePacket(pVElan->MiniportAdapterHandle,
  1328. &MyPacket,
  1329. 1);
  1330. //
  1331. // Reclaim the indicated packet. Since we had set its status
  1332. // to NDIS_STATUS_RESOURCES, we are guaranteed that protocols
  1333. // above are done with it. Our ReturnPacket handler will
  1334. // not be called for this packet, so call it ourselves.
  1335. //
  1336. MPReturnPacket((NDIS_HANDLE)pVElan, MyPacket);
  1337. //
  1338. // Done with this VELAN.
  1339. //
  1340. continue;
  1341. }
  1342. //
  1343. // else...
  1344. //
  1345. // Failed to allocate a packet to indicate up - fall through.
  1346. // We will still indicate up using the non-packet API, but
  1347. // other per-packet/OOB information won't be available
  1348. // to protocols above.
  1349. //
  1350. }
  1351. else
  1352. {
  1353. //
  1354. // The miniport below us uses the old-style (not packet)
  1355. // receive indication. Fall through.
  1356. //
  1357. }
  1358. //
  1359. // Fall through to here if the miniport below us has
  1360. // either not indicated an NDIS_PACKET or we could not
  1361. // allocate one.
  1362. //
  1363. //
  1364. // Mark the VELAN so that we will forward up a receive
  1365. // complete indication.
  1366. //
  1367. pVElan->IndicateRcvComplete = TRUE;
  1368. #if IEEE_VLAN_SUPPORT
  1369. //
  1370. // Get at the EtherType field.
  1371. //
  1372. pTpid = (PUSHORT)((PUCHAR)HeaderBuffer + 2 * ETH_LENGTH_OF_ADDRESS);
  1373. //
  1374. // Check if the EtherType indicates presence of a tag header.
  1375. //
  1376. if (*pTpid == TPID)
  1377. {
  1378. pTagHeader = (VLAN_TAG_HEADER UNALIGNED *)LookAheadBuffer;
  1379. //
  1380. // Drop this frame if it contains Routing information;
  1381. // we don't support this.
  1382. //
  1383. if (GET_CANONICAL_FORMAT_ID_FROM_TAG(pTagHeader) != 0)
  1384. {
  1385. Status = NDIS_STATUS_INVALID_PACKET;
  1386. MUX_DECR_PENDING_RECEIVES(pVElan);
  1387. MUX_INCR_STATISTICS(&pVElan->RcvFormatErrors);
  1388. continue;
  1389. }
  1390. //
  1391. // If there is a VLAN ID in this frame, and we have
  1392. // a configured VLAN ID for this VELAN, check if they
  1393. // are the same - drop if not.
  1394. //
  1395. if ((GET_VLAN_ID_FROM_TAG(pTagHeader) != (unsigned)0) &&
  1396. (pVElan->VlanId != (unsigned)0) &&
  1397. (ULONG)(GET_VLAN_ID_FROM_TAG(pTagHeader) != pVElan->VlanId))
  1398. {
  1399. Status = NDIS_STATUS_NOT_ACCEPTED;
  1400. MUX_DECR_PENDING_RECEIVES(pVElan);
  1401. MUX_INCR_STATISTICS(&pVElan->RcvVlanIdErrors);
  1402. continue;
  1403. }
  1404. //
  1405. // Copy information from the tag header to per-packet
  1406. // info fields.
  1407. //
  1408. MuxRcvContext.NdisPacket8021QInfo.Value = NULL;
  1409. COPY_TAG_INFO_FROM_HEADER_TO_PACKET_INFO(
  1410. MuxRcvContext.NdisPacket8021QInfo,
  1411. pTagHeader);
  1412. //
  1413. // Prepare for indicating up this frame (the tag
  1414. // header must be removed). First, copy in the real
  1415. // EtherType value from the tag header.
  1416. //
  1417. *pTpid = *((PUSHORT)((PUCHAR)LookAheadBuffer + sizeof(pTagHeader->TagInfo)));
  1418. //
  1419. // Account for removing the tag header.
  1420. //
  1421. LookAheadBuffer = (PVOID)((PUCHAR)LookAheadBuffer + VLAN_TAG_HEADER_SIZE);
  1422. LookAheadBufferSize -= VLAN_TAG_HEADER_SIZE;
  1423. PacketSize -= VLAN_TAG_HEADER_SIZE;
  1424. //
  1425. // Use MuxRcvContext to store context for the receive,
  1426. // to be used in MpTransferData, if called.
  1427. //
  1428. MuxRcvContext.TagHeaderLen = VLAN_TAG_HEADER_SIZE;
  1429. }
  1430. else
  1431. {
  1432. MuxRcvContext.TagHeaderLen = 0;
  1433. }
  1434. MuxRcvContext.MacRcvContext = MacReceiveContext;
  1435. //
  1436. // In order not to change the code a lot
  1437. //
  1438. MacReceiveContext = &MuxRcvContext;
  1439. #endif
  1440. MUX_INCR_STATISTICS64(&pVElan->GoodReceives);
  1441. //
  1442. // Indicate receive using the non-packet API.
  1443. //
  1444. NdisMEthIndicateReceive(pVElan->MiniportAdapterHandle,
  1445. MacReceiveContext,
  1446. HeaderBuffer,
  1447. HeaderBufferSize,
  1448. LookAheadBuffer,
  1449. LookAheadBufferSize,
  1450. PacketSize);
  1451. MUX_DECR_PENDING_RECEIVES(pVElan);
  1452. } // for (each VELAN)
  1453. MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
  1454. }
  1455. while(FALSE);
  1456. return Status;
  1457. }
  1458. VOID
  1459. PtReceiveComplete(
  1460. IN NDIS_HANDLE ProtocolBindingContext
  1461. )
  1462. /*++
  1463. Routine Description:
  1464. Called by the adapter below us when it is done indicating a batch of
  1465. received packets. We forward this up on all VELANs that need
  1466. this indication.
  1467. Arguments:
  1468. ProtocolBindingContext Pointer to our adapter structure.
  1469. Return Value:
  1470. None
  1471. --*/
  1472. {
  1473. PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
  1474. PLIST_ENTRY p;
  1475. PVELAN pVElan;
  1476. LOCK_STATE LockState;
  1477. MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
  1478. for (p = pAdapt->VElanList.Flink;
  1479. p != &pAdapt->VElanList;
  1480. p = p->Flink)
  1481. {
  1482. pVElan = CONTAINING_RECORD(p, VELAN, Link);
  1483. if (pVElan->IndicateRcvComplete)
  1484. {
  1485. pVElan->IndicateRcvComplete = FALSE;
  1486. NdisMEthIndicateReceiveComplete(pVElan->MiniportAdapterHandle);
  1487. }
  1488. }
  1489. MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
  1490. }
  1491. INT
  1492. PtReceivePacket(
  1493. IN NDIS_HANDLE ProtocolBindingContext,
  1494. IN PNDIS_PACKET Packet
  1495. )
  1496. /*++
  1497. Routine Description:
  1498. ReceivePacket handler. Called by NDIS if the miniport below supports
  1499. NDIS 4.0 style receives. Re-package the buffer chain in a new packet
  1500. and indicate the new packet to interested protocols above us.
  1501. Arguments:
  1502. ProtocolBindingContext - Pointer to our adapter structure.
  1503. Packet - Pointer to the packet
  1504. Return Value:
  1505. == 0 -> We are done with the packet
  1506. != 0 -> We will keep the packet and call NdisReturnPackets() this
  1507. many times when done.
  1508. --*/
  1509. {
  1510. PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
  1511. PVELAN pVElan;
  1512. PLIST_ENTRY p;
  1513. NDIS_STATUS Status;
  1514. NDIS_STATUS PacketStatus;
  1515. PNDIS_PACKET MyPacket;
  1516. PUCHAR pData;
  1517. PNDIS_BUFFER pNdisBuffer;
  1518. UINT FirstBufferLength;
  1519. UINT TotalLength;
  1520. PUCHAR pDstMac;
  1521. BOOLEAN bIsMulticast, bIsBroadcast;
  1522. PMUX_RECV_RSVD pRecvReserved;
  1523. ULONG ReturnCount;
  1524. LOCK_STATE LockState;
  1525. ReturnCount = 0;
  1526. do
  1527. {
  1528. if (pAdapt->PacketFilter == 0)
  1529. {
  1530. //
  1531. // We could get receives in the interval between
  1532. // initiating a request to set the packet filter on
  1533. // the binding to 0 and completion of that request.
  1534. // Drop such packets.
  1535. //
  1536. break;
  1537. }
  1538. #ifdef NDIS51
  1539. //
  1540. // Collect some information from the packet.
  1541. //
  1542. NdisGetFirstBufferFromPacketSafe(Packet,
  1543. &pNdisBuffer,
  1544. &pData,
  1545. &FirstBufferLength,
  1546. &TotalLength,
  1547. NormalPagePriority);
  1548. if (pNdisBuffer == NULL)
  1549. {
  1550. //
  1551. // Out of system resources. Drop this packet.
  1552. //
  1553. break;
  1554. }
  1555. #else
  1556. NdisGetFirstBufferFromPacket(Packet,
  1557. &pNdisBuffer,
  1558. &pData,
  1559. &FirstBufferLength,
  1560. &TotalLength);
  1561. #endif
  1562. pDstMac = pData;
  1563. bIsMulticast = ETH_IS_MULTICAST(pDstMac);
  1564. bIsBroadcast = ETH_IS_BROADCAST(pDstMac);
  1565. //
  1566. // Lock down the VELAN list on the adapter so that
  1567. // no insertions/deletions to this list happen while
  1568. // we loop through it. The packet filter will also not
  1569. // change during the time we hold the read lock.
  1570. //
  1571. MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
  1572. for (p = pAdapt->VElanList.Flink;
  1573. p != &pAdapt->VElanList;
  1574. p = p->Flink)
  1575. {
  1576. BOOLEAN bIndicateReceive;
  1577. pVElan = CONTAINING_RECORD(p, VELAN, Link);
  1578. //
  1579. // Should the packet be indicated up on this VELAN?
  1580. //
  1581. bIndicateReceive = PtMatchPacketToVElan(pVElan,
  1582. pDstMac,
  1583. bIsMulticast,
  1584. bIsBroadcast);
  1585. if (!bIndicateReceive)
  1586. {
  1587. continue;
  1588. }
  1589. //
  1590. // Make sure we don't Halt the VELAN miniport while
  1591. // we are accessing it here. See MPHalt.
  1592. //
  1593. // Also don't indicate receives if the virtual miniport
  1594. // has been set to a low power state. A specific case
  1595. // is when the system is resuming from "Stand-by", if
  1596. // the lower adapter is restored to D0 before the upper
  1597. // miniports are.
  1598. //
  1599. MUX_INCR_PENDING_RECEIVES(pVElan);
  1600. if ((pVElan->MiniportHalting) ||
  1601. (MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState)))
  1602. {
  1603. MUX_DECR_PENDING_RECEIVES(pVElan);
  1604. continue;
  1605. }
  1606. //
  1607. // Get a packet off the pool and indicate that up
  1608. //
  1609. NdisDprAllocatePacket(&Status,
  1610. &MyPacket,
  1611. pVElan->RecvPacketPoolHandle);
  1612. if (Status == NDIS_STATUS_SUCCESS)
  1613. {
  1614. PacketStatus = NDIS_GET_PACKET_STATUS(Packet);
  1615. pRecvReserved = MUX_RSVD_FROM_RECV_PACKET(MyPacket);
  1616. if (PacketStatus != NDIS_STATUS_RESOURCES)
  1617. {
  1618. pRecvReserved->pOriginalPacket = Packet;
  1619. }
  1620. else
  1621. {
  1622. //
  1623. // This will ensure we don't call NdisReturnPacket for the packet if the packet
  1624. // status is NDIS_STATUS_RESOURCES
  1625. //
  1626. pRecvReserved->pOriginalPacket = NULL;
  1627. }
  1628. MyPacket->Private.Head = Packet->Private.Head;
  1629. MyPacket->Private.Tail = Packet->Private.Tail;
  1630. //
  1631. // Get the original packet (it could be the same
  1632. // packet as the one received or a different one
  1633. // based on the number of layered miniports below)
  1634. // and set it on the indicated packet so the OOB
  1635. // data is visible correctly to protocols above us.
  1636. //
  1637. NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
  1638. //
  1639. // Copy Packet Flags
  1640. //
  1641. NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
  1642. NDIS_SET_PACKET_STATUS(MyPacket, PacketStatus);
  1643. NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));
  1644. #if IEEE_VLAN_SUPPORT
  1645. Status = PtHandleRcvTagging(pVElan, Packet, MyPacket);
  1646. if (Status != NDIS_STATUS_SUCCESS)
  1647. {
  1648. NdisFreePacket(MyPacket);
  1649. MUX_DECR_PENDING_RECEIVES(pVElan);
  1650. continue;
  1651. }
  1652. #endif
  1653. MUX_INCR_STATISTICS64(&pVElan->GoodReceives);
  1654. //
  1655. // Indicate it up.
  1656. //
  1657. if (PacketStatus != NDIS_STATUS_RESOURCES)
  1658. {
  1659. ReturnCount++;
  1660. }
  1661. NdisMIndicateReceivePacket(pVElan->MiniportAdapterHandle,
  1662. &MyPacket,
  1663. 1);
  1664. //
  1665. // Check if we had indicated up the packet with
  1666. // status set to NDIS_STATUS_RESOURCES.
  1667. //
  1668. // NOTE -- do not use NDIS_GET_PACKET_STATUS(MyPacket)
  1669. // for this since it might have changed! Use the value
  1670. // saved in the local variable.
  1671. //
  1672. if (PacketStatus == NDIS_STATUS_RESOURCES)
  1673. {
  1674. //
  1675. // Our ReturnPackets handler will not be called
  1676. // for this packet. We should reclaim it right here.
  1677. //
  1678. MPReturnPacket((NDIS_HANDLE)pVElan, MyPacket);
  1679. }
  1680. }
  1681. else
  1682. {
  1683. //
  1684. // Failed to allocate a packet.
  1685. //
  1686. MUX_INCR_STATISTICS(&pVElan->RcvResourceErrors);
  1687. MUX_DECR_PENDING_RECEIVES(pVElan);
  1688. }
  1689. } // for (loop thru all VELANs)
  1690. MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
  1691. }
  1692. while (FALSE);
  1693. //
  1694. // Return the # of receive indications made for this packet.
  1695. // We will call NdisReturnPackets for this packet as many
  1696. // times (see MPReturnPackets).
  1697. //
  1698. return (ReturnCount);
  1699. }
  1700. NDIS_STATUS
  1701. PtPnPNetEventSetPower(
  1702. IN PADAPT pAdapt,
  1703. IN PNET_PNP_EVENT pNetPnPEvent
  1704. )
  1705. /*++
  1706. Routine Description:
  1707. This is a notification to our protocol edge of the power state
  1708. of the lower miniport. If it is going to a low-power state, we must
  1709. wait here for all outstanding sends and requests to complete.
  1710. Arguments:
  1711. pAdapt - Pointer to the adpater structure
  1712. pNetPnPEvent - The Net Pnp Event. this contains the new device state
  1713. Return Value:
  1714. NDIS_STATUS_SUCCESS
  1715. --*/
  1716. {
  1717. PLIST_ENTRY p;
  1718. PVELAN pVElan;
  1719. LOCK_STATE LockState;
  1720. NDIS_STATUS Status;
  1721. //
  1722. // Store the new power state.
  1723. //
  1724. pAdapt->PtDevicePowerState = *(PNDIS_DEVICE_POWER_STATE)pNetPnPEvent->Buffer;
  1725. DBGPRINT(MUX_LOUD, ("PnPNetEventSetPower: Adapt %p, SetPower to %d\n",
  1726. pAdapt, pAdapt->PtDevicePowerState));
  1727. //
  1728. // Check if the miniport below is going to a low power state.
  1729. //
  1730. if (MUX_IS_LOW_POWER_STATE(pAdapt->PtDevicePowerState))
  1731. {
  1732. ULONG i;
  1733. //
  1734. // It is going to a low power state. Wait for outstanding
  1735. // I/O to complete on the adapter.
  1736. //
  1737. for (i = 0; i < 10000; i++)
  1738. {
  1739. MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
  1740. for (p = pAdapt->VElanList.Flink;
  1741. p != &pAdapt->VElanList;
  1742. p = p->Flink)
  1743. {
  1744. pVElan = CONTAINING_RECORD(p, VELAN, Link);
  1745. if ((pVElan->OutstandingSends != 0) ||
  1746. (pVElan->OutstandingReceives != 0))
  1747. {
  1748. break;
  1749. }
  1750. }
  1751. MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
  1752. if (p == &pAdapt->VElanList)
  1753. {
  1754. //
  1755. // There are no VELANs with pending I/O.
  1756. //
  1757. break;
  1758. }
  1759. DBGPRINT(MUX_INFO, ("SetPower: Adapt %p, waiting for pending IO to complete\n",
  1760. pAdapt));
  1761. NdisMSleep(1000);
  1762. }
  1763. }
  1764. else
  1765. {
  1766. //
  1767. // The device below is powered on. If we had requests
  1768. // pending on any VELANs, send them down now.
  1769. //
  1770. MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
  1771. for (p = pAdapt->VElanList.Flink;
  1772. p != &pAdapt->VElanList;
  1773. p = p->Flink)
  1774. {
  1775. pVElan = CONTAINING_RECORD(p, VELAN, Link);
  1776. //
  1777. // Need to make sure other threads do not try to acquire the write lock while holding
  1778. // the same spin lock
  1779. //
  1780. NdisAcquireSpinLock(&pVElan->Lock);
  1781. if (pVElan->QueuedRequest)
  1782. {
  1783. pVElan->QueuedRequest = FALSE;
  1784. NdisReleaseSpinLock(&pVElan->Lock);
  1785. NdisRequest(&Status,
  1786. pAdapt->BindingHandle,
  1787. &pVElan->Request.Request);
  1788. if (Status != NDIS_STATUS_PENDING)
  1789. {
  1790. PtRequestComplete(pAdapt,
  1791. &pVElan->Request.Request,
  1792. Status);
  1793. }
  1794. }
  1795. else
  1796. {
  1797. NdisReleaseSpinLock(&pVElan->Lock);
  1798. }
  1799. }
  1800. MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
  1801. }
  1802. return (NDIS_STATUS_SUCCESS);
  1803. }
  1804. NDIS_STATUS
  1805. PtPNPHandler(
  1806. IN NDIS_HANDLE ProtocolBindingContext,
  1807. IN PNET_PNP_EVENT pNetPnPEvent
  1808. )
  1809. /*++
  1810. Routine Description:
  1811. This is called by NDIS to notify us of a PNP event related to a lower
  1812. binding. Based on the event, this dispatches to other helper routines.
  1813. Arguments:
  1814. ProtocolBindingContext - Pointer to our adapter structure. Can be NULL
  1815. for "global" notifications
  1816. pNetPnPEvent - Pointer to the PNP event to be processed.
  1817. Return Value:
  1818. NDIS_STATUS code indicating status of event processing.
  1819. --*/
  1820. {
  1821. PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
  1822. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1823. PLIST_ENTRY p;
  1824. DBGPRINT(MUX_LOUD, ("PtPnPHandler: Adapt %p, NetPnPEvent %d\n", pAdapt,
  1825. pNetPnPEvent->NetEvent));
  1826. switch (pNetPnPEvent->NetEvent)
  1827. {
  1828. case NetEventSetPower:
  1829. Status = PtPnPNetEventSetPower(pAdapt, pNetPnPEvent);
  1830. break;
  1831. case NetEventReconfigure:
  1832. //
  1833. // Rescan configuration and bring up any VELANs that
  1834. // have been newly added. Make sure that the global
  1835. // adapter list is undisturbed while we traverse it.
  1836. //
  1837. MUX_ACQUIRE_MUTEX(&GlobalMutex);
  1838. for (p = AdapterList.Flink;
  1839. p != &AdapterList;
  1840. p = p->Flink)
  1841. {
  1842. pAdapt = CONTAINING_RECORD(p, ADAPT, Link);
  1843. PtBootStrapVElans(pAdapt);
  1844. }
  1845. MUX_RELEASE_MUTEX(&GlobalMutex);
  1846. Status = NDIS_STATUS_SUCCESS;
  1847. break;
  1848. default:
  1849. Status = NDIS_STATUS_SUCCESS;
  1850. break;
  1851. }
  1852. return Status;
  1853. }
  1854. NDIS_STATUS
  1855. PtCreateAndStartVElan(
  1856. IN PADAPT pAdapt,
  1857. IN PNDIS_STRING pVElanKey
  1858. )
  1859. /*++
  1860. Routine Description:
  1861. Create and start a VELAN with the given key name. Check if a VELAN
  1862. with this key name already exists; if so do nothing.
  1863. ASSUMPTION: this is called from either the BindAdapter handler for
  1864. the underlying adapter, or from the PNP reconfig handler. Both these
  1865. routines are protected by NDIS against pre-emption by UnbindAdapter.
  1866. If this routine will be called from any other context, it should
  1867. be protected against a simultaneous call to our UnbindAdapter handler.
  1868. Arguments:
  1869. pAdapt - Pointer to Adapter structure
  1870. pVElanKey - Points to a Unicode string naming the VELAN to create.
  1871. Return Value:
  1872. NDIS_STATUS_SUCCESS if we either found a duplicate VELAN or
  1873. successfully initiated a new ELAN with the given key.
  1874. NDIS_STATUS_XXX error code otherwise (failure initiating a new VELAN).
  1875. --*/
  1876. {
  1877. NDIS_STATUS Status;
  1878. PVELAN pVElan;
  1879. Status = NDIS_STATUS_SUCCESS;
  1880. pVElan = NULL;
  1881. DBGPRINT(MUX_LOUD, ("=> Create VElan: Adapter %p, ElanKey %ws\n",
  1882. pAdapt, pVElanKey->Buffer));
  1883. do
  1884. {
  1885. //
  1886. // Weed out duplicates.
  1887. //
  1888. if (pVElanKey != NULL)
  1889. {
  1890. pVElan = PtFindVElan(pAdapt, pVElanKey);
  1891. if (NULL != pVElan)
  1892. {
  1893. //
  1894. // Duplicate - bail out silently.
  1895. //
  1896. DBGPRINT(MUX_WARN, ("CreateElan: found duplicate pVElan %x\n", pVElan));
  1897. Status = NDIS_STATUS_SUCCESS;
  1898. pVElan = NULL;
  1899. break;
  1900. }
  1901. }
  1902. pVElan = PtAllocateAndInitializeVElan(pAdapt, pVElanKey);
  1903. if (pVElan == NULL)
  1904. {
  1905. Status = NDIS_STATUS_RESOURCES;
  1906. break;
  1907. }
  1908. //
  1909. // Request NDIS to initialize the virtual miniport. Set
  1910. // the flag below just in case an unbind occurs before
  1911. // MiniportInitialize is called.
  1912. //
  1913. pVElan->MiniportInitPending = TRUE;
  1914. NdisInitializeEvent(&pVElan->MiniportInitEvent);
  1915. Status = NdisIMInitializeDeviceInstanceEx(DriverHandle,
  1916. &pVElan->CfgDeviceName,
  1917. pVElan);
  1918. if (Status != NDIS_STATUS_SUCCESS)
  1919. {
  1920. PtUnlinkVElanFromAdapter(pVElan); // IMInit failed
  1921. pVElan = NULL;
  1922. break;
  1923. }
  1924. }
  1925. while (FALSE);
  1926. DBGPRINT(MUX_INFO, ("<= Create VElan: Adapter %p, VELAN %p\n", pAdapt, pVElan));
  1927. return Status;
  1928. }
  1929. PVELAN
  1930. PtAllocateAndInitializeVElan(
  1931. IN PADAPT pAdapt,
  1932. IN PNDIS_STRING pVElanKey
  1933. )
  1934. /*++
  1935. Routine Description:
  1936. Allocates and initializes a VELAN structure. Also links it to
  1937. the specified ADAPT.
  1938. Arguments:
  1939. pAdapt - Adapter to link VELAN to
  1940. pVElanKey - Key to the VELAN
  1941. Return Value:
  1942. Pointer to VELAN structure if successful, NULL otherwise.
  1943. --*/
  1944. {
  1945. PVELAN pVElan;
  1946. ULONG Length;
  1947. NDIS_STATUS Status;
  1948. LOCK_STATE LockState;
  1949. pVElan = NULL;
  1950. Status = NDIS_STATUS_SUCCESS;
  1951. do
  1952. {
  1953. Length = sizeof(VELAN) + pVElanKey->Length + sizeof(WCHAR);
  1954. //
  1955. // Allocate a VELAN data structure.
  1956. //
  1957. NdisAllocateMemoryWithTag(&pVElan, Length, TAG);
  1958. if (pVElan == NULL)
  1959. {
  1960. DBGPRINT(MUX_FATAL, ("AllocateVElan: Failed to allocate %d bytes for VELAN\n",
  1961. Length));
  1962. Status = NDIS_STATUS_RESOURCES;
  1963. break;
  1964. }
  1965. //
  1966. // Initialize it.
  1967. //
  1968. NdisZeroMemory(pVElan, Length);
  1969. NdisInitializeListHead(&pVElan->Link);
  1970. //
  1971. // Initialize the built-in request structure to signify
  1972. // that it is used to forward NDIS requests.
  1973. //
  1974. pVElan->Request.pVElan = pVElan;
  1975. NdisInitializeEvent(&pVElan->Request.Event);
  1976. //
  1977. // Store in the key name.
  1978. //
  1979. pVElan->CfgDeviceName.Length = 0;
  1980. pVElan->CfgDeviceName.Buffer = (PWCHAR)((PUCHAR)pVElan +
  1981. sizeof(VELAN));
  1982. pVElan->CfgDeviceName.MaximumLength =
  1983. pVElanKey->MaximumLength + sizeof(WCHAR);
  1984. (VOID)NdisUpcaseUnicodeString(&pVElan->CfgDeviceName, pVElanKey);
  1985. pVElan->CfgDeviceName.Buffer[pVElanKey->Length/sizeof(WCHAR)] =
  1986. ((WCHAR)0);
  1987. //
  1988. // Initialize LastIndicatedStatus to media connect
  1989. //
  1990. pVElan->LastIndicatedStatus = NDIS_STATUS_MEDIA_CONNECT;
  1991. //
  1992. // Set power state of virtual miniport to D0.
  1993. //
  1994. pVElan->MPDevicePowerState = NdisDeviceStateD0;
  1995. //
  1996. // Cache the binding handle for quick reference.
  1997. //
  1998. pVElan->BindingHandle = pAdapt->BindingHandle;
  1999. pVElan->pAdapt = pAdapt;
  2000. //
  2001. // Copy in some adapter parameters.
  2002. //
  2003. pVElan->LookAhead = pAdapt->MaxLookAhead;
  2004. pVElan->LinkSpeed = pAdapt->LinkSpeed;
  2005. NdisMoveMemory(pVElan->PermanentAddress,
  2006. pAdapt->CurrentAddress,
  2007. sizeof(pVElan->PermanentAddress));
  2008. NdisMoveMemory(pVElan->CurrentAddress,
  2009. pAdapt->CurrentAddress,
  2010. sizeof(pVElan->CurrentAddress));
  2011. DBGPRINT(MUX_LOUD, ("Alloced VELAN %p, MAC addr %s\n",
  2012. pVElan, MacAddrToString(pVElan->CurrentAddress)));
  2013. NdisAllocateSpinLock(&pVElan->Lock);
  2014. #if IEEE_VLAN_SUPPORT
  2015. //
  2016. // Allocate lookaside list for tag headers.
  2017. //
  2018. NdisInitializeNPagedLookasideList (
  2019. &pVElan->TagLookaside,
  2020. NULL,
  2021. NULL,
  2022. 0,
  2023. ETH_HEADER_SIZE + VLAN_TAG_HEADER_SIZE,
  2024. 'TxuM',
  2025. 0);
  2026. #endif
  2027. //
  2028. // Allocate a packet pool for sends.
  2029. //
  2030. NdisAllocatePacketPoolEx(&Status,
  2031. &pVElan->SendPacketPoolHandle,
  2032. MIN_PACKET_POOL_SIZE,
  2033. MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
  2034. sizeof(MUX_SEND_RSVD));
  2035. if (Status != NDIS_STATUS_SUCCESS)
  2036. {
  2037. DBGPRINT(MUX_FATAL, ("PtAllocateVElan: failed to allocate send packet pool\n"));
  2038. break;
  2039. }
  2040. //
  2041. // NOTE: this sample driver does not -originate- packets in the
  2042. // send or receive directions. If the driver must originate packets,
  2043. // here is a good place to allocate NDIS buffer pool(s) for
  2044. // this purpose.
  2045. //
  2046. #if IEEE_VLAN_SUPPORT
  2047. //
  2048. // Allocate a buffer pool for tag headers.
  2049. //
  2050. NdisAllocateBufferPool (&Status,
  2051. &pVElan->BufferPoolHandle,
  2052. MIN_PACKET_POOL_SIZE);
  2053. ASSERT(Status == NDIS_STATUS_SUCCESS);
  2054. #endif
  2055. //
  2056. // Allocate a packet pool for receives.
  2057. //
  2058. NdisAllocatePacketPoolEx(&Status,
  2059. &pVElan->RecvPacketPoolHandle,
  2060. MIN_PACKET_POOL_SIZE,
  2061. MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
  2062. PROTOCOL_RESERVED_SIZE_IN_PACKET);
  2063. if (Status != NDIS_STATUS_SUCCESS)
  2064. {
  2065. DBGPRINT(MUX_FATAL, ("PtAllocateVElan: failed to allocate receive packet pool\n"));
  2066. break;
  2067. }
  2068. //
  2069. // Finally link this VELAN to the Adapter's VELAN list.
  2070. //
  2071. PtReferenceVElan(pVElan, (PUCHAR)"adapter");
  2072. MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  2073. PtReferenceAdapter(pAdapt, (PUCHAR)"VElan");
  2074. InsertTailList(&pAdapt->VElanList, &pVElan->Link);
  2075. pAdapt->VElanCount++;
  2076. pVElan->VElanNumber = NdisInterlockedIncrement((PLONG)&NextVElanNumber);
  2077. MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  2078. }
  2079. while (FALSE);
  2080. if (Status != NDIS_STATUS_SUCCESS)
  2081. {
  2082. if (pVElan)
  2083. {
  2084. PtDeallocateVElan(pVElan);
  2085. pVElan = NULL;
  2086. }
  2087. }
  2088. return (pVElan);
  2089. }
  2090. VOID
  2091. PtDeallocateVElan(
  2092. IN PVELAN pVElan
  2093. )
  2094. /*++
  2095. Routine Description:
  2096. Free up all resources allocated to a VELAN, and then the VELAN
  2097. structure itself.
  2098. Arguments:
  2099. pVElan - Pointer to VELAN to be deallocated.
  2100. Return Value:
  2101. None
  2102. --*/
  2103. {
  2104. if (pVElan->SendPacketPoolHandle != NULL)
  2105. {
  2106. NdisFreePacketPool(pVElan->SendPacketPoolHandle);
  2107. }
  2108. if (pVElan->RecvPacketPoolHandle != NULL)
  2109. {
  2110. NdisFreePacketPool(pVElan->RecvPacketPoolHandle);
  2111. }
  2112. #if IEEE_VLAN_SUPPORT
  2113. NdisFreeBufferPool(pVElan->BufferPoolHandle);
  2114. NdisDeleteNPagedLookasideList(&pVElan->TagLookaside);
  2115. #endif
  2116. NdisFreeMemory(pVElan, 0, 0);
  2117. }
  2118. VOID
  2119. PtStopVElan(
  2120. IN PVELAN pVElan
  2121. )
  2122. /*++
  2123. Routine Description:
  2124. Stop a VELAN by requesting NDIS to halt the virtual miniport.
  2125. The caller has a reference on the VELAN, so it won't go away
  2126. while we are executing in this routine.
  2127. ASSUMPTION: this is only called in the context of unbinding
  2128. from the underlying miniport. If it may be called from elsewhere,
  2129. this should protect itself from re-entrancy.
  2130. Arguments:
  2131. pVElan - Pointer to VELAN to be stopped.
  2132. Return Value:
  2133. None
  2134. --*/
  2135. {
  2136. NDIS_STATUS Status;
  2137. NDIS_HANDLE MiniportAdapterHandle;
  2138. BOOLEAN bMiniportInitCancelled = FALSE;
  2139. DBGPRINT(MUX_LOUD, ("=> StopVElan: VELAN %p, Adapt %p\n", pVElan, pVElan->pAdapt));
  2140. //
  2141. // We make blocking calls below.
  2142. //
  2143. ASSERT_AT_PASSIVE();
  2144. //
  2145. // If there was a queued request on this VELAN, fail it now.
  2146. //
  2147. NdisAcquireSpinLock(&pVElan->Lock);
  2148. ASSERT(pVElan->DeInitializing == TRUE);
  2149. if (pVElan->QueuedRequest)
  2150. {
  2151. pVElan->QueuedRequest = FALSE;
  2152. NdisReleaseSpinLock(&pVElan->Lock);
  2153. PtRequestComplete(pVElan->pAdapt,
  2154. &pVElan->Request.Request,
  2155. NDIS_STATUS_FAILURE);
  2156. }
  2157. else
  2158. {
  2159. NdisReleaseSpinLock(&pVElan->Lock);
  2160. }
  2161. //
  2162. // Check if we had called NdisIMInitializeDeviceInstanceEx and
  2163. // we are awaiting a call to MiniportInitialize.
  2164. //
  2165. if (pVElan->MiniportInitPending)
  2166. {
  2167. //
  2168. // Attempt to cancel miniport init.
  2169. //
  2170. Status = NdisIMCancelInitializeDeviceInstance(
  2171. DriverHandle,
  2172. &pVElan->CfgDeviceName);
  2173. if (Status == NDIS_STATUS_SUCCESS)
  2174. {
  2175. //
  2176. // Successfully cancelled IM initialization; our
  2177. // Miniport Init routine will not be called for this
  2178. // VELAN miniport.
  2179. //
  2180. pVElan->MiniportInitPending = FALSE;
  2181. ASSERT(pVElan->MiniportAdapterHandle == NULL);
  2182. bMiniportInitCancelled = TRUE;
  2183. }
  2184. else
  2185. {
  2186. //
  2187. // Our Miniport Initialize routine will be called
  2188. // (may be running on another thread at this time).
  2189. // Wait for it to finish.
  2190. //
  2191. NdisWaitEvent(&pVElan->MiniportInitEvent, 0);
  2192. ASSERT(pVElan->MiniportInitPending == FALSE);
  2193. }
  2194. }
  2195. //
  2196. // Check if Miniport Init has run. If so, deinitialize the virtual
  2197. // miniport. This will result in a call to our Miniport Halt routine,
  2198. // where the VELAN will be cleaned up.
  2199. //
  2200. MiniportAdapterHandle = pVElan->MiniportAdapterHandle;
  2201. if ((NULL != MiniportAdapterHandle) &&
  2202. (!pVElan->MiniportHalting))
  2203. {
  2204. //
  2205. // The miniport was initialized, and has not yet halted.
  2206. //
  2207. ASSERT(bMiniportInitCancelled == FALSE);
  2208. (VOID)NdisIMDeInitializeDeviceInstance(MiniportAdapterHandle);
  2209. }
  2210. else
  2211. {
  2212. if (bMiniportInitCancelled)
  2213. {
  2214. //
  2215. // No NDIS events can come to this VELAN since it
  2216. // was never initialized as a miniport. We need to unlink
  2217. // it explicitly here.
  2218. //
  2219. PtUnlinkVElanFromAdapter(pVElan);
  2220. }
  2221. }
  2222. }
  2223. VOID
  2224. PtUnlinkVElanFromAdapter(
  2225. IN PVELAN pVElan
  2226. )
  2227. /*++
  2228. Routine Description:
  2229. Utility routine to unlink a VELAN from its parent ADAPT structure.
  2230. Arguments:
  2231. pVElan - Pointer to VELAN to be unlinked.
  2232. Return Value:
  2233. None
  2234. --*/
  2235. {
  2236. PADAPT pAdapt = pVElan->pAdapt;
  2237. LOCK_STATE LockState;
  2238. ASSERT(pAdapt != NULL);
  2239. //
  2240. // Remove this VELAN from the Adapter list
  2241. //
  2242. MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  2243. RemoveEntryList(&pVElan->Link);
  2244. pAdapt->VElanCount--;
  2245. MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  2246. pVElan->pAdapt = NULL;
  2247. PtDereferenceVElan(pVElan, (PUCHAR)"adapter");
  2248. PtDereferenceAdapter(pAdapt, (PUCHAR)"VElan");
  2249. }
  2250. PVELAN
  2251. PtFindVElan(
  2252. IN PADAPT pAdapt,
  2253. IN PNDIS_STRING pVElanKey
  2254. )
  2255. /*++
  2256. Routine Description:
  2257. Find an ELAN by bind name/key
  2258. Arguments:
  2259. pAdapt - Pointer to an adapter struct.
  2260. pVElanKey - The VELAN's device name
  2261. Return Value:
  2262. Pointer to matching VELAN or NULL if not found.
  2263. --*/
  2264. {
  2265. PLIST_ENTRY p;
  2266. PVELAN pVElan;
  2267. BOOLEAN Found;
  2268. NDIS_STRING VElanKeyName;
  2269. LOCK_STATE LockState;
  2270. ASSERT_AT_PASSIVE();
  2271. DBGPRINT(MUX_LOUD, ("FindElan: Adapter %p, ElanKey %ws\n", pAdapt,
  2272. pVElanKey->Buffer));
  2273. pVElan = NULL;
  2274. Found = FALSE;
  2275. VElanKeyName.Buffer = NULL;
  2276. do
  2277. {
  2278. //
  2279. // Make an up-cased copy of the given string.
  2280. //
  2281. NdisAllocateMemoryWithTag(&VElanKeyName.Buffer,
  2282. pVElanKey->MaximumLength, TAG);
  2283. if (VElanKeyName.Buffer == NULL)
  2284. {
  2285. break;
  2286. }
  2287. VElanKeyName.Length = pVElanKey->Length;
  2288. VElanKeyName.MaximumLength = pVElanKey->MaximumLength;
  2289. (VOID)NdisUpcaseUnicodeString(&VElanKeyName, pVElanKey);
  2290. //
  2291. // Go through all VELANs on the ADAPT structure, looking
  2292. // for a VELAN that has a matching device name.
  2293. //
  2294. MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
  2295. p = pAdapt->VElanList.Flink;
  2296. while (p != &pAdapt->VElanList)
  2297. {
  2298. pVElan = CONTAINING_RECORD(p, VELAN, Link);
  2299. if ((VElanKeyName.Length == pVElan->CfgDeviceName.Length) &&
  2300. (memcmp(VElanKeyName.Buffer, pVElan->CfgDeviceName.Buffer,
  2301. VElanKeyName.Length) == 0))
  2302. {
  2303. Found = TRUE;
  2304. break;
  2305. }
  2306. p = p->Flink;
  2307. }
  2308. MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
  2309. }
  2310. while (FALSE);
  2311. if (!Found)
  2312. {
  2313. DBGPRINT(MUX_INFO, ( "FindElan: No match found!\n"));
  2314. pVElan = NULL;
  2315. }
  2316. if (VElanKeyName.Buffer)
  2317. {
  2318. NdisFreeMemory(VElanKeyName.Buffer, VElanKeyName.Length, 0);
  2319. }
  2320. return pVElan;
  2321. }
  2322. NDIS_STATUS
  2323. PtBootStrapVElans(
  2324. IN PADAPT pAdapt
  2325. )
  2326. /*++
  2327. Routine Description:
  2328. Start up the VELANs configured for an adapter.
  2329. Arguments:
  2330. pAdapt - Pointer to ATMLANE Adapter structure
  2331. Return Value:
  2332. None
  2333. --*/
  2334. {
  2335. NDIS_STATUS Status;
  2336. NDIS_HANDLE AdapterConfigHandle;
  2337. PNDIS_CONFIGURATION_PARAMETER Param;
  2338. NDIS_STRING DeviceStr = NDIS_STRING_CONST("UpperBindings");
  2339. PWSTR buffer;
  2340. LOCK_STATE LockState;
  2341. //
  2342. // Initialize.
  2343. //
  2344. Status = NDIS_STATUS_SUCCESS;
  2345. AdapterConfigHandle = NULL;
  2346. do
  2347. {
  2348. DBGPRINT(MUX_LOUD, ("BootStrapElans: Starting ELANs on adapter %x\n", pAdapt));
  2349. //
  2350. // Open the protocol configuration section for this adapter.
  2351. //
  2352. NdisOpenProtocolConfiguration(&Status,
  2353. &AdapterConfigHandle,
  2354. &pAdapt->ConfigString);
  2355. if (NDIS_STATUS_SUCCESS != Status)
  2356. {
  2357. AdapterConfigHandle = NULL;
  2358. DBGPRINT(MUX_ERROR, ("BootStrapElans: OpenProtocolConfiguration failed\n"));
  2359. Status = NDIS_STATUS_OPEN_FAILED;
  2360. break;
  2361. }
  2362. //
  2363. // Read the "UpperBindings" reserved key that contains a list
  2364. // of device names representing our miniport instances corresponding
  2365. // to this lower binding. The UpperBindings is a
  2366. // MULTI_SZ containing a list of device names. We will loop through
  2367. // this list and initialize the virtual miniports.
  2368. //
  2369. NdisReadConfiguration(&Status,
  2370. &Param,
  2371. AdapterConfigHandle,
  2372. &DeviceStr,
  2373. NdisParameterMultiString);
  2374. if (NDIS_STATUS_SUCCESS != Status)
  2375. {
  2376. DBGPRINT(MUX_ERROR, ("BootStrapElans: NdisReadConfiguration failed\n"));
  2377. break;
  2378. }
  2379. //
  2380. // Parse the Multi_sz string to extract the device name of each VELAN.
  2381. // This is used as the key name for the VELAN.
  2382. //
  2383. buffer = (PWSTR)Param->ParameterData.StringData.Buffer;
  2384. while(*buffer != L'\0')
  2385. {
  2386. NDIS_STRING DeviceName;
  2387. NdisInitUnicodeString(&DeviceName, buffer);
  2388. Status = PtCreateAndStartVElan(pAdapt, &DeviceName);
  2389. if (NDIS_STATUS_SUCCESS != Status)
  2390. {
  2391. DBGPRINT(MUX_ERROR, ("BootStrapElans: CreateVElan failed\n"));
  2392. break;
  2393. }
  2394. buffer = (PWSTR)((PUCHAR)buffer + DeviceName.Length + sizeof(WCHAR));
  2395. };
  2396. } while (FALSE);
  2397. //
  2398. // Close config handles
  2399. //
  2400. if (NULL != AdapterConfigHandle)
  2401. {
  2402. NdisCloseConfiguration(AdapterConfigHandle);
  2403. }
  2404. //
  2405. // If the driver cannot create any velan for the adapter
  2406. //
  2407. if (Status != NDIS_STATUS_SUCCESS)
  2408. {
  2409. MUX_ACQUIRE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  2410. //
  2411. // No VElan is created for this adapter
  2412. //
  2413. if (pAdapt->VElanCount != 0)
  2414. {
  2415. Status = NDIS_STATUS_SUCCESS;
  2416. }
  2417. MUX_RELEASE_ADAPT_WRITE_LOCK(pAdapt, &LockState);
  2418. }
  2419. return Status;
  2420. }
  2421. VOID
  2422. PtReferenceVElan(
  2423. IN PVELAN pVElan,
  2424. IN PUCHAR String
  2425. )
  2426. /*++
  2427. Routine Description:
  2428. Add a references to an Elan structure.
  2429. Arguments:
  2430. pElan - Pointer to the Elan structure.
  2431. Return Value:
  2432. None.
  2433. --*/
  2434. {
  2435. NdisInterlockedIncrement((PLONG)&pVElan->RefCount);
  2436. #if !DBG
  2437. UNREFERENCED_PARAMETER(String);
  2438. #endif
  2439. DBGPRINT(MUX_LOUD, ("ReferenceElan: Elan %p (%s) new count %d\n",
  2440. pVElan, String, pVElan->RefCount));
  2441. return;
  2442. }
  2443. ULONG
  2444. PtDereferenceVElan(
  2445. IN PVELAN pVElan,
  2446. IN PUCHAR String
  2447. )
  2448. /*++
  2449. Routine Description:
  2450. Subtract a reference from an VElan structure.
  2451. If the reference count becomes zero, deallocate it.
  2452. Arguments:
  2453. pElan - Pointer to an VElan structure.
  2454. Return Value:
  2455. None.
  2456. --*/
  2457. {
  2458. ULONG rc;
  2459. #if !DBG
  2460. UNREFERENCED_PARAMETER(String);
  2461. #endif
  2462. ASSERT(pVElan->RefCount > 0);
  2463. rc = NdisInterlockedDecrement((PLONG)&pVElan->RefCount);
  2464. if (rc == 0)
  2465. {
  2466. //
  2467. // Free memory if there is no outstanding reference.
  2468. // Note: Length field is not required if the memory
  2469. // is allocated with NdisAllocateMemoryWithTag.
  2470. //
  2471. PtDeallocateVElan(pVElan);
  2472. }
  2473. DBGPRINT(MUX_LOUD, ("DereferenceElan: VElan %p (%s) new count %d\n",
  2474. pVElan, String, rc));
  2475. return (rc);
  2476. }
  2477. BOOLEAN
  2478. PtReferenceAdapter(
  2479. IN PADAPT pAdapt,
  2480. IN PUCHAR String
  2481. )
  2482. /*++
  2483. Routine Description:
  2484. Add a references to an Adapter structure.
  2485. Arguments:
  2486. pAdapt - Pointer to the Adapter structure.
  2487. Return Value:
  2488. None.
  2489. --*/
  2490. {
  2491. #if !DBG
  2492. UNREFERENCED_PARAMETER(String);
  2493. #endif
  2494. NdisInterlockedIncrement((PLONG)&pAdapt->RefCount);
  2495. DBGPRINT(MUX_LOUD, ("ReferenceAdapter: Adapter %x (%s) new count %d\n",
  2496. pAdapt, String, pAdapt->RefCount));
  2497. return TRUE;
  2498. }
  2499. ULONG
  2500. PtDereferenceAdapter(
  2501. IN PADAPT pAdapt,
  2502. IN PUCHAR String
  2503. )
  2504. /*++
  2505. Routine Description:
  2506. Subtract a reference from an Adapter structure.
  2507. If the reference count becomes zero, deallocate it.
  2508. Arguments:
  2509. pAdapt - Pointer to an adapter structure.
  2510. Return Value:
  2511. None.
  2512. --*/
  2513. {
  2514. ULONG rc;
  2515. #if !DBG
  2516. UNREFERENCED_PARAMETER(String);
  2517. #endif
  2518. ASSERT(pAdapt->RefCount > 0);
  2519. rc = NdisInterlockedDecrement ((PLONG)&pAdapt->RefCount);
  2520. if (rc == 0)
  2521. {
  2522. //
  2523. // Free memory if there is no outstanding reference.
  2524. // Note: Length field is not required if the memory
  2525. // is allocated with NdisAllocateMemoryWithTag.
  2526. //
  2527. NdisFreeMemory(pAdapt, 0, 0);
  2528. }
  2529. DBGPRINT(MUX_LOUD, ("DereferenceAdapter: Adapter %x (%s) new count %d\n",
  2530. pAdapt, String, rc));
  2531. return (rc);
  2532. }
  2533. #if IEEE_VLAN_SUPPORT
  2534. NDIS_STATUS
  2535. PtHandleRcvTagging(
  2536. IN PVELAN pVElan,
  2537. IN PNDIS_PACKET Packet,
  2538. IN OUT PNDIS_PACKET MyPacket
  2539. )
  2540. /*++
  2541. Routine Description:
  2542. Parse a received Ethernet frame for 802.1Q tag information.
  2543. If a tag header is present, copy in relevant field values to
  2544. per-packet information to the new packet (MyPacket) used to
  2545. indicate up this frame.
  2546. Arguments:
  2547. pVElan - Pointer to the VELAN structure.
  2548. Packet - Pointer to the indicated packet from the lower miniport
  2549. MyPacket - Pointer to the new allocated packet
  2550. Return Value:
  2551. NDIS_STATUS_SUCCESS if the frame was successfully parsed
  2552. and hence should be indicated up this VELAN. NDIS_STATUS_XXX
  2553. otherwise.
  2554. --*/
  2555. {
  2556. VLAN_TAG_HEADER UNALIGNED * pTagHeader;
  2557. USHORT UNALIGNED * pTpid;
  2558. PVOID pVa;
  2559. ULONG BufferLength;
  2560. PNDIS_BUFFER pNdisBuffer;
  2561. NDIS_PACKET_8021Q_INFO NdisPacket8021qInfo;
  2562. PVOID pDst;
  2563. BOOLEAN OnlyOneBuffer = FALSE;
  2564. NDIS_STATUS Status;
  2565. Status = NDIS_STATUS_SUCCESS;
  2566. do
  2567. {
  2568. //
  2569. // If the vlan ID the virtual miniport is 0, the miniport should act like it doesn't support
  2570. // VELAN tag processing
  2571. //
  2572. if (pVElan->VlanId == 0)
  2573. {
  2574. break;
  2575. }
  2576. pNdisBuffer = Packet->Private.Head;
  2577. #ifdef NDIS51_MINIPORT
  2578. NdisQueryBufferSafe(pNdisBuffer, &pVa, (PUINT)&BufferLength, NormalPagePriority );
  2579. if (pVa == NULL)
  2580. {
  2581. Status = NDIS_STATUS_RESOURCES;
  2582. MUX_INCR_STATISTICS(&pVElan->RcvResourceErrors);
  2583. break;
  2584. }
  2585. #else
  2586. NdisQueryBuffer(pNdisBuffer, &pVa, &BufferLength);
  2587. #endif
  2588. //
  2589. // The first NDIS buffer (lookahead) must be longer than
  2590. // ETH_HEADER_SIZE + VLAN_TAG_HEADER_SIZE
  2591. //
  2592. ASSERT(BufferLength >= ETH_HEADER_SIZE + VLAN_TAG_HEADER_SIZE);
  2593. //
  2594. // Get at the EtherType field.
  2595. //
  2596. pTpid = (USHORT UNALIGNED *)((PUCHAR)pVa + 2 * ETH_LENGTH_OF_ADDRESS);
  2597. //
  2598. // Check if a tag header is present.
  2599. //
  2600. if (*pTpid != TPID)
  2601. {
  2602. //
  2603. // No tag header exists - nothing more to do here.
  2604. //
  2605. NDIS_PER_PACKET_INFO_FROM_PACKET(MyPacket, Ieee8021QInfo) = 0;
  2606. break;
  2607. }
  2608. //
  2609. // We do have a tag header. Parse it further.
  2610. //
  2611. //
  2612. // If E-RIF is present, discard the packet - we don't
  2613. // support this variation.
  2614. //
  2615. pTagHeader = (VLAN_TAG_HEADER UNALIGNED *)(pTpid + 1);
  2616. if (GET_CANONICAL_FORMAT_ID_FROM_TAG(pTagHeader) != 0)
  2617. {
  2618. //
  2619. // Drop the packet
  2620. //
  2621. Status = NDIS_STATUS_NOT_ACCEPTED;
  2622. MUX_INCR_STATISTICS(&pVElan->RcvFormatErrors);
  2623. break;
  2624. }
  2625. //
  2626. // If there is a VLAN ID in this frame, and we have
  2627. // a configured VLAN ID for this VELAN, check if they
  2628. // are the same - drop if not.
  2629. //
  2630. if ((GET_VLAN_ID_FROM_TAG(pTagHeader) != 0) &&
  2631. (GET_VLAN_ID_FROM_TAG(pTagHeader) != pVElan->VlanId))
  2632. {
  2633. Status = NDIS_STATUS_NOT_ACCEPTED;
  2634. MUX_INCR_STATISTICS(&pVElan->RcvVlanIdErrors);
  2635. break;
  2636. }
  2637. //
  2638. // Parsed this frame successfully. Copy in relevant
  2639. // parts of the tag header to per-packet information.
  2640. //
  2641. NdisPacket8021qInfo.Value = NULL; // initialize
  2642. COPY_TAG_INFO_FROM_HEADER_TO_PACKET_INFO(NdisPacket8021qInfo, pTagHeader);
  2643. NDIS_PER_PACKET_INFO_FROM_PACKET(MyPacket, Ieee8021QInfo) =
  2644. NdisPacket8021qInfo.Value;
  2645. //
  2646. // Strip off the tag header "in place":
  2647. //
  2648. pDst = (PVOID)((PUCHAR)pVa + VLAN_TAG_HEADER_SIZE);
  2649. RtlMoveMemory(pDst, pVa, 2 * ETH_LENGTH_OF_ADDRESS);
  2650. //
  2651. // Allocate a new buffer to describe the new first
  2652. // buffer in the packet. This could very well be the
  2653. // only buffer in the packet.
  2654. //
  2655. NdisAllocateBuffer(&Status,
  2656. &pNdisBuffer,
  2657. pVElan->BufferPoolHandle,
  2658. pDst,
  2659. BufferLength - VLAN_TAG_HEADER_SIZE);
  2660. if (Status != NDIS_STATUS_SUCCESS)
  2661. {
  2662. //
  2663. // Drop the packet
  2664. //
  2665. Status = NDIS_STATUS_RESOURCES;
  2666. MUX_INCR_STATISTICS(&pVElan->RcvResourceErrors);
  2667. break;
  2668. }
  2669. //
  2670. // Prepare the new packet to be indicated up: this consists
  2671. // of the buffer chain starting with the second buffer,
  2672. // appended to the first buffer set up in the previous step.
  2673. //
  2674. MyPacket->Private.Head = NDIS_BUFFER_LINKAGE(Packet->Private.Head);
  2675. //
  2676. // Only one buffer in the packet
  2677. //
  2678. if (MyPacket->Private.Head == NULL)
  2679. {
  2680. OnlyOneBuffer = TRUE;
  2681. }
  2682. NdisChainBufferAtFront(MyPacket, pNdisBuffer);
  2683. if (OnlyOneBuffer)
  2684. {
  2685. MyPacket->Private.Tail = MyPacket->Private.Head;
  2686. }
  2687. else
  2688. {
  2689. MyPacket->Private.Tail = Packet->Private.Tail;
  2690. }
  2691. }
  2692. while (FALSE);
  2693. return Status;
  2694. }
  2695. #endif // IEEE_VLAN_SUPPORT