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

5384 lines
136 KiB

  1. /*++
  2. Copyright(c) 1992 Microsoft Corporation
  3. Module Name:
  4. protocol.c
  5. Abstract:
  6. ATM Ethernet PVC driver.
  7. Author:
  8. ADube - created
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. const WCHAR c_szIMMiniportList[] = L"IMMiniportList";
  14. const WCHAR c_szUpperBindings[] = L"UpperBindings";
  15. #define MAX_PACKET_POOL_SIZE 0x0000FFFF
  16. #define MIN_PACKET_POOL_SIZE 0x000000FF
  17. VOID
  18. EpvcResetComplete(
  19. IN NDIS_HANDLE ProtocolBindingContext,
  20. IN NDIS_STATUS Status
  21. )
  22. /*++
  23. Routine Description:
  24. Completion for the reset.
  25. Arguments:
  26. ProtocolBindingContext Pointer to the adapter structure
  27. Status Completion status
  28. Return Value:
  29. None.
  30. --*/
  31. {
  32. PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
  33. //
  34. // We never issue a reset, so we should not be here.
  35. //
  36. ASSERT(0);
  37. }
  38. VOID
  39. EpvcRequestComplete(
  40. IN NDIS_HANDLE ProtocolBindingContext,
  41. IN PNDIS_REQUEST pNdisRequest,
  42. IN NDIS_STATUS Status
  43. )
  44. /*++
  45. Routine Description:
  46. Completion handler for the previously posted request. All OIDS are completed by and sent to
  47. the same miniport that they were requested for.
  48. If Oid == OID_PNP_QUERY_POWER then the data structure needs to returned with all entries =
  49. NdisDeviceStateUnspecified
  50. Arguments:
  51. ProtocolBindingContext Pointer to the adapter structure
  52. NdisRequest The posted request
  53. Status Completion status
  54. Return Value:
  55. None
  56. --*/
  57. {
  58. ENTER("EpvcRequestComplete", 0x44a78b21)
  59. PEPVC_ADAPTER pAdapter =(PEPVC_ADAPTER)ProtocolBindingContext;
  60. PEPVC_NDIS_REQUEST pEpvcRequest = (PEPVC_NDIS_REQUEST )pNdisRequest;
  61. RM_DECLARE_STACK_RECORD(sr)
  62. pEpvcRequest = CONTAINING_RECORD(pNdisRequest, EPVC_NDIS_REQUEST, Request);
  63. pEpvcRequest->Status = Status;
  64. if (pEpvcRequest->pFunc == NULL)
  65. {
  66. //
  67. // Unblock the calling thread
  68. //
  69. NdisSetEvent(&pEpvcRequest ->Event);
  70. }
  71. else
  72. {
  73. //
  74. // Invoke the REquest completion handler
  75. //
  76. (pEpvcRequest->pFunc) (pEpvcRequest, Status);
  77. }
  78. EXIT()
  79. RM_ASSERT_CLEAR(&sr);
  80. }
  81. VOID
  82. PtStatus(
  83. IN NDIS_HANDLE ProtocolBindingContext,
  84. IN NDIS_STATUS GeneralStatus,
  85. IN PVOID StatusBuffer,
  86. IN UINT StatusBufferSize
  87. )
  88. /*++
  89. Routine Description:
  90. Status handler for the lower-edge(protocol).
  91. Arguments:
  92. ProtocolBindingContext Pointer to the adapter structure
  93. GeneralStatus Status code
  94. StatusBuffer Status buffer
  95. StatusBufferSize Size of the status buffer
  96. Return Value:
  97. None
  98. --*/
  99. {
  100. PEPVC_ADAPTER pAdapter =(PEPVC_ADAPTER)ProtocolBindingContext;
  101. TRACE (TL_T, TM_Pt, ("== PtStatus Status %x", GeneralStatus));
  102. }
  103. VOID
  104. EpvcStatus(
  105. IN NDIS_HANDLE ProtocolBindingContext,
  106. IN NDIS_STATUS GeneralStatus,
  107. IN PVOID StatusBuffer,
  108. IN UINT StatusBufferSize
  109. )
  110. /*++
  111. Routine Description:
  112. Status handler for the lower-edge(protocol).
  113. Call the Status indication function of all the miniports
  114. associated with this adapter
  115. Arguments:
  116. ProtocolBindingContext Pointer to the adapter structure
  117. GeneralStatus Status code
  118. StatusBuffer Status buffer
  119. StatusBufferSize Size of the status buffer
  120. Return Value:
  121. None
  122. --*/
  123. {
  124. ENTER ("EpvcStatus",0x733e2f9e)
  125. PEPVC_ADAPTER pAdapter =(PEPVC_ADAPTER)ProtocolBindingContext;
  126. PEPVC_WORKITEM pWorkItem = NULL;
  127. STATUS_INDICATION_CONTEXT Context;
  128. BOOLEAN bDoNotProcess = FALSE;
  129. BOOLEAN bIsMediaEvent = FALSE;
  130. NDIS_MEDIA_STATE NewMediaState;
  131. RM_DECLARE_STACK_RECORD(SR);
  132. //
  133. // Store the parameter, these will be passed to the miniports
  134. //
  135. Context.StatusBuffer = StatusBuffer ;
  136. Context.StatusBufferSize = StatusBufferSize;
  137. Context.GeneralStatus = GeneralStatus;
  138. do
  139. {
  140. LOCKOBJ(pAdapter, &SR);
  141. //
  142. // Check for 2 conditions i Is it a Media event and
  143. // 2) if it is a repeat indication
  144. //
  145. bIsMediaEvent = (GeneralStatus == NDIS_STATUS_MEDIA_CONNECT ||
  146. GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT );
  147. //
  148. // Check for repitions next
  149. //
  150. if (GeneralStatus == NDIS_STATUS_MEDIA_CONNECT &&
  151. pAdapter->info.MediaState == NdisMediaStateConnected)
  152. {
  153. bDoNotProcess = TRUE;
  154. }
  155. if (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT &&
  156. pAdapter->info.MediaState == NdisMediaStateDisconnected)
  157. {
  158. bDoNotProcess = TRUE;
  159. }
  160. //
  161. // Convert the Media Status into an NdisMediaState
  162. //
  163. if (bIsMediaEvent == TRUE && bDoNotProcess == FALSE)
  164. {
  165. if (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT )
  166. {
  167. pAdapter->info.MediaState = NdisMediaStateDisconnected;
  168. }
  169. if (GeneralStatus == NDIS_STATUS_MEDIA_CONNECT)
  170. {
  171. pAdapter->info.MediaState = NdisMediaStateConnected;
  172. }
  173. }
  174. //
  175. // Update the Media state, if we have a new state
  176. //
  177. UNLOCKOBJ(pAdapter, &SR);
  178. if (bDoNotProcess == TRUE)
  179. {
  180. break;
  181. }
  182. epvcEnumerateObjectsInGroup(&pAdapter->MiniportsGroup,
  183. epvcProcessStatusIndication ,
  184. (PVOID)&Context,
  185. &SR);
  186. } while (FALSE);
  187. RM_ASSERT_CLEAR(&SR);
  188. EXIT()
  189. return;
  190. }
  191. INT
  192. epvcProcessStatusIndication (
  193. PRM_OBJECT_HEADER pHdr,
  194. PVOID pvContext,
  195. PRM_STACK_RECORD pSR
  196. )
  197. /*++
  198. Routine Description:
  199. Status handler for the lower-edge(protocol).
  200. If we get a media connect, we queue a task to do the Vc Setup
  201. If we get a media disconnect, we queue a task to tear the VC down
  202. Arguments:
  203. ProtocolBindingContext Pointer to the adapter structure
  204. GeneralStatus Status code
  205. StatusBuffer Status buffer
  206. StatusBufferSize Size of the status buffer
  207. Return Value:
  208. None
  209. --*/
  210. {
  211. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT)pHdr;
  212. PEPVC_ADAPTER pAdapter = pMiniport->pAdapter;
  213. BOOLEAN fIsMiniportActive = FALSE;
  214. PSTATUS_INDICATION_CONTEXT pContext = (PSTATUS_INDICATION_CONTEXT)pvContext ;
  215. NDIS_STATUS GeneralStatus = pContext->GeneralStatus;
  216. do
  217. {
  218. //
  219. // if this is not a media indication pass it up to ndis.
  220. //
  221. fIsMiniportActive = MiniportTestFlag(pMiniport, fMP_MiniportInitialized);
  222. if (fIsMiniportActive == FALSE)
  223. {
  224. break;
  225. }
  226. //
  227. // Only pass up an indication if the miniport has been initialized
  228. //
  229. //
  230. // Filter out a duplicate Indication
  231. //
  232. if (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT &&
  233. pMiniport->info.MediaState == NdisMediaStateDisconnected)
  234. {
  235. break;
  236. }
  237. if (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT &&
  238. pMiniport->info.MediaState == NdisMediaStateDisconnected)
  239. {
  240. break;
  241. }
  242. //
  243. // Record the status and indicate it up to the protocols
  244. //
  245. if (GeneralStatus == NDIS_STATUS_MEDIA_CONNECT)
  246. {
  247. pMiniport->info.MediaState = NdisMediaStateConnected;
  248. }
  249. if (GeneralStatus == NDIS_STATUS_MEDIA_DISCONNECT )
  250. {
  251. pMiniport->info.MediaState = NdisMediaStateDisconnected;
  252. }
  253. epvcMIndicateStatus(pMiniport,
  254. GeneralStatus,
  255. pContext->StatusBuffer,
  256. pContext->StatusBufferSize
  257. );
  258. } while (FALSE);
  259. //
  260. // As we continue the iteration, return TRUE
  261. //
  262. return TRUE;
  263. }
  264. VOID
  265. epvcMediaWorkItem(
  266. PNDIS_WORK_ITEM pWorkItem,
  267. PVOID Context
  268. )
  269. /*++
  270. Routine Description:
  271. Status handler for the lower-edge(protocol).
  272. If we get a media connect, we queue a task to do the Vc Setup
  273. If we get a media disconnect, we queue a task to tear the VC down
  274. Arguments:
  275. ProtocolBindingContext Pointer to the adapter structure
  276. GeneralStatus Status code
  277. StatusBuffer Status buffer
  278. StatusBufferSize Size of the status buffer
  279. Return Value:
  280. None
  281. --*/
  282. {
  283. ASSERT (0);
  284. }
  285. INT
  286. epvcMiniportIndicateStatusComplete(
  287. PRM_OBJECT_HEADER pHdr,
  288. PVOID pvContext,
  289. PRM_STACK_RECORD pSR
  290. )
  291. /*++
  292. Routine Description:
  293. Indicate the status upto the protocols
  294. Arguments:
  295. Return Value:
  296. --*/
  297. {
  298. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT) pHdr;
  299. BOOLEAN fIsMiniportActive = MiniportTestFlag(pMiniport, fMP_MiniportInitialized);
  300. //
  301. // Only pass up an indication if the miniport has been initialized
  302. //
  303. if (fIsMiniportActive == TRUE )
  304. {
  305. NdisMIndicateStatusComplete(pMiniport->ndis.MiniportAdapterHandle);
  306. }
  307. return TRUE;
  308. }
  309. VOID
  310. PtStatusComplete(
  311. IN NDIS_HANDLE ProtocolBindingContext
  312. )
  313. /*++
  314. Routine Description:
  315. Arguments:
  316. Return Value:
  317. --*/
  318. {
  319. ENTER("PtStatusComplete", 0x5729d194)
  320. PEPVC_ADAPTER pAdapter = (PEPVC_ADAPTER) ProtocolBindingContext;
  321. RM_DECLARE_STACK_RECORD(SR);
  322. //
  323. // Iterate through all the miniports and stop them
  324. //
  325. epvcEnumerateObjectsInGroup (&pAdapter->MiniportsGroup,
  326. epvcMiniportIndicateStatusComplete,
  327. NULL,
  328. &SR );
  329. }
  330. VOID
  331. PtTransferDataComplete(
  332. IN NDIS_HANDLE ProtocolBindingContext,
  333. IN PNDIS_PACKET Packet,
  334. IN NDIS_STATUS Status,
  335. IN UINT BytesTransferred
  336. )
  337. /*++
  338. Routine Description:
  339. Arguments:
  340. Return Value:
  341. --*/
  342. {
  343. PEPVC_I_MINIPORT pMiniport =(PEPVC_I_MINIPORT )ProtocolBindingContext;
  344. if(pMiniport->ndis.MiniportAdapterHandle)
  345. {
  346. NdisMTransferDataComplete(pMiniport->ndis.MiniportAdapterHandle,
  347. Packet,
  348. Status,
  349. BytesTransferred);
  350. }
  351. }
  352. NDIS_STATUS
  353. PtReceive(
  354. IN NDIS_HANDLE ProtocolBindingContext,
  355. IN NDIS_HANDLE MacReceiveContext,
  356. IN PVOID HeaderBuffer,
  357. IN UINT HeaderBufferSize,
  358. IN PVOID LookAheadBuffer,
  359. IN UINT LookAheadBufferSize,
  360. IN UINT PacketSize
  361. )
  362. /*++
  363. Routine Description:
  364. LBFO - need to use primary for all receives
  365. Arguments:
  366. Return Value:
  367. --*/
  368. {
  369. PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
  370. PNDIS_PACKET MyPacket, Packet;
  371. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  372. if(!pAdapt->ndis.MiniportAdapterHandle)
  373. {
  374. Status = NDIS_STATUS_FAILURE;
  375. }
  376. return Status;
  377. }
  378. VOID
  379. PtReceiveComplete(
  380. IN NDIS_HANDLE ProtocolBindingContext
  381. )
  382. /*++
  383. Routine Description:
  384. Called by the adapter below us when it is done indicating a batch of received buffers.
  385. Arguments:
  386. ProtocolBindingContext Pointer to our adapter structure.
  387. Return Value:
  388. None
  389. --*/
  390. {
  391. PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
  392. }
  393. INT
  394. PtReceivePacket(
  395. IN NDIS_HANDLE ProtocolBindingContext,
  396. IN PNDIS_PACKET Packet
  397. )
  398. /*++
  399. Routine Description:
  400. ReceivePacket handler. Called up by the miniport below when it supports NDIS 4.0 style receives.
  401. Re-package the packet and hand it back to NDIS for protocols above us. The re-package part is
  402. important since NDIS uses the WrapperReserved part of the packet for its own book-keeping. Also
  403. the re-packaging works differently when packets flow-up or down. In the up-path(here) the protocol
  404. reserved is owned by the protocol above. We need to use the miniport reserved here.
  405. Arguments:
  406. ProtocolBindingContext Pointer to our adapter structure.
  407. Packet - Pointer to the packet
  408. Return Value:
  409. == 0 -> We are done with the packet
  410. != 0 -> We will keep the packet and call NdisReturnPackets() this many times when done.
  411. --*/
  412. {
  413. PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
  414. NDIS_STATUS Status;
  415. PNDIS_PACKET MyPacket;
  416. PEPVC_PKT_CONTEXT Resvd;
  417. return 0;
  418. }
  419. //--------------------------------------------------------------------------------
  420. // //
  421. // Address Family - Entry points and Tasks //
  422. // //
  423. // //
  424. //--------------------------------------------------------------------------------
  425. VOID
  426. EpvcAfRegisterNotify(
  427. IN NDIS_HANDLE ProtocolBindingContext,
  428. IN PCO_ADDRESS_FAMILY pAddressFamily
  429. )
  430. /*++
  431. Routine Description:
  432. This informs us that the Call manager is bound to a NIC. and that the call
  433. manager is telling us that it is ready to accepts calls.
  434. We expect there to be one interesting Address Family per underlying adapter
  435. Arguments:
  436. UserParam for (Code == RM_TASKOP_START) : UnbindContext
  437. --*/
  438. {
  439. ENTER("EpvcAfRegisterNotify", 0xaea79b12)
  440. PEPVC_ADAPTER pAdapter = (PEPVC_ADAPTER) ProtocolBindingContext;
  441. RM_DECLARE_STACK_RECORD(SR);
  442. TRACE (TL_T, TM_Pt,("==>EpvcAfRegisterNotify\n"));
  443. do
  444. {
  445. if (pAddressFamily->AddressFamily != CO_ADDRESS_FAMILY_Q2931)
  446. {
  447. //
  448. // The call manager is not indicating the address family for an atm
  449. // miniport. We are not interested
  450. //
  451. break;
  452. }
  453. LOCKOBJ(pAdapter, &SR);
  454. RmTmpReferenceObject(&pAdapter->Hdr, &SR);
  455. pAdapter->af.AddressFamily = *pAddressFamily;
  456. //
  457. //Begin a task that will call NdisClOpenAddressFamily asynchronously
  458. //
  459. UNLOCKOBJ(pAdapter, &SR);
  460. epvcEnumerateObjectsInGroup(&pAdapter->MiniportsGroup,
  461. epvcAfInitEnumerate,
  462. NULL, // Context
  463. &SR );
  464. LOCKOBJ(pAdapter, &SR);
  465. RmTmpDereferenceObject(&pAdapter->Hdr, &SR);
  466. UNLOCKOBJ(pAdapter, &SR);
  467. } while (FALSE);
  468. TRACE (TL_T, TM_Pt, ("<==EpvcAfRegisterNotify\n"));
  469. RM_ASSERT_CLEAR(&SR);
  470. EXIT()
  471. }
  472. // Enum function
  473. //
  474. INT
  475. epvcAfInitEnumerate(
  476. PRM_OBJECT_HEADER pHdr,
  477. PVOID pvContext, // Unused
  478. PRM_STACK_RECORD pSR
  479. )
  480. /*++
  481. Routine Description:
  482. We have been notified of an acceptable address family
  483. Iterate through all the miniort structures and open the address family
  484. and InitDeviceInstance on each of the miniports
  485. Arguments:
  486. --*/
  487. {
  488. ENTER("epvcAfInitEnumerate ",0x72eb5b98 )
  489. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT) pHdr;
  490. //
  491. // Get miniport lock and tmpref it.
  492. //
  493. LOCKOBJ(pMiniport, pSR);
  494. RmTmpReferenceObject(&pMiniport->Hdr, pSR);
  495. do
  496. {
  497. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  498. PRM_TASK pTask= NULL;
  499. PEPVC_ADAPTER pAdapter = (PEPVC_ADAPTER)pMiniport->Hdr.pParentObject;
  500. ASSERT (pAdapter->Hdr.Sig == TAG_ADAPTER);
  501. //
  502. // Allocate task to complete the unbind.
  503. //
  504. Status = epvcAllocateTask(
  505. &pMiniport->Hdr, // pParentObject,
  506. epvcTaskStartIMiniport, // pfnHandler,
  507. 0, // Timeout,
  508. "Task: Open address Family", // szDescription
  509. &pTask,
  510. pSR
  511. );
  512. if (FAIL(Status))
  513. {
  514. // Ugly situation. We'll just leave things as they are...
  515. //
  516. pTask = NULL;
  517. TR_WARN(("FATAL: couldn't allocate unbind task!\n"));
  518. break;
  519. }
  520. // Start the task to complete the Open Address Family.
  521. // No locks must be held. RmStartTask uses up the tmpref on the task
  522. // which was added by epvcAllocateTask.
  523. //
  524. UNLOCKOBJ(pMiniport, pSR);
  525. ((PTASK_AF) pTask)->pAf= &pAdapter->af.AddressFamily ;
  526. ((PTASK_AF) pTask)->Cause = TaskCause_AfNotify;
  527. RmStartTask(pTask, 0, pSR);
  528. LOCKOBJ(pMiniport, pSR);
  529. } while(FALSE);
  530. UNLOCKOBJ(pMiniport, pSR);
  531. RmTmpDereferenceObject(&pMiniport->Hdr, pSR);
  532. EXIT()
  533. //
  534. // As we want the enumeration to cotinue
  535. //
  536. return TRUE;
  537. }
  538. NDIS_STATUS
  539. epvcTaskStartIMiniport(
  540. IN struct _RM_TASK * pTask,
  541. IN RM_TASK_OPERATION Code,
  542. IN UINT_PTR UserParam,
  543. IN PRM_STACK_RECORD pSR
  544. )
  545. /*++
  546. Routine Description:
  547. Task handler for opening address families on an underlying adapters.
  548. The number of address families instantiated is determined by the
  549. configuration read in the registry
  550. Arguments:
  551. UserParam for (Code == RM_TASKOP_START) : UnbindContext
  552. --*/
  553. {
  554. ENTER("epvcTaskStartIMiniport", 0xaac34d81)
  555. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  556. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT ) RM_PARENT_OBJECT(pTask);
  557. NDIS_STATUS InitStatus = NDIS_STATUS_SUCCESS;
  558. PTASK_AF pAfTask = (PTASK_AF) pTask;
  559. NDIS_HANDLE NdisAfHandle = NULL;
  560. PEPVC_ADAPTER pAdapter = pMiniport->pAdapter;
  561. ULONG State = pTask->Hdr.State;
  562. enum
  563. {
  564. Stage_Start =0, // default
  565. Stage_OpenAfComplete,
  566. Stage_CloseAfComplete, // In case of failure
  567. Stage_TaskCompleted,
  568. Stage_End
  569. }; // To be used in pTask->Hdr.State to indicate the state of the Task
  570. TRACE ( TL_T, TM_Pt, ("==>epvcTaskStartIMiniport Code %x", Code) );
  571. TRACE (TL_V, TM_Pt, ("epvcTaskStartIMiniport Task %p Task is in state %x\n", pTask, pTask->Hdr.State));
  572. switch(pTask->Hdr.State)
  573. {
  574. case Stage_Start:
  575. {
  576. //
  577. // is there another open address family task active
  578. //
  579. LOCKOBJ (pMiniport, pSR);
  580. if (epvcIsThisTaskPrimary ( pTask, &(PRM_TASK)(pMiniport->af.pAfTask)) == FALSE)
  581. {
  582. PRM_TASK pOtherTask = (PRM_TASK)(pMiniport->af.pAfTask);
  583. RmTmpReferenceObject (&pOtherTask->Hdr, pSR);
  584. //
  585. // Set The state so we restart this code after main task completes
  586. //
  587. pTask->Hdr.State = Stage_Start;
  588. UNLOCKOBJ(pMiniport, pSR);
  589. RmPendTaskOnOtherTask (pTask, 0, pOtherTask, pSR);
  590. RmTmpDereferenceObject(&pOtherTask->Hdr,pSR);
  591. Status = NDIS_STATUS_PENDING;
  592. break;
  593. }
  594. //
  595. // We are the primary task
  596. //
  597. ASSERT (pMiniport->af.pAfTask == pAfTask);
  598. //
  599. // make sure we are bound to the adapter below. If not exit
  600. //
  601. if (CHECK_AD_PRIMARY_STATE (pAdapter, EPVC_AD_PS_INITED) == FALSE &&
  602. pAdapter->bind.BindingHandle == NULL)
  603. {
  604. //
  605. // quietly exit as the protocol is not bound to the adapter below
  606. //
  607. UNLOCKOBJ(pMiniport, pSR);
  608. pTask->Hdr.State = Stage_TaskCompleted; // we're finished.
  609. Status = NDIS_STATUS_SUCCESS; // Exit
  610. break;
  611. }
  612. //
  613. // Check to see if our work is already done
  614. //
  615. if (MiniportTestFlag (pMiniport, fMP_AddressFamilyOpened) == TRUE)
  616. {
  617. //
  618. // quietly exit as the address family is already Opened
  619. //
  620. UNLOCKOBJ(pMiniport, pSR);
  621. pTask->Hdr.State = Stage_TaskCompleted; // we're finished.
  622. Status = NDIS_STATUS_SUCCESS; // Exit
  623. break;
  624. }
  625. UNLOCKOBJ(pMiniport,pSR);
  626. //
  627. // Get Ready to suspend the task.
  628. // First update the state so that the resume
  629. // will take it to the correct place
  630. //
  631. pTask->Hdr.State = Stage_OpenAfComplete;
  632. RmSuspendTask( pTask, 0 ,pSR);
  633. //
  634. // Call Ndis to open address family
  635. //
  636. Status = epvcClOpenAddressFamily(pAdapter->bind.BindingHandle,
  637. &pAdapter->af.AddressFamily,
  638. (NDIS_HANDLE)pMiniport,
  639. &EpvcGlobals.ndis.CC,
  640. sizeof (EpvcGlobals.ndis.CC),
  641. &NdisAfHandle
  642. );
  643. if (PEND(Status)== FALSE)
  644. {
  645. //
  646. // Call the completion handler
  647. //
  648. EpvcCoOpenAfComplete(Status,
  649. pMiniport,
  650. NdisAfHandle );
  651. Status = NDIS_STATUS_PENDING;
  652. }
  653. //
  654. // Now let this thread exit. Make the Async
  655. // Completion handler complete the task
  656. //
  657. break;
  658. }
  659. case Stage_OpenAfComplete:
  660. {
  661. InitStatus = NDIS_STATUS_SUCCESS;
  662. //
  663. // If the status is success then initialize the miniport
  664. //
  665. do
  666. {
  667. if (pAfTask->ReturnStatus != NDIS_STATUS_SUCCESS)
  668. {
  669. break;
  670. }
  671. //
  672. // Success, so Now initialize the miniport
  673. //
  674. LOCKOBJ (pMiniport, pSR);
  675. //
  676. // Set the appropriate flag
  677. //
  678. MiniportSetFlag(pMiniport, fMP_DevInstanceInitialized);
  679. UNLOCKOBJ (pMiniport, pSR);
  680. RM_ASSERT_NOLOCKS(pSR);
  681. InitStatus = NdisIMInitializeDeviceInstanceEx( EpvcGlobals.driver.DriverHandle,
  682. &pMiniport->ndis.DeviceName,
  683. pMiniport);
  684. } while (FALSE);
  685. //
  686. // Handle Failure
  687. //
  688. if (FAIL(InitStatus) || FAIL(pAfTask->ReturnStatus))
  689. {
  690. TRACE (TL_V, TM_Mp, ("epvcStartImMiniport Failed Status %x, InitStatus %x",Status, InitStatus));
  691. LOCKOBJ (pMiniport, pSR);
  692. //
  693. // Clear the appropriate flags
  694. //
  695. if (MiniportTestFlag(pMiniport, fMP_AddressFamilyOpened)== TRUE)
  696. {
  697. MiniportClearFlag (pMiniport, fMP_AddressFamilyOpened);
  698. }
  699. else
  700. {
  701. ASSERT (pMiniport->af.AfHandle == NULL);
  702. }
  703. UNLOCKOBJ (pMiniport, pSR);
  704. //
  705. // Close the Af if there was one.
  706. //
  707. if (pMiniport->af.AfHandle != NULL)
  708. {
  709. pTask->Hdr.State = Stage_CloseAfComplete;
  710. //
  711. // Prepare to so an Async Close Af
  712. //
  713. RmSuspendTask (pTask, 0, pSR);
  714. //
  715. // Close Address Family
  716. //
  717. Status = epvcClCloseAddressFamily(pMiniport->af.AfHandle);
  718. if (Status != NDIS_STATUS_PENDING)
  719. {
  720. EpvcCoCloseAfComplete(Status,pMiniport );
  721. Status = NDIS_STATUS_PENDING;
  722. }
  723. break;
  724. }
  725. }
  726. //
  727. // We've finished task;
  728. //
  729. //
  730. // Fall through
  731. //
  732. }
  733. case Stage_CloseAfComplete:
  734. {
  735. pTask->Hdr.State = Stage_TaskCompleted;
  736. Status = NDIS_STATUS_SUCCESS;
  737. }
  738. case Stage_End:
  739. {
  740. Status = NDIS_STATUS_SUCCESS;
  741. break;
  742. }
  743. default:
  744. {
  745. ASSERTEX(!"Unknown task op", pTask);
  746. }
  747. }
  748. if (pTask->Hdr.State == Stage_TaskCompleted)
  749. {
  750. pTask->Hdr.State = Stage_End;
  751. LOCKOBJ(pMiniport, pSR);
  752. pMiniport->af.pAfTask = NULL;
  753. UNLOCKOBJ(pMiniport, pSR);
  754. ASSERT (Status == NDIS_STATUS_SUCCESS);
  755. }
  756. RM_ASSERT_NOLOCKS(pSR);
  757. EXIT()
  758. TRACE ( TL_T, TM_Pt, ("<==epvcTaskStartIMiniport Status %x", Status) );
  759. return Status;
  760. }
  761. NDIS_STATUS
  762. epvcTaskCloseIMiniport(
  763. IN struct _RM_TASK * pTask,
  764. IN RM_TASK_OPERATION Code,
  765. IN UINT_PTR UserParam,
  766. IN PRM_STACK_RECORD pSR
  767. )
  768. /*++
  769. Routine Description:
  770. This is the task that Closes the miniport, the Device Instance and
  771. the Address Family/
  772. There are three reason that the task could be called.
  773. 1) Miniport Halt -MiniportInstance functions need not be called
  774. 2) Protocol Unbind- MiniportInstance functions HAVE to be called
  775. 3) CloseAddress Family - Miniport function are already called
  776. Arguments:
  777. UserParam for (Code == RM_TASKOP_START) : UnbindContext
  778. --*/
  779. {
  780. ENTER ("epvcTaskCloseIMiniport", 0x83342651)
  781. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  782. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT ) RM_PARENT_OBJECT(pTask);
  783. PTASK_AF pAfTask = (PTASK_AF) pTask;
  784. BOOLEAN fNeedToHalt = FALSE;
  785. BOOLEAN fNeedToCancel = FALSE;
  786. ULONG State;
  787. BOOLEAN fAddressFamilyOpened = FALSE;
  788. BOOLEAN fIsDevInstanceInitialized = FALSE;
  789. BOOLEAN fIsMiniportHalting = FALSE;
  790. enum
  791. {
  792. Stage_Start =0, // default
  793. Stage_CloseAddressFamilyCompleted,
  794. Stage_TaskCompleted,
  795. Stage_End
  796. }; // To be used in pTask->Hdr.State to indicate the state of the Task
  797. TRACE ( TL_T, TM_Pt, ("==> epvcTaskCloseIMiniport State %x", pTask->Hdr.State) );
  798. State = pTask->Hdr.State;
  799. switch(pTask->Hdr.State)
  800. {
  801. case Stage_Start:
  802. {
  803. //
  804. // Check to see if the miniport has already opened an address family.
  805. // If so exit
  806. //
  807. LOCKOBJ (pMiniport, pSR );
  808. if (epvcIsThisTaskPrimary ( pTask, &(PRM_TASK)(pMiniport->af.pAfTask)) == FALSE)
  809. {
  810. PRM_TASK pOtherTask = (PRM_TASK)(pMiniport->af.pAfTask);
  811. RmTmpReferenceObject (&pOtherTask->Hdr, pSR);
  812. //
  813. // Set The state so we restart this code after main task completes
  814. //
  815. pTask->Hdr.State = Stage_Start;
  816. UNLOCKOBJ(pMiniport, pSR);
  817. RmPendTaskOnOtherTask (pTask, 0, pOtherTask, pSR);
  818. RmTmpDereferenceObject(&pOtherTask->Hdr,pSR);
  819. Status = NDIS_STATUS_PENDING;
  820. break;
  821. }
  822. //
  823. // We are the primary task
  824. //
  825. ASSERT (pMiniport->af.pAfTask == pAfTask);
  826. //
  827. // Check to see if our work is already done
  828. //
  829. if (MiniportTestFlag (pMiniport, fMP_AddressFamilyOpened) == FALSE)
  830. {
  831. //
  832. // quietly exit as the address family is already closed
  833. //
  834. UNLOCKOBJ(pMiniport, pSR);
  835. State = Stage_TaskCompleted; // we're finished.
  836. Status = NDIS_STATUS_FAILURE; // Exit
  837. break;
  838. }
  839. fIsDevInstanceInitialized = MiniportTestFlag (pMiniport, fMP_DevInstanceInitialized);
  840. fIsMiniportHalting = (pAfTask->Cause == TaskCause_MiniportHalt );
  841. //
  842. // Now do we need to halt the miniport. -
  843. // Q1. Are we are in the middle of a Halt
  844. // Q2. Has Our Miniport Instance been initialized -
  845. // Has miniportInitialize been called - then DeInit the miniport
  846. // If not then - cancel the Device Instance
  847. //
  848. if ((TRUE == fIsDevInstanceInitialized ) &&
  849. ( FALSE ==fIsMiniportHalting) )
  850. {
  851. if (MiniportTestFlag (pMiniport, fMP_MiniportInitialized) == TRUE)
  852. {
  853. //
  854. // Our Halt Handler has not been called,
  855. //
  856. fNeedToHalt = TRUE;
  857. }
  858. else
  859. {
  860. //
  861. // Our miniport's initalized handler has not been called
  862. //
  863. //
  864. // We are not in the middle of a halt, so this probably
  865. // an unbind .
  866. //
  867. fNeedToCancel = TRUE;
  868. }
  869. //
  870. // Clear the Device Instance flag.
  871. //
  872. MiniportClearFlag (pMiniport, fMP_DevInstanceInitialized);
  873. }
  874. //
  875. // Mark the address family as closed ,because this task will close it.
  876. //
  877. fAddressFamilyOpened = MiniportTestFlag (pMiniport, fMP_AddressFamilyOpened);
  878. MiniportClearFlag (pMiniport, fMP_AddressFamilyOpened);
  879. UNLOCKOBJ(pMiniport,pSR);
  880. //
  881. // Call Ndis to Deinitialize the miniport, The miniport is already Refed
  882. //
  883. TRACE ( TL_T, TM_Pt, ("epvcTaskCloseIMiniport ----") );
  884. if (TRUE == fNeedToHalt )
  885. {
  886. epvcIMDeInitializeDeviceInstance(pMiniport);
  887. }
  888. if (TRUE== fNeedToCancel)
  889. {
  890. ASSERT (!" Need To cancel in Task close Miniport");
  891. epvcCancelDeviceInstance(pMiniport, pSR);
  892. }
  893. //
  894. // Now close the address family asynchronously.
  895. // First suspend this task
  896. //
  897. pTask->Hdr.State = Stage_CloseAddressFamilyCompleted;
  898. RmSuspendTask (pTask, 0 , pSR);
  899. if (fAddressFamilyOpened == TRUE)
  900. {
  901. //
  902. // We need to start a task to complete the Close Call And DeleteVC
  903. //
  904. Status = epvcClCloseAddressFamily(pMiniport->af.AfHandle);
  905. if (Status != NDIS_STATUS_PENDING)
  906. {
  907. EpvcCoCloseAfComplete(Status, pMiniport);
  908. Status = NDIS_STATUS_PENDING;
  909. }
  910. }
  911. else
  912. {
  913. State = Stage_TaskCompleted; // we're finished.
  914. Status = NDIS_STATUS_SUCCESS; // Exit
  915. }
  916. //
  917. // End this thread. If this thread is closing the addres family
  918. // then we exit. If not, then we do the cleanup below
  919. //
  920. break;
  921. }
  922. case Stage_CloseAddressFamilyCompleted:
  923. {
  924. Status = pAfTask->ReturnStatus;
  925. State = Stage_TaskCompleted ;
  926. break;
  927. }
  928. case Stage_End:
  929. {
  930. Status = NDIS_STATUS_SUCCESS;
  931. break;
  932. }
  933. default:
  934. {
  935. ASSERTEX(!"Unknown task op", pTask);
  936. }
  937. }
  938. if (Stage_TaskCompleted == State )
  939. {
  940. pTask->Hdr.State = Stage_End;
  941. Status = NDIS_STATUS_SUCCESS;
  942. //
  943. // Clear the task here
  944. //
  945. LOCKOBJ (pMiniport, pSR);
  946. pMiniport->af.pAfTask = NULL;
  947. UNLOCKOBJ (pMiniport, pSR);
  948. //
  949. // Set the complete event here
  950. //
  951. if (pAfTask->Cause == TaskCause_ProtocolUnbind)
  952. {
  953. epvcSetEvent (&pAfTask->CompleteEvent);
  954. }
  955. if (pAfTask->Cause == TaskCause_AfCloseRequest)
  956. {
  957. //
  958. // Nothing to do
  959. //
  960. }
  961. }
  962. RM_ASSERT_NOLOCKS(pSR);
  963. TRACE ( TL_T, TM_Pt, ("<== epvcTaskCloseIMiniport Status %x", Status) );
  964. EXIT();
  965. return Status;
  966. }
  967. VOID
  968. epvcInstantiateMiniport(
  969. IN PEPVC_ADAPTER pAdapter,
  970. NDIS_HANDLE MIniportConfigHandle,
  971. PRM_STACK_RECORD pSR
  972. )
  973. /*++
  974. Routine Description:
  975. This routine goes to the registry and reads the device name for the IM miniport.
  976. It then allocates a structure for it.
  977. If the allocation fails, it quietly returns as there is no more work to be done.
  978. (Maybe we should deregister the protocol)
  979. Arguments:
  980. Return Value:
  981. None.
  982. --*/
  983. {
  984. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  985. PEPVC_I_MINIPORT pMiniport = NULL;
  986. NDIS_STRING UpperBindings;
  987. PNDIS_CONFIGURATION_PARAMETER pParameterValue = NULL;
  988. EPVC_I_MINIPORT_PARAMS Params;
  989. TRACE (TL_T, TM_Mp, ("==> epvcInstantiateMiniport pAdapter %p KeyName %p \n", pAdapter));
  990. do
  991. {
  992. //
  993. // Now read the upper bindings
  994. //
  995. NdisInitUnicodeString(&UpperBindings, c_szUpperBindings);
  996. NdisReadConfiguration(
  997. &NdisStatus,
  998. &pParameterValue,
  999. MIniportConfigHandle,
  1000. &UpperBindings,
  1001. NdisParameterString);
  1002. if (NDIS_STATUS_SUCCESS != NdisStatus)
  1003. {
  1004. TRACE (TL_T, TM_Mp, (" epvcInstantiateMiniport NdisReadConfiguration Failed"));
  1005. break;
  1006. }
  1007. TRACE (TL_I, TM_Pt, ("Creating Miniport Adapter %x, KeyName: len %d, max %d, name: [%ws]\n",
  1008. pAdapter,
  1009. pParameterValue->ParameterData.StringData.Length,
  1010. pParameterValue->ParameterData.StringData.MaximumLength,
  1011. (unsigned char*)pParameterValue->ParameterData.StringData.Buffer));
  1012. //
  1013. // Check and see if we already have a miniport
  1014. //
  1015. RmLookupObjectInGroup( &pAdapter->MiniportsGroup,
  1016. 0 , // no flags (not locked)
  1017. &pParameterValue->ParameterData.StringData,
  1018. NULL,
  1019. &(PRM_OBJECT_HEADER)pMiniport,
  1020. NULL,
  1021. pSR
  1022. );
  1023. if (pMiniport!= NULL)
  1024. {
  1025. //
  1026. // we already have a miniport, therefore exit.
  1027. //
  1028. break;
  1029. }
  1030. //
  1031. // Create and Initialize the miniport here
  1032. //
  1033. Params.pDeviceName = &pParameterValue->ParameterData.StringData;
  1034. Params.pAdapter = pAdapter;
  1035. Params.CurLookAhead = pAdapter->info.MaxAAL5PacketSize;
  1036. Params.NumberOfMiniports = (NdisInterlockedIncrement (&pAdapter->info.NumberOfMiniports) - 1);
  1037. Params.LinkSpeed = pAdapter->info.LinkSpeed;
  1038. Params.MacAddress = pAdapter->info.MacAddress;
  1039. Params.MediaState = pAdapter->info.MediaState;
  1040. NdisStatus = RM_CREATE_AND_LOCK_OBJECT_IN_GROUP(
  1041. &pAdapter->MiniportsGroup,
  1042. Params.pDeviceName, // Key
  1043. &Params, // Init params
  1044. &((PRM_OBJECT_HEADER)pMiniport),
  1045. NULL, // pfCreated
  1046. pSR
  1047. );
  1048. if (FAIL(NdisStatus))
  1049. {
  1050. TR_WARN(("FATAL: Couldn't create adapter object\n"));
  1051. pMiniport = NULL;
  1052. break;
  1053. }
  1054. UNLOCKOBJ(pMiniport,pSR);
  1055. //
  1056. // Initalize new miniport specific events here
  1057. //
  1058. epvcInitializeEvent (&pMiniport->pnp.HaltCompleteEvent);
  1059. epvcInitializeEvent (&pMiniport->pnp.DeInitEvent);
  1060. } while (FALSE);
  1061. if (FAIL(NdisStatus ) == TRUE)
  1062. {
  1063. //
  1064. // Do nothing
  1065. //
  1066. ASSERT (FAIL(NdisStatus ) == FALSE);
  1067. }
  1068. else
  1069. {
  1070. RmTmpDereferenceObject(&pMiniport->Hdr, pSR);
  1071. }
  1072. TRACE (TL_T, TM_Mp, ("<== epvcInstantiateMiniport pMiniport %p \n", pMiniport));
  1073. }
  1074. //--------------------------------------------------------------------------------
  1075. // //
  1076. // Adapter RM Object - Create, Delete, Hash and Compare functions //
  1077. // //
  1078. // //
  1079. //--------------------------------------------------------------------------------
  1080. PRM_OBJECT_HEADER
  1081. epvcAdapterCreate(
  1082. PRM_OBJECT_HEADER pParentObject,
  1083. PVOID pCreateParams,
  1084. PRM_STACK_RECORD psr
  1085. )
  1086. /*++
  1087. Routine Description:
  1088. Allocate and initialize an object of type EPVC_ADAPTER.
  1089. Arguments:
  1090. pParentObject - Object that is to be the parent of the adapter.
  1091. pCreateParams - Actually a pointer to a EPVC_ADAPTER_PARAMS structure,
  1092. which contains information required to create the adapter.
  1093. Return Value:
  1094. Pointer to the allocated and initialized object on success.
  1095. NULL otherwise.
  1096. --*/
  1097. {
  1098. PEPVC_ADAPTER pA;
  1099. PEPVC_ADAPTER_PARAMS pBindParams = (PEPVC_ADAPTER_PARAMS)pCreateParams;
  1100. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1101. extern RM_STATIC_OBJECT_INFO EpvcGlobals_AdapterStaticInfo;
  1102. extern RM_STATIC_OBJECT_INFO EpvcGlobals_I_MiniportStaticInfo ;
  1103. ENTER("AdapterCreate", 0x9cb433f4);
  1104. TRACE (TL_V, TM_Pt, ("--> epvcAdapterCreate") );
  1105. EPVC_ALLOCSTRUCT(pA, TAG_PROTOCOL);
  1106. do
  1107. {
  1108. if (pA == NULL)
  1109. {
  1110. break;
  1111. }
  1112. EPVC_ZEROSTRUCT(pA);
  1113. //
  1114. // Do all the initialization work here
  1115. //
  1116. pA->Hdr.Sig = TAG_ADAPTER;
  1117. RmInitializeLock(
  1118. &pA->Lock,
  1119. LOCKLEVEL_ADAPTER
  1120. );
  1121. RmInitializeHeader(
  1122. pParentObject,
  1123. &pA->Hdr,
  1124. TAG_ADAPTER,
  1125. &pA->Lock,
  1126. &EpvcGlobals_AdapterStaticInfo,
  1127. NULL,
  1128. psr
  1129. );
  1130. //
  1131. // Now initialize the adapter structure with the parameters
  1132. // that were passed in.
  1133. //
  1134. // Create up-cased version of the DeviceName and save it.
  1135. //
  1136. //
  1137. Status = epvcCopyUnicodeString(
  1138. &(pA->bind.DeviceName),
  1139. pBindParams->pDeviceName,
  1140. TRUE // Upcase
  1141. );
  1142. if (FAIL(Status))
  1143. {
  1144. pA->bind.DeviceName.Buffer=NULL; // so we don't try to free it later
  1145. break;
  1146. }
  1147. pA->bind.pEpvcConfigName = pBindParams->pEpvcConfigName;
  1148. Status = epvcCopyUnicodeString(
  1149. &(pA->bind.EpvcConfigName),
  1150. pBindParams->pEpvcConfigName,
  1151. FALSE
  1152. );
  1153. pA->bind.BindContext = pBindParams->BindContext;
  1154. //
  1155. // Initialize and allocate a group for all the intermediate miniports that
  1156. // will be instantiated over this physical adapter
  1157. //
  1158. RmInitializeGroup(
  1159. &pA->Hdr, // pOwningObject
  1160. &EpvcGlobals_I_MiniportStaticInfo ,
  1161. &(pA->MiniportsGroup),
  1162. "Intermediate miniports", // szDescription
  1163. psr
  1164. );
  1165. Status = NDIS_STATUS_SUCCESS;
  1166. }
  1167. while(FALSE);
  1168. if (FAIL(Status))
  1169. {
  1170. if (pA != NULL)
  1171. {
  1172. epvcAdapterDelete ((PRM_OBJECT_HEADER) pA, psr);
  1173. pA = NULL;
  1174. }
  1175. }
  1176. TRACE (TL_V, TM_Pt, ("<-- epvcAdapterCreate pAdpater. %p",pA) );
  1177. return (PRM_OBJECT_HEADER) pA;
  1178. }
  1179. VOID
  1180. epvcAdapterDelete (
  1181. PRM_OBJECT_HEADER pObj,
  1182. PRM_STACK_RECORD pSR
  1183. )
  1184. /*++
  1185. Routine Description:
  1186. Free an object of type EPVC_ADAPTER.
  1187. Arguments:
  1188. pHdr - Actually a pointer to the EPVC_ADAPTER to be deleted.
  1189. --*/
  1190. {
  1191. PEPVC_ADAPTER pAdapter = (PEPVC_ADAPTER) pObj;
  1192. TRACE (TL_V, TM_Pt, ("-- epvcAdapterDelete pAdapter %p",pAdapter) );
  1193. pAdapter->Hdr.Sig = TAG_FREED;
  1194. EPVC_FREE (pAdapter);
  1195. }
  1196. BOOLEAN
  1197. epvcAdapterCompareKey(
  1198. PVOID pKey,
  1199. PRM_HASH_LINK pItem
  1200. )
  1201. /*++
  1202. Routine Description:
  1203. Hash comparison function for EPVC_ADAPTER.
  1204. Arguments:
  1205. pKey - Points to a Epvc Protocol object.
  1206. pItem - Points to EPVC_ADAPTER.Hdr.HashLink.
  1207. Return Value:
  1208. TRUE IFF the key (adapter name) exactly matches the key of the specified
  1209. adapter object.
  1210. --*/
  1211. {
  1212. PEPVC_ADAPTER pA = NULL;
  1213. PNDIS_STRING pName = (PNDIS_STRING) pKey;
  1214. BOOLEAN fCompare;
  1215. pA = CONTAINING_RECORD(pItem, EPVC_ADAPTER, Hdr.HashLink);
  1216. //
  1217. // TODO: maybe case-insensitive compare?
  1218. //
  1219. if ( (pA->bind.DeviceName.Length == pName->Length)
  1220. && NdisEqualMemory(pA->bind.DeviceName.Buffer, pName->Buffer, pName->Length))
  1221. {
  1222. return TRUE;
  1223. }
  1224. else
  1225. {
  1226. return FALSE;
  1227. }
  1228. TRACE (TL_V, TM_Pt, ("-- epvcProtocolCompareKey pAdapter %p, pKey, return %x",pA, pKey, fCompare ) );
  1229. return fCompare;
  1230. }
  1231. ULONG
  1232. epvcAdapterHash(
  1233. PVOID pKey
  1234. )
  1235. /*++
  1236. Routine Description:
  1237. Hash function responsible for returning a hash of pKey, which
  1238. we expect to be a pointer to an Epvc Protocol block.
  1239. Return Value:
  1240. ULONG-sized hash of the string.
  1241. --*/
  1242. {
  1243. PNDIS_STRING pName = (PNDIS_STRING) pKey;
  1244. WCHAR *pwch = pName->Buffer;
  1245. WCHAR *pwchEnd = pName->Buffer + pName->Length/sizeof(*pwch);
  1246. ULONG Hash = 0;
  1247. for (;pwch < pwchEnd; pwch++)
  1248. {
  1249. Hash ^= (Hash<<1) ^ *pwch;
  1250. }
  1251. return Hash;
  1252. }
  1253. //--------------------------------------------------------------------------------
  1254. // //
  1255. // Bind Adapter - Entry Points and Tasks //
  1256. // //
  1257. // //
  1258. //--------------------------------------------------------------------------------
  1259. VOID
  1260. EpvcBindAdapter(
  1261. OUT PNDIS_STATUS pStatus,
  1262. IN NDIS_HANDLE BindContext,
  1263. IN PNDIS_STRING pDeviceName,
  1264. IN PVOID SystemSpecific1,
  1265. IN PVOID SystemSpecific2
  1266. )
  1267. /*++
  1268. Routine Description:
  1269. This is called by NDIS when it has an adapter for which there is a
  1270. binding to the Epvc Protocol.
  1271. We first allocate an Adapter structure. Then we open our configuration
  1272. section for this adapter and save the handle in the Adapter structure.
  1273. Finally, we open the adapter.
  1274. We then read the registry and find out how many intermediate Miniports are
  1275. sitting on top of this adapter. Data structures are initialized for these Miniports
  1276. We don't do anything more for this adapter until NDIS notifies us of
  1277. the presence of a Call manager (via our AfRegisterNotify handler).
  1278. Arguments:
  1279. pStatus - Place to return status of this call
  1280. BindContext - Not used, because we don't pend this call
  1281. pDeviceName - The name of the adapter we are requested to bind to
  1282. SystemSpecific1 - Opaque to us; to be used to access configuration info
  1283. SystemSpecific2 - Opaque to us; not used.
  1284. Return Value:
  1285. Always TRUE. We set *pStatus to an error code if something goes wrong before
  1286. we
  1287. call NdisOpenAdapter, otherwise NDIS_STATUS_PENDING.
  1288. --*/
  1289. {
  1290. NDIS_STATUS Status;
  1291. EPVC_ADAPTER *pAdapter;
  1292. #if DBG
  1293. KIRQL EntryIrql = KeGetCurrentIrql();
  1294. #endif // DBG
  1295. ENTER("BindAdapter", 0xa830f919)
  1296. RM_DECLARE_STACK_RECORD(SR)
  1297. TIMESTAMP("==>BindAdapter");
  1298. do
  1299. {
  1300. PRM_TASK pTask;
  1301. EPVC_ADAPTER_PARAMS BindParams;
  1302. // Setup initialization parameters
  1303. //
  1304. BindParams.pDeviceName = pDeviceName;
  1305. BindParams.pEpvcConfigName = (PNDIS_STRING) SystemSpecific1;
  1306. BindParams.BindContext = BindContext;
  1307. // Allocate and initialize adapter object.
  1308. // This also sets up ref counts for all linkages, plus one
  1309. // tempref for us, which we must deref when done.
  1310. //
  1311. Status = RM_CREATE_AND_LOCK_OBJECT_IN_GROUP(
  1312. &EpvcGlobals.adapters.Group,
  1313. pDeviceName, // Key
  1314. &BindParams, // Init params
  1315. &((PRM_OBJECT_HEADER)pAdapter),
  1316. NULL, // pfCreated
  1317. &SR
  1318. );
  1319. if (FAIL(Status))
  1320. {
  1321. TR_WARN(("FATAL: Couldn't create adapter object\n"));
  1322. pAdapter = NULL;
  1323. break;
  1324. }
  1325. // Allocate task to complete the initialization.
  1326. // The task is tmp ref'd for us, and we must deref it when we're done here.
  1327. // We implicitly do this by calling RmStartTask below.
  1328. //
  1329. Status = epvcAllocateTask(
  1330. &pAdapter->Hdr, // pParentObject,
  1331. epvcTaskInitializeAdapter, // pfnHandler,
  1332. 0, // Timeout,
  1333. "Task: Initialize Adapter", // szDescription
  1334. &pTask,
  1335. &SR
  1336. );
  1337. if (FAIL(Status))
  1338. {
  1339. pTask = NULL;
  1340. break;
  1341. }
  1342. UNLOCKOBJ(pAdapter, &SR);
  1343. // Start the task to complete this initialization.
  1344. // NO locks must be held at this time.
  1345. // RmStartTask expect's a tempref on the task, which it deref's when done.
  1346. // RmStartTask will free the task automatically, whether it completes
  1347. // synchronously or asynchronously.
  1348. //
  1349. RmStartTask(pTask, 0, &SR);
  1350. TRACE (TL_V, TM_Pt, ("Task InitializeAdapter - Start Task returned %x", Status));
  1351. LOCKOBJ(pAdapter, &SR);
  1352. } while(FALSE);
  1353. if (pAdapter)
  1354. {
  1355. UNLOCKOBJ(pAdapter, &SR);
  1356. if (!PEND(Status) && FAIL(Status))
  1357. {
  1358. // At this point the adapter should be a "zombie object."
  1359. //
  1360. ASSERTEX(RM_IS_ZOMBIE(pAdapter), pAdapter);
  1361. }
  1362. RmTmpDereferenceObject(&pAdapter->Hdr, &SR);
  1363. *pStatus = NDIS_STATUS_PENDING;
  1364. }
  1365. else
  1366. {
  1367. //
  1368. // Fail the bind as the adapter was not allocated
  1369. //
  1370. *pStatus = NDIS_STATUS_FAILURE;
  1371. }
  1372. #if DBG
  1373. {
  1374. KIRQL ExitIrql = KeGetCurrentIrql();
  1375. TR_INFO(("Exiting. EntryIrql=%lu, ExitIrql = %lu\n", EntryIrql, ExitIrql));
  1376. }
  1377. #endif //DBG
  1378. RM_ASSERT_CLEAR(&SR);
  1379. EXIT()
  1380. TIMESTAMP("<==BindAdapter");
  1381. TRACE (TL_T, TM_Pt, ("<==BindAdapter %x", *pStatus));
  1382. RM_ASSERT_CLEAR(&SR);
  1383. return ;
  1384. }
  1385. NDIS_STATUS
  1386. epvcTaskInitializeAdapter(
  1387. IN struct _RM_TASK * pTask,
  1388. IN RM_TASK_OPERATION Code,
  1389. IN UINT_PTR UserParam,
  1390. IN PRM_STACK_RECORD pSR
  1391. )
  1392. /*++
  1393. Routine Description:
  1394. Task handler responsible for initializing an adapter.
  1395. Arguments:
  1396. UserParam for (Code == RM_TASKOP_START) : unused
  1397. --*/
  1398. {
  1399. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1400. PEPVC_ADAPTER pAdapter = (PEPVC_ADAPTER) RM_PARENT_OBJECT(pTask);
  1401. PTASK_ADAPTERINIT pAdapterInitTask;
  1402. enum
  1403. {
  1404. STAGE_BecomePrimaryTask,
  1405. STAGE_ActivateAdapterComplete,
  1406. STAGE_DeactivateAdapterComplete,
  1407. STAGE_End
  1408. } Stage;
  1409. ENTER("TaskInitializeAdapter", 0x18f9277a)
  1410. pAdapterInitTask = (PTASK_ADAPTERINIT) pTask;
  1411. TRACE (TL_T, TM_Pt, ("==>epvcTaskInitializeAdapter Code %x \n", Code));
  1412. //
  1413. // Message normalizing code
  1414. //
  1415. switch(Code)
  1416. {
  1417. case RM_TASKOP_START:
  1418. Stage = STAGE_BecomePrimaryTask;
  1419. break;
  1420. case RM_TASKOP_PENDCOMPLETE:
  1421. Status = (NDIS_STATUS) UserParam;
  1422. ASSERT(!PEND(Status));
  1423. Stage = RM_PEND_CODE(pTask);
  1424. break;
  1425. case RM_TASKOP_END:
  1426. Status = (NDIS_STATUS) UserParam;
  1427. Stage= STAGE_End;
  1428. break;
  1429. default:
  1430. ASSERT(FALSE);
  1431. return NDIS_STATUS_FAILURE; // ** EARLY RETURN **
  1432. }
  1433. ASSERTEX(!PEND(Status), pTask);
  1434. switch(Stage)
  1435. {
  1436. case STAGE_BecomePrimaryTask:
  1437. {
  1438. // If there is a primary task, pend on it, else make ourselves
  1439. // the primary task.
  1440. //
  1441. LOCKOBJ(pAdapter, pSR);
  1442. if (pAdapter->bind.pPrimaryTask == NULL)
  1443. {
  1444. epvcSetPrimaryAdapterTask(pAdapter, pTask, EPVC_AD_PS_INITING, pSR);
  1445. UNLOCKOBJ(pAdapter, pSR);
  1446. }
  1447. else
  1448. {
  1449. PRM_TASK pOtherTask = pAdapter->bind.pPrimaryTask;
  1450. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  1451. UNLOCKOBJ(pAdapter, pSR);
  1452. RmPendTaskOnOtherTask(
  1453. pTask,
  1454. STAGE_BecomePrimaryTask, // we'll try again...
  1455. pOtherTask,
  1456. pSR
  1457. );
  1458. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  1459. Status = NDIS_STATUS_PENDING;
  1460. break;
  1461. }
  1462. //
  1463. // We're now the primary task. Since we're starting out,
  1464. // there should be NO activate/deactivate task.
  1465. // (Note: we don't bother getting the adapter lock for these asserts).
  1466. //
  1467. ASSERT(pAdapter->bind.pPrimaryTask == pTask);
  1468. ASSERT(pAdapter->bind.pSecondaryTask == NULL);
  1469. //
  1470. // Allocate and start the activate adapter task.
  1471. //
  1472. {
  1473. PRM_TASK pActivateTask;
  1474. Status = epvcAllocateTask(
  1475. &pAdapter->Hdr, // pParentObject,
  1476. epvcTaskActivateAdapter, // pfnHandler,
  1477. 0, // Timeout,
  1478. "Task: Activate Adapter(init)", // szDescription
  1479. &pActivateTask,
  1480. pSR
  1481. );
  1482. if (FAIL(Status))
  1483. {
  1484. pActivateTask = NULL;
  1485. TR_WARN(("FATAL: couldn't alloc activate task!\n"));
  1486. }
  1487. else
  1488. {
  1489. RmPendTaskOnOtherTask(
  1490. pTask,
  1491. STAGE_ActivateAdapterComplete,
  1492. pActivateTask, // task to pend on
  1493. pSR
  1494. );
  1495. // RmStartTask uses up the tmpref on the task
  1496. // which was added by arpAllocateTask.
  1497. //
  1498. Status = RmStartTask(
  1499. pActivateTask,
  1500. 0, // UserParam (unused)
  1501. pSR
  1502. );
  1503. }
  1504. }
  1505. }
  1506. if (PEND(Status)) break;
  1507. // FALL THROUGH TO NEXT STAGE
  1508. case STAGE_ActivateAdapterComplete:
  1509. {
  1510. //
  1511. // We've run the active-adapter task. On failure, we need to
  1512. // cleanup state by calling the deactivate-adapter task.
  1513. //
  1514. // Save away the failure code for later...
  1515. //
  1516. pAdapterInitTask->ReturnStatus = Status;
  1517. if (FAIL(Status))
  1518. {
  1519. PRM_TASK pDeactivateTask;
  1520. Status = epvcAllocateTask(
  1521. &pAdapter->Hdr, // pParentObject,
  1522. epvcTaskDeactivateAdapter, // pfnHandler,
  1523. 0, // Timeout,
  1524. "Task: Deactivate Adapter(init)", // szDescription
  1525. &pDeactivateTask,
  1526. pSR
  1527. );
  1528. if (FAIL(Status))
  1529. {
  1530. pDeactivateTask = NULL;
  1531. ASSERT(FALSE); // TODO: use special dealloc task pool for this.
  1532. TR_WARN(("FATAL: couldn't alloc deactivate task!\n"));
  1533. }
  1534. else
  1535. {
  1536. RmPendTaskOnOtherTask(
  1537. pTask,
  1538. STAGE_DeactivateAdapterComplete,
  1539. pDeactivateTask, // task to pend on
  1540. pSR
  1541. );
  1542. //
  1543. // RmStartTask uses up the tmpref on the task
  1544. // which was added by arpAllocateTask.
  1545. //
  1546. Status = RmStartTask(
  1547. pDeactivateTask,
  1548. 0, // UserParam (unused)
  1549. pSR
  1550. );
  1551. }
  1552. }
  1553. }
  1554. break;
  1555. case STAGE_DeactivateAdapterComplete:
  1556. {
  1557. //
  1558. // We've completed the deactivate adapter task which we started
  1559. // because of some init-adapter failure.
  1560. //
  1561. // In general, we don't expect the deactivate task to return failure.
  1562. //
  1563. ASSERT(!FAIL(Status));
  1564. // We expect the original status of the init to be a failure (that's
  1565. // why we started the deinit in the first place!
  1566. //
  1567. ASSERT(FAIL(pAdapterInitTask->ReturnStatus));
  1568. Status = pAdapterInitTask->ReturnStatus;
  1569. }
  1570. break;
  1571. case STAGE_End:
  1572. {
  1573. NDIS_HANDLE BindContext;
  1574. //
  1575. // We HAVE to be the primary task at this point, becase we simply
  1576. // wait and retry until we become one.
  1577. //
  1578. // Clear the primary task in the adapter object.
  1579. //
  1580. LOCKOBJ(pAdapter, pSR);
  1581. {
  1582. ULONG InitState;
  1583. InitState = FAIL(Status) ? EPVC_AD_PS_FAILEDINIT : EPVC_AD_PS_INITED;
  1584. epvcClearPrimaryAdapterTask(pAdapter, pTask, InitState, pSR);
  1585. }
  1586. BindContext = pAdapter->bind.BindContext;
  1587. UNLOCKOBJ(pAdapter, pSR);
  1588. // On failure, pAdapter should be deallocated.
  1589. //
  1590. if (FAIL(Status))
  1591. {
  1592. if(RM_IS_ZOMBIE(pAdapter))
  1593. {
  1594. TR_WARN(("END: pAdapter is already deallocated.\n"));
  1595. }
  1596. else
  1597. {
  1598. //
  1599. // On failure, free the adapter here itself, because we're
  1600. // not going to call the shutdown task.
  1601. //
  1602. RmFreeObjectInGroup(
  1603. &EpvcGlobals.adapters.Group,
  1604. &(pAdapter->Hdr),
  1605. NULL, // NULL pTask == synchronous.
  1606. pSR
  1607. );
  1608. pAdapter = NULL;
  1609. }
  1610. }
  1611. //
  1612. // Clear out the variables that are valid only
  1613. // during the BindAdapter Call
  1614. //
  1615. if (pAdapter != NULL)
  1616. {
  1617. pAdapter->bind.pEpvcConfigName = NULL;
  1618. }
  1619. // Signal Ndis that the bind is complete.
  1620. //
  1621. NdisCompleteBindAdapter(BindContext ,
  1622. Status,
  1623. NDIS_STATUS_PENDING);
  1624. TIMESTAMP("== Completing the Adapter Bind");
  1625. RM_ASSERT_NOLOCKS(pSR);
  1626. }
  1627. break;
  1628. default:
  1629. {
  1630. ASSERTEX(!"Unknown task op", pTask);
  1631. }
  1632. break;
  1633. } // switch (Code)
  1634. RM_ASSERT_NOLOCKS(pSR);
  1635. EXIT()
  1636. TRACE (TL_T, TM_Pt, ("<==epvcTaskInitializeAdapter Status %x\n", Status));
  1637. return Status;
  1638. }
  1639. NDIS_STATUS
  1640. epvcTaskActivateAdapter(
  1641. IN struct _RM_TASK * pTask,
  1642. IN RM_TASK_OPERATION Code,
  1643. IN UINT_PTR UserParam,
  1644. IN PRM_STACK_RECORD pSR
  1645. )
  1646. /*++
  1647. Routine Description:
  1648. Task handler responsible for initializing an adapter.
  1649. Arguments:
  1650. UserParam for (Code == RM_TASKOP_START) : unused
  1651. --*/
  1652. {
  1653. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1654. PEPVC_ADAPTER pAdapter = (PEPVC_ADAPTER) RM_PARENT_OBJECT(pTask);
  1655. enum
  1656. {
  1657. PEND_OpenAdapter,
  1658. PEND_GetAdapterInfo
  1659. };
  1660. ENTER("TaskInitializeAdapter", 0xb6ada31d)
  1661. TRACE (TL_T, TM_Pt, ("==>epvcTaskActivateAdapter pAdapter %p Code %x",pAdapter, Code ));
  1662. switch(Code)
  1663. {
  1664. case RM_TASKOP_START:
  1665. {
  1666. NDIS_MEDIUM Medium = NdisMediumAtm;
  1667. UINT SelMediumIndex = 0;
  1668. NDIS_STATUS OpenStatus;
  1669. TRACE (TL_T, TM_Pt, (" epvcTaskActivateAdapter RM_TASKOP_START "));
  1670. // Set ourselves as the secondary task.
  1671. //
  1672. LOCKOBJ(pAdapter, pSR);
  1673. epvcSetSecondaryAdapterTask(pAdapter, pTask, EPVC_AD_AS_ACTIVATING, pSR);
  1674. UNLOCKOBJ(pAdapter, pSR);
  1675. //
  1676. // Suspend task and call NdisOpenAdapter...
  1677. //
  1678. RmSuspendTask(pTask, PEND_OpenAdapter, pSR);
  1679. RM_ASSERT_NOLOCKS(pSR);
  1680. epvcOpenAdapter(
  1681. &Status,
  1682. &OpenStatus,
  1683. &pAdapter->bind.BindingHandle,
  1684. &SelMediumIndex, // selected medium index
  1685. &Medium, // Array of medium types
  1686. 1, // Size of Media list
  1687. EpvcGlobals.driver.ProtocolHandle,
  1688. (NDIS_HANDLE)pAdapter, // our adapter bind context
  1689. &pAdapter->bind.DeviceName, // pDeviceName
  1690. 0, // Open options
  1691. (PSTRING)NULL, // Addressing Info...
  1692. pSR);
  1693. if (Status != NDIS_STATUS_PENDING)
  1694. {
  1695. EpvcOpenAdapterComplete(
  1696. (NDIS_HANDLE)pAdapter,
  1697. Status,
  1698. OpenStatus
  1699. );
  1700. }
  1701. Status = NDIS_STATUS_PENDING;
  1702. }
  1703. break;
  1704. case RM_TASKOP_PENDCOMPLETE:
  1705. {
  1706. PTASK_ADAPTERACTIVATE pAdapterInitTask;
  1707. pAdapterInitTask = (PTASK_ADAPTERACTIVATE) pTask;
  1708. Status = (NDIS_STATUS) UserParam;
  1709. ASSERT(!PEND(Status));
  1710. ASSERT(sizeof(TASK_ADAPTERACTIVATE) <= sizeof(EPVC_TASK));
  1711. switch(RM_PEND_CODE(pTask))
  1712. {
  1713. case PEND_OpenAdapter:
  1714. //
  1715. // The open adapter operation is complete. Get adapter
  1716. // information and notify IP on success. On failure,
  1717. // shutdown the adapter if required, and notify IP of
  1718. // the failure.
  1719. //
  1720. TRACE (TL_T, TM_Pt, (" epvcTaskActivateAdapter RM_TASKOP_PENDCOMPLETE - PEND_OpenAdapter "));
  1721. if (FAIL(Status))
  1722. {
  1723. // Set adapter handle to null -- it may not be hull.
  1724. // even though the open adapter has succeeded.
  1725. //
  1726. pAdapter->bind.BindingHandle = NULL;
  1727. break;
  1728. }
  1729. ASSERT (pAdapter->bind.BindingHandle != NULL);
  1730. // FALL THROUGH on synchronous completion of arpGetAdapterInfo...
  1731. case PEND_GetAdapterInfo:
  1732. //
  1733. // Done with getting adapter info.
  1734. // We need to switch to passive before going further
  1735. //
  1736. TRACE (TL_T, TM_Pt, (" epvcTaskActivateAdapter RM_TASKOP_PENDCOMPLETE - PEND_GetAdapterInfo "));
  1737. ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
  1738. if (!EPVC_ATPASSIVE())
  1739. {
  1740. ASSERT (!"Should not be here");
  1741. // We're not at passive level, but we need to be when we
  1742. // call IP's add interface. So we switch to passive...
  1743. // NOTE: we specify completion code PEND_GetAdapterInfo
  1744. // because we want to get back here (except
  1745. // we'll be at passive).
  1746. //
  1747. /*RmSuspendTask(pTask, PEND_GetAdapterInfo, pSR);
  1748. RmResumeTaskAsync(
  1749. pTask,
  1750. Status,
  1751. &pAdapterInitTask->WorkItem,
  1752. pSR
  1753. );
  1754. Status = NDIS_STATUS_PENDING;*/
  1755. break;
  1756. }
  1757. if (Status == NDIS_STATUS_SUCCESS)
  1758. {
  1759. //
  1760. // Copy over adapter info into pAdapter->info...
  1761. // Then read configuration information.
  1762. //
  1763. //
  1764. // Query the ATM adapter for HW specific Info
  1765. //
  1766. epvcGetAdapterInfo(pAdapter, pSR, NULL);
  1767. // Read Adapter Configuration Information
  1768. //
  1769. Status = epvcReadAdapterConfiguration(pAdapter, pSR);
  1770. Status = NDIS_STATUS_SUCCESS;
  1771. }
  1772. //
  1773. // NOTE: if we fail, a higher level task is responsible
  1774. // for "running the compensating transaction", i.e., running
  1775. // epvcTaskDeactivateAdapter.
  1776. //
  1777. // end case PEND_OpenAdapter, PEND_GetAdapterInfo
  1778. break;
  1779. default:
  1780. {
  1781. ASSERTEX(!"Unknown pend op", pTask);
  1782. }
  1783. break;
  1784. } // end switch(RM_PEND_CODE(pTask))
  1785. } // case RM_TASKOP_PENDCOMPLETE
  1786. break;
  1787. case RM_TASKOP_END:
  1788. {
  1789. TRACE (TL_T, TM_Pt, (" epvcTaskActivateAdapter RM_TASKOP_END"));
  1790. Status = (NDIS_STATUS) UserParam;
  1791. // We're done -- the status had better not be pending!
  1792. //
  1793. ASSERTEX(!PEND(Status), pTask);
  1794. // Clear ourselves as the secondary task in the adapter object.
  1795. //
  1796. {
  1797. ULONG InitState;
  1798. LOCKOBJ(pAdapter, pSR);
  1799. InitState = FAIL(Status)
  1800. ? EPVC_AD_AS_FAILEDACTIVATE
  1801. : EPVC_AD_AS_ACTIVATED;
  1802. epvcClearSecondaryAdapterTask(pAdapter, pTask, InitState, pSR);
  1803. UNLOCKOBJ(pAdapter, pSR);
  1804. }
  1805. Status = NDIS_STATUS_SUCCESS;
  1806. }
  1807. break;
  1808. default:
  1809. {
  1810. ASSERTEX(!"Unknown task op", pTask);
  1811. }
  1812. break;
  1813. } // switch (Code)
  1814. RM_ASSERT_NOLOCKS(pSR);
  1815. EXIT()
  1816. TRACE (TL_T, TM_Pt, ("<==epvcTaskActivateAdapter Status %x", Status ));
  1817. return Status;
  1818. }
  1819. VOID
  1820. EpvcOpenAdapterComplete(
  1821. IN NDIS_HANDLE ProtocolBindingContext,
  1822. IN NDIS_STATUS Status,
  1823. IN NDIS_STATUS OpenErrorStatus
  1824. )
  1825. /*++
  1826. Routine Description:
  1827. This is called by NDIS when a previous call to NdisOpenAdapter
  1828. that had pended has completed. We now complete the BindAdapter
  1829. that lead to this.
  1830. Arguments:
  1831. ProtocolBindingContext - Our context for this adapter binding, which
  1832. is a pointer to an EPVC_ADAPTER structure.
  1833. Status - Status of OpenAdapter
  1834. OpenErrorStatus - Error code in case of failure.
  1835. --*/
  1836. {
  1837. ENTER("OpenAdapterComplete", 0x06d9342c)
  1838. EPVC_ADAPTER * pAdapter = (EPVC_ADAPTER*) ProtocolBindingContext;
  1839. RM_DECLARE_STACK_RECORD(SR)
  1840. TIMESTAMP("==>OpenAdapterComplete");
  1841. TRACE ( TL_T, TM_Mp, ("==>OpenAdapterComplete"));
  1842. // We expect a nonzero task here (the bind task), which we unpend.
  1843. // No need to grab locks or anything at this stage.
  1844. //
  1845. {
  1846. TR_INFO((
  1847. "BindCtxt=0x%p, status=0x%p, OpenErrStatus=0x%p",
  1848. ProtocolBindingContext,
  1849. Status,
  1850. OpenErrorStatus
  1851. ));
  1852. // We don't pass on OpenErrorStatus, so we have just the status
  1853. // to pass on, which we do directly as the UINT_PTR "Param".
  1854. //
  1855. RmResumeTask(pAdapter->bind.pSecondaryTask, (UINT_PTR) Status, &SR);
  1856. }
  1857. RM_ASSERT_CLEAR(&SR)
  1858. EXIT()
  1859. TRACE ( TL_T, TM_Mp, ("<==OpenAdapterComplete"));
  1860. TIMESTAMP("<==OpenAdapterComplete");
  1861. RM_ASSERT_CLEAR(&SR);
  1862. }
  1863. NDIS_STATUS
  1864. epvcTaskDeactivateAdapter(
  1865. IN struct _RM_TASK * pTask,
  1866. IN RM_TASK_OPERATION Code,
  1867. IN UINT_PTR UserParam,
  1868. IN PRM_STACK_RECORD pSR
  1869. )
  1870. /*++
  1871. Routine Description:
  1872. Task handler responsible for shutting down an IP interface.
  1873. Arguments:
  1874. UserParam for (Code == RM_TASKOP_START) : UnbindContext
  1875. --*/
  1876. {
  1877. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1878. EPVC_ADAPTER * pAdapter = (EPVC_ADAPTER*) RM_PARENT_OBJECT(pTask);
  1879. BOOLEAN fContinueShutdown = FALSE;
  1880. enum
  1881. {
  1882. PEND_CloseAdapter
  1883. };
  1884. ENTER("TaskShutdownAdapter", 0xe262e828)
  1885. TRACE ( TL_T, TM_Pt, ("==>epvcTaskDeactivateAdapter Code %x", Code) );
  1886. switch(Code)
  1887. {
  1888. case RM_TASKOP_START:
  1889. {
  1890. NDIS_HANDLE NdisAdapterHandle;
  1891. LOCKOBJ(pAdapter, pSR);
  1892. epvcSetSecondaryAdapterTask(pAdapter, pTask, EPVC_AD_AS_DEACTIVATING, pSR);
  1893. UNLOCKOBJ(pAdapter, pSR);
  1894. fContinueShutdown = TRUE;
  1895. //
  1896. // Iterate through all the miniports and stop them
  1897. //
  1898. epvcEnumerateObjectsInGroup (&pAdapter->MiniportsGroup,
  1899. epvcMiniportDoUnbind,
  1900. NULL,
  1901. pSR );
  1902. //
  1903. // Close the adapter below
  1904. //
  1905. LOCKOBJ(pAdapter, pSR);
  1906. NdisAdapterHandle = pAdapter->bind.BindingHandle;
  1907. pAdapter->bind.BindingHandle = NULL;
  1908. UNLOCKOBJ(pAdapter, pSR);
  1909. if (NdisAdapterHandle != NULL)
  1910. {
  1911. //
  1912. // Suspend task and call NdisCloseAdapter...
  1913. //
  1914. RmSuspendTask(pTask, PEND_CloseAdapter, pSR);
  1915. RM_ASSERT_NOLOCKS(pSR);
  1916. epvcCloseAdapter(
  1917. &Status,
  1918. NdisAdapterHandle,
  1919. pSR
  1920. );
  1921. if (Status != NDIS_STATUS_PENDING)
  1922. {
  1923. EpvcCloseAdapterComplete(
  1924. (NDIS_HANDLE)pAdapter,
  1925. Status
  1926. );
  1927. }
  1928. Status = NDIS_STATUS_PENDING;
  1929. }
  1930. break;
  1931. }
  1932. case RM_TASKOP_PENDCOMPLETE:
  1933. {
  1934. switch(RM_PEND_CODE(pTask))
  1935. {
  1936. case PEND_CloseAdapter:
  1937. {
  1938. //
  1939. // The close adapter operation is complete. Free the the
  1940. // adapter and if there is an unbind context, notify NDIS
  1941. // of unbind completion.
  1942. //
  1943. ASSERTEX(pAdapter->bind.BindingHandle == NULL, pAdapter);
  1944. Status = (NDIS_STATUS) UserParam;
  1945. // Status of the completed operation can't itself be pending!
  1946. //
  1947. ASSERT(Status != NDIS_STATUS_PENDING);
  1948. }
  1949. break;
  1950. }
  1951. }
  1952. break;
  1953. case RM_TASKOP_END:
  1954. {
  1955. Status = (NDIS_STATUS) UserParam;
  1956. // Clear the secondary task in the adapter object.
  1957. //
  1958. LOCKOBJ(pAdapter, pSR);
  1959. epvcClearSecondaryAdapterTask(pAdapter, pTask, EPVC_AD_AS_DEACTIVATED, pSR);
  1960. UNLOCKOBJ(pAdapter, pSR);
  1961. }
  1962. break;
  1963. default:
  1964. {
  1965. ASSERTEX(!"Unknown task op", pTask);
  1966. }
  1967. break;
  1968. } // switch (Code)
  1969. RM_ASSERT_NOLOCKS(pSR);
  1970. EXIT()
  1971. TRACE ( TL_T, TM_Pt, ("<==epvcTaskDeactivateAdapter Status %x", Status) );
  1972. return Status;
  1973. }
  1974. VOID
  1975. EpvcCloseAdapterComplete(
  1976. IN NDIS_HANDLE ProtocolBindingContext,
  1977. IN NDIS_STATUS Status
  1978. )
  1979. /*++
  1980. Routine Description:
  1981. This is called by NDIS when a previous call to NdisCloseAdapter
  1982. that had pended has completed. The task that called NdisCloseAdapter
  1983. would have suspended itself, so we simply resume it now.
  1984. Arguments:
  1985. ProtocolBindingContext - Our context for this adapter binding, which
  1986. is a pointer to an EPVC_ADAPTER structure.
  1987. Status - Status of CloseAdapter
  1988. Return Value:
  1989. None
  1990. --*/
  1991. {
  1992. ENTER("CloseAdapterComplete", 0xe23bfba7)
  1993. PEPVC_ADAPTER pAdapter = (PEPVC_ADAPTER) ProtocolBindingContext;
  1994. RM_DECLARE_STACK_RECORD(sr)
  1995. TIMESTAMP("==>CloseAdapterComplete");
  1996. TRACE (TL_T, TM_Pt, ("== EpvcCloseAdapterComplete"));
  1997. LOCKOBJ (pAdapter, &sr);
  1998. AdapterSetFlag (pAdapter,EPVC_AD_INFO_AD_CLOSED);
  1999. UNLOCKOBJ (pAdapter, &sr);
  2000. // We expect a nonzero task here (UNbind task), which we unpend.
  2001. // No need to grab locks or anything at this stage.
  2002. //
  2003. RmResumeTask(pAdapter->bind.pSecondaryTask, (UINT_PTR) Status, &sr);
  2004. TIMESTAMP("<==CloseAdapterComplete");
  2005. RM_ASSERT_CLEAR(&sr)
  2006. EXIT()
  2007. }
  2008. NDIS_STATUS
  2009. epvcReadAdapterConfiguration(
  2010. PEPVC_ADAPTER pAdapter,
  2011. PRM_STACK_RECORD pSR
  2012. )
  2013. /*++
  2014. Routine Description:
  2015. This function can only be called from the BindAdapter function
  2016. Arguments:
  2017. pAdapter - Underlying adapter whose configuration is being read/
  2018. pSR - Stack Record
  2019. Return Value:
  2020. None
  2021. ++*/
  2022. {
  2023. NDIS_HANDLE AdaptersConfigHandle = NULL;
  2024. NDIS_HANDLE MiniportListConfigHandle = NULL;
  2025. NDIS_STRING MiniportListKeyName;
  2026. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  2027. ENTER("ReadAdapterConfiguration", 0x83c48ad8)
  2028. TRACE(TL_T, TM_Pt, ("==> epvcReadAdapterConfigurationpAdapter %p", pAdapter));
  2029. do
  2030. {
  2031. //
  2032. // Start off by opening the config section and reading our instance which we want
  2033. // to export for this binding
  2034. //
  2035. epvcOpenProtocolConfiguration(&NdisStatus,
  2036. &AdaptersConfigHandle ,
  2037. &pAdapter->bind.EpvcConfigName,
  2038. pSR);
  2039. if (NDIS_STATUS_SUCCESS != NdisStatus )
  2040. {
  2041. AdaptersConfigHandle = NULL;
  2042. TRACE_BREAK(TM_Pt, ("epvcOpenProtocolConfiguration failed " ) );
  2043. }
  2044. //
  2045. // this should get us to the protocol\paramters\adapters\guid section in the registry
  2046. //
  2047. //
  2048. // Open the Elan List configuration key.
  2049. //
  2050. NdisInitUnicodeString(&MiniportListKeyName, c_szIMMiniportList);
  2051. epvcOpenConfigurationKeyByName(
  2052. &NdisStatus,
  2053. AdaptersConfigHandle ,
  2054. &MiniportListKeyName,
  2055. &MiniportListConfigHandle,
  2056. pSR);
  2057. if (NDIS_STATUS_SUCCESS != NdisStatus)
  2058. {
  2059. MiniportListConfigHandle = NULL;
  2060. NdisStatus = NDIS_STATUS_FAILURE;
  2061. TRACE_BREAK(TM_Pt, ("NdisOpenConfigurationKeyByName failed " ) );
  2062. }
  2063. //
  2064. // Allocate and initialize all IM miniport instances that are present
  2065. // in the registry under this adapter
  2066. //
  2067. (VOID)epvcReadIntermediateMiniportConfiguration( pAdapter,
  2068. MiniportListConfigHandle,
  2069. pSR);
  2070. } while (FALSE);
  2071. if (MiniportListConfigHandle!= NULL)
  2072. {
  2073. NdisCloseConfiguration(MiniportListConfigHandle);
  2074. MiniportListConfigHandle = NULL;
  2075. }
  2076. if (AdaptersConfigHandle != NULL)
  2077. {
  2078. NdisCloseConfiguration(AdaptersConfigHandle );
  2079. AdaptersConfigHandle = NULL;
  2080. }
  2081. if (STATUS_NO_MORE_ENTRIES == NdisStatus )
  2082. {
  2083. NdisStatus = NDIS_STATUS_SUCCESS;
  2084. }
  2085. TRACE(TL_T, TM_Pt, ("<== epvcReadAdapterConfiguration Status %x", NdisStatus));
  2086. EXIT()
  2087. return NdisStatus;
  2088. }
  2089. NDIS_STATUS
  2090. epvcReadIntermediateMiniportConfiguration(
  2091. IN PEPVC_ADAPTER pAdapter,
  2092. IN NDIS_HANDLE MiniportListConfigHandle,
  2093. IN PRM_STACK_RECORD pSR
  2094. )
  2095. {
  2096. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  2097. ENTER ("ReadMiniportConfiguration", 0xb974a6fa)
  2098. TRACE(TL_T, TM_Pt, ("==> epvcReadIntermediateMiniportConfiguration pAdapter %p", pAdapter));
  2099. {
  2100. NDIS_HANDLE MiniportConfigHandle;
  2101. NDIS_STRING MiniportKeyName;
  2102. PEPVC_I_MINIPORT pMiniport = NULL;
  2103. UINT Index = 0;
  2104. //
  2105. // Iterate thru the configured Miniport
  2106. //
  2107. for (Index = 0;
  2108. ; // Stop only on error or no more Elans
  2109. Index++)
  2110. {
  2111. EPVC_I_MINIPORT_PARAMS Params;
  2112. //
  2113. // Open the "next" Miniport key
  2114. //
  2115. epvcOpenConfigurationKeyByIndex(
  2116. &NdisStatus,
  2117. MiniportListConfigHandle,
  2118. Index,
  2119. &MiniportKeyName,
  2120. &MiniportConfigHandle,
  2121. pSR
  2122. );
  2123. if (NDIS_STATUS_SUCCESS != NdisStatus)
  2124. {
  2125. MiniportConfigHandle = NULL;
  2126. }
  2127. //
  2128. // If NULL handle, assume no more Miniports.
  2129. //
  2130. if (MiniportConfigHandle == NULL)
  2131. {
  2132. break;
  2133. }
  2134. //
  2135. // Creating this Miniport
  2136. //
  2137. epvcInstantiateMiniport (pAdapter,
  2138. MiniportConfigHandle,
  2139. pSR);
  2140. NdisCloseConfiguration(MiniportConfigHandle);
  2141. MiniportConfigHandle = NULL;
  2142. }
  2143. //
  2144. // Close config handles
  2145. //
  2146. if (NULL != MiniportConfigHandle)
  2147. {
  2148. NdisCloseConfiguration(MiniportConfigHandle);
  2149. MiniportConfigHandle = NULL;
  2150. }
  2151. }
  2152. if (STATUS_NO_MORE_ENTRIES == NdisStatus )
  2153. {
  2154. NdisStatus = NDIS_STATUS_SUCCESS;
  2155. }
  2156. TRACE(TL_T, TM_Pt, ("<== epvcReadIntermediateMiniportConfiguration NdisStatus %x", NdisStatus));
  2157. EXIT()
  2158. return NdisStatus;
  2159. }
  2160. VOID
  2161. EpvcUnbindAdapter(
  2162. OUT PNDIS_STATUS pStatus,
  2163. IN NDIS_HANDLE ProtocolBindingContext,
  2164. IN NDIS_HANDLE UnbindContext
  2165. )
  2166. /*++
  2167. Routine Description:
  2168. This routine is called by NDIS when it wants us to unbind
  2169. from an adapter. Or, this may be called from within our Unload
  2170. handler. We undo the sequence of operations we performed
  2171. in our BindAdapter handler.
  2172. Arguments:
  2173. pStatus - Place to return status of this operation
  2174. ProtocolBindingContext - Our context for this adapter binding, which
  2175. is a pointer to an ATMEPVC Adapter structure.
  2176. UnbindContext - This is NULL if this routine is called from
  2177. within our Unload handler. Otherwise (i.e.
  2178. NDIS called us), we retain this for later use
  2179. when calling NdisCompleteUnbindAdapter.
  2180. Return Value:
  2181. None. We set *pStatus to NDIS_STATUS_PENDING always.
  2182. --*/
  2183. {
  2184. ENTER("UnbindAdapter", 0x3f25396e)
  2185. EPVC_ADAPTER * pAdapter = (EPVC_ADAPTER*) ProtocolBindingContext;
  2186. RM_DECLARE_STACK_RECORD(sr)
  2187. TIMESTAMP("==>UnbindAdapter");
  2188. TRACE ( TL_T, TM_Pt, ("==>UnbindAdapter ProtocolBindingContext %x\n", ProtocolBindingContext) );
  2189. //
  2190. // Get adapter lock and tmpref it.
  2191. //
  2192. LOCKOBJ(pAdapter, &sr);
  2193. RmTmpReferenceObject(&pAdapter->Hdr, &sr);
  2194. do
  2195. {
  2196. NDIS_STATUS Status;
  2197. PRM_TASK pTask;
  2198. // Allocate task to complete the unbind.
  2199. //
  2200. Status = epvcAllocateTask(
  2201. &pAdapter->Hdr, // pParentObject,
  2202. epvcTaskShutdownAdapter, // pfnHandler,
  2203. 0, // Timeout,
  2204. "Task: Shutdown Adapter", // szDescription
  2205. &pTask,
  2206. &sr
  2207. );
  2208. if (FAIL(Status))
  2209. {
  2210. // Ugly situation. We'll just leave things as they are...
  2211. //
  2212. pTask = NULL;
  2213. TR_WARN(("FATAL: couldn't allocate unbind task!\n"));
  2214. break;
  2215. }
  2216. // Start the task to complete the unbind.
  2217. // No locks must be held. RmStartTask uses up the tmpref on the task
  2218. // which was added by arpAllocateTask.
  2219. //
  2220. UNLOCKOBJ(pAdapter, &sr);
  2221. ((PTASK_ADAPTERSHUTDOWN) pTask)->pUnbindContext = UnbindContext;
  2222. RmStartTask(pTask, (UINT_PTR) UnbindContext, &sr);
  2223. LOCKOBJ(pAdapter, &sr);
  2224. } while(FALSE);
  2225. UNLOCKOBJ(pAdapter, &sr);
  2226. RmTmpDereferenceObject(&pAdapter->Hdr, &sr);
  2227. *pStatus = NDIS_STATUS_PENDING;
  2228. RM_ASSERT_CLEAR(&sr);
  2229. TIMESTAMP("<==UnbindAdapter");
  2230. EXIT()
  2231. }
  2232. NDIS_STATUS
  2233. epvcTaskShutdownAdapter(
  2234. IN struct _RM_TASK * pTask,
  2235. IN RM_TASK_OPERATION Code,
  2236. IN UINT_PTR UserParam,
  2237. IN PRM_STACK_RECORD pSR
  2238. )
  2239. /*++
  2240. Routine Description:
  2241. Task handler responsible for shutting down an ATMEPVC adapter.
  2242. Arguments:
  2243. UserParam for (Code == RM_TASKOP_START) : UnbindContext
  2244. --*/
  2245. {
  2246. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2247. EPVC_ADAPTER * pAdapter = (EPVC_ADAPTER*) RM_PARENT_OBJECT(pTask);
  2248. TASK_ADAPTERSHUTDOWN *pMyTask = (TASK_ADAPTERSHUTDOWN*) pTask;
  2249. enum
  2250. {
  2251. STAGE_BecomePrimaryTask,
  2252. STAGE_DeactivateAdapterComplete,
  2253. STAGE_End
  2254. } Stage;
  2255. ENTER("TaskShutdownAdapter", 0x3f25396e)
  2256. TRACE (TL_T, TM_Pt, ("==>epvcTaskShutdownAdapter Code %x", Code));
  2257. //
  2258. // Message normalizing code
  2259. //
  2260. switch(Code)
  2261. {
  2262. case RM_TASKOP_START:
  2263. Stage = STAGE_BecomePrimaryTask;
  2264. // Save away the UnbindContext (which we get as UserParam) in
  2265. // the task's private context, for use later.
  2266. //
  2267. pMyTask->pUnbindContext = (NDIS_HANDLE) UserParam;
  2268. break;
  2269. case RM_TASKOP_PENDCOMPLETE:
  2270. Status = (NDIS_STATUS) UserParam;
  2271. ASSERT(!PEND(Status));
  2272. Stage = RM_PEND_CODE(pTask);
  2273. break;
  2274. case RM_TASKOP_END:
  2275. Status = (NDIS_STATUS) UserParam;
  2276. Stage= STAGE_End;
  2277. break;
  2278. default:
  2279. ASSERT(FALSE);
  2280. return NDIS_STATUS_FAILURE; // ** EARLY RETURN **
  2281. }
  2282. ASSERTEX(!PEND(Status), pTask);
  2283. switch(Stage)
  2284. {
  2285. case STAGE_BecomePrimaryTask:
  2286. {
  2287. // If there is a primary task, pend on it, else make ourselves
  2288. // the primary task.
  2289. // We could get in this situation if someone does a
  2290. // "net stop arp1394" while we're in the middle of initializing or
  2291. // shutting down the adapter.
  2292. //
  2293. //
  2294. TRACE (TL_V, TM_Pt, (" epvcTaskShutdownAdapter STAGE_BecomePrimaryTask" ));
  2295. LOCKOBJ(pAdapter, pSR);
  2296. if (pAdapter->bind.pPrimaryTask == NULL)
  2297. {
  2298. epvcSetPrimaryAdapterTask(pAdapter, pTask, EPVC_AD_PS_DEINITING, pSR);
  2299. UNLOCKOBJ(pAdapter, pSR);
  2300. }
  2301. else
  2302. {
  2303. PRM_TASK pOtherTask = pAdapter->bind.pPrimaryTask;
  2304. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  2305. UNLOCKOBJ(pAdapter, pSR);
  2306. RmPendTaskOnOtherTask(
  2307. pTask,
  2308. STAGE_BecomePrimaryTask, // we'll try again...
  2309. pOtherTask,
  2310. pSR
  2311. );
  2312. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  2313. Status = NDIS_STATUS_PENDING;
  2314. break;
  2315. }
  2316. //
  2317. // We're now the primary task. Since we're starting out,
  2318. // there should be NO activate/deactivate task.
  2319. // (Note: we don't bother getting the adapter lock for these asserts).
  2320. //
  2321. ASSERT(pAdapter->bind.pPrimaryTask == pTask);
  2322. ASSERT(pAdapter->bind.pSecondaryTask == NULL);
  2323. //
  2324. // Allocate and start the deactivate adapter task.
  2325. //
  2326. {
  2327. PRM_TASK pDeactivateTask;
  2328. Status = epvcAllocateTask(
  2329. &pAdapter->Hdr, // pParentObject,
  2330. epvcTaskDeactivateAdapter, // pfnHandler,
  2331. 0, // Timeout,
  2332. "Task: Deactivate Adapter(shutdown)", // szDescription
  2333. &pDeactivateTask,
  2334. pSR
  2335. );
  2336. if (FAIL(Status))
  2337. {
  2338. pDeactivateTask = NULL;
  2339. TR_WARN(("FATAL: couldn't alloc deactivate task!\n"));
  2340. }
  2341. else
  2342. {
  2343. RmPendTaskOnOtherTask(
  2344. pTask,
  2345. STAGE_DeactivateAdapterComplete,
  2346. pDeactivateTask, // task to pend on
  2347. pSR
  2348. );
  2349. // RmStartTask uses up the tmpref on the task
  2350. // which was added by arpAllocateTask.
  2351. //
  2352. Status = RmStartTask(
  2353. pDeactivateTask,
  2354. 0, // UserParam (unused)
  2355. pSR
  2356. );
  2357. }
  2358. }
  2359. }
  2360. break;
  2361. case STAGE_DeactivateAdapterComplete:
  2362. {
  2363. TRACE (TL_V, TM_Pt,( " epvcTaskShutdownAdapter STAGE_DeactivateAdapterComplete" ));
  2364. // Nothing to do here -- we clean up in STAGE_End.
  2365. //
  2366. break;
  2367. }
  2368. case STAGE_End:
  2369. {
  2370. TRACE (TL_V, TM_Pt, (" epvcTaskShutdownAdapter STAGE_End" ));
  2371. //
  2372. // We HAVE to be the primary task at this point, becase we simply
  2373. // wait and retry until we become one.
  2374. //
  2375. ASSERT(pAdapter->bind.pPrimaryTask == pTask);
  2376. // Clear the primary task in the adapter object.
  2377. //
  2378. LOCKOBJ(pAdapter, pSR);
  2379. epvcClearPrimaryAdapterTask(pAdapter, pTask, EPVC_AD_PS_DEINITED, pSR);
  2380. UNLOCKOBJ(pAdapter, pSR);
  2381. if(RM_IS_ZOMBIE(pAdapter))
  2382. {
  2383. TR_WARN(("END: pAdapter is already deallocated.\n"));
  2384. }
  2385. else
  2386. {
  2387. // Free the adapter.
  2388. // (pAdapter will be allocated, but it will be in a "zombie" state).
  2389. //
  2390. RmDeinitializeGroup(&(pAdapter->MiniportsGroup), pSR);
  2391. RmFreeObjectInGroup(
  2392. &EpvcGlobals.adapters.Group,
  2393. &(pAdapter->Hdr),
  2394. NULL, // NULL pTask == synchronous.
  2395. pSR
  2396. );
  2397. }
  2398. // If there is an unbind-context, signal NDIS that the unbind is
  2399. // complete.
  2400. //
  2401. if (pMyTask->pUnbindContext)
  2402. {
  2403. TR_WARN(("END: Calling NdisCompleteUnbindAdapter. Status= 0x%lx\n",
  2404. Status));
  2405. RM_ASSERT_NOLOCKS(pSR);
  2406. TIMESTAMP("===Calling NdisCompleteUnbindAdapter");
  2407. NdisCompleteUnbindAdapter(
  2408. pMyTask->pUnbindContext,
  2409. Status
  2410. );
  2411. }
  2412. }
  2413. break;
  2414. default:
  2415. {
  2416. ASSERTEX(!"Unknown task op", pTask);
  2417. }
  2418. break;
  2419. } // switch (Code)
  2420. RM_ASSERT_NOLOCKS(pSR);
  2421. EXIT()
  2422. return Status;
  2423. }
  2424. VOID
  2425. epvcGetAdapterInfo(
  2426. IN PEPVC_ADAPTER pAdapter,
  2427. IN PRM_STACK_RECORD pSR,
  2428. IN PRM_TASK pTask // OPTIONAL
  2429. )
  2430. /*++
  2431. Routine Description:
  2432. Query an adapter for hardware-specific information that we need:
  2433. - burnt in hardware address (ESI part)
  2434. - Max packet size
  2435. - line rate
  2436. Arguments:
  2437. pAdapter - Pointer to EPVC adapter structure
  2438. Return Value:
  2439. None
  2440. --*/
  2441. {
  2442. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2443. EPVC_NDIS_REQUEST Request;
  2444. NDIS_MEDIA_STATE MediaState= NdisMediaStateDisconnected;
  2445. do
  2446. {
  2447. //
  2448. // Initialize.
  2449. //
  2450. NdisZeroMemory(&pAdapter->info.MacAddress, sizeof(MAC_ADDRESS));
  2451. pAdapter->info.MediaState = MediaState;
  2452. pAdapter->info.MaxAAL5PacketSize = ATMEPVC_DEF_MAX_AAL5_PDU_SIZE;
  2453. pAdapter->info.LinkSpeed.Outbound = pAdapter->info.LinkSpeed.Inbound = ATM_USER_DATA_RATE_SONET_155;
  2454. //
  2455. // MAC Address:
  2456. //
  2457. Status = epvcPrepareAndSendNdisRequest (pAdapter,
  2458. &Request,
  2459. NULL, // OPTIONAL
  2460. OID_ATM_HW_CURRENT_ADDRESS,
  2461. (PVOID)(&pAdapter->info.MacAddress),
  2462. sizeof (pAdapter->info.MacAddress),
  2463. NdisRequestQueryInformation,
  2464. NULL, // No miniport
  2465. FALSE, // No request was pended
  2466. FALSE, // Pended Request info
  2467. pSR);
  2468. ASSERT (PEND(Status) == FALSE);
  2469. if (FAIL(Status)== TRUE)
  2470. {
  2471. //
  2472. // Don't break .continue on
  2473. //
  2474. TRACE (TL_I, TM_Pt, ("Oid - Atm Hw Address failed %x", Status));
  2475. }
  2476. Status = epvcPrepareAndSendNdisRequest(
  2477. pAdapter,
  2478. &Request,
  2479. NULL, // OPTIONAL
  2480. OID_ATM_MAX_AAL5_PACKET_SIZE,
  2481. (PVOID)(&pAdapter->info.MaxAAL5PacketSize),
  2482. sizeof(pAdapter->info.MaxAAL5PacketSize),
  2483. NdisRequestQueryInformation,
  2484. NULL, // No miniport
  2485. FALSE, // No request was pended
  2486. FALSE, // Pended Request info
  2487. pSR);
  2488. if (FAIL(Status)== TRUE)
  2489. {
  2490. TRACE (TL_I, TM_Pt, ("Oid - Atm Max AAL5 Packet Size failed %x", Status));
  2491. }
  2492. if (pAdapter->info.MaxAAL5PacketSize > ATMEPVC_DEF_MAX_AAL5_PDU_SIZE)
  2493. {
  2494. pAdapter->info.MaxAAL5PacketSize = ATMEPVC_DEF_MAX_AAL5_PDU_SIZE;
  2495. }
  2496. //
  2497. // Link speed:
  2498. //
  2499. Status = epvcPrepareAndSendNdisRequest(
  2500. pAdapter,
  2501. &Request,
  2502. NULL, // OPTIONAL
  2503. OID_GEN_CO_LINK_SPEED,
  2504. &pAdapter->info.LinkSpeed,
  2505. sizeof(pAdapter->info.LinkSpeed),
  2506. NdisRequestQueryInformation,
  2507. NULL, // No miniport
  2508. FALSE, // No request was pended
  2509. FALSE, // Pended Request info
  2510. pSR);
  2511. TRACE (TL_V, TM_Mp, ("Outbound %x Inbound %x",
  2512. pAdapter->info.LinkSpeed.Outbound,
  2513. pAdapter->info.LinkSpeed.Inbound));
  2514. if ((NDIS_STATUS_SUCCESS != Status) ||
  2515. (0 == pAdapter->info.LinkSpeed.Inbound) ||
  2516. (0 == pAdapter->info.LinkSpeed.Outbound))
  2517. {
  2518. TRACE (TL_I, TM_Pt, ( "GetAdapterInfo: OID_GEN_CO_LINK_SPEED failed\n"));
  2519. //
  2520. // Default and assume data rate for 155.52Mbps SONET
  2521. //
  2522. pAdapter->info.LinkSpeed.Outbound = pAdapter->info.LinkSpeed.Inbound = ATM_USER_DATA_RATE_SONET_155;
  2523. }
  2524. //
  2525. // Link speed:
  2526. //
  2527. Status = epvcPrepareAndSendNdisRequest(
  2528. pAdapter,
  2529. &Request,
  2530. NULL, // OPTIONAL
  2531. OID_GEN_MEDIA_CONNECT_STATUS,
  2532. &MediaState,
  2533. sizeof(MediaState),
  2534. NdisRequestQueryInformation,
  2535. NULL, // No miniport
  2536. FALSE, // No request was pended
  2537. FALSE, // Pended Request info
  2538. pSR);
  2539. TRACE (TL_V, TM_Mp, ("MediaConnectivity %x ",MediaState));
  2540. if (NDIS_STATUS_SUCCESS != Status )
  2541. {
  2542. TRACE (TL_I, TM_Pt, ( "GetAdapterInfo: OID_GEN_CO_LINK_SPEED failed\n"));
  2543. //
  2544. // Default and assume data rate for 155.52Mbps SONET
  2545. //
  2546. MediaState = NdisMediaStateDisconnected;
  2547. }
  2548. pAdapter->info.MediaState = MediaState ;
  2549. TRACE( TL_V, TM_Pt,("GetAdapterInfo: Outbound Linkspeed %d", pAdapter->info.LinkSpeed.Outbound));
  2550. TRACE( TL_V, TM_Pt,("GetAdapterInfo: Inbound Linkspeed %d\n", pAdapter->info.LinkSpeed.Inbound));
  2551. }while (FALSE);
  2552. return;
  2553. }
  2554. NDIS_STATUS
  2555. EpvcPtPNPHandler(
  2556. IN NDIS_HANDLE ProtocolBindingContext,
  2557. IN PNET_PNP_EVENT pNetPnPEvent
  2558. )
  2559. /*++
  2560. Routine Description:
  2561. This is the Protocol PNP handlers.
  2562. All PNP Related OIDS(requests) are routed to this function
  2563. Arguments:
  2564. ProtocolBindingContext Pointer to our adapter structure.
  2565. pNetPnPEvent Pointer to a Net_PnP_Event
  2566. Return Value:
  2567. NDIS_STATUS_SUCCESS: as we do not do much here
  2568. --*/
  2569. {
  2570. ENTER("EpvcPtPnPHandler", 0xacded1ce)
  2571. PEPVC_ADAPTER pAdapter =(PEPVC_ADAPTER)ProtocolBindingContext;
  2572. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  2573. RM_DECLARE_STACK_RECORD (SR);
  2574. TRACE (TL_T, TM_Pt, ("==> EpvcPtPNPHandler Adapter %p, pNetPnpEvent %x", pAdapter, pNetPnPEvent));
  2575. //
  2576. // This will happen when all entities in the system need to be notified
  2577. //
  2578. switch(pNetPnPEvent->NetEvent)
  2579. {
  2580. case NetEventReconfigure :
  2581. Status = epvcPtNetEventReconfigure(pAdapter, pNetPnPEvent->Buffer, &SR);
  2582. break;
  2583. default :
  2584. Status = NDIS_STATUS_SUCCESS;
  2585. break;
  2586. }
  2587. TRACE (TL_T, TM_Pt, ("<== EpvcPtPNPHandler Status %x", Status));
  2588. RM_ASSERT_NOLOCKS(&SR)
  2589. EXIT();
  2590. return Status;
  2591. }
  2592. NDIS_STATUS
  2593. epvcPtNetEventReconfigure(
  2594. IN PEPVC_ADAPTER pAdapter,
  2595. IN PVOID pBuffer,
  2596. IN PRM_STACK_RECORD pSR
  2597. )
  2598. /*++
  2599. Routine Description:
  2600. This is the function that will be called by the PNP handler
  2601. whenever a PNPNetEventReconfigure happens
  2602. THis will happen if a new physical adapter has come in or the user
  2603. has re-enabled a virtual miniport.
  2604. To process:
  2605. Iterate through all the adapter. If adapters are bound, then make sure that
  2606. all of its miniport's are initialized.
  2607. If not, then leave it and call NdisReenumerate to connect all our protocol
  2608. instances with valid adapters
  2609. Arguments:
  2610. ProtocolBindingContext Pointer to our adapter structure.
  2611. Return Value:
  2612. NDIS_STATUS_SUCCESS: as we do not do much here
  2613. --*/
  2614. {
  2615. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2616. TRACE (TL_T, TM_Pt, ("==> epvcPtNetEventReconfigure Adapter %p, pBuffer %x", pAdapter, pBuffer));
  2617. do
  2618. {
  2619. //
  2620. // The notify object sets the REconfig buffer.
  2621. //
  2622. if (pBuffer != NULL)
  2623. {
  2624. ASSERT (!"PnPBuffer != NULL - not implemented yet");
  2625. break;
  2626. }
  2627. if (pAdapter == NULL)
  2628. {
  2629. //
  2630. // Iterate through all the adapters and initialize
  2631. // uninitialized miniports
  2632. //
  2633. epvcEnumerateObjectsInGroup ( &EpvcGlobals.adapters.Group,
  2634. epvcReconfigureAdapter,
  2635. pBuffer,
  2636. pSR);
  2637. //
  2638. // Re-enumerate the protocol bindings, this will cause us to get
  2639. // a BindAdapter on all our unbound adapters, and then we
  2640. // will InitDeviceInstance.
  2641. // This is called when the protcol is not bound to the physical adapter
  2642. //
  2643. NdisReEnumerateProtocolBindings(EpvcGlobals.driver.ProtocolHandle);
  2644. break;
  2645. }
  2646. } while (FALSE);
  2647. Status = NDIS_STATUS_SUCCESS;
  2648. TRACE (TL_T, TM_Pt, ("<== epvcPtNetEventReconfigure " ));
  2649. return Status;
  2650. }
  2651. INT
  2652. epvcReconfigureAdapter(
  2653. PRM_OBJECT_HEADER pHdr,
  2654. PVOID pvContext,
  2655. PRM_STACK_RECORD pSR
  2656. )
  2657. /*++
  2658. Routine Description:
  2659. When the Protocol's Reconfigure handler is called, this adapter will be in one
  2660. of two condtions - Its binding to the adapter below is open or the binding is
  2661. closed.
  2662. if the blinding is closed, then the protocol will call NdisReEnumerate Bindings
  2663. and this will restart the Binding and re-instantiate the miniports.
  2664. Arguments:
  2665. ProtocolBindingContext Pointer to our adapter structure.
  2666. Return Value:
  2667. TRUE: so that iteration continues
  2668. --*/
  2669. {
  2670. ENTER("epvcReconfigureAdapter", 0x2906a037)
  2671. PEPVC_ADAPTER pAdapter = (PEPVC_ADAPTER )pHdr;
  2672. do
  2673. {
  2674. if (CHECK_AD_PRIMARY_STATE(pAdapter, EPVC_AD_PS_INITED)== FALSE)
  2675. {
  2676. //
  2677. // no more work to be done on this adapter,
  2678. //
  2679. break;
  2680. }
  2681. //
  2682. // TODO: Go through the registry and initialize
  2683. // all the IM miniports present
  2684. //
  2685. epvcReadAdapterConfiguration(pAdapter, pSR);
  2686. //
  2687. // Now go through all the miniports on this group and
  2688. // initialize them
  2689. //
  2690. epvcEnumerateObjectsInGroup ( &pAdapter->MiniportsGroup,
  2691. epvcReconfigureMiniport,
  2692. NULL,
  2693. pSR);
  2694. } while (FALSE);
  2695. EXIT()
  2696. return TRUE;
  2697. }
  2698. INT
  2699. epvcReconfigureMiniport (
  2700. PRM_OBJECT_HEADER pHdr,
  2701. PVOID pvContext,
  2702. PRM_STACK_RECORD pSR
  2703. )
  2704. /*++
  2705. Routine Description:
  2706. This should check to see if the InitDev instance has been
  2707. called on this miniport. IF not, then queue the task to
  2708. do it.
  2709. Arguments:
  2710. ProtocolBindingContext Pointer to our adapter structure.
  2711. Return Value:
  2712. TRUE: so that iteration continues
  2713. --*/
  2714. {
  2715. ENTER( "epvcReconfigureMiniport" ,0xdd9ecb01)
  2716. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT)pHdr;
  2717. PTASK_AF pTask = NULL;
  2718. PEPVC_ADAPTER pAdapter = (PEPVC_ADAPTER)pMiniport->Hdr.pParentObject;
  2719. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2720. LOCKOBJ(pMiniport, pSR);
  2721. //
  2722. // If the device instance is not initialized (i.e it has been halted)
  2723. // then this thread reinitializes the device instance
  2724. //
  2725. do
  2726. {
  2727. //
  2728. // If the device is already Initialized then exit.
  2729. //
  2730. if (MiniportTestFlag (pMiniport, fMP_DevInstanceInitialized ) == TRUE)
  2731. {
  2732. break;
  2733. }
  2734. //
  2735. // Allocate task to Initialize the Device Instance.
  2736. //
  2737. Status = epvcAllocateTask(
  2738. &pMiniport->Hdr, // pParentObject,
  2739. epvcTaskStartIMiniport, // pfnHandler,
  2740. 0, // Timeout,
  2741. "Task: Open address Family", // szDescription
  2742. &((PRM_TASK)pTask),
  2743. pSR
  2744. );
  2745. if (FAIL(Status))
  2746. {
  2747. // Ugly situation. We'll just leave things as they are...
  2748. //
  2749. pTask = NULL;
  2750. TR_WARN(("FATAL: couldn't allocate unbind task!\n"));
  2751. break;
  2752. }
  2753. // Start the task to complete the Open Address Family.
  2754. // No locks must be held. RmStartTask uses up the tmpref on the task
  2755. // which was added by epvcAllocateTask.
  2756. //
  2757. UNLOCKOBJ(pMiniport, pSR);
  2758. pTask->pAf= &pAdapter->af.AddressFamily ;
  2759. pTask->Cause = TaskCause_ProtocolBind;
  2760. RmStartTask((PRM_TASK)pTask, 0, pSR);
  2761. LOCKOBJ(pMiniport, pSR);
  2762. } while(FALSE);
  2763. UNLOCKOBJ(pMiniport, pSR);
  2764. EXIT()
  2765. return TRUE;
  2766. }
  2767. VOID
  2768. epvcExtractSendCompleteInfo (
  2769. OUT PEPVC_SEND_COMPLETE pStruct,
  2770. PEPVC_I_MINIPORT pMiniport,
  2771. PNDIS_PACKET pPacket
  2772. )
  2773. /*++
  2774. Routine Description:
  2775. Arguments:
  2776. Return Value:
  2777. --*/
  2778. {
  2779. NDIS_HANDLE PoolHandle = NULL;
  2780. pStruct->pPacket = pPacket;
  2781. PoolHandle = NdisGetPoolFromPacket(pPacket);
  2782. if (PoolHandle != pMiniport->PktPool.Send.Handle)
  2783. {
  2784. //
  2785. // We had passed down a packet belonging to the protocol above us.
  2786. //
  2787. pStruct->fUsedPktStack = TRUE;
  2788. }
  2789. else
  2790. {
  2791. pStruct->fUsedPktStack = FALSE;
  2792. }
  2793. epvcSendCompleteStats();
  2794. }
  2795. VOID
  2796. EpvcPtSendComplete(
  2797. IN NDIS_STATUS Status,
  2798. IN NDIS_HANDLE ProtocolVcContext,
  2799. IN PNDIS_PACKET Packet
  2800. )
  2801. /*++
  2802. Routine Description:
  2803. The Vc Context is the miniport block, Use it to complete the send
  2804. Arguments:
  2805. Return Value:
  2806. --*/
  2807. {
  2808. ENTER("EpvcPtSendComplete", 0x76beac72)
  2809. PEPVC_I_MINIPORT pMiniport =(PEPVC_I_MINIPORT)ProtocolVcContext;
  2810. EPVC_SEND_COMPLETE Struct;
  2811. RM_DECLARE_STACK_RECORD (SR);
  2812. TRACE (TL_T, TM_Send, ("EpvcPtSendComplete"));
  2813. EPVC_ZEROSTRUCT (&Struct);
  2814. #define OUR_EXTERNAL_ENTITY ((UINT_PTR) Packet)
  2815. #define szEPVCASSOC_EXTLINK_DEST_TO_PKT_FORMAT " send pkt 0x%p\n"
  2816. do
  2817. {
  2818. epvcExtractSendCompleteInfo (&Struct, pMiniport, Packet);
  2819. //
  2820. // If we are using the Packetstacking, then this packet is the
  2821. // original packet
  2822. //
  2823. if (Struct.fUsedPktStack == TRUE)
  2824. {
  2825. BOOLEAN Remaining = FALSE;
  2826. Struct.pOrigPkt = Packet;
  2827. Struct.pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining);
  2828. Struct.pContext = (PEPVC_STACK_CONTEXT)(&Struct.pStack->IMReserved[0]) ;
  2829. }
  2830. else
  2831. {
  2832. Struct.pPktContext =(PEPVC_PKT_CONTEXT)(Packet->ProtocolReserved);
  2833. Struct.pContext = &Struct.pPktContext->Stack;
  2834. Struct.pOrigPkt = Struct.pPktContext->pOriginalPacket;
  2835. NdisIMCopySendCompletePerPacketInfo (Struct.pOrigPkt , Packet);
  2836. }
  2837. LOCKOBJ (pMiniport, &SR);
  2838. epvcDerefSendPkt(Packet, &pMiniport->Hdr);
  2839. UNLOCKOBJ (pMiniport, &SR);
  2840. //
  2841. // Make sure the original packet is in the same state
  2842. // when it was sent to the miniport
  2843. //
  2844. Struct.pPacket = Packet;
  2845. //
  2846. // Remove the ethernet padding - if necessary
  2847. //
  2848. epvcRemoveEthernetPad (pMiniport, Packet);
  2849. //
  2850. // Remove the ethernet padding buffer - if necessary
  2851. //
  2852. epvcRemoveEthernetTail (pMiniport, Packet, Struct.pPktContext);
  2853. //
  2854. // Remove the LLC Snap headers - if necessary
  2855. //
  2856. epvcRemoveExtraNdisBuffers (pMiniport, &Struct);
  2857. if (Struct.fUsedPktStack == FALSE)
  2858. {
  2859. epvcDprFreePacket(Packet,
  2860. &pMiniport->PktPool.Send);
  2861. }
  2862. if (Status == NDIS_STATUS_SUCCESS)
  2863. {
  2864. pMiniport->count.FramesXmitOk ++;
  2865. }
  2866. } while (FALSE);
  2867. //
  2868. // Complete the send
  2869. //
  2870. epvcMSendComplete(pMiniport,
  2871. Struct.pOrigPkt,
  2872. Status);
  2873. EXIT();
  2874. RM_ASSERT_CLEAR(&SR);
  2875. return;
  2876. }
  2877. VOID
  2878. epvcRemoveExtraNdisBuffers (
  2879. IN PEPVC_I_MINIPORT pMiniport,
  2880. IN PEPVC_SEND_COMPLETE pStruct
  2881. )
  2882. /*++
  2883. Routine Description:
  2884. In the case of IP encapsulation, there will be an extra ndis buffer
  2885. that has been made the head of the Ndispacket. Remove it and
  2886. reattach the old one.
  2887. Arguments:
  2888. Return Value:
  2889. --*/
  2890. {
  2891. PNDIS_BUFFER pOldHead = NULL;
  2892. UINT OldHeadLength = 0;
  2893. do
  2894. {
  2895. //
  2896. // if an LLC header was used, remove it and free the MDL
  2897. // use the packet that was completed
  2898. //
  2899. if (pMiniport->fAddLLCHeader== TRUE)
  2900. {
  2901. PNDIS_PACKET_PRIVATE pPrivate = &pStruct->pPacket->Private;
  2902. PNDIS_BUFFER pHead = pPrivate->Head;
  2903. //
  2904. // Move the head of the packet past the LLC Header
  2905. //
  2906. pPrivate->Head = pHead->Next;
  2907. //
  2908. // Free the Head MDL
  2909. //
  2910. epvcFreeBuffer(pHead);
  2911. }
  2912. //
  2913. // if we are not doing IP encapsulation, then we are done.
  2914. //
  2915. if (pMiniport->fDoIpEncapsulation== FALSE)
  2916. {
  2917. break;
  2918. }
  2919. //
  2920. // if the Ethernet header was stripped off, then put it back
  2921. //
  2922. pOldHead = pStruct->pContext->ipv4Send.pOldHeadNdisBuffer;
  2923. ASSERT (pOldHead != NULL);
  2924. OldHeadLength = NdisBufferLength(pOldHead);
  2925. //
  2926. // two ways this can happen
  2927. // 1) if the ethernet header was in a seperate MDL
  2928. // then simply take the old Head and make it the Head again
  2929. //
  2930. if (OldHeadLength == sizeof (EPVC_ETH_HEADER))
  2931. {
  2932. PNDIS_PACKET_PRIVATE pPrivate = &pStruct->pPacket->Private;
  2933. PNDIS_BUFFER pHead = pPrivate->Head;
  2934. ASSERT (pOldHead->Next == pPrivate->Head);
  2935. pOldHead->Next = pPrivate->Head;
  2936. pPrivate->Head = pOldHead ;
  2937. break; // we are done
  2938. }
  2939. //
  2940. // 2nd Way 2) A new MDL had been allocated which just points to the
  2941. // IP part of the header.
  2942. // For this - free the Head in Packet, Take the old Head and put it back
  2943. // in the packet as the New Head
  2944. //
  2945. if (OldHeadLength > sizeof (EPVC_ETH_HEADER))
  2946. {
  2947. PNDIS_PACKET_PRIVATE pPrivate = &pStruct->pPacket->Private;
  2948. ASSERT (pOldHead->Next == pPrivate->Head->Next);
  2949. if (pPrivate->Head == pPrivate->Tail)
  2950. {
  2951. pPrivate->Tail = pOldHead;
  2952. pOldHead->Next = NULL;
  2953. }
  2954. else
  2955. {
  2956. pOldHead->Next = pPrivate->Head->Next;
  2957. }
  2958. epvcFreeBuffer(pPrivate->Head );
  2959. pPrivate->Head = pOldHead;
  2960. break; // we are done
  2961. }
  2962. } while (FALSE);
  2963. }
  2964. VOID
  2965. EpvcPtReceiveComplete(
  2966. IN NDIS_HANDLE ProtocolBindingContext
  2967. )
  2968. /*++
  2969. Routine Description:
  2970. Called by the adapter below us when it is done indicating a batch of
  2971. received packets.
  2972. Arguments:
  2973. ProtocolBindingContext Pointer to our adapter structure.
  2974. Return Value:
  2975. None
  2976. --*/
  2977. {
  2978. PEPVC_ADAPTER pAdapter = (PEPVC_ADAPTER)ProtocolBindingContext;
  2979. return;
  2980. }
  2981. INT
  2982. epvcMiniportDoUnbind(
  2983. PRM_OBJECT_HEADER pHdr,
  2984. PVOID pvContext,
  2985. PRM_STACK_RECORD pSR
  2986. )
  2987. {
  2988. /*++
  2989. Routine Description:
  2990. This is called from the Protocl Unbind code path
  2991. This should halt the current miniport and close the address
  2992. family. This is all done in the CloseMiniportTask, so we
  2993. will simply start the task and wait for it to complete
  2994. Arguments:
  2995. Return Value:
  2996. TRUE - as we want to iterate to the very end
  2997. --*/
  2998. ENTER ("epvcMiniportDoUnbind", 0x26dc5d35)
  2999. PRM_TASK pRmTask = NULL;
  3000. PTASK_AF pAfTask = NULL;
  3001. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  3002. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT)pHdr;
  3003. PEPVC_ADAPTER pAdapter = (PEPVC_ADAPTER) pMiniport->Hdr.pParentObject;
  3004. BOOLEAN fHaltNotCompleted = FALSE;
  3005. TRACE (TL_T, TM_Mp, ("==>epvcMiniportDoUnbind pMiniport %x", pMiniport) );
  3006. do
  3007. {
  3008. if (MiniportTestFlag (pMiniport, fMP_AddressFamilyOpened) == TRUE)
  3009. {
  3010. //
  3011. // allocate a close Miniport Task
  3012. //
  3013. Status = epvcAllocateTask(
  3014. &pMiniport->Hdr, // pParentObject,
  3015. epvcTaskCloseIMiniport, // pfnHandler,
  3016. 0, // Timeout,
  3017. "Task: CloseIMiniport- Unbind", // szDescription
  3018. &pRmTask,
  3019. pSR
  3020. );
  3021. if (Status != NDIS_STATUS_SUCCESS)
  3022. {
  3023. ASSERT (Status == NDIS_STATUS_SUCCESS);
  3024. pAfTask = NULL;
  3025. break;
  3026. }
  3027. pAfTask= (PTASK_AF)pRmTask ;
  3028. pAfTask->Cause = TaskCause_ProtocolUnbind;
  3029. //
  3030. // Reference the task so it is around until our Wait for completion
  3031. // is complete
  3032. //
  3033. RmTmpReferenceObject (&pAfTask->TskHdr.Hdr, pSR);
  3034. epvcInitializeEvent (&pAfTask->CompleteEvent);
  3035. RmStartTask (pRmTask, 0, pSR);
  3036. epvcWaitEvent(&pAfTask->CompleteEvent, WAIT_INFINITE);
  3037. RmTmpDereferenceObject (&pAfTask->TskHdr.Hdr, pSR);
  3038. }
  3039. LOCKOBJ (pMiniport, pSR);
  3040. //
  3041. // If the Halt has not already completed then, we should wait for it
  3042. //
  3043. if (MiniportTestFlag(pMiniport ,fMP_MiniportInitialized) == TRUE )
  3044. {
  3045. //
  3046. // prepare to wait for halt
  3047. //
  3048. epvcResetEvent (&pMiniport->pnp.HaltCompleteEvent);
  3049. //
  3050. // Set the flag to mark it as waiting for halt
  3051. //
  3052. MiniportSetFlag (pMiniport, fMP_WaitingForHalt);
  3053. fHaltNotCompleted = TRUE;
  3054. }
  3055. UNLOCKOBJ (pMiniport, pSR);
  3056. if (fHaltNotCompleted == TRUE)
  3057. {
  3058. BOOLEAN bWaitSuccessful;
  3059. bWaitSuccessful = epvcWaitEvent (&pMiniport->pnp.HaltCompleteEvent,WAIT_INFINITE);
  3060. if (bWaitSuccessful == FALSE)
  3061. {
  3062. ASSERT (bWaitSuccessful == TRUE);
  3063. }
  3064. }
  3065. //
  3066. // Free the miniport object because there should be no more tasks on it.
  3067. // this Thread will have either caused the Miniport to Halt and waited
  3068. // for its completion (above) or the miniport will already have been halted
  3069. //
  3070. TRACE ( TL_I, TM_Mp, ("epvcMiniportDoUnbind Freeing miniport %p", pMiniport) );
  3071. RmFreeObjectInGroup (&pAdapter->MiniportsGroup,&pMiniport->Hdr, NULL, pSR);
  3072. } while (FALSE);
  3073. TRACE (TL_T, TM_Mp, ("<==epvcMiniportDoUnbind pMiniport %x", pMiniport) );
  3074. EXIT();
  3075. return TRUE;
  3076. }
  3077. NDIS_STATUS
  3078. epvcProcessOidCloseAf(
  3079. PEPVC_I_MINIPORT pMiniport,
  3080. PRM_STACK_RECORD pSR
  3081. )
  3082. /*++
  3083. Routine Description:
  3084. This is called from the Af Close Request Code path
  3085. This simply starts a worktitem to close the Af, if the
  3086. Af is open
  3087. Arguments:
  3088. Return Value:
  3089. --*/
  3090. {
  3091. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  3092. PTASK_AF pTaskAf = NULL;
  3093. PEPVC_WORK_ITEM pCloseAfWorkItem = NULL;
  3094. TRACE (TL_T, TM_Mp, ("==> epvcProcessOidCloseAf pMiniport %x", pMiniport) );
  3095. //
  3096. // reference the adapter as it is going to passed to a workiter.
  3097. // decremented in the workitem
  3098. //
  3099. do
  3100. {
  3101. if (MiniportTestFlag( pMiniport, fMP_AddressFamilyOpened) == FALSE)
  3102. {
  3103. Status = NDIS_STATUS_SUCCESS;
  3104. break;
  3105. }
  3106. Status = epvcAllocateMemoryWithTag (&pCloseAfWorkItem,
  3107. sizeof(*pCloseAfWorkItem) ,
  3108. TAG_WORKITEM);
  3109. if (Status != NDIS_STATUS_SUCCESS)
  3110. {
  3111. pCloseAfWorkItem= NULL;
  3112. break;
  3113. }
  3114. epvcMiniportQueueWorkItem (pCloseAfWorkItem,
  3115. pMiniport,
  3116. epvcOidCloseAfWorkItem,
  3117. Status, // Ignored
  3118. pSR
  3119. );
  3120. Status = NDIS_STATUS_SUCCESS;
  3121. } while (FALSE);
  3122. if (Status != NDIS_STATUS_SUCCESS)
  3123. {
  3124. //
  3125. // free locally allocated memory
  3126. //
  3127. if (pCloseAfWorkItem != NULL)
  3128. {
  3129. epvcFreeMemory(pCloseAfWorkItem, sizeof (*pCloseAfWorkItem), 0);
  3130. }
  3131. }
  3132. return Status;
  3133. }
  3134. VOID
  3135. epvcOidCloseAfWorkItem(
  3136. IN PRM_OBJECT_HEADER pObj,
  3137. IN NDIS_STATUS Status,
  3138. IN PRM_STACK_RECORD pSR
  3139. )
  3140. /*++
  3141. Routine Description:
  3142. This is called from the Af Close Request Code path
  3143. This simply starts a worktitem to close the Af, if the
  3144. Af is open
  3145. Arguments:
  3146. Return Value:
  3147. --*/
  3148. {
  3149. PTASK_AF pTaskAf = NULL;
  3150. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT)pObj;
  3151. TRACE (TL_T, TM_Mp, ("==> epvcProcessOidCloseAf pMiniport %x", pMiniport) );
  3152. Status = NDIS_STATUS_FAILURE;
  3153. //
  3154. // reference the adapter as it is going to passed to a workiter.
  3155. // decremented in the workitem
  3156. //
  3157. do
  3158. {
  3159. if (MiniportTestFlag( pMiniport, fMP_AddressFamilyOpened) == FALSE)
  3160. {
  3161. Status = NDIS_STATUS_SUCCESS;
  3162. break;
  3163. }
  3164. Status = epvcAllocateTask(
  3165. &pMiniport->Hdr, // pParentObject,
  3166. epvcTaskCloseIMiniport, // pfnHandler,
  3167. 0, // Timeout,
  3168. "Task: CloseIMiniport - OID CloseAf", // szDescription
  3169. &(PRM_TASK)pTaskAf,
  3170. pSR
  3171. );
  3172. if (FAIL(Status))
  3173. {
  3174. pTaskAf = NULL;
  3175. ASSERT (Status == NDIS_STATUS_SUCCESS);
  3176. break;
  3177. }
  3178. pTaskAf->Cause = TaskCause_AfCloseRequest;
  3179. pTaskAf->pRequest = NULL;
  3180. RmStartTask ((PRM_TASK)pTaskAf , 0, pSR);
  3181. } while (FALSE);
  3182. return ;
  3183. }
  3184. UINT
  3185. EpvcCoReceive(
  3186. IN NDIS_HANDLE ProtocolBindingContext,
  3187. IN NDIS_HANDLE ProtocolVcContext,
  3188. IN PNDIS_PACKET Packet
  3189. )
  3190. /*++
  3191. Routine Description:
  3192. Arguments:
  3193. Return Value:
  3194. --*/
  3195. {
  3196. ENTER ("EpvcPtCoReceive", 0x1bfc168e)
  3197. PEPVC_ADAPTER pAdapter =(PEPVC_ADAPTER)ProtocolBindingContext;
  3198. PEPVC_I_MINIPORT pMiniport = (PEPVC_I_MINIPORT)ProtocolVcContext;
  3199. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  3200. EPVC_RCV_STRUCT RcvStruct;
  3201. RM_DECLARE_STACK_RECORD (SR);
  3202. TRACE (TL_T, TM_Pt, ("==> EpvcCoReceive Pkt %x", Packet));
  3203. EPVC_ZEROSTRUCT (&RcvStruct);
  3204. TRACE (TL_T, TM_Recv, ("EpvcPtCoReceive pAd %p, pMp %p, pPkt %p", pAdapter, pMiniport, Packet));
  3205. do
  3206. {
  3207. if (MiniportTestFlag (pMiniport, fMP_MiniportInitialized) == FALSE)
  3208. {
  3209. Status = NDIS_STATUS_FAILURE;
  3210. break;
  3211. }
  3212. Status = epvcGetRecvPkt (&RcvStruct,pMiniport, Packet);
  3213. if (Status != NDIS_STATUS_SUCCESS)
  3214. {
  3215. break;
  3216. }
  3217. ASSERT (RcvStruct.pNewPacket != NULL);
  3218. Status = epvcStripHeaderFromNewPacket (&RcvStruct, pMiniport);
  3219. if (Status != NDIS_STATUS_SUCCESS)
  3220. {
  3221. break;
  3222. }
  3223. Status = epvcAddEthHeaderToNewPacket (&RcvStruct, pMiniport);
  3224. if (Status != NDIS_STATUS_SUCCESS)
  3225. {
  3226. break;
  3227. }
  3228. //
  3229. // Now indicate the packet up
  3230. //
  3231. NDIS_SET_PACKET_HEADER_SIZE(RcvStruct.pNewPacket,
  3232. sizeof (EPVC_ETH_HEADER)) ;
  3233. ASSERT (NDIS_GET_PACKET_HEADER_SIZE(RcvStruct.pNewPacket) == 14);
  3234. //
  3235. // Force protocols above to make a copy if they want to hang
  3236. // on to data in this packet. This is because we are in our
  3237. // Receive handler (not ReceivePacket) and we can't return a
  3238. // ref count from here.
  3239. //
  3240. RcvStruct.OldPacketStatus = NDIS_GET_PACKET_STATUS(Packet);
  3241. NDIS_SET_PACKET_STATUS(RcvStruct.pNewPacket,
  3242. RcvStruct.OldPacketStatus );
  3243. epvcDumpPkt (RcvStruct.pNewPacket);
  3244. epvcValidatePacket (RcvStruct.pNewPacket);
  3245. NdisMIndicateReceivePacket(pMiniport->ndis.MiniportAdapterHandle,
  3246. &RcvStruct.pNewPacket,
  3247. 1);
  3248. } while (FALSE);
  3249. //
  3250. // Check if we had indicated up the packet with NDIS_STATUS_RESOURCES
  3251. // NOTE -- do not use NDIS_GET_PACKET_STATUS(MyPacket) for this since
  3252. // it might have changed! Use the value saved in the local variable.
  3253. //
  3254. if (RcvStruct.OldPacketStatus == NDIS_STATUS_RESOURCES)
  3255. {
  3256. epvcProcessReturnPacket (pMiniport, RcvStruct.pNewPacket,NULL, &SR);
  3257. Status = NDIS_STATUS_RESOURCES;
  3258. }
  3259. else if (Status != NDIS_STATUS_SUCCESS)
  3260. {
  3261. epvcProcessReturnPacket (pMiniport, RcvStruct.pNewPacket,NULL, &SR);
  3262. Status = NDIS_STATUS_RESOURCES;
  3263. pMiniport->count.RecvDropped ++;
  3264. }
  3265. RM_ASSERT_CLEAR(&SR);
  3266. TRACE (TL_T, TM_Pt, ("<== EpvcCoReceive Pkt %x", Packet))
  3267. return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
  3268. }
  3269. NDIS_STATUS
  3270. epvcGetRecvPkt (
  3271. IN PEPVC_RCV_STRUCT pRcvStruct,
  3272. IN PEPVC_I_MINIPORT pMiniport,
  3273. IN PNDIS_PACKET Packet
  3274. )
  3275. {
  3276. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  3277. TRACE (TL_T, TM_Pt, ("==>epvcGetRecvPkt "))
  3278. do
  3279. {
  3280. if (MiniportTestFlag (pMiniport, fMP_MiniportInitialized) == FALSE)
  3281. {
  3282. Status = NDIS_STATUS_FAILURE;
  3283. break;
  3284. }
  3285. epvcValidatePacket (Packet);
  3286. //
  3287. // See if the packet is large enough
  3288. //
  3289. if (epvcIsPacketLengthAcceptable (Packet, pMiniport)== FALSE)
  3290. {
  3291. Status = NDIS_STATUS_FAILURE;
  3292. break;
  3293. }
  3294. pRcvStruct->pPacket = Packet;
  3295. //
  3296. // Check if we can reuse the same packet for indicating up.
  3297. //
  3298. pRcvStruct->pStack = NdisIMGetCurrentPacketStack(Packet, &pRcvStruct->fRemaining);
  3299. if (pRcvStruct->fRemaining)
  3300. {
  3301. //
  3302. // We can reuse "Packet".
  3303. //
  3304. // NOTE: if we needed to keep per-packet information in packets
  3305. // indicated up, we can use pStack->IMReserved[].
  3306. //
  3307. pRcvStruct->pNewPacket = Packet;
  3308. pRcvStruct->fUsedPktStacks = TRUE;
  3309. pRcvStruct->pPktContext = (PEPVC_PKT_CONTEXT)pRcvStruct->pStack;
  3310. // Zero out our context
  3311. NdisZeroMemory (&pRcvStruct->pPktContext->Stack, sizeof(EPVC_STACK_CONTEXT));
  3312. NDIS_SET_PACKET_HEADER_SIZE(Packet, 14);
  3313. Status = NDIS_STATUS_SUCCESS; // We are done
  3314. break;
  3315. }
  3316. //
  3317. // Get a packet off the pool and indicate that up
  3318. //
  3319. epvcDprAllocatePacket(&Status,
  3320. &pRcvStruct->pNewPacket,
  3321. &pMiniport->PktPool.Recv);
  3322. if (Status != NDIS_STATUS_SUCCESS)
  3323. {
  3324. pRcvStruct->pNewPacket = NULL;
  3325. break;
  3326. }
  3327. {
  3328. //
  3329. // set up the new packet to look exactly like the old one
  3330. //
  3331. PNDIS_PACKET MyPacket = pRcvStruct->pNewPacket;
  3332. MyPacket->Private.Head = Packet->Private.Head;
  3333. MyPacket->Private.Tail = Packet->Private.Tail;
  3334. //
  3335. // Set the standard Ethernet header size
  3336. //
  3337. NDIS_SET_PACKET_HEADER_SIZE(MyPacket, 14);
  3338. //
  3339. // Copy packet flags.
  3340. //
  3341. NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
  3342. //
  3343. // Set up the context pointers
  3344. //
  3345. pRcvStruct->pPktContext = (PEPVC_PKT_CONTEXT)&MyPacket->MiniportReservedEx[0];
  3346. NdisZeroMemory (pRcvStruct->pPktContext, sizeof (*pRcvStruct->pPktContext));
  3347. pRcvStruct->pPktContext->pOriginalPacket = Packet;
  3348. }
  3349. Status = NDIS_STATUS_SUCCESS; // We are done
  3350. } while (FALSE);
  3351. TRACE (TL_T, TM_Pt, ("<==epvcGetRecvPkt Old %p, New %p ",
  3352. pRcvStruct->pPacket, pRcvStruct->pNewPacket))
  3353. return Status;
  3354. }
  3355. NDIS_STATUS
  3356. epvcStripLLCHeaderFromNewPacket (
  3357. IN PEPVC_RCV_STRUCT pRcvStruct,
  3358. IN PEPVC_I_MINIPORT pMiniport
  3359. )
  3360. {
  3361. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  3362. PNDIS_PACKET pPacket = NULL;
  3363. PNDIS_BUFFER pHead, pNewHead =NULL;
  3364. ULONG CurLength = 0;
  3365. PUCHAR pCurVa = NULL;
  3366. ULONG LlcHeaderLength = 0;
  3367. BOOLEAN fIsCorrectHeader ;
  3368. do
  3369. {
  3370. if (pMiniport->fAddLLCHeader == FALSE)
  3371. {
  3372. Status = NDIS_STATUS_SUCCESS;
  3373. break;
  3374. }
  3375. pPacket = pRcvStruct->pNewPacket;
  3376. pHead = pPacket->Private.Head;
  3377. LlcHeaderLength = pMiniport->LlcHeaderLength;
  3378. //
  3379. // Move the Head past the LLC Header
  3380. //
  3381. ASSERT (NdisBufferLength (pHead) > LlcHeaderLength);
  3382. //
  3383. // Adjust the length and start VA of the MDL
  3384. //
  3385. CurLength = NdisBufferLength(pHead);
  3386. pCurVa = NdisBufferVirtualAddress(pHead);
  3387. //
  3388. // Check arguments
  3389. //
  3390. if (pCurVa == NULL)
  3391. {
  3392. break;
  3393. }
  3394. if (CurLength <= LlcHeaderLength)
  3395. {
  3396. break;
  3397. }
  3398. //
  3399. // Compare and make sure that it is the right header
  3400. //
  3401. fIsCorrectHeader = NdisEqualMemory (pCurVa ,
  3402. pMiniport->pLllcHeader,
  3403. pMiniport->LlcHeaderLength) ;
  3404. // If the IsCorrectheader is still false, then there is more to do
  3405. if (fIsCorrectHeader == FALSE)
  3406. {
  3407. break;
  3408. }
  3409. if (pMiniport->fDoIpEncapsulation == TRUE)
  3410. {
  3411. //
  3412. // In the case of IPEncap + LLC Header, the function
  3413. // which adds the Mac Header will strip the LLC Header
  3414. //
  3415. Status= NDIS_STATUS_SUCCESS;
  3416. break;
  3417. }
  3418. //
  3419. // Strip the LLC Header Length
  3420. //
  3421. CurLength -= pMiniport->LlcHeaderLength;
  3422. pCurVa += pMiniport->LlcHeaderLength;
  3423. epvcAllocateBuffer(&Status ,
  3424. &pNewHead,
  3425. NULL,
  3426. pCurVa,
  3427. CurLength
  3428. );
  3429. if (Status != NDIS_STATUS_SUCCESS)
  3430. {
  3431. pNewHead = NULL;
  3432. break;
  3433. }
  3434. //
  3435. // Set up the Packet context
  3436. //
  3437. pPacket->Private.ValidCounts= FALSE;
  3438. pRcvStruct->pPktContext->Stack.EthLLC.pOldHead = pHead;
  3439. pRcvStruct->pPktContext->Stack.EthLLC.pOldTail = pPacket->Private.Tail;
  3440. //
  3441. // Set the New Ndis buffer in the Packet
  3442. //
  3443. pNewHead->Next = pHead->Next;
  3444. pPacket->Private.Head = pNewHead;
  3445. if (pPacket->Private.Tail == pHead)
  3446. {
  3447. //
  3448. // Update the Tail of the packet as well
  3449. //
  3450. pPacket->Private.Tail = pNewHead;
  3451. }
  3452. Status = NDIS_STATUS_SUCCESS;
  3453. } while (FALSE);
  3454. return Status;
  3455. }
  3456. NDIS_STATUS
  3457. epvcAddEthHeaderToNewPacket (
  3458. IN PEPVC_RCV_STRUCT pRcvStruct,
  3459. IN PEPVC_I_MINIPORT pMiniport
  3460. )
  3461. {
  3462. NDIS_STATUS Status = NDIS_STATUS_FAILURE ;
  3463. PNDIS_BUFFER pOldHead = NULL;
  3464. PNDIS_BUFFER pNewBuffer = NULL;
  3465. PNDIS_PACKET pNewPacket = NULL;
  3466. PUCHAR pStartOfValidData = NULL;
  3467. PUCHAR pCurrOffset = NULL;
  3468. PEPVC_IP_RCV_BUFFER pIpBuffer = NULL;
  3469. extern UCHAR LLCSnapIpv4[8] ;
  3470. TRACE (TL_T, TM_Pt, ("==>epvcAddEthHeaderToNewPacket pRcvStruct %p ", pRcvStruct))
  3471. do
  3472. {
  3473. if (pMiniport->fDoIpEncapsulation == FALSE)
  3474. {
  3475. Status = NDIS_STATUS_SUCCESS;
  3476. break;
  3477. }
  3478. //
  3479. // Copy the data into a new buffer. The start of the data is adjusted
  3480. // to account for the LLC header and ethernet header
  3481. //
  3482. pNewPacket = pRcvStruct->pNewPacket;
  3483. pOldHead = pNewPacket->Private.Head;
  3484. pStartOfValidData = NdisBufferVirtualAddress (pOldHead );
  3485. if (pStartOfValidData == NULL)
  3486. {
  3487. Status = NDIS_STATUS_FAILURE;
  3488. break;
  3489. }
  3490. if (pMiniport->fAddLLCHeader == TRUE)
  3491. {
  3492. pStartOfValidData += sizeof (LLCSnapIpv4);
  3493. pRcvStruct->fLLCHeader = TRUE;
  3494. }
  3495. pRcvStruct->pStartOfValidData = pStartOfValidData ;
  3496. //
  3497. // Get a locally allocated buffer to copy the packet into
  3498. //
  3499. pIpBuffer = epvcGetLookasideBuffer (&pMiniport->rcv.LookasideList);
  3500. if (pIpBuffer == NULL)
  3501. {
  3502. Status = NDIS_STATUS_FAILURE;
  3503. break;
  3504. }
  3505. //
  3506. // Start of the data
  3507. //
  3508. pCurrOffset = pRcvStruct->pLocalMemory = (PUCHAR)(&pIpBuffer->u.Pkt.Eth);
  3509. //
  3510. // First copy the Ethernet Header into the LocalMemory
  3511. //
  3512. NdisMoveMemory (pCurrOffset ,
  3513. &pMiniport->RcvEnetHeader,
  3514. sizeof(pMiniport->RcvEnetHeader));
  3515. pCurrOffset += sizeof(pMiniport->RcvEnetHeader);
  3516. pRcvStruct->BytesCopied += sizeof(pMiniport->RcvEnetHeader);
  3517. //
  3518. // Now copy the NdisBufferChain into the Locally allocated memory
  3519. //
  3520. Status = epvcCopyNdisBufferChain (pRcvStruct,
  3521. pOldHead ,
  3522. pCurrOffset
  3523. );
  3524. //
  3525. // We have to add an Ethernet Header for this packet.
  3526. //
  3527. epvcAllocateBuffer (&Status,
  3528. &pNewBuffer,
  3529. NULL,
  3530. pRcvStruct->pLocalMemory,
  3531. pRcvStruct->BytesCopied);
  3532. if (Status != NDIS_STATUS_SUCCESS)
  3533. {
  3534. pNewBuffer = NULL;
  3535. ASSERTAndBreak(Status == NDIS_STATUS_SUCCESS);
  3536. break;
  3537. }
  3538. //
  3539. // Make the new Ndis Buffer the head
  3540. //
  3541. {
  3542. PNDIS_PACKET_PRIVATE pPrivate = &pRcvStruct->pNewPacket->Private;
  3543. //
  3544. // Save the head and tail of the old packet
  3545. //
  3546. pIpBuffer->pOldHead = pPrivate->Head ;
  3547. pIpBuffer->pOldTail = pPrivate->Tail ;
  3548. //
  3549. // Now set up the new packet
  3550. //
  3551. pNewBuffer->Next = NULL;
  3552. pPrivate->Head = pNewBuffer;
  3553. pPrivate->Tail = pNewBuffer;
  3554. pPrivate->ValidCounts= FALSE;
  3555. pRcvStruct->pPktContext->Stack.ipv4Recv.pIpBuffer = pIpBuffer;
  3556. }
  3557. Status = NDIS_STATUS_SUCCESS;
  3558. } while (FALSE);
  3559. if (Status == NDIS_STATUS_SUCCESS)
  3560. {
  3561. pRcvStruct->pNewBuffer = pNewBuffer;
  3562. pRcvStruct->pIpBuffer = pIpBuffer;
  3563. }
  3564. else
  3565. {
  3566. pRcvStruct->pNewBuffer = NULL;
  3567. pRcvStruct->pIpBuffer = NULL;
  3568. if (pIpBuffer != NULL)
  3569. {
  3570. epvcFreeToNPagedLookasideList (&pMiniport->rcv.LookasideList,
  3571. (PVOID)pIpBuffer);
  3572. }
  3573. }
  3574. TRACE (TL_T, TM_Pt, ("<==epvcAddEthHeaderToNewPacket Status %x ", Status))
  3575. return Status;
  3576. }
  3577. NDIS_STATUS
  3578. epvcCopyNdisBufferChain (
  3579. IN PEPVC_RCV_STRUCT pRcvStruct,
  3580. IN PNDIS_BUFFER pInBuffer,
  3581. IN PUCHAR pCurrOffset
  3582. )
  3583. {
  3584. //
  3585. // This function copies the data the belongs to the
  3586. // pInMdl chain to the local Buffer.
  3587. // BufferLength is used for validation purposes only
  3588. // Fragmentation and insertion of headers will take place here
  3589. //
  3590. UINT BufferLength = MAX_ETHERNET_FRAME- sizeof (EPVC_ETH_HEADER);
  3591. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  3592. UINT LocalBufferIndex = 0; // Used as an index to the LocalBuffer, used for validation
  3593. UINT MdlLength = 0;
  3594. PUCHAR MdlAddress = NULL;
  3595. PNDIS_BUFFER pCurrBuffer = pInBuffer;
  3596. PUCHAR pLocalBuffer = pCurrOffset;
  3597. extern UCHAR LLCSnapIpv4[8];
  3598. //
  3599. // Use the pStartOfValidData for the first MDL
  3600. //
  3601. MdlLength = NdisBufferLength(pCurrBuffer);
  3602. MdlAddress= NdisBufferVirtualAddress(pCurrBuffer);
  3603. //
  3604. // Adjust for the LLC Header if any
  3605. //
  3606. if (pRcvStruct->fLLCHeader == TRUE)
  3607. {
  3608. //
  3609. // We have an LLC encapsulation
  3610. //
  3611. MdlLength -= sizeof (LLCSnapIpv4);
  3612. ASSERT (pRcvStruct->pStartOfValidData - MdlAddress == sizeof (LLCSnapIpv4));
  3613. MdlAddress = pRcvStruct->pStartOfValidData;
  3614. }
  3615. //
  3616. // Copy the first buffer Data to local memory.
  3617. //
  3618. NdisMoveMemory((PVOID)((ULONG_PTR)pLocalBuffer),
  3619. MdlAddress,
  3620. MdlLength);
  3621. LocalBufferIndex += MdlLength;
  3622. pCurrBuffer = pCurrBuffer->Next;
  3623. //
  3624. // now walk through the ndis buffer chain
  3625. //
  3626. while (pCurrBuffer!= NULL)
  3627. {
  3628. MdlLength = NdisBufferLength(pCurrBuffer);
  3629. MdlAddress= NdisBufferVirtualAddress(pCurrBuffer);
  3630. if (MdlLength != 0)
  3631. {
  3632. if (MdlAddress == NULL)
  3633. {
  3634. NdisStatus = NDIS_STATUS_FAILURE;
  3635. break;
  3636. }
  3637. if ( LocalBufferIndex + MdlLength > BufferLength)
  3638. {
  3639. ASSERT(LocalBufferIndex + MdlLength <= BufferLength);
  3640. NdisStatus = NDIS_STATUS_BUFFER_TOO_SHORT;
  3641. break;
  3642. }
  3643. //
  3644. // Copy the Data to local memory.
  3645. //
  3646. NdisMoveMemory((PVOID)((ULONG_PTR)pLocalBuffer+LocalBufferIndex),
  3647. MdlAddress,
  3648. MdlLength);
  3649. LocalBufferIndex += MdlLength;
  3650. }
  3651. pCurrBuffer = pCurrBuffer->Next;
  3652. }
  3653. pRcvStruct->BytesCopied += LocalBufferIndex;
  3654. return NdisStatus;
  3655. }
  3656. VOID
  3657. epvcValidatePacket (
  3658. IN PNDIS_PACKET pPacket
  3659. )
  3660. /*++
  3661. Routine Description:
  3662. Takes a packet and makes sure that the MDL chain is valid
  3663. Arguments:
  3664. Return Value:
  3665. --*/
  3666. {
  3667. ULONG TotalLength = 0;
  3668. //ASSERT (pPacket->Private.Tail->Next == NULL);
  3669. if (pPacket->Private.Head != pPacket->Private.Tail)
  3670. {
  3671. PNDIS_BUFFER pTemp = pPacket->Private.Head;
  3672. while (pTemp != NULL)
  3673. {
  3674. TotalLength += NdisBufferLength(pTemp);
  3675. pTemp = pTemp->Next;
  3676. }
  3677. }
  3678. else
  3679. {
  3680. TotalLength += NdisBufferLength(pPacket->Private.Head);
  3681. }
  3682. if (TotalLength != pPacket->Private.TotalLength)
  3683. {
  3684. ASSERT (pPacket->Private.ValidCounts == FALSE);
  3685. }
  3686. }
  3687. BOOLEAN
  3688. epvcIsPacketLengthAcceptable (
  3689. IN PNDIS_PACKET Packet,
  3690. IN PEPVC_I_MINIPORT pMiniport
  3691. )
  3692. /*++
  3693. Routine Description:
  3694. Validates the packet length of an incoming packet
  3695. Arguments:
  3696. Return Value:
  3697. --*/
  3698. {
  3699. UINT PktLength;
  3700. BOOLEAN fValid = FALSE;
  3701. epvcQueryPacket (Packet, NULL, NULL, NULL, &PktLength);
  3702. fValid = (PktLength >= pMiniport->MinAcceptablePkt);
  3703. if (fValid == TRUE)
  3704. {
  3705. fValid = (PktLength <= pMiniport->MaxAcceptablePkt);
  3706. }
  3707. return fValid;
  3708. }
  3709. NDIS_STATUS
  3710. epvcStripHeaderFromNewPacket (
  3711. IN PEPVC_RCV_STRUCT pRcvStruct,
  3712. IN PEPVC_I_MINIPORT pMiniport
  3713. )
  3714. /*++
  3715. Routine Description:
  3716. In the pure bridged (ethernet) encapsulation, all ethernet packets
  3717. are preceeded by a 0x00, 0x00 header. Check if it is present
  3718. in the ethernet/llc case, verify the LLC header is correct.
  3719. In both cases, allocate a new Ndis Buffer which does not include the
  3720. 2684 headers.
  3721. Store the old head and tail into the NdisPacket and send it up to the
  3722. Arguments:
  3723. Return Value:
  3724. --*/
  3725. {
  3726. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  3727. PNDIS_PACKET pPacket = NULL;
  3728. PNDIS_BUFFER pHead, pNewHead =NULL;
  3729. ULONG CurLength = 0;
  3730. PUCHAR pCurVa = NULL;
  3731. ULONG EpvcHeaderLength = 0;
  3732. PUCHAR pEpvcHeader = NULL;
  3733. BOOLEAN fIsCorrectHeader ;
  3734. do
  3735. {
  3736. //
  3737. // we are not interested in the pure ipv4 case
  3738. //
  3739. if (pMiniport->Encap == IPV4_ENCAP_TYPE)
  3740. {
  3741. Status = NDIS_STATUS_SUCCESS;
  3742. break;
  3743. }
  3744. pPacket = pRcvStruct->pNewPacket;
  3745. pHead = pPacket->Private.Head;
  3746. switch (pMiniport->Encap)
  3747. {
  3748. case IPV4_LLC_SNAP_ENCAP_TYPE:
  3749. case ETHERNET_LLC_SNAP_ENCAP_TYPE:
  3750. {
  3751. EpvcHeaderLength = pMiniport->LlcHeaderLength;
  3752. pEpvcHeader = pMiniport->pLllcHeader;
  3753. break;
  3754. }
  3755. case ETHERNET_ENCAP_TYPE:
  3756. {
  3757. EpvcHeaderLength = ETHERNET_PADDING_LENGTH;
  3758. pEpvcHeader = &gPaddingBytes[0];
  3759. break;
  3760. }
  3761. case IPV4_ENCAP_TYPE:
  3762. default:
  3763. {
  3764. //
  3765. // pMiniport->Encap is only allowed four values,
  3766. // therefore we should never hit the defualt case.
  3767. //
  3768. Status = NDIS_STATUS_FAILURE;
  3769. ASSERT (Status != NDIS_STATUS_FAILURE);
  3770. return Status;
  3771. }
  3772. }
  3773. //
  3774. // Adjust the length and start VA of the MDL
  3775. //
  3776. CurLength = NdisBufferLength(pHead);
  3777. pCurVa = NdisBufferVirtualAddress(pHead);
  3778. //
  3779. // Check arguments
  3780. //
  3781. if (pCurVa == NULL)
  3782. {
  3783. break;
  3784. }
  3785. if (CurLength <= EpvcHeaderLength )
  3786. {
  3787. //
  3788. // we do not handle the case where the header is longer than
  3789. // the first mdl
  3790. //
  3791. ASSERT (CurLength > EpvcHeaderLength );
  3792. break;
  3793. }
  3794. //
  3795. // Compare and make sure that it is the right header
  3796. //
  3797. fIsCorrectHeader = NdisEqualMemory (pCurVa ,
  3798. pEpvcHeader,
  3799. EpvcHeaderLength) ;
  3800. // If the IsCorrectheader is still false, then there is more to do
  3801. if (fIsCorrectHeader == FALSE)
  3802. {
  3803. break;
  3804. }
  3805. if (pMiniport->fDoIpEncapsulation == TRUE)
  3806. {
  3807. //
  3808. // In the case of IPEncap + LLC Header, the function
  3809. // which adds the Mac Header will strip the LLC Header
  3810. //
  3811. Status= NDIS_STATUS_SUCCESS;
  3812. break;
  3813. }
  3814. //
  3815. // Strip the LLC Header Length
  3816. //
  3817. CurLength -= EpvcHeaderLength;
  3818. pCurVa += EpvcHeaderLength;
  3819. epvcAllocateBuffer(&Status ,
  3820. &pNewHead,
  3821. NULL,
  3822. pCurVa,
  3823. CurLength
  3824. );
  3825. if (Status != NDIS_STATUS_SUCCESS)
  3826. {
  3827. pNewHead = NULL;
  3828. break;
  3829. }
  3830. //
  3831. // Set up the Packet context
  3832. //
  3833. pPacket->Private.ValidCounts= FALSE;
  3834. pRcvStruct->pPktContext->Stack.EthLLC.pOldHead = pHead;
  3835. pRcvStruct->pPktContext->Stack.EthLLC.pOldTail = pPacket->Private.Tail;
  3836. //
  3837. // Set the New Ndis buffer in the Packet
  3838. //
  3839. pNewHead->Next = pHead->Next;
  3840. pPacket->Private.Head = pNewHead;
  3841. if (pPacket->Private.Tail == pHead)
  3842. {
  3843. //
  3844. // Update the Tail of the packet as well
  3845. //
  3846. pPacket->Private.Tail = pNewHead;
  3847. }
  3848. Status = NDIS_STATUS_SUCCESS;
  3849. } while (FALSE);
  3850. return Status;
  3851. }