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.

1871 lines
74 KiB

  1. /***************************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. COMINI.C
  5. Abstract:
  6. CO-NDIS Miniport driver entry points for the Remote NDIS miniport.
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13. PURPOSE.
  14. Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 12/16/99: Created
  17. Author:
  18. ArvindM
  19. ****************************************************************************/
  20. #include "precomp.h"
  21. /****************************************************************************/
  22. /* RndismpCoCreateVc */
  23. /****************************************************************************/
  24. /* */
  25. /* Routine Description: */
  26. /* */
  27. /* Entry point to create a VC. We allocate a local VC structure, and send */
  28. /* off a CreateVc message to the device. */
  29. /* */
  30. /* Arguments: */
  31. /* */
  32. /* MiniportAdapterContext - pointer to our adapter structure */
  33. /* NdisVcHandle - the NDIS wrapper's handle for this VC */
  34. /* pMiniportVcContext - place to return our context for this VC */
  35. /* */
  36. /* Return: */
  37. /* */
  38. /* NDIS_STATUS */
  39. /* */
  40. /****************************************************************************/
  41. NDIS_STATUS
  42. RndismpCoCreateVc(IN NDIS_HANDLE MiniportAdapterContext,
  43. IN NDIS_HANDLE NdisVcHandle,
  44. OUT PNDIS_HANDLE pMiniportVcContext)
  45. {
  46. PRNDISMP_ADAPTER pAdapter;
  47. PRNDISMP_VC pVc;
  48. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  49. NDIS_STATUS Status;
  50. ULONG RefCount = 0;
  51. pVc = NULL;
  52. // get adapter context
  53. pAdapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  54. do
  55. {
  56. if (pAdapter->Halting)
  57. {
  58. Status = NDIS_STATUS_NOT_ACCEPTED;
  59. break;
  60. }
  61. pVc = AllocateVc(pAdapter);
  62. if (pVc == NULL)
  63. {
  64. Status = NDIS_STATUS_RESOURCES;
  65. break;
  66. }
  67. RNDISMP_REF_VC(pVc); // Creation ref
  68. //
  69. // Prepare a CreateVc message to send to the device.
  70. //
  71. pMsgFrame = BuildRndisMessageCoMiniport(pAdapter,
  72. pVc,
  73. REMOTE_CONDIS_MP_CREATE_VC_MSG,
  74. NULL);
  75. if (pMsgFrame == NULL)
  76. {
  77. Status = NDIS_STATUS_RESOURCES;
  78. break;
  79. }
  80. pVc->VcState = RNDISMP_VC_CREATING;
  81. RNDISMP_REF_VC(pVc); // Pending CreateVc response
  82. RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, TRUE, CompleteSendCoCreateVc);
  83. }
  84. while (FALSE);
  85. //
  86. // Clean up if failure.
  87. //
  88. if (Status != NDIS_STATUS_SUCCESS)
  89. {
  90. if (pVc != NULL)
  91. {
  92. RNDISMP_DEREF_VC(pVc, &RefCount); // Creation ref
  93. ASSERT(RefCount == 0); // the Vc should be dealloc'ed above.
  94. }
  95. }
  96. return (Status);
  97. }
  98. /****************************************************************************/
  99. /* CompleteSendCoCreateVc */
  100. /****************************************************************************/
  101. /* */
  102. /* Routine Description: */
  103. /* */
  104. /* Callback routine called when microport completes sending a CreateVc */
  105. /* message to the device. */
  106. /* */
  107. /* Arguments: */
  108. /* */
  109. /* pMsgFrame - Pointer to message frame */
  110. /* SendStatus - status of the microport send. */
  111. /* */
  112. /* Return: */
  113. /* */
  114. /* VOID */
  115. /* */
  116. /****************************************************************************/
  117. VOID
  118. CompleteSendCoCreateVc(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
  119. IN NDIS_STATUS SendStatus)
  120. {
  121. PRNDISMP_VC pVc;
  122. PRNDISMP_ADAPTER pAdapter;
  123. PRNDISMP_MESSAGE_FRAME pTmpMsgFrame;
  124. ULONG RefCount = 0;
  125. if (SendStatus == NDIS_STATUS_SUCCESS)
  126. {
  127. //
  128. // The message was sent successfully. Do nothing until
  129. // we get a response from the device.
  130. //
  131. }
  132. else
  133. {
  134. pVc = pMsgFrame->pVc;
  135. pAdapter = pVc->pAdapter;
  136. TRACE1(("CompleteSendCoCreateVc: VC %x, Adapter %x, fail status %x\n",
  137. pVc, pAdapter, SendStatus));
  138. //
  139. // Failed to send it to the device. Remove this message from
  140. // the pending list and free it.
  141. //
  142. RNDISMP_LOOKUP_PENDING_MESSAGE(pTmpMsgFrame, pAdapter, pMsgFrame->RequestId);
  143. ASSERT(pMsgFrame == pTmpMsgFrame);
  144. DereferenceMsgFrame(pMsgFrame);
  145. HandleCoCreateVcFailure(pVc, SendStatus);
  146. }
  147. } // CompleteSendCoCreateVc
  148. /****************************************************************************/
  149. /* HandleCoCreateVcFailure */
  150. /****************************************************************************/
  151. /* */
  152. /* Routine Description: */
  153. /* */
  154. /* Utility routine to handle failure of a CreateVc, either due to a local */
  155. /* microport send failure, or via explicit rejection by the device. */
  156. /* */
  157. /* Arguments: */
  158. /* */
  159. /* pVc - Pointer to VC on which this failure has occurred */
  160. /* Status - NDIS status associated with this failure */
  161. /* */
  162. /* Return: */
  163. /* */
  164. /* VOID */
  165. /* */
  166. /****************************************************************************/
  167. VOID
  168. HandleCoCreateVcFailure(IN PRNDISMP_VC pVc,
  169. IN NDIS_STATUS Status)
  170. {
  171. NDIS_HANDLE NdisVcHandle;
  172. BOOLEAN bFailActivateVc = FALSE;
  173. PCO_CALL_PARAMETERS pCallParameters;
  174. ULONG RefCount = 0;
  175. RNDISMP_ACQUIRE_VC_LOCK(pVc);
  176. NdisVcHandle = pVc->NdisVcHandle;
  177. switch (pVc->VcState)
  178. {
  179. case RNDISMP_VC_CREATING:
  180. pVc->VcState = RNDISMP_VC_CREATE_FAILURE;
  181. break;
  182. case RNDISMP_VC_CREATING_DELETE_PENDING:
  183. pVc->VcState = RNDISMP_VC_ALLOCATED;
  184. break;
  185. case RNDISMP_VC_CREATING_ACTIVATE_PENDING:
  186. bFailActivateVc = TRUE;
  187. pCallParameters = pVc->pCallParameters;
  188. pVc->VcState = RNDISMP_VC_CREATE_FAILURE;
  189. break;
  190. default:
  191. ASSERT(FALSE);
  192. break;
  193. }
  194. RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // Pending CreateVc response
  195. if (RefCount != 0)
  196. {
  197. RNDISMP_RELEASE_VC_LOCK(pVc);
  198. }
  199. if (bFailActivateVc)
  200. {
  201. NdisMCoActivateVcComplete(Status,
  202. NdisVcHandle,
  203. pCallParameters);
  204. }
  205. } // HandleCoCreateVcFailure
  206. /****************************************************************************/
  207. /* RndismpCoDeleteVc */
  208. /****************************************************************************/
  209. /* */
  210. /* Routine Description: */
  211. /* */
  212. /* Entry point to delete a VC. We send a DeleteVc message to the device. */
  213. /* */
  214. /* Arguments: */
  215. /* */
  216. /* MiniportVcContext - pointer to our VC structure */
  217. /* */
  218. /* Return: */
  219. /* */
  220. /* NDIS_STATUS */
  221. /* */
  222. /****************************************************************************/
  223. NDIS_STATUS
  224. RndismpCoDeleteVc(IN NDIS_HANDLE MiniportVcContext)
  225. {
  226. PRNDISMP_VC pVc;
  227. NDIS_STATUS Status;
  228. pVc = PRNDISMP_VC_FROM_CONTEXT_HANDLE(MiniportVcContext);
  229. Status = StartVcDeletion(pVc);
  230. return (Status);
  231. } // RndismpCoDeleteVc
  232. /****************************************************************************/
  233. /* StartVcDeletion */
  234. /****************************************************************************/
  235. /* */
  236. /* Routine Description: */
  237. /* */
  238. /* Initiate a DeleteVc operation on the specified VC. */
  239. /* */
  240. /* Arguments: */
  241. /* */
  242. /* pVc - Pointer to VC structure */
  243. /* */
  244. /* Return: */
  245. /* */
  246. /* NDIS_STATUS */
  247. /* */
  248. /****************************************************************************/
  249. NDIS_STATUS
  250. StartVcDeletion(IN PRNDISMP_VC pVc)
  251. {
  252. PRNDISMP_ADAPTER pAdapter;
  253. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  254. NDIS_STATUS Status;
  255. ULONG RefCount = 0;
  256. BOOLEAN bSendDeleteVc;
  257. pAdapter = pVc->pAdapter;
  258. bSendDeleteVc = FALSE;
  259. pMsgFrame = NULL;
  260. do
  261. {
  262. //
  263. // Prepare a DeleteVc message to send to the device.
  264. //
  265. pMsgFrame = BuildRndisMessageCoMiniport(pAdapter,
  266. pVc,
  267. REMOTE_CONDIS_MP_DELETE_VC_MSG,
  268. NULL);
  269. Status = NDIS_STATUS_SUCCESS;
  270. TRACE2(("StartVcDeletion: VC %x, state %d, Msg %x\n", pVc, pVc->VcState, pMsgFrame));
  271. RNDISMP_ACQUIRE_VC_LOCK(pVc);
  272. switch (pVc->VcState)
  273. {
  274. case RNDISMP_VC_CREATED:
  275. if (pMsgFrame != NULL)
  276. {
  277. pVc->VcState = RNDISMP_VC_DELETING;
  278. bSendDeleteVc = TRUE;
  279. }
  280. else
  281. {
  282. Status = NDIS_STATUS_RESOURCES;
  283. bSendDeleteVc = FALSE;
  284. }
  285. break;
  286. case RNDISMP_VC_CREATING:
  287. bSendDeleteVc = FALSE;
  288. pVc->VcState = RNDISMP_VC_CREATING_DELETE_PENDING;
  289. break;
  290. case RNDISMP_VC_CREATE_FAILURE:
  291. bSendDeleteVc = FALSE;
  292. pVc->VcState = RNDISMP_VC_ALLOCATED;
  293. break;
  294. default:
  295. bSendDeleteVc = FALSE;
  296. Status = NDIS_STATUS_NOT_ACCEPTED;
  297. break;
  298. }
  299. RNDISMP_RELEASE_VC_LOCK(pVc);
  300. if (Status != NDIS_STATUS_SUCCESS)
  301. {
  302. break;
  303. }
  304. if (bSendDeleteVc)
  305. {
  306. ASSERT(pMsgFrame != NULL);
  307. RNDISMP_REF_VC(pVc); // pending DeleteVc message
  308. RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, TRUE, CompleteSendCoDeleteVc);
  309. }
  310. RNDISMP_DEREF_VC(pVc, &RefCount); // successful DeleteVc
  311. }
  312. while (FALSE);
  313. if (!bSendDeleteVc)
  314. {
  315. if (pMsgFrame != NULL)
  316. {
  317. DereferenceMsgFrame(pMsgFrame);
  318. }
  319. }
  320. return (Status);
  321. } // StartVcDeletion
  322. /****************************************************************************/
  323. /* CompleteSendCoDeleteVc */
  324. /****************************************************************************/
  325. /* */
  326. /* Routine Description: */
  327. /* */
  328. /* Callback routine called when microport completes sending a DeleteVc */
  329. /* message to the device. */
  330. /* */
  331. /* Arguments: */
  332. /* */
  333. /* pMsgFrame - Pointer to message frame */
  334. /* SendStatus - status of the microport send. */
  335. /* */
  336. /* Return: */
  337. /* */
  338. /* VOID */
  339. /* */
  340. /****************************************************************************/
  341. VOID
  342. CompleteSendCoDeleteVc(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
  343. IN NDIS_STATUS SendStatus)
  344. {
  345. PRNDISMP_VC pVc;
  346. PRNDISMP_ADAPTER pAdapter;
  347. PRNDISMP_MESSAGE_FRAME pTmpMsgFrame;
  348. if (SendStatus == NDIS_STATUS_SUCCESS)
  349. {
  350. //
  351. // The message was sent successfully. Do nothing until
  352. // we get a response from the device.
  353. //
  354. }
  355. else
  356. {
  357. pVc = pMsgFrame->pVc;
  358. pAdapter = pVc->pAdapter;
  359. TRACE1(("CompleteSendCoDeleteVc: VC %x, Adapter %x, fail status %x\n",
  360. pVc, pAdapter, SendStatus));
  361. //
  362. // Failed to send it to the device. Remove this message from
  363. // the pending list and free it.
  364. //
  365. RNDISMP_LOOKUP_PENDING_MESSAGE(pTmpMsgFrame, pAdapter, pMsgFrame->RequestId);
  366. ASSERT(pMsgFrame == pTmpMsgFrame);
  367. DereferenceMsgFrame(pMsgFrame);
  368. //
  369. // Take care of the VC now.
  370. //
  371. HandleCoDeleteVcFailure(pVc, SendStatus);
  372. }
  373. } // CompleteSendCoDeleteVc
  374. /****************************************************************************/
  375. /* HandleCoDeleteVcFailure */
  376. /****************************************************************************/
  377. /* */
  378. /* Routine Description: */
  379. /* */
  380. /* Utility routine to handle failure of a DeleteVc, either due to a local */
  381. /* microport send failure, or via explicit rejection by the device. */
  382. /* */
  383. /* Arguments: */
  384. /* */
  385. /* pVc - Pointer to VC on which this failure has occurred */
  386. /* Status - NDIS status associated with this failure */
  387. /* */
  388. /* Return: */
  389. /* */
  390. /* VOID */
  391. /* */
  392. /****************************************************************************/
  393. VOID
  394. HandleCoDeleteVcFailure(IN PRNDISMP_VC pVc,
  395. IN NDIS_STATUS Status)
  396. {
  397. ULONG RefCount = 0;
  398. RNDISMP_ACQUIRE_VC_LOCK(pVc);
  399. switch (pVc->VcState)
  400. {
  401. case RNDISMP_VC_DELETING:
  402. pVc->VcState = RNDISMP_VC_DELETE_FAIL;
  403. break;
  404. default:
  405. ASSERT(FALSE);
  406. break;
  407. }
  408. RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // Pending DeleteVc response
  409. if (RefCount != 0)
  410. {
  411. RNDISMP_RELEASE_VC_LOCK(pVc);
  412. }
  413. } // HandleCoDeleteVcFailure
  414. /****************************************************************************/
  415. /* RndismpCoActivateVc */
  416. /****************************************************************************/
  417. /* */
  418. /* Routine Description: */
  419. /* */
  420. /* Entry point to activate a VC. We send an ActivateVc message to the */
  421. /* device. */
  422. /* */
  423. /* Arguments: */
  424. /* */
  425. /* MiniportVcContext - pointer to our VC structure */
  426. /* pCallParameters - CONDIS parameters for the VC */
  427. /* */
  428. /* Return: */
  429. /* */
  430. /* NDIS_STATUS */
  431. /* */
  432. /****************************************************************************/
  433. NDIS_STATUS
  434. RndismpCoActivateVc(IN NDIS_HANDLE MiniportVcContext,
  435. IN PCO_CALL_PARAMETERS pCallParameters)
  436. {
  437. PRNDISMP_VC pVc;
  438. NDIS_STATUS Status;
  439. pVc = PRNDISMP_VC_FROM_CONTEXT_HANDLE(MiniportVcContext);
  440. pVc->pCallParameters = pCallParameters;
  441. Status = StartVcActivation(pVc);
  442. return (Status);
  443. } // RndismpCoActivateVc
  444. /****************************************************************************/
  445. /* StartVcActivation */
  446. /****************************************************************************/
  447. /* */
  448. /* Routine Description: */
  449. /* */
  450. /* Start an Activate-VC operation on the specified VC. */
  451. /* */
  452. /* Arguments: */
  453. /* */
  454. /* pVc - Pointer to VC structure */
  455. /* */
  456. /* Return: */
  457. /* */
  458. /* NDIS_STATUS */
  459. /* */
  460. /****************************************************************************/
  461. NDIS_STATUS
  462. StartVcActivation(IN PRNDISMP_VC pVc)
  463. {
  464. NDIS_STATUS Status;
  465. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  466. PRNDISMP_ADAPTER pAdapter;
  467. BOOLEAN bSendActivateVc;
  468. NDIS_HANDLE NdisVcHandle;
  469. PCO_CALL_PARAMETERS pCallParameters;
  470. Status = NDIS_STATUS_PENDING;
  471. bSendActivateVc = FALSE;
  472. NdisVcHandle = pVc->NdisVcHandle;
  473. pCallParameters = pVc->pCallParameters;
  474. pAdapter = pVc->pAdapter;
  475. do
  476. {
  477. //
  478. // Prepare an ActivateVc message to send to the device.
  479. //
  480. pMsgFrame = BuildRndisMessageCoMiniport(pAdapter,
  481. pVc,
  482. REMOTE_CONDIS_MP_ACTIVATE_VC_MSG,
  483. pCallParameters);
  484. RNDISMP_ACQUIRE_VC_LOCK(pVc);
  485. switch (pVc->VcState)
  486. {
  487. case RNDISMP_VC_CREATING:
  488. pVc->VcState = RNDISMP_VC_CREATING_ACTIVATE_PENDING;
  489. break;
  490. case RNDISMP_VC_CREATED:
  491. if (pMsgFrame != NULL)
  492. {
  493. pVc->VcState = RNDISMP_VC_ACTIVATING;
  494. bSendActivateVc = TRUE;
  495. }
  496. else
  497. {
  498. TRACE1(("StartVcAct: VC %x, failed to build msg!\n", pVc));
  499. Status = NDIS_STATUS_RESOURCES;
  500. }
  501. break;
  502. default:
  503. TRACE1(("StartVcAct: VC %x in invalid state %d\n", pVc, pVc->VcState));
  504. Status = NDIS_STATUS_NOT_ACCEPTED;
  505. break;
  506. }
  507. RNDISMP_RELEASE_VC_LOCK(pVc);
  508. if (Status != NDIS_STATUS_PENDING)
  509. {
  510. break;
  511. }
  512. if (bSendActivateVc)
  513. {
  514. ASSERT(pMsgFrame != NULL);
  515. RNDISMP_REF_VC(pVc); // pending ActivateVc message
  516. RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, TRUE, CompleteSendCoActivateVc);
  517. }
  518. }
  519. while (FALSE);
  520. if (!bSendActivateVc)
  521. {
  522. if (pMsgFrame != NULL)
  523. {
  524. DereferenceMsgFrame(pMsgFrame);
  525. }
  526. }
  527. if (Status != NDIS_STATUS_PENDING)
  528. {
  529. NdisMCoActivateVcComplete(
  530. Status,
  531. NdisVcHandle,
  532. pCallParameters);
  533. Status = NDIS_STATUS_PENDING;
  534. }
  535. return (Status);
  536. } // StartVcActivation
  537. /****************************************************************************/
  538. /* CompleteSendCoActivateVc */
  539. /****************************************************************************/
  540. /* */
  541. /* Routine Description: */
  542. /* */
  543. /* Callback routine to handle send-completion of an Activate VC message. */
  544. /* */
  545. /* Arguments: */
  546. /* */
  547. /* pMsgFrame - Pointer to message frame */
  548. /* SendStatus - status of the microport send. */
  549. /* */
  550. /* Return: */
  551. /* */
  552. /* VOID */
  553. /* */
  554. /****************************************************************************/
  555. VOID
  556. CompleteSendCoActivateVc(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
  557. IN NDIS_STATUS SendStatus)
  558. {
  559. PRNDISMP_VC pVc;
  560. PRNDISMP_ADAPTER pAdapter;
  561. PRNDISMP_MESSAGE_FRAME pTmpMsgFrame;
  562. PCO_CALL_PARAMETERS pCallParameters;
  563. ULONG RefCount = 0;
  564. NDIS_HANDLE NdisVcHandle;
  565. if (SendStatus == NDIS_STATUS_SUCCESS)
  566. {
  567. //
  568. // The message was sent successfully. Do nothing until
  569. // we get a response from the device.
  570. //
  571. }
  572. else
  573. {
  574. pVc = pMsgFrame->pVc;
  575. pAdapter = pVc->pAdapter;
  576. TRACE1(("CompleteSendCoActivateVc: VC %x, Adapter %x, fail status %x\n",
  577. pVc, pAdapter, SendStatus));
  578. ASSERT(SendStatus != NDIS_STATUS_PENDING);
  579. //
  580. // Failed to send it to the device. Remove this message from
  581. // the pending list and free it.
  582. //
  583. RNDISMP_LOOKUP_PENDING_MESSAGE(pTmpMsgFrame, pAdapter, pMsgFrame->RequestId);
  584. ASSERT(pMsgFrame == pTmpMsgFrame);
  585. DereferenceMsgFrame(pMsgFrame);
  586. //
  587. // Take care of the VC now.
  588. //
  589. RNDISMP_ACQUIRE_VC_LOCK(pVc);
  590. NdisVcHandle = pVc->NdisVcHandle;
  591. pCallParameters = pVc->pCallParameters;
  592. pVc->VcState = RNDISMP_VC_CREATED;
  593. RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // pending ActivateVc
  594. if (RefCount != 0)
  595. {
  596. RNDISMP_RELEASE_VC_LOCK(pVc);
  597. }
  598. NdisMCoActivateVcComplete(
  599. SendStatus,
  600. NdisVcHandle,
  601. pCallParameters);
  602. }
  603. } // CompleteSendCoActivateVc
  604. /****************************************************************************/
  605. /* RndismpCoDeactivateVc */
  606. /****************************************************************************/
  607. /* */
  608. /* Routine Description: */
  609. /* */
  610. /* Entry point to de-activate a VC. We send an DeactivateVc message to the */
  611. /* device. */
  612. /* */
  613. /* Arguments: */
  614. /* */
  615. /* MiniportVcContext - pointer to our VC structure */
  616. /* */
  617. /* Return: */
  618. /* */
  619. /* NDIS_STATUS */
  620. /* */
  621. /****************************************************************************/
  622. NDIS_STATUS
  623. RndismpCoDeactivateVc(IN NDIS_HANDLE MiniportVcContext)
  624. {
  625. PRNDISMP_VC pVc;
  626. PRNDISMP_ADAPTER pAdapter;
  627. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  628. NDIS_STATUS Status;
  629. NDIS_HANDLE NdisVcHandle;
  630. BOOLEAN bVcLockAcquired = FALSE;
  631. BOOLEAN bSendDeactivateVc = FALSE;
  632. pMsgFrame = NULL;
  633. pVc = PRNDISMP_VC_FROM_CONTEXT_HANDLE(MiniportVcContext);
  634. pAdapter = pVc->pAdapter;
  635. Status = NDIS_STATUS_PENDING;
  636. do
  637. {
  638. //
  639. // Prepare a DeactivateVc message to send to the device.
  640. //
  641. pMsgFrame = BuildRndisMessageCoMiniport(pAdapter,
  642. pVc,
  643. REMOTE_CONDIS_MP_DEACTIVATE_VC_MSG,
  644. NULL);
  645. bVcLockAcquired = TRUE;
  646. RNDISMP_ACQUIRE_VC_LOCK(pVc);
  647. NdisVcHandle = pVc->NdisVcHandle;
  648. if (pVc->VcState != RNDISMP_VC_ACTIVATED)
  649. {
  650. Status = NDIS_STATUS_NOT_ACCEPTED;
  651. break;
  652. }
  653. switch (pVc->VcState)
  654. {
  655. case RNDISMP_VC_ACTIVATED:
  656. if (pMsgFrame != NULL)
  657. {
  658. bSendDeactivateVc = TRUE;
  659. pVc->VcState = RNDISMP_VC_DEACTIVATING;
  660. }
  661. else
  662. {
  663. bSendDeactivateVc = FALSE;
  664. Status = NDIS_STATUS_RESOURCES;
  665. }
  666. break;
  667. default:
  668. bSendDeactivateVc = FALSE;
  669. break;
  670. }
  671. if (bSendDeactivateVc)
  672. {
  673. RNDISMP_REF_VC(pVc); // pending Deactivate VC
  674. RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, TRUE, CompleteSendCoDeactivateVc);
  675. }
  676. }
  677. while (FALSE);
  678. if (!bSendDeactivateVc)
  679. {
  680. if (pMsgFrame != NULL)
  681. {
  682. DereferenceMsgFrame(pMsgFrame);
  683. }
  684. }
  685. if (Status != NDIS_STATUS_PENDING)
  686. {
  687. ASSERT(Status != NDIS_STATUS_SUCCESS);
  688. NdisMCoDeactivateVcComplete(
  689. Status,
  690. NdisVcHandle);
  691. Status = NDIS_STATUS_PENDING;
  692. }
  693. return (Status);
  694. }
  695. /****************************************************************************/
  696. /* CompleteSendCoDeactivateVc */
  697. /****************************************************************************/
  698. /* */
  699. /* Routine Description: */
  700. /* */
  701. /* Callback routine to handle send-completion of a deactivate VC message. */
  702. /* */
  703. /* Arguments: */
  704. /* */
  705. /* pMsgFrame - Pointer to message frame */
  706. /* SendStatus - status of the microport send. */
  707. /* */
  708. /* Return: */
  709. /* */
  710. /* VOID */
  711. /* */
  712. /****************************************************************************/
  713. VOID
  714. CompleteSendCoDeactivateVc(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
  715. IN NDIS_STATUS SendStatus)
  716. {
  717. PRNDISMP_VC pVc;
  718. PRNDISMP_ADAPTER pAdapter;
  719. PRNDISMP_MESSAGE_FRAME pTmpMsgFrame;
  720. PCO_CALL_PARAMETERS pCallParameters;
  721. ULONG RefCount = 0;
  722. NDIS_HANDLE NdisVcHandle;
  723. if (SendStatus == NDIS_STATUS_SUCCESS)
  724. {
  725. //
  726. // The message was sent successfully. Do nothing until
  727. // we get a response from the device.
  728. //
  729. }
  730. else
  731. {
  732. pVc = pMsgFrame->pVc;
  733. pAdapter = pVc->pAdapter;
  734. TRACE1(("CompleteSendCoDeactivateVc: VC %x, Adapter %x, fail status %x\n",
  735. pVc, pAdapter, SendStatus));
  736. ASSERT(SendStatus != NDIS_STATUS_PENDING);
  737. //
  738. // Failed to send it to the device. Remove this message from
  739. // the pending list and free it.
  740. //
  741. RNDISMP_LOOKUP_PENDING_MESSAGE(pTmpMsgFrame, pAdapter, pMsgFrame->RequestId);
  742. ASSERT(pMsgFrame == pTmpMsgFrame);
  743. DereferenceMsgFrame(pMsgFrame);
  744. //
  745. // Take care of the VC now.
  746. //
  747. RNDISMP_ACQUIRE_VC_LOCK(pVc);
  748. NdisVcHandle = pVc->NdisVcHandle;
  749. pCallParameters = pVc->pCallParameters;
  750. pVc->VcState = RNDISMP_VC_ACTIVATED;
  751. RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // pending DeactivateVc
  752. if (RefCount != 0)
  753. {
  754. RNDISMP_RELEASE_VC_LOCK(pVc);
  755. }
  756. NdisMCoDeactivateVcComplete(
  757. SendStatus,
  758. NdisVcHandle);
  759. }
  760. } // CompleteSendCoDeactivateVc
  761. /****************************************************************************/
  762. /* RndismpCoRequest */
  763. /****************************************************************************/
  764. /* */
  765. /* Routine Description: */
  766. /* */
  767. /* Entry point to handle a CO-request. We send a MiniportCoRequest message */
  768. /* to the device. */
  769. /* */
  770. /* Arguments: */
  771. /* */
  772. /* MiniportAdapterContext - pointer to our adapter structure */
  773. /* MiniportVcContext - pointer to our VC structure */
  774. /* pRequest - Pointer to NDIS request */
  775. /* */
  776. /* Return: */
  777. /* */
  778. /* NDIS_STATUS */
  779. /* */
  780. /****************************************************************************/
  781. NDIS_STATUS
  782. RndismpCoRequest(IN NDIS_HANDLE MiniportAdapterContext,
  783. IN NDIS_HANDLE MiniportVcContext,
  784. IN OUT PNDIS_REQUEST pRequest)
  785. {
  786. PRNDISMP_ADAPTER pAdapter;
  787. PRNDISMP_VC pVc;
  788. NDIS_STATUS Status;
  789. NDIS_OID Oid;
  790. pAdapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  791. pVc = PRNDISMP_VC_FROM_CONTEXT_HANDLE(MiniportVcContext);
  792. switch (pRequest->RequestType)
  793. {
  794. case NdisRequestQueryInformation:
  795. case NdisRequestQueryStatistics:
  796. Oid = pRequest->DATA.QUERY_INFORMATION.Oid;
  797. TRACE2(("CoReq: Adapter %x, Req %x, QueryInfo/Stat (%d) Oid %x\n",
  798. pAdapter, pRequest, pRequest->RequestType, Oid));
  799. Status = ProcessQueryInformation(pAdapter,
  800. pVc,
  801. pRequest,
  802. Oid,
  803. pRequest->DATA.QUERY_INFORMATION.InformationBuffer,
  804. pRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
  805. &pRequest->DATA.QUERY_INFORMATION.BytesWritten,
  806. &pRequest->DATA.QUERY_INFORMATION.BytesNeeded);
  807. break;
  808. case NdisRequestSetInformation:
  809. Oid = pRequest->DATA.SET_INFORMATION.Oid;
  810. TRACE1(("CoReq: Adapter %x, Req %x, SetInfo Oid %x\n",
  811. pAdapter, pRequest, Oid));
  812. Status = ProcessSetInformation(pAdapter,
  813. pVc,
  814. pRequest,
  815. Oid,
  816. pRequest->DATA.SET_INFORMATION.InformationBuffer,
  817. pRequest->DATA.SET_INFORMATION.InformationBufferLength,
  818. &pRequest->DATA.SET_INFORMATION.BytesRead,
  819. &pRequest->DATA.SET_INFORMATION.BytesNeeded);
  820. break;
  821. default:
  822. TRACE1(("CoReq: Unsupported request type %d\n",
  823. pRequest->RequestType));
  824. Status = NDIS_STATUS_NOT_SUPPORTED;
  825. break;
  826. }
  827. return (Status);
  828. }
  829. /****************************************************************************/
  830. /* RndismpCoSendPackets */
  831. /****************************************************************************/
  832. /* */
  833. /* Routine Description: */
  834. /* */
  835. /* Entry point to send one or more packets on a VC. */
  836. /* */
  837. /* Arguments: */
  838. /* */
  839. /* MiniportVcContext - pointer to our VC structure */
  840. /* PacketArray - Array of packet pointers */
  841. /* NumberOfPackets - number of packets in array above */
  842. /* */
  843. /* Return: */
  844. /* */
  845. /* VOID */
  846. /* */
  847. /****************************************************************************/
  848. VOID
  849. RndismpCoSendPackets(IN NDIS_HANDLE MiniportVcContext,
  850. IN PNDIS_PACKET * PacketArray,
  851. IN UINT NumberOfPackets)
  852. {
  853. PRNDISMP_VC pVc;
  854. UINT i;
  855. pVc = PRNDISMP_VC_FROM_CONTEXT_HANDLE(MiniportVcContext);
  856. RNDISMP_ACQUIRE_VC_LOCK(pVc);
  857. pVc->RefCount += NumberOfPackets;
  858. if (pVc->VcState == RNDISMP_VC_ACTIVATED)
  859. {
  860. RNDISMP_RELEASE_VC_LOCK(pVc);
  861. DoMultipleSend(pVc->pAdapter,
  862. pVc,
  863. PacketArray,
  864. NumberOfPackets);
  865. }
  866. else
  867. {
  868. RNDISMP_RELEASE_VC_LOCK(pVc);
  869. for (i = 0; i < NumberOfPackets; i++)
  870. {
  871. CompleteSendDataOnVc(pVc, PacketArray[i], NDIS_STATUS_VC_NOT_ACTIVATED);
  872. }
  873. }
  874. } // RndismpCoSendPackets
  875. /****************************************************************************/
  876. /* ReceiveCreateVcComplete */
  877. /****************************************************************************/
  878. /* */
  879. /* Routine Description: */
  880. /* */
  881. /* Process a CONDIS CreateVcComplete message from the device */
  882. /* */
  883. /* Arguments: */
  884. /* */
  885. /* pAdapter - pointer to our Adapter structure */
  886. /* pMessage - pointer to RNDIS message */
  887. /* pMdl - pointer to MDL received from microport */
  888. /* TotalLength - length of complete message */
  889. /* MicroportMessageContext - context for message from micorport */
  890. /* ReceiveStatus - used by microport to indicate it is low on resource */
  891. /* bMessageCopied - is this a copy of the original message? */
  892. /* */
  893. /* Return: */
  894. /* */
  895. /* BOOLEAN - should the message be returned to the microport? */
  896. /* */
  897. /****************************************************************************/
  898. BOOLEAN
  899. ReceiveCreateVcComplete(IN PRNDISMP_ADAPTER pAdapter,
  900. IN PRNDIS_MESSAGE pMessage,
  901. IN PMDL pMdl,
  902. IN ULONG TotalLength,
  903. IN NDIS_HANDLE MicroportMessageContext,
  904. IN NDIS_STATUS ReceiveStatus,
  905. IN BOOLEAN bMessageCopied)
  906. {
  907. BOOLEAN bDiscardPkt = TRUE;
  908. PRNDISMP_VC pVc;
  909. PRNDISMP_MESSAGE_FRAME pCreateVcMsgFrame;
  910. PRCONDIS_MP_CREATE_VC_COMPLETE pCreateVcComp;
  911. RNDISMP_VC_STATE VcState;
  912. BOOLEAN bVcLockAcquired = FALSE;
  913. ULONG RefCount = 0;
  914. NDIS_STATUS Status;
  915. pVc = NULL;
  916. do
  917. {
  918. pCreateVcComp = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
  919. //
  920. // TBD - Validate lengths?
  921. //
  922. //
  923. // Check the request Id.
  924. //
  925. RNDISMP_LOOKUP_PENDING_MESSAGE(pCreateVcMsgFrame, pAdapter, pCreateVcComp->RequestId);
  926. if (pCreateVcMsgFrame == NULL)
  927. {
  928. TRACE1(("CreateVcComp: Adapter %x, Invalid ReqId %d!\n",
  929. pAdapter, pCreateVcComp->RequestId));
  930. break;
  931. }
  932. pVc = pCreateVcMsgFrame->pVc;
  933. Status = pCreateVcComp->Status;
  934. DereferenceMsgFrame(pCreateVcMsgFrame);
  935. if (Status != NDIS_STATUS_SUCCESS)
  936. {
  937. HandleCoCreateVcFailure(pVc, Status);
  938. break;
  939. }
  940. bVcLockAcquired = TRUE;
  941. RNDISMP_ACQUIRE_VC_LOCK(pVc);
  942. RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // pending CreateVc
  943. if (RefCount == 0)
  944. {
  945. bVcLockAcquired = FALSE;
  946. break;
  947. }
  948. pVc->DeviceVcContext = pCreateVcComp->DeviceVcHandle;
  949. VcState = pVc->VcState;
  950. switch (VcState)
  951. {
  952. case RNDISMP_VC_CREATING:
  953. pVc->VcState = RNDISMP_VC_CREATED;
  954. break;
  955. case RNDISMP_VC_CREATING_ACTIVATE_PENDING:
  956. pVc->VcState = RNDISMP_VC_CREATED;
  957. RNDISMP_RELEASE_VC_LOCK(pVc);
  958. bVcLockAcquired = FALSE;
  959. Status = StartVcActivation(pVc);
  960. ASSERT(Status == NDIS_STATUS_PENDING);
  961. break;
  962. case RNDISMP_VC_CREATING_DELETE_PENDING:
  963. pVc->VcState = RNDISMP_VC_CREATED;
  964. RNDISMP_RELEASE_VC_LOCK(pVc);
  965. bVcLockAcquired = FALSE;
  966. Status = StartVcDeletion(pVc);
  967. break;
  968. default:
  969. TRACE1(("CreateVcComp: VC %x, wrong state %d\n",
  970. pVc, VcState));
  971. break;
  972. }
  973. }
  974. while (FALSE);
  975. if (bVcLockAcquired)
  976. {
  977. RNDISMP_RELEASE_VC_LOCK(pVc);
  978. }
  979. return (bDiscardPkt);
  980. }
  981. /****************************************************************************/
  982. /* ReceiveActivateVcComplete */
  983. /****************************************************************************/
  984. /* */
  985. /* Routine Description: */
  986. /* */
  987. /* Process a CONDIS ActivateVcComplete message from the device */
  988. /* */
  989. /* Arguments: */
  990. /* */
  991. /* pAdapter - pointer to our Adapter structure */
  992. /* pMessage - pointer to RNDIS message */
  993. /* pMdl - pointer to MDL received from microport */
  994. /* TotalLength - length of complete message */
  995. /* MicroportMessageContext - context for message from micorport */
  996. /* ReceiveStatus - used by microport to indicate it is low on resource */
  997. /* bMessageCopied - is this a copy of the original message? */
  998. /* */
  999. /* Return: */
  1000. /* */
  1001. /* BOOLEAN - should the message be returned to the microport? */
  1002. /* */
  1003. /****************************************************************************/
  1004. BOOLEAN
  1005. ReceiveActivateVcComplete(IN PRNDISMP_ADAPTER pAdapter,
  1006. IN PRNDIS_MESSAGE pMessage,
  1007. IN PMDL pMdl,
  1008. IN ULONG TotalLength,
  1009. IN NDIS_HANDLE MicroportMessageContext,
  1010. IN NDIS_STATUS ReceiveStatus,
  1011. IN BOOLEAN bMessageCopied)
  1012. {
  1013. BOOLEAN bDiscardPkt = TRUE;
  1014. PRNDISMP_VC pVc;
  1015. PRNDISMP_MESSAGE_FRAME pActVcMsgFrame;
  1016. PRCONDIS_MP_ACTIVATE_VC_COMPLETE pActVcComp;
  1017. BOOLEAN bVcLockAcquired = FALSE;
  1018. ULONG RefCount = 0;
  1019. NDIS_STATUS Status;
  1020. NDIS_HANDLE NdisVcHandle;
  1021. PCO_CALL_PARAMETERS pCallParameters;
  1022. pVc = NULL;
  1023. do
  1024. {
  1025. pActVcComp = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
  1026. //
  1027. // TBD - Validate lengths?
  1028. //
  1029. //
  1030. // Check the request Id.
  1031. //
  1032. RNDISMP_LOOKUP_PENDING_MESSAGE(pActVcMsgFrame, pAdapter, pActVcComp->RequestId);
  1033. if (pActVcMsgFrame == NULL)
  1034. {
  1035. TRACE1(("ActVcComp: Adapter %x, Invalid ReqId %d!\n",
  1036. pAdapter, pActVcComp->RequestId));
  1037. break;
  1038. }
  1039. pVc = pActVcMsgFrame->pVc;
  1040. DereferenceMsgFrame(pActVcMsgFrame);
  1041. bVcLockAcquired = TRUE;
  1042. RNDISMP_ACQUIRE_VC_LOCK(pVc);
  1043. RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // pending ActivateVc
  1044. if (RefCount == 0)
  1045. {
  1046. bVcLockAcquired = FALSE;
  1047. break;
  1048. }
  1049. if (pVc->VcState != RNDISMP_VC_ACTIVATING)
  1050. {
  1051. TRACE1(("ActVcComp: Adapter %x, VC %x: invalid state %d\n",
  1052. pAdapter, pVc, pVc->VcState));
  1053. break;
  1054. }
  1055. Status = pActVcComp->Status;
  1056. if (Status == NDIS_STATUS_SUCCESS)
  1057. {
  1058. pVc->VcState = RNDISMP_VC_ACTIVATED;
  1059. }
  1060. else
  1061. {
  1062. pVc->VcState = RNDISMP_VC_CREATED;
  1063. }
  1064. NdisVcHandle = pVc->NdisVcHandle;
  1065. pCallParameters = pVc->pCallParameters;
  1066. RNDISMP_RELEASE_VC_LOCK(pVc);
  1067. bVcLockAcquired = FALSE;
  1068. NdisMCoActivateVcComplete(
  1069. pActVcComp->Status,
  1070. NdisVcHandle,
  1071. pCallParameters);
  1072. }
  1073. while (FALSE);
  1074. if (bVcLockAcquired)
  1075. {
  1076. RNDISMP_RELEASE_VC_LOCK(pVc);
  1077. }
  1078. return (bDiscardPkt);
  1079. }
  1080. /****************************************************************************/
  1081. /* ReceiveDeleteVcComplete */
  1082. /****************************************************************************/
  1083. /* */
  1084. /* Routine Description: */
  1085. /* */
  1086. /* Process a CONDIS DeleteVcComplete message from the device */
  1087. /* */
  1088. /* Arguments: */
  1089. /* */
  1090. /* pAdapter - pointer to our Adapter structure */
  1091. /* pMessage - pointer to RNDIS message */
  1092. /* pMdl - pointer to MDL received from microport */
  1093. /* TotalLength - length of complete message */
  1094. /* MicroportMessageContext - context for message from micorport */
  1095. /* ReceiveStatus - used by microport to indicate it is low on resource */
  1096. /* bMessageCopied - is this a copy of the original message? */
  1097. /* */
  1098. /* Return: */
  1099. /* */
  1100. /* BOOLEAN - should the message be returned to the microport? */
  1101. /* */
  1102. /****************************************************************************/
  1103. BOOLEAN
  1104. ReceiveDeleteVcComplete(IN PRNDISMP_ADAPTER pAdapter,
  1105. IN PRNDIS_MESSAGE pMessage,
  1106. IN PMDL pMdl,
  1107. IN ULONG TotalLength,
  1108. IN NDIS_HANDLE MicroportMessageContext,
  1109. IN NDIS_STATUS ReceiveStatus,
  1110. IN BOOLEAN bMessageCopied)
  1111. {
  1112. BOOLEAN bDiscardPkt = TRUE;
  1113. PRNDISMP_VC pVc;
  1114. PRCONDIS_MP_DELETE_VC_COMPLETE pDeleteVcComp;
  1115. PRNDISMP_MESSAGE_FRAME pDeleteVcMsgFrame;
  1116. RNDISMP_VC_STATE VcState;
  1117. BOOLEAN bVcLockAcquired = FALSE;
  1118. ULONG RefCount = 0;
  1119. NDIS_STATUS Status;
  1120. pVc = NULL;
  1121. do
  1122. {
  1123. pDeleteVcComp = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
  1124. //
  1125. // TBD - Validate lengths?
  1126. //
  1127. //
  1128. // Check the request Id.
  1129. //
  1130. RNDISMP_LOOKUP_PENDING_MESSAGE(pDeleteVcMsgFrame, pAdapter, pDeleteVcComp->RequestId);
  1131. if (pDeleteVcMsgFrame == NULL)
  1132. {
  1133. TRACE1(("DeleteVcComp: Adapter %x, Invalid ReqId %d!\n",
  1134. pAdapter, pDeleteVcComp->RequestId));
  1135. break;
  1136. }
  1137. pVc = pDeleteVcMsgFrame->pVc;
  1138. Status = pDeleteVcComp->Status;
  1139. DereferenceMsgFrame(pDeleteVcMsgFrame);
  1140. if (Status != NDIS_STATUS_SUCCESS)
  1141. {
  1142. HandleCoDeleteVcFailure(pVc, Status);
  1143. break;
  1144. }
  1145. bVcLockAcquired = TRUE;
  1146. RNDISMP_ACQUIRE_VC_LOCK(pVc);
  1147. RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // pending DeleteVc
  1148. if (RefCount == 0)
  1149. {
  1150. bVcLockAcquired = FALSE;
  1151. break;
  1152. }
  1153. if (pVc->VcState != RNDISMP_VC_DELETING)
  1154. {
  1155. TRACE1(("DeleteVcComp: Adapter %x, VC %x: invalid state %d\n",
  1156. pAdapter, pVc, pVc->VcState));
  1157. break;
  1158. }
  1159. pVc->VcState = RNDISMP_VC_ALLOCATED;
  1160. RNDISMP_DEREF_VC(pVc, &RefCount); // remove create ref
  1161. if (RefCount == 0)
  1162. {
  1163. bVcLockAcquired = FALSE;
  1164. }
  1165. }
  1166. while (FALSE);
  1167. if (bVcLockAcquired)
  1168. {
  1169. RNDISMP_RELEASE_VC_LOCK(pVc);
  1170. }
  1171. return (bDiscardPkt);
  1172. }
  1173. /****************************************************************************/
  1174. /* ReceiveDeactivateVcComplete */
  1175. /****************************************************************************/
  1176. /* */
  1177. /* Routine Description: */
  1178. /* */
  1179. /* Process a CONDIS DeActivateVcComplete message from the device */
  1180. /* */
  1181. /* Arguments: */
  1182. /* */
  1183. /* pAdapter - pointer to our Adapter structure */
  1184. /* pMessage - pointer to RNDIS message */
  1185. /* pMdl - pointer to MDL received from microport */
  1186. /* TotalLength - length of complete message */
  1187. /* MicroportMessageContext - context for message from micorport */
  1188. /* ReceiveStatus - used by microport to indicate it is low on resource */
  1189. /* bMessageCopied - is this a copy of the original message? */
  1190. /* */
  1191. /* Return: */
  1192. /* */
  1193. /* BOOLEAN - should the message be returned to the microport? */
  1194. /* */
  1195. /****************************************************************************/
  1196. BOOLEAN
  1197. ReceiveDeactivateVcComplete(IN PRNDISMP_ADAPTER pAdapter,
  1198. IN PRNDIS_MESSAGE pMessage,
  1199. IN PMDL pMdl,
  1200. IN ULONG TotalLength,
  1201. IN NDIS_HANDLE MicroportMessageContext,
  1202. IN NDIS_STATUS ReceiveStatus,
  1203. IN BOOLEAN bMessageCopied)
  1204. {
  1205. BOOLEAN bDiscardPkt = TRUE;
  1206. PRNDISMP_VC pVc;
  1207. RNDISMP_VC_STATE VcState;
  1208. PRNDISMP_MESSAGE_FRAME pDeactivateVcMsgFrame;
  1209. PRCONDIS_MP_DEACTIVATE_VC_COMPLETE pDeactivateVcComp;
  1210. BOOLEAN bVcLockAcquired = FALSE;
  1211. BOOLEAN bAddTempRef = FALSE;
  1212. ULONG RefCount = 0;
  1213. NDIS_STATUS Status;
  1214. pVc = NULL;
  1215. do
  1216. {
  1217. pDeactivateVcComp = RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(pMessage);
  1218. //
  1219. // TBD - Validate lengths?
  1220. //
  1221. //
  1222. // Check the request Id.
  1223. //
  1224. RNDISMP_LOOKUP_PENDING_MESSAGE(pDeactivateVcMsgFrame, pAdapter, pDeactivateVcComp->RequestId);
  1225. if (pDeactivateVcMsgFrame == NULL)
  1226. {
  1227. TRACE1(("DeactivateVcComp: Adapter %x, Invalid ReqId %d!\n",
  1228. pAdapter, pDeactivateVcComp->RequestId));
  1229. break;
  1230. }
  1231. pVc = pDeactivateVcMsgFrame->pVc;
  1232. DereferenceMsgFrame(pDeactivateVcMsgFrame);
  1233. bVcLockAcquired = TRUE;
  1234. RNDISMP_ACQUIRE_VC_LOCK(pVc);
  1235. RNDISMP_DEREF_VC_LOCKED(pVc, &RefCount); // pending DeactivateVc
  1236. if (RefCount == 0)
  1237. {
  1238. bVcLockAcquired = FALSE;
  1239. break;
  1240. }
  1241. if (pVc->VcState != RNDISMP_VC_DEACTIVATING)
  1242. {
  1243. TRACE1(("DeactVcComp: Adapter %x, VC %x: invalid state %d\n",
  1244. pAdapter, pVc, pVc->VcState));
  1245. ASSERT(FALSE);
  1246. break;
  1247. }
  1248. if (pDeactivateVcComp->Status == NDIS_STATUS_SUCCESS)
  1249. {
  1250. pVc->VcState = RNDISMP_VC_DEACTIVATED;
  1251. //
  1252. // We add a temp ref on the VC to help complete deactivate-VC
  1253. // from a common place (see bAddTempRef below).
  1254. //
  1255. RNDISMP_REF_VC(pVc); // temp ref, deactivate vc complete OK
  1256. bAddTempRef = TRUE;
  1257. }
  1258. else
  1259. {
  1260. pVc->VcState = RNDISMP_VC_ACTIVATED;
  1261. }
  1262. RNDISMP_RELEASE_VC_LOCK(pVc);
  1263. bVcLockAcquired = FALSE;
  1264. if (bAddTempRef)
  1265. {
  1266. //
  1267. // The following deref will check and call NDIS'
  1268. // deactivate vc complete API if we don't have any
  1269. // outstanding sends or receives on this VC.
  1270. //
  1271. RNDISMP_DEREF_VC(pVc, &RefCount); // temp ref
  1272. }
  1273. }
  1274. while (FALSE);
  1275. if (bVcLockAcquired)
  1276. {
  1277. RNDISMP_RELEASE_VC_LOCK(pVc);
  1278. }
  1279. return (bDiscardPkt);
  1280. }
  1281. /****************************************************************************/
  1282. /* BuildRndisMessageCoMiniport */
  1283. /****************************************************************************/
  1284. /* */
  1285. /* Routine Description: */
  1286. /* */
  1287. /* Allocate resources for message and frame and build an RNDIS message */
  1288. /* for sending to a remote CONDIS Miniport device. */
  1289. /* */
  1290. /* Arguments: */
  1291. /* */
  1292. /* pAdapter - Pointer to adapter structure */
  1293. /* pVc - Pointer to VC structure */
  1294. /* NdisMessageType - RNDIS message type */
  1295. /* pCallParameters - optional pointer to call parameters, applicable to */
  1296. /* certain message types. */
  1297. /* */
  1298. /* Return: */
  1299. /* */
  1300. /* PRNDISMP_MESSAGE_FRAME */
  1301. /* */
  1302. /****************************************************************************/
  1303. PRNDISMP_MESSAGE_FRAME
  1304. BuildRndisMessageCoMiniport(IN PRNDISMP_ADAPTER pAdapter,
  1305. IN PRNDISMP_VC pVc,
  1306. IN UINT NdisMessageType,
  1307. IN PCO_CALL_PARAMETERS pCallParameters OPTIONAL)
  1308. {
  1309. PRNDIS_MESSAGE pMessage;
  1310. UINT MessageSize;
  1311. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  1312. switch (NdisMessageType)
  1313. {
  1314. case REMOTE_CONDIS_MP_CREATE_VC_MSG:
  1315. {
  1316. PRCONDIS_MP_CREATE_VC pCreateVc;
  1317. MessageSize = RNDIS_MESSAGE_SIZE(RCONDIS_MP_CREATE_VC);
  1318. pMsgFrame = AllocateMessageAndFrame(pAdapter, MessageSize);
  1319. if (pMsgFrame == NULL)
  1320. {
  1321. break;
  1322. }
  1323. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  1324. pMessage->NdisMessageType = NdisMessageType;
  1325. pMsgFrame->NdisMessageType = NdisMessageType;
  1326. pCreateVc = &pMessage->Message.CoMiniportCreateVc;
  1327. pCreateVc->RequestId = pMsgFrame->RequestId;
  1328. pCreateVc->NdisVcHandle = pVc->VcId;
  1329. break;
  1330. }
  1331. case REMOTE_CONDIS_MP_DELETE_VC_MSG:
  1332. {
  1333. PRCONDIS_MP_DELETE_VC pDeleteVc;
  1334. MessageSize = RNDIS_MESSAGE_SIZE(RCONDIS_MP_DELETE_VC);
  1335. pMsgFrame = AllocateMessageAndFrame(pAdapter, MessageSize);
  1336. if (pMsgFrame == NULL)
  1337. {
  1338. break;
  1339. }
  1340. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  1341. pMessage->NdisMessageType = NdisMessageType;
  1342. pMsgFrame->NdisMessageType = NdisMessageType;
  1343. pDeleteVc = &pMessage->Message.CoMiniportDeleteVc;
  1344. pDeleteVc->RequestId = pMsgFrame->RequestId;
  1345. pDeleteVc->DeviceVcHandle = pVc->DeviceVcContext;
  1346. break;
  1347. }
  1348. case REMOTE_CONDIS_MP_ACTIVATE_VC_MSG:
  1349. {
  1350. PRCONDIS_MP_ACTIVATE_VC_REQUEST pActivateVc;
  1351. PRCONDIS_CALL_MANAGER_PARAMETERS pCallMgrParams;
  1352. PRCONDIS_MEDIA_PARAMETERS pMediaParams;
  1353. ULONG_PTR FillLocation;
  1354. UINT FillOffset;
  1355. ASSERT(pCallParameters != NULL);
  1356. MessageSize = RNDIS_MESSAGE_SIZE(RCONDIS_MP_ACTIVATE_VC_REQUEST);
  1357. if (pCallParameters->CallMgrParameters)
  1358. {
  1359. MessageSize += (sizeof(RCONDIS_CALL_MANAGER_PARAMETERS) +
  1360. pCallParameters->CallMgrParameters->CallMgrSpecific.Length);
  1361. }
  1362. if (pCallParameters->MediaParameters)
  1363. {
  1364. MessageSize += (sizeof(RCONDIS_MEDIA_PARAMETERS) +
  1365. pCallParameters->MediaParameters->MediaSpecific.Length);
  1366. }
  1367. pMsgFrame = AllocateMessageAndFrame(pAdapter, MessageSize);
  1368. if (pMsgFrame == NULL)
  1369. {
  1370. break;
  1371. }
  1372. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  1373. pMessage->NdisMessageType = NdisMessageType;
  1374. pMsgFrame->NdisMessageType = NdisMessageType;
  1375. pActivateVc = &pMessage->Message.CoMiniportActivateVc;
  1376. pActivateVc->RequestId = pMsgFrame->RequestId;
  1377. pActivateVc->DeviceVcHandle = pVc->DeviceVcContext;
  1378. pActivateVc->Flags = pCallParameters->Flags;
  1379. FillOffset = RNDIS_MESSAGE_SIZE(RCONDIS_MP_ACTIVATE_VC_REQUEST);
  1380. FillLocation = ((ULONG_PTR)pMessage + FillOffset);
  1381. //
  1382. // Fill in Media parameters, if present.
  1383. //
  1384. if (pCallParameters->MediaParameters)
  1385. {
  1386. PCO_SPECIFIC_PARAMETERS pMediaSpecific;
  1387. pMediaSpecific = &pCallParameters->MediaParameters->MediaSpecific;
  1388. pMediaParams = (PRCONDIS_MEDIA_PARAMETERS)FillLocation;
  1389. pActivateVc->MediaParamsOffset = (UINT32)(FillLocation - (ULONG_PTR)pActivateVc);
  1390. pActivateVc->MediaParamsLength = sizeof(RCONDIS_MEDIA_PARAMETERS) +
  1391. pMediaSpecific->Length;
  1392. RNDISMP_MOVE_MEM(pMediaParams,
  1393. pCallParameters->MediaParameters,
  1394. FIELD_OFFSET(RCONDIS_MEDIA_PARAMETERS, MediaSpecific));
  1395. FillLocation += sizeof(RCONDIS_MEDIA_PARAMETERS);
  1396. FillOffset += sizeof(RCONDIS_MEDIA_PARAMETERS);
  1397. pMediaParams->MediaSpecific.ParameterOffset =
  1398. sizeof(RCONDIS_SPECIFIC_PARAMETERS);
  1399. pMediaParams->MediaSpecific.ParameterType =
  1400. pMediaSpecific->ParamType;
  1401. pMediaParams->MediaSpecific.ParameterLength =
  1402. pMediaSpecific->Length;
  1403. RNDISMP_MOVE_MEM((PVOID)FillLocation,
  1404. &pMediaSpecific->Parameters[0],
  1405. pMediaSpecific->Length);
  1406. FillLocation += pMediaSpecific->Length;
  1407. FillOffset += pMediaSpecific->Length;
  1408. }
  1409. else
  1410. {
  1411. pActivateVc->MediaParamsOffset = 0;
  1412. pActivateVc->MediaParamsLength = 0;
  1413. }
  1414. //
  1415. // Fill in Call manager parameters, if present.
  1416. //
  1417. if (pCallParameters->CallMgrParameters)
  1418. {
  1419. PCO_SPECIFIC_PARAMETERS pCallMgrSpecific;
  1420. pCallMgrSpecific = &pCallParameters->CallMgrParameters->CallMgrSpecific;
  1421. pCallMgrParams = (PRCONDIS_CALL_MANAGER_PARAMETERS)FillLocation;
  1422. pActivateVc->CallMgrParamsOffset = (UINT32)(FillLocation - (ULONG_PTR)pActivateVc);
  1423. pActivateVc->CallMgrParamsLength = sizeof(RCONDIS_CALL_MANAGER_PARAMETERS) +
  1424. pCallMgrSpecific->Length;
  1425. RNDISMP_MOVE_MEM(pCallMgrParams,
  1426. pCallParameters->CallMgrParameters,
  1427. FIELD_OFFSET(RCONDIS_CALL_MANAGER_PARAMETERS, CallMgrSpecific));
  1428. FillLocation += sizeof(RCONDIS_CALL_MANAGER_PARAMETERS);
  1429. FillOffset += sizeof(RCONDIS_CALL_MANAGER_PARAMETERS);
  1430. pCallMgrParams->CallMgrSpecific.ParameterOffset =
  1431. sizeof(RCONDIS_SPECIFIC_PARAMETERS);
  1432. pCallMgrParams->CallMgrSpecific.ParameterType =
  1433. pCallMgrSpecific->ParamType;
  1434. pCallMgrParams->CallMgrSpecific.ParameterLength =
  1435. pCallMgrSpecific->Length;
  1436. RNDISMP_MOVE_MEM((PVOID)FillLocation,
  1437. &pCallMgrSpecific->Parameters[0],
  1438. pCallMgrSpecific->Length);
  1439. FillLocation += pCallMgrSpecific->Length;
  1440. FillOffset += pCallMgrSpecific->Length;
  1441. }
  1442. else
  1443. {
  1444. pActivateVc->CallMgrParamsOffset = 0;
  1445. pActivateVc->CallMgrParamsLength = 0;
  1446. }
  1447. break;
  1448. }
  1449. case REMOTE_CONDIS_MP_DEACTIVATE_VC_MSG:
  1450. {
  1451. PRCONDIS_MP_DEACTIVATE_VC_REQUEST pDeactivateVc;
  1452. MessageSize = RNDIS_MESSAGE_SIZE(RCONDIS_MP_DEACTIVATE_VC_REQUEST);
  1453. pMsgFrame = AllocateMessageAndFrame(pAdapter, MessageSize);
  1454. if (pMsgFrame == NULL)
  1455. {
  1456. break;
  1457. }
  1458. pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame);
  1459. pMessage->NdisMessageType = NdisMessageType;
  1460. pMsgFrame->NdisMessageType = NdisMessageType;
  1461. pDeactivateVc = &pMessage->Message.CoMiniportDeactivateVc;
  1462. pDeactivateVc->RequestId = pMsgFrame->RequestId;
  1463. pDeactivateVc->DeviceVcHandle = pVc->DeviceVcContext;
  1464. break;
  1465. }
  1466. default:
  1467. ASSERT(FALSE);
  1468. pMsgFrame = NULL;
  1469. break;
  1470. }
  1471. return (pMsgFrame);
  1472. } // BuildRndisMessageCoMiniport
  1473. /****************************************************************************/
  1474. /* CompleteSendDataOnVc */
  1475. /****************************************************************************/
  1476. /* */
  1477. /* Routine Description: */
  1478. /* */
  1479. /* Handle send-completion of CONDIS data */
  1480. /* */
  1481. /* Arguments: */
  1482. /* */
  1483. /* pVc - Pointer to Vc */
  1484. /* pNdisPacket - Packet being completed */
  1485. /* Status - send completion status */
  1486. /* */
  1487. /* Return: */
  1488. /* */
  1489. /* VOID */
  1490. /* */
  1491. /****************************************************************************/
  1492. VOID
  1493. CompleteSendDataOnVc(IN PRNDISMP_VC pVc,
  1494. IN PNDIS_PACKET pNdisPacket,
  1495. IN NDIS_STATUS Status)
  1496. {
  1497. ULONG RefCount;
  1498. NdisMCoSendComplete(Status,
  1499. pVc->NdisVcHandle,
  1500. pNdisPacket);
  1501. RNDISMP_DEREF_VC(pVc, &RefCount);
  1502. }
  1503. /****************************************************************************/
  1504. /* IndicateReceiveDataOnVc */
  1505. /****************************************************************************/
  1506. /* */
  1507. /* Routine Description: */
  1508. /* */
  1509. /* Handle reception of a bunch of CONDIS packets on a Vc. */
  1510. /* */
  1511. /* Arguments: */
  1512. /* */
  1513. /* pVc - Pointer to VC on which data arrived. */
  1514. /* PacketArray - Array of packets */
  1515. /* NumberOfPackets - size of above array */
  1516. /* */
  1517. /* Return: */
  1518. /* */
  1519. /* VOID */
  1520. /* */
  1521. /****************************************************************************/
  1522. VOID
  1523. IndicateReceiveDataOnVc(IN PRNDISMP_VC pVc,
  1524. IN PNDIS_PACKET * PacketArray,
  1525. IN UINT NumberOfPackets)
  1526. {
  1527. UINT i;
  1528. do
  1529. {
  1530. if (pVc->VcState != RNDISMP_VC_ACTIVATED)
  1531. {
  1532. TRACE1(("Rcv VC data: VC %x, invalid state %d\n", pVc, pVc->VcState));
  1533. break;
  1534. }
  1535. for (i = 0; i < NumberOfPackets; i++)
  1536. {
  1537. RNDISMP_REF_VC(pVc);
  1538. }
  1539. NdisMCoIndicateReceivePacket(pVc->NdisVcHandle,
  1540. PacketArray,
  1541. NumberOfPackets);
  1542. }
  1543. while (FALSE);
  1544. } // IndicateReceiveDataOnVc