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

851 lines
18 KiB

  1. /*++
  2. Copyright (c) 1995-1998 Microsoft Corporation
  3. Module Name:
  4. RCACoCl.c
  5. Abstract:
  6. The module implements the RCA Co-NDIS client.
  7. Author:
  8. Shyam Pather (SPATHER)
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. SPATHER 04-20-99 Created / adapted from original RCA code by RMachin/JameelH
  13. --*/
  14. #include <precomp.h>
  15. #define MODULE_NUMBER MODULE_COCL
  16. #define _FILENUMBER 'LCOC'
  17. #if PACKET_POOL_OPTIMIZATION
  18. // RecvPPOpt - Start
  19. LONG g_alRecvPPOptBuckets[RECVPPOPT_NUM_BUCKETS];
  20. LONG g_lRecvPPOptOutstanding;
  21. NDIS_SPIN_LOCK g_RecvPPOptLock;
  22. // RecvPPOpt - End
  23. #endif
  24. BOOLEAN
  25. RCAReferenceVc(
  26. IN PRCA_VC pRcaVc
  27. )
  28. {
  29. PRCA_ADAPTER pAdapter = pRcaVc->pAdapter;
  30. BOOLEAN rc = FALSE;
  31. RCADEBUGP(RCA_INFO, ("RCAReferenceVc: Enter\n"));
  32. ACQUIRE_SPIN_LOCK(&pAdapter->SpinLock);
  33. if ((pRcaVc->Flags & VC_CLOSING) == 0)
  34. {
  35. pRcaVc->RefCount++;
  36. rc = TRUE;
  37. }
  38. RCADEBUGP(RCA_LOUD, ("RCAReferenceVc: pRcaVc (0x%x) ref count is %d\n",
  39. pRcaVc, pRcaVc->RefCount));
  40. RELEASE_SPIN_LOCK(&pAdapter->SpinLock);
  41. RCADEBUGP(RCA_INFO, ("RCAReferenceVc: Exit, returning 0x%x\n", rc));
  42. return(rc);
  43. }
  44. VOID
  45. RCADereferenceVc(
  46. IN PRCA_VC pRcaVc
  47. )
  48. {
  49. PRCA_ADAPTER pAdapter = pRcaVc->pAdapter;
  50. RCADEBUGP(RCA_INFO, ("RCADerefenceVc: Enter\n"));
  51. ACQUIRE_SPIN_LOCK(&pAdapter->SpinLock);
  52. pRcaVc->RefCount--;
  53. RCADEBUGP(RCA_LOUD, ("RCADereferenceVc: pRcaVc (0x%x) ref count is %d\n",
  54. pRcaVc, pRcaVc->RefCount));
  55. if (pRcaVc->RefCount == 0)
  56. {
  57. ASSERT((pRcaVc->Flags & VC_ACTIVE) == 0);
  58. //
  59. // Take VC out of the adapter list
  60. //
  61. UnlinkDouble(pRcaVc, NextVcOnAdapter, PrevVcOnAdapter);
  62. RCADEBUGP(RCA_LOUD, ("RCADereferenceVc: Took vc out of list\n"));
  63. RCAFreeLock(&(pRcaVc->Lock));
  64. RCAFreeMem(pRcaVc);
  65. }
  66. RELEASE_SPIN_LOCK(&pAdapter->SpinLock);
  67. RCADEBUGP(RCA_INFO, ("RCADerefenceVc: Exit\n"));
  68. }
  69. VOID
  70. RCACoSendComplete(
  71. IN NDIS_STATUS Status,
  72. IN NDIS_HANDLE ProtocolVcContext,
  73. IN PNDIS_PACKET pNdisPacket)
  74. /*++
  75. Routine Description
  76. Handle completion of a send. All we need to do is free the resources and
  77. complete the event.
  78. Arguments
  79. Status - Result of the send
  80. ProtocolVcContext - RCA VC
  81. Packet - The Packet sent
  82. Return Value:
  83. None
  84. --*/
  85. {
  86. PRCA_PROTOCOL_CONTEXT pProtocolContext = &GlobalContext;
  87. PMDL pMdl;
  88. RCADEBUGP(RCA_INFO, ("RCACoSendComplete: enter. VC=%x, Packet=%x\n", ProtocolVcContext, pNdisPacket));
  89. InterlockedDecrement(&((PRCA_VC)ProtocolVcContext)->PendingSends);
  90. //
  91. // Get the MDL out of the packet and give it back to the client.
  92. //
  93. pMdl = (PMDL) pNdisPacket->Private.Head;
  94. ACQUIRE_SPIN_LOCK(&(((PRCA_VC)ProtocolVcContext)->SpinLock));
  95. if (pProtocolContext->Handlers.SendCompleteCallback) {
  96. pProtocolContext->Handlers.SendCompleteCallback((PVOID)ProtocolVcContext,
  97. ((PRCA_VC)ProtocolVcContext)->ClientSendContext,
  98. PKT_RSVD_FROM_PKT(pNdisPacket)->PacketContext,
  99. pMdl,
  100. Status);
  101. }
  102. RELEASE_SPIN_LOCK(&(((PRCA_VC)ProtocolVcContext)->SpinLock));
  103. #if PACKET_POOL_OPTIMIZATION
  104. // SendPPOpt - Start
  105. NdisAcquireSpinLock(&g_SendPPOptLock);
  106. g_lSendPPOptOutstanding--;
  107. NdisReleaseSpinLock(&g_SendPPOptLock);
  108. // SendPPOpt - End
  109. #endif
  110. NdisFreePacket(pNdisPacket);
  111. RCADEBUGP(RCA_LOUD, ("RCACoSendComplete: exit\n"));
  112. }
  113. PNDIS_PACKET
  114. RCAAllocCopyPacket(
  115. IN PRCA_VC pRcaVc,
  116. IN PNDIS_PACKET pNdisPacket
  117. )
  118. /*++
  119. Routine Description:
  120. Allocate and copy a received packet to a private packet.
  121. Note: We set the returned packet's status to NDIS_STATUS_RESOURCES,
  122. which lets us know later on that this packet belongs to us and
  123. not to the miniport.
  124. Arguments:
  125. pRcaVc - Pointer to our Adapter structure
  126. pNdisPacket - Packet to be copied.
  127. Return Value:
  128. The allocated copy of the given packet, if successful. NULL otherwise.
  129. --*/
  130. {
  131. PUCHAR pBuffer;
  132. NDIS_STATUS Status;
  133. PNDIS_PACKET pNewPacket;
  134. PNDIS_BUFFER pNdisBuffer, pNewBuffer;
  135. ULONG TotalLength;
  136. ULONG BytesCopied;
  137. pBuffer = NULL;
  138. pNewPacket = NULL;
  139. pNewBuffer = NULL;
  140. do
  141. {
  142. //
  143. // Copy the received packet into this one. First get the
  144. // length to copy.
  145. //
  146. NdisQueryPacket(pNdisPacket,
  147. NULL,
  148. NULL,
  149. NULL,
  150. &TotalLength);
  151. RCAAllocMem(pBuffer, UCHAR, TotalLength);
  152. if (pBuffer == NULL)
  153. {
  154. break;
  155. }
  156. //
  157. // Get a new NDIS buffer.
  158. //
  159. NdisAllocateBuffer(&Status,
  160. &pNewBuffer,
  161. pRcaVc->pAdapter->RecvBufferPool,
  162. pBuffer,
  163. TotalLength);
  164. if (Status != NDIS_STATUS_SUCCESS)
  165. {
  166. break;
  167. }
  168. //
  169. // Allocate a new packet.
  170. //
  171. #if PACKET_POOL_OPTIMIZATION
  172. // RecvPPOpt - Start
  173. NdisAcquireSpinLock(&g_RecvPPOptLock);
  174. g_alRecvPPOptBuckets[g_lRecvPPOptOutstanding]++;
  175. g_lRecvPPOptOutstanding++;
  176. NdisReleaseSpinLock(&g_RecvPPOptLock);
  177. // RecvPPOpt - End
  178. #endif
  179. NdisAllocatePacket(&Status,
  180. &pNewPacket,
  181. pRcaVc->pAdapter->RecvPacketPool);
  182. if (Status != NDIS_STATUS_SUCCESS)
  183. {
  184. break;
  185. }
  186. NDIS_SET_PACKET_STATUS(pNewPacket, 0);
  187. //
  188. // Link the buffer to the packet.
  189. //
  190. NdisChainBufferAtFront(pNewPacket, pNewBuffer);
  191. //copy the packet
  192. NdisCopyFromPacketToPacket(pNewPacket,
  193. 0, // Destn offset
  194. TotalLength,
  195. pNdisPacket,
  196. 0, // Src offset
  197. &BytesCopied);
  198. RCAAssert(TotalLength == BytesCopied);
  199. NdisAdjustBufferLength(pNewBuffer, TotalLength);
  200. } while (FALSE);
  201. if (pNewPacket != (PNDIS_PACKET)NULL)
  202. {
  203. NDIS_SET_PACKET_STATUS(pNewPacket, NDIS_STATUS_RESOURCES);
  204. }
  205. else
  206. {
  207. if (pNewBuffer != NULL)
  208. {
  209. NdisFreeBuffer(pNewBuffer);
  210. }
  211. if (pBuffer != NULL)
  212. {
  213. RCAFreeMem(pBuffer);
  214. }
  215. }
  216. return(pNewPacket);
  217. }
  218. UINT
  219. RCACoReceivePacket(
  220. IN NDIS_HANDLE ProtocolBindingContext,
  221. IN NDIS_HANDLE ProtocolVcContext,
  222. IN PNDIS_PACKET pNdisPacket
  223. )
  224. /*++
  225. Routine Description:
  226. Called by NDIS when a packet is received on a VC owned
  227. by RCA. If there's a 'streamto' device indicated in teh VC,
  228. we get an IRP, point the IR at teh MDL, and send it to
  229. the next streaming driver.
  230. If there is no 'streamto' device, since this is 'live' data
  231. we currently dump the packet.
  232. Arguments:
  233. ProtocolBindingContext - our ClientBind structure for this adapter
  234. ProtocolVcContext - our VC structure
  235. pNdisPacket - NDIS packet
  236. Return Value:
  237. Success, whether we dumped or not.
  238. --*/
  239. {
  240. PRCA_PROTOCOL_CONTEXT pProtocolContext = &GlobalContext;
  241. PFN_RCARECEIVE_CALLBACK pfnReceiveCallback;
  242. NDIS_STATUS Status = 0;
  243. PRCA_VC pRcaVc = (PRCA_VC) ProtocolVcContext;
  244. PNDIS_PACKET pCopiedPacket, pPacket;
  245. UINT PacketRefs = 0;
  246. RCADEBUGP(RCA_INFO, ("RCACoReceivePacket: Enter\n"));
  247. do {
  248. ACQUIRE_SPIN_LOCK(&pRcaVc->SpinLock);
  249. pfnReceiveCallback = pProtocolContext->Handlers.ReceiveCallback;
  250. if (pfnReceiveCallback == NULL ||
  251. pRcaVc->ClientReceiveContext == NULL) {
  252. PacketRefs = 0;
  253. RELEASE_SPIN_LOCK(&pRcaVc->SpinLock);
  254. break;
  255. }
  256. if (NDIS_GET_PACKET_STATUS (pNdisPacket) == NDIS_STATUS_RESOURCES) {
  257. //
  258. // Miniport's short on resources. Copy the packet.
  259. //
  260. RCADEBUGP(RCA_LOUD, ("RCACoReceivePacket: Miniport is low on resources, have to copy packet\n"));
  261. pCopiedPacket = RCAAllocCopyPacket(pRcaVc, pNdisPacket);
  262. PacketRefs = 0;
  263. if (pCopiedPacket == NULL) {
  264. RCADEBUGP(RCA_ERROR, ("RcaCoReceivePacket: Failed to copy packet\n"));
  265. RELEASE_SPIN_LOCK(&pRcaVc->SpinLock);
  266. break;
  267. }
  268. pPacket = pCopiedPacket;
  269. WORK_ITEM_FROM_PKT(pPacket)->bFreeThisPacket = TRUE;
  270. } else {
  271. PacketRefs = 1;
  272. pPacket = pNdisPacket;
  273. WORK_ITEM_FROM_PKT(pPacket)->bFreeThisPacket = FALSE;
  274. }
  275. pfnReceiveCallback((PVOID)pRcaVc,
  276. pRcaVc->ClientReceiveContext,
  277. pPacket);
  278. RELEASE_SPIN_LOCK(&pRcaVc->SpinLock);
  279. } while (FALSE);
  280. RCADEBUGP(RCA_INFO,("CoReceivePacket: Exit return %lu\n", PacketRefs));
  281. return(PacketRefs);
  282. }
  283. VOID
  284. RCAReceiveComplete(
  285. IN NDIS_HANDLE ProtocolBindingContext
  286. )
  287. {
  288. RCADEBUGP(RCA_INFO, (" RCACoReceiveComplete: Enter\n"));
  289. RCADEBUGP(RCA_INFO, (" RCACoReceiveComplete: Exit\n"));
  290. }
  291. NDIS_STATUS
  292. RCACreateVc(
  293. IN NDIS_HANDLE ProtocolAfContext,
  294. IN NDIS_HANDLE NdisVcHandle,
  295. OUT PNDIS_HANDLE pProtocolVcContext
  296. )
  297. /*++
  298. Routine Description:
  299. Entry point called by NDIS when the Call Manager wants to create
  300. a new endpoint (VC) for a new inbound call on our SAP.
  301. We accept the VC and do the main part of the work in our RCAIncomingCall
  302. function.
  303. Arguments:
  304. ProtocolAfContext - Actually a pointer to the client bind structure we specified on OpenAddressFamily
  305. NdisVcHandle - Handle for this VC for all future references
  306. pProtocolVcContext - Place where we (protocol) return our context for the VC
  307. Return Value:
  308. NDIS_STATUS_SUCCESS if we could create a VC
  309. NDIS_STATUS_RESOURCES otherwise
  310. --*/
  311. {
  312. PRCA_ADAPTER pAdapter;
  313. PRCA_VC pRcaVc;
  314. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  315. RCADEBUGP(RCA_INFO, ("RCACreateVc - Enter\n"));
  316. pAdapter = (PRCA_ADAPTER)ProtocolAfContext;
  317. RCADEBUGP(RCA_LOUD, ("RCACreateVc: pAdapter is 0x%x\n", pAdapter));
  318. do
  319. {
  320. //
  321. // Allocate a new VC structure.
  322. //
  323. RCAAllocMem(pRcaVc, RCA_VC, sizeof(RCA_VC));
  324. if(pRcaVc != (PRCA_VC)NULL)
  325. {
  326. RCADEBUGP(RCA_LOUD, ("RCACreateVc: Allocated Vc 0x%x\n", pRcaVc));
  327. //
  328. // Initialize the interesting fields.
  329. //
  330. RCAMemSet(pRcaVc, 0, sizeof(RCA_VC));
  331. #if DBG
  332. pRcaVc->rca_sig = rca_signature;
  333. #endif
  334. pRcaVc->pAdapter = pAdapter;
  335. pRcaVc->RefCount = 1;
  336. NdisAllocateSpinLock(&pRcaVc->SpinLock);
  337. pRcaVc->NdisVcHandle = NdisVcHandle;
  338. ACQUIRE_SPIN_LOCK(&pAdapter->SpinLock);
  339. LinkDoubleAtHead(pAdapter->VcList, pRcaVc, NextVcOnAdapter, PrevVcOnAdapter);
  340. RELEASE_SPIN_LOCK(&pAdapter->SpinLock);
  341. } else {
  342. RCADEBUGP(RCA_ERROR, ("RCACreateVc: Failed to allocate VC structure, "
  343. "setting Status = NDIS_STATUS_RESOURCES\n"));
  344. Status = NDIS_STATUS_RESOURCES;
  345. break;
  346. }
  347. *pProtocolVcContext = (NDIS_HANDLE)pRcaVc;
  348. } while (FALSE);
  349. RCADEBUGP(RCA_INFO, ("RCACreateVc: Exit, returning Status 0x%x\n", Status));
  350. return(Status);
  351. }
  352. NDIS_STATUS
  353. RCADeleteVc(
  354. IN NDIS_HANDLE ProtocolVcContext
  355. )
  356. /*++
  357. Routine Description:
  358. Handles requests from a call mgr to delete a VC.
  359. We need to delete the VC pointer
  360. At this time, this VC structure should be free of any calls, and we
  361. simply free it.
  362. Arguments:
  363. ProtocolVcContext - pointer to our VC structure
  364. Return Value:
  365. NDIS_STATUS_SUCCESS always
  366. --*/
  367. {
  368. PRCA_VC pRcaVc;
  369. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  370. PRCA_ADAPTER pAdapter;
  371. RCADEBUGP(RCA_INFO, ("RCADeleteVc: Enter\n"));
  372. pRcaVc = (PRCA_VC)ProtocolVcContext;
  373. pAdapter = pRcaVc->pAdapter;
  374. RCADEBUGP(RCA_INFO, ("RCADeleteVc: pRcaVc is 0x%x\n", pRcaVc));
  375. ASSERT((pRcaVc->ClientReceiveContext == NULL) && (pRcaVc->ClientSendContext == NULL));
  376. ACQUIRE_SPIN_LOCK(&pAdapter->SpinLock);
  377. pRcaVc->ClosingState |= CLOSING_DELETE_VC;
  378. RELEASE_SPIN_LOCK(&pAdapter->SpinLock);
  379. RCADereferenceVc(pRcaVc);
  380. ACQUIRE_SPIN_LOCK(&pAdapter->SpinLock);
  381. if (pAdapter->VcList == NULL) {
  382. RCADEBUGP(RCA_LOUD, ("RCADeleteVc: All VCs gone, unblocking RCADeactivateAdapter().\n"));
  383. if (pAdapter->BlockedOnClose) {
  384. RCASignal(&pAdapter->CloseBlock, Status);
  385. }
  386. } else {
  387. RCADEBUGP(RCA_INFO, ("RCADeleteVc: There are still some VCs remaining.\n"));
  388. }
  389. RELEASE_SPIN_LOCK(&pAdapter->SpinLock);
  390. return(NDIS_STATUS_SUCCESS);
  391. }
  392. NDIS_STATUS
  393. RCAIncomingCall(
  394. IN NDIS_HANDLE ProtocolSapContext,
  395. IN NDIS_HANDLE ProtocolVcContext,
  396. IN OUT PCO_CALL_PARAMETERS pCallParams
  397. )
  398. /*++
  399. Routine Description:
  400. This handler is called when there is an incoming call matching:
  401. - a SAP we registered on behalf of a client
  402. - our own SAP (systemwide RCA for this adapter/AF.
  403. Arguments:
  404. ProtocolSapContext - Pointer to our SAP structure
  405. ProtocolVcContext - Pointer to our RCA_VC structure
  406. pCallParameters - Call parameters
  407. Return Value:
  408. NDIS_STATUS_SUCCESS if we accept this call
  409. NDIS_STATUS_FAILURE if we reject it.
  410. --*/
  411. {
  412. PRCA_PROTOCOL_CONTEXT pProtocolContext = &GlobalContext;
  413. PRCA_VC pRcaVc = (PRCA_VC)ProtocolVcContext;
  414. ULONG HashIndex = HASH_VC((ULONG_PTR)pRcaVc);
  415. RCADEBUGP(RCA_INFO, ("RCAIncomingCall: Adapter: 0x%x, RCAVC: 0x%x, pCallParams: 0x%x\n",
  416. pRcaVc->pAdapter, pRcaVc, pCallParams));
  417. ACQUIRE_SPIN_LOCK(&pProtocolContext->SpinLock);
  418. RCADEBUGP(RCA_LOUD, ("RCAIncomingCall: Acquired global protocol context lock\n"));
  419. //
  420. // Stick the RCA VC in the Hash Table at the hashed position.
  421. //
  422. LinkDoubleAtHead(pProtocolContext->VcHashTable[HashIndex], pRcaVc, NextVcOnHash, PrevVcOnHash);
  423. RELEASE_SPIN_LOCK(&pProtocolContext->SpinLock);
  424. RCADEBUGP(RCA_LOUD, ("RCAIncomingCall: Release global protocol context lock\n"));
  425. //
  426. // Copy the call parameters for use later.
  427. //
  428. RtlCopyMemory(&pRcaVc->CallParameters, pCallParams, sizeof(CO_CALL_PARAMETERS));
  429. //
  430. // Accept the call
  431. //
  432. NdisClIncomingCallComplete(NDIS_STATUS_SUCCESS,
  433. pRcaVc->NdisVcHandle,
  434. pCallParams);
  435. RCADEBUGP(RCA_INFO, ("RCAIncomingCall: Exit - Returning NDIS_STATUS_SUCCESS\n"));
  436. return(NDIS_STATUS_SUCCESS);
  437. }
  438. VOID
  439. RCAIncomingCloseCall(
  440. IN NDIS_STATUS closeStatus,
  441. IN NDIS_HANDLE ProtocolVcContext,
  442. IN PVOID CloseData OPTIONAL,
  443. IN UINT Size OPTIONAL
  444. )
  445. {
  446. PRCA_PROTOCOL_CONTEXT pProtocolContext = &GlobalContext;
  447. PRCA_VC pRcaVc;
  448. NDIS_STATUS Status = NDIS_STATUS_PENDING;
  449. RCADEBUGP(RCA_INFO, ("RCAIncomingCloseCall: Enter\n"));
  450. //
  451. // First close the call from our perspective, then let the KS client know that the
  452. // call is closed by invoking the VC close callback.
  453. //
  454. pRcaVc = (PRCA_VC)ProtocolVcContext;
  455. Status = RCACoNdisCloseCallOnVcNoWait((PVOID)pRcaVc);
  456. //
  457. // Call this callback only if we have either a send or a receive client
  458. // context - if we don't have either, assume no-one cares that this
  459. // VC is closing. The actual callback should check for NULL contexts.
  460. //
  461. ACQUIRE_SPIN_LOCK(&pRcaVc->SpinLock);
  462. if ((pRcaVc->ClientReceiveContext || pRcaVc->ClientSendContext) &&
  463. (pProtocolContext->Handlers.VcCloseCallback)) {
  464. //
  465. // Release the spin lock here because this callback will very likely
  466. // call RCACoNdisReleaseXXxVcContext() etc which will want the lock.
  467. //
  468. // There is a teensy tiny race here - if someone releases the VC context
  469. // between when we release the lock and when we call the callback, we
  470. // could be in trouble.
  471. //
  472. RELEASE_SPIN_LOCK(&pRcaVc->SpinLock);
  473. pProtocolContext->Handlers.VcCloseCallback((PVOID)pRcaVc,
  474. pRcaVc->ClientReceiveContext,
  475. pRcaVc->ClientSendContext);
  476. } else {
  477. RELEASE_SPIN_LOCK(&pRcaVc->SpinLock);
  478. }
  479. RCADEBUGP(RCA_INFO, ("RCAIncomingCloseCall: Exit\n"));
  480. }
  481. VOID
  482. RCACloseCallComplete(
  483. IN NDIS_STATUS Status,
  484. IN NDIS_HANDLE ProtocolVcContext,
  485. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL
  486. )
  487. /*++
  488. Routine Description:
  489. This routine handles completion of a previous NdisClCloseCall.
  490. It is assumed that Status is always NDIS_STATUS_SUCCESS.
  491. Arguments:
  492. Status - Status of the Close Call.
  493. ProtocolVcContext - Pointer to VC structure.
  494. ProtocolPartyContext - Not used.
  495. Return Value:
  496. None
  497. --*/
  498. {
  499. PRCA_PROTOCOL_CONTEXT pProtocolContext = &GlobalContext;
  500. PRCA_VC pRcaVc = (PRCA_VC)ProtocolVcContext;
  501. RCADEBUGP(RCA_INFO, ("RCACloseCallComplete: Enter\n"));
  502. ACQUIRE_SPIN_LOCK(&(pRcaVc->pAdapter->SpinLock));
  503. pRcaVc->ClosingState |= CLOSING_CLOSE_COMPLETE;
  504. RELEASE_SPIN_LOCK(&(pRcaVc->pAdapter->SpinLock));
  505. ACQUIRE_SPIN_LOCK(&pProtocolContext->SpinLock);
  506. RCADEBUGP(RCA_LOUD, ("RCACloseCallComplete: Acquired global protocol context lock\n"));
  507. //
  508. // Take VC out of hash table
  509. //
  510. UnlinkDouble(pRcaVc, NextVcOnHash, PrevVcOnHash);
  511. RELEASE_SPIN_LOCK(&pProtocolContext->SpinLock);
  512. RCADEBUGP(RCA_LOUD, ("RCACloseCallComplete: Released global protocol context lock\n"));
  513. RCASignal(&pRcaVc->CloseBlock, Status);
  514. RCADEBUGP(RCA_INFO, ("RCACloseCallComplete: Exit\n"));
  515. }
  516. VOID
  517. RCACallConnected(
  518. IN NDIS_HANDLE ProtocolVcContext
  519. )
  520. /*++
  521. Routine Description:
  522. This is the final step of an incoming call. The call on this VC
  523. is now fully set up.
  524. Arguments:
  525. ProtocolVcContext - Call Manager's VC
  526. Return Value:
  527. None
  528. --*/
  529. {
  530. PRCA_VC pRcaVc = (PRCA_VC)ProtocolVcContext;
  531. RCADEBUGP(RCA_INFO, ("RCACallConnected: Enter\n"));
  532. ACQUIRE_SPIN_LOCK(&pRcaVc->pAdapter->SpinLock);
  533. pRcaVc = (PRCA_VC)ProtocolVcContext;
  534. pRcaVc->Flags |= VC_ACTIVE;
  535. RELEASE_SPIN_LOCK(&pRcaVc->pAdapter->SpinLock);
  536. RCADEBUGP(RCA_INFO, ("RCACallConnected: Exit\n"));
  537. }
  538. NDIS_STATUS
  539. RCARequest(
  540. IN NDIS_HANDLE ProtocolAfContext,
  541. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  542. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
  543. IN OUT PNDIS_REQUEST NdisRequest
  544. )
  545. /*++
  546. Routine Description:
  547. This routine is called by NDIS when a call manager sends us an NDIS Request.
  548. Arguments:
  549. ProtocolAfContext - Our context for the client binding
  550. ProtocolVcContext - Our context for a VC
  551. ProtocolPartyContext - Our context for a Party; RCA VC's Party list.
  552. pNdisRequest - Pointer to the NDIS Request.
  553. Return Value:
  554. NDIS_STATUS_SUCCESS
  555. --*/
  556. {
  557. PRCA_ADAPTER pAdapter = (PRCA_ADAPTER)ProtocolAfContext;
  558. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  559. RCADEBUGP(RCA_INFO, ("RCARequest: Enter - pAdapter->NdisAfHandle = 0X%x\n", pAdapter->NdisAfHandle));
  560. if (NdisRequest->DATA.QUERY_INFORMATION.Oid == OID_CO_AF_CLOSE)
  561. {
  562. RCADEBUGP(RCA_LOUD, ("RCARequest: received OID_CO_AF_CLOSE\n"));
  563. ACQUIRE_SPIN_LOCK(&pAdapter->SpinLock);
  564. if (!(pAdapter->AdapterFlags & RCA_ADAPTERFLAGS_DEACTIVATE_IN_PROGRESS)) {
  565. pAdapter->AdapterFlags |= RCA_ADAPTERFLAGS_DEACTIVATE_IN_PROGRESS;
  566. RELEASE_SPIN_LOCK(&pAdapter->SpinLock);
  567. Status = NdisScheduleWorkItem(&pAdapter->DeactivateWorkItem);
  568. if (Status != NDIS_STATUS_SUCCESS) {
  569. RCADEBUGP(RCA_ERROR, ("RCARequest: NdisScheduleWorkItem failed with status 0x%x\n", Status));
  570. }
  571. } else {
  572. RELEASE_SPIN_LOCK(&pAdapter->SpinLock);
  573. }
  574. }
  575. RCADEBUGP(RCA_INFO, ("RCARequest: Exit - Returning NDIS_STATUS_SUCCESS\n"));
  576. return Status;
  577. }