Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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