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.

663 lines
15 KiB

  1. /*++
  2. Copyright (c) 1995-1998 Microsoft Corporation
  3. Module Name:
  4. RCAKsNdi.c
  5. Abstract:
  6. The module implements the Co-NDIS wrapper functions that the KS parts of
  7. RCA use to avoid having to deal with Co-NDIS directly.
  8. Author:
  9. Shyam Pather (SPATHER)
  10. Revision History:
  11. Who When What
  12. -------- -------- ----------------------------------------------
  13. SPATHER 04-20-99 Created
  14. --*/
  15. #include <precomp.h>
  16. #define MODULE_NUMBER MODULE_KSNDIS
  17. #define _FILENUMBER 'DNSK'
  18. #if PACKET_POOL_OPTIMIZATION
  19. // SendPPOpt - Start
  20. LONG g_alSendPPOptBuckets[SENDPPOPT_NUM_BUCKETS];
  21. LONG g_lSendPPOptOutstanding;
  22. NDIS_SPIN_LOCK g_SendPPOptLock;
  23. // SendPPOpt - End
  24. #endif
  25. PRCA_VC
  26. RCARefVcFromHashTable(
  27. IN PRCA_VC VcContext
  28. )
  29. /*++
  30. Routine Description:
  31. Searches for an RCA_VC structure in the hash table. If found, the structure is referenced.
  32. Arguments:
  33. VcContext -- The RCA_VC structure to look for.
  34. Return Value:
  35. RCA VC structure, or NULL if there's no entry. (Caller should assert this is never
  36. NULL, since both RCA and NDIS think their respective pointers should still be valid...)
  37. --*/
  38. {
  39. PRCA_PROTOCOL_CONTEXT pProtocolContext = &GlobalContext;
  40. ULONG HashIndex = HASH_VC((ULONG_PTR)VcContext);
  41. PRCA_VC pRcaVc;
  42. RCADEBUGP(RCA_INFO, ("RCARefVcFromHashTable: enter\n" ));
  43. ACQUIRE_SPIN_LOCK(&pProtocolContext->SpinLock);
  44. RCADEBUGP(RCA_LOUD, ("RCARefVcFromHashTable: Acquired global protocol context lock\n"));
  45. for (pRcaVc = pProtocolContext->VcHashTable[HashIndex];
  46. pRcaVc != NULL;
  47. pRcaVc = pRcaVc->NextVcOnHash)
  48. {
  49. PRCA_ADAPTER pAdapter;
  50. if (pRcaVc == VcContext)
  51. {
  52. pAdapter = pRcaVc->pAdapter;
  53. DPR_ACQUIRE_SPIN_LOCK(&pAdapter->SpinLock);
  54. if (pRcaVc->Flags & VC_CLOSING)
  55. {
  56. pRcaVc = NULL;
  57. }
  58. else
  59. {
  60. pRcaVc->RefCount++;
  61. }
  62. DPR_RELEASE_SPIN_LOCK(&pAdapter->SpinLock);
  63. break;
  64. }
  65. }
  66. RELEASE_SPIN_LOCK(&pProtocolContext->SpinLock);
  67. RCADEBUGP(RCA_LOUD, ("RCARefVcFromHashTable: Released global protocol context lock\n"));
  68. RCADEBUGP(RCA_INFO, ("RCARefVcFromHashTable: Exit - Returning VC %x\n", pRcaVc));
  69. return(pRcaVc);
  70. }
  71. NDIS_STATUS
  72. RCACoNdisGetVcContext(
  73. IN UNICODE_STRING VcHandle,
  74. IN PVOID ClientContext,
  75. IN BOOL bRefForReceive,
  76. OUT PVOID *VcContext
  77. )
  78. {
  79. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  80. PRCA_VC pRcaVc;
  81. RCADEBUGP(RCA_INFO, ("RCACoNdisGetVcContext: Enter\n"));
  82. do {
  83. //
  84. // Convert the unicode string to a pointer (this is
  85. // equivalent to turning it into an NDIS_HANDLE).
  86. //
  87. Status = NdisClGetProtocolVcContextFromTapiCallId(VcHandle, (PNDIS_HANDLE)&pRcaVc);
  88. if (Status != STATUS_SUCCESS) {
  89. RCADEBUGP(RCA_ERROR, ("RCACoNdisGetVcContext: "
  90. "Failed to get vc context from string, Status == 0x%x \n", Status));
  91. break;
  92. }
  93. //
  94. // Validate the VC by looking for it in our hash table. This increments the ref count on the VC.
  95. //
  96. pRcaVc = RCARefVcFromHashTable(pRcaVc);
  97. if (pRcaVc == NULL) {
  98. RCADEBUGP(RCA_ERROR, ("RCACoNdisGetVcContext: Could not find VC in hash table\n"));
  99. Status = STATUS_NOT_FOUND;
  100. break;
  101. }
  102. //
  103. // Store away the client context, and give back the VC structure address as the
  104. // VcContext to the client.
  105. //
  106. ACQUIRE_SPIN_LOCK(&pRcaVc->SpinLock);
  107. if (bRefForReceive)
  108. pRcaVc->ClientReceiveContext = ClientContext;
  109. else
  110. pRcaVc->ClientSendContext = ClientContext;
  111. RELEASE_SPIN_LOCK(&pRcaVc->SpinLock);
  112. *VcContext = pRcaVc;
  113. } while (FALSE);
  114. RCADEBUGP(RCA_INFO, ("RCACoNdisGetVcContext: Exit - Returning Status 0x%x\n", Status));
  115. return Status;
  116. }
  117. NDIS_STATUS
  118. RCACoNdisGetVcContextForReceive(
  119. IN UNICODE_STRING VcHandle,
  120. IN PVOID ClientReceiveContext,
  121. OUT PVOID *VcContext
  122. )
  123. /*++
  124. Routine Description:
  125. Retrieves VC context for a VC handle that will be used to receive packets.
  126. Arguments:
  127. VcHandle - The Unicode string representation of the VC Handle.
  128. ClientReceiveContext - Caller-supplied context to be passed to the receive handler
  129. when packets are received on this VC
  130. VcContext - Address of a pointer in which the Co-NDIS VC Context will be
  131. returned.
  132. Return value:
  133. NDIS_STATUS_SUCCESS in the case of success, STATUS_NOT_FOUND in the case of an invalid
  134. VC handle, or some other relevant error code otherwise.
  135. --*/
  136. {
  137. return RCACoNdisGetVcContext(VcHandle, ClientReceiveContext, TRUE, VcContext);
  138. }
  139. NDIS_STATUS
  140. RCACoNdisGetVcContextForSend(
  141. IN UNICODE_STRING VcHandle,
  142. IN PVOID ClientSendContext,
  143. OUT PVOID *VcContext
  144. )
  145. /*++
  146. Routine Description:
  147. Retrieves VC context for a VC handle that will be used to send packets.
  148. Arguments:
  149. VcHandle - The Unicode string representation of the VC Handle.
  150. ClientSendContext - Caller-supplied context to be passed to the send complete handler
  151. when packets sends are completed on this VC
  152. VcContext - Address of a pointer in which the Co-NDIS VC Context will be
  153. returned.
  154. Return value:
  155. NDIS_STATUS_SUCCESS in the case of success, STATUS_NOT_FOUND in the case of an invalid
  156. VC handle, or some other relevant error code otherwise.
  157. --*/
  158. {
  159. return RCACoNdisGetVcContext(VcHandle, ClientSendContext, FALSE, VcContext);
  160. }
  161. NDIS_STATUS
  162. RCACoNdisReleaseSendVcContext(
  163. IN PVOID VcContext
  164. )
  165. /*++
  166. Routine Description:
  167. This routine should be called when a client has finished using a VC Context
  168. returned by RCACoNdisGetVcContextForSend().
  169. Failure to do so will prevent the resources used by the VC from being freed.
  170. Arguments:
  171. VcContext - The VC Context (returned by RCACoNdisGetVcContextForSend()).
  172. Return value:
  173. NDIS_STATUS_SUCCESS
  174. --*/
  175. {
  176. PRCA_VC pRcaVc = (PRCA_VC) VcContext;
  177. RCADEBUGP(RCA_INFO, ("RCACoNdisReleaseSendVcContext: Enter\n"));
  178. ACQUIRE_SPIN_LOCK(&pRcaVc->SpinLock);
  179. pRcaVc->ClientSendContext = NULL;
  180. RELEASE_SPIN_LOCK(&pRcaVc->SpinLock);
  181. RCADereferenceVc(pRcaVc);
  182. RCADEBUGP(RCA_INFO, ("RCACoNdisReleaseSendVcContext: Exit, Returning NDIS_STATUS_SUCCESS\n"));
  183. return NDIS_STATUS_SUCCESS;
  184. }
  185. NDIS_STATUS
  186. RCACoNdisReleaseReceiveVcContext(
  187. IN PVOID VcContext
  188. )
  189. /*++
  190. Routine Description:
  191. This routine should be called when a client has finished using a VC Context
  192. returned by RCACoNdisGetVcContextForReceive().
  193. Failure to do so will prevent the resources used by the VC from being freed.
  194. Arguments:
  195. VcContext - The VC Context (returned by RCACoNdisGetVcContextForReceive()).
  196. Return value:
  197. NDIS_STATUS_SUCCESS
  198. --*/
  199. {
  200. PRCA_VC pRcaVc = (PRCA_VC) VcContext;
  201. RCADEBUGP(RCA_INFO, ("RCACoNdisReleaseReceiveVcContext: Enter\n"));
  202. ACQUIRE_SPIN_LOCK(&pRcaVc->SpinLock);
  203. pRcaVc->ClientReceiveContext = NULL;
  204. RELEASE_SPIN_LOCK(&pRcaVc->SpinLock);
  205. RCADereferenceVc(pRcaVc);
  206. RCADEBUGP(RCA_INFO, ("RCACoNdisReleaseReceiveVcContext: Exit, Returning NDIS_STATUS_SUCCESS\n"));
  207. return NDIS_STATUS_SUCCESS;
  208. }
  209. NDIS_STATUS
  210. RCACoNdisCloseCallOnVc(
  211. IN PVOID VcContext
  212. )
  213. /*++
  214. Routine Description:
  215. Closes the call (if any) that is active on a particular VC
  216. Arguments:
  217. VcContext - The VC Context (returned by RCACoNdisGetVcContextForXXXX()).
  218. Return value:
  219. NDIS_STATUS_SUCCESS for a successful close, NDIS_STATUS_PENDING for a close that is still
  220. proceeding, or a relevant error code otherwise.
  221. --*/
  222. {
  223. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  224. PRCA_VC pRcaVc = (PRCA_VC)VcContext;
  225. PRCA_ADAPTER pAdapter = pRcaVc->pAdapter;
  226. BOOL bNeedToClose = FALSE;
  227. RCADEBUGP(RCA_INFO, ("RCACoNdisCloseCallOnVc: Enter\n"));
  228. RCAInitBlockStruc(&pRcaVc->CloseBlock);
  229. ACQUIRE_SPIN_LOCK(&pAdapter->SpinLock);
  230. pRcaVc->Flags &= ~VC_ACTIVE;
  231. pRcaVc->Flags |= VC_CLOSING;
  232. if (!(pRcaVc->ClosingState & CLOSING_INCOMING_CLOSE)) {
  233. pRcaVc->ClosingState |= CLOSING_INCOMING_CLOSE;
  234. bNeedToClose = TRUE;
  235. }
  236. RELEASE_SPIN_LOCK(&pAdapter->SpinLock);
  237. if (bNeedToClose) {
  238. Status = NdisClCloseCall(pRcaVc->NdisVcHandle, NULL, NULL, 0);
  239. if (Status != NDIS_STATUS_PENDING) {
  240. RCADEBUGP(RCA_LOUD, ("RCACoNdisCloseCallOnVc: "
  241. "NdisClClose call returned status 0x%x, manually calling RCACloseCallComplete\n",
  242. Status));
  243. RCACloseCallComplete(Status, (NDIS_HANDLE)pRcaVc, NULL);
  244. } else {
  245. RCABlock(&pRcaVc->CloseBlock, &Status);
  246. }
  247. }
  248. RCADEBUGP(RCA_INFO, ("RCACoNdisCloseCallOnVc: Exit - Returning Status 0x%x\n", Status));
  249. return Status;
  250. }
  251. NDIS_STATUS
  252. RCACoNdisCloseCallOnVcNoWait(
  253. IN PVOID VcContext
  254. )
  255. /*++
  256. Routine Description:
  257. Closes the call (if any) that is active on a particular VC without waiting for the close
  258. call operation to complete.
  259. Arguments:
  260. VcContext - The VC Context (returned by RCACoNdisGetVcContextForXXXX()).
  261. Return value:
  262. NDIS_STATUS_SUCCESS for a successful close, NDIS_STATUS_PENDING for a close that is still
  263. proceeding, or a relevant error code otherwise.
  264. --*/
  265. {
  266. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  267. PRCA_VC pRcaVc = (PRCA_VC)VcContext;
  268. PRCA_ADAPTER pAdapter = pRcaVc->pAdapter;
  269. BOOL bNeedToClose = FALSE;
  270. RCADEBUGP(RCA_INFO, ("RCACoNdisCloseCallOnVc: Enter\n"));
  271. //
  272. // Though we aren't going to block, I have to init this here
  273. // because the completion routine will signal it whether we're
  274. // blocking or not.
  275. //
  276. RCAInitBlockStruc(&pRcaVc->CloseBlock);
  277. ACQUIRE_SPIN_LOCK(&pAdapter->SpinLock);
  278. pRcaVc->Flags &= ~VC_ACTIVE;
  279. pRcaVc->Flags |= VC_CLOSING;
  280. if (!(pRcaVc->ClosingState & CLOSING_INCOMING_CLOSE)) {
  281. pRcaVc->ClosingState |= CLOSING_INCOMING_CLOSE;
  282. bNeedToClose = TRUE;
  283. }
  284. RELEASE_SPIN_LOCK(&pAdapter->SpinLock);
  285. if (bNeedToClose) {
  286. Status = NdisClCloseCall(pRcaVc->NdisVcHandle, NULL, NULL, 0);
  287. if (Status != NDIS_STATUS_PENDING) {
  288. RCADEBUGP(RCA_LOUD, ("RCACoNdisCloseCallOnVc: "
  289. "NdisClClose call returned status 0x%x, manually calling RCACloseCallComplete\n",
  290. Status));
  291. RCACloseCallComplete(Status, (NDIS_HANDLE)pRcaVc, NULL);
  292. }
  293. }
  294. RCADEBUGP(RCA_INFO, ("RCACoNdisCloseCallOnVc: Exit - Returning Status 0x%x\n", Status));
  295. return Status;
  296. }
  297. NDIS_STATUS
  298. RCACoNdisSendFrame(
  299. IN PVOID VcContext,
  300. IN PMDL pMdl,
  301. IN PVOID PacketContext
  302. )
  303. /*++
  304. Routine Description:
  305. Sends a frame of data out on a VC.
  306. Arguments:
  307. VcContext - The VC Context (returned by RCACoNdisGetVcContextForXXXX()).
  308. pMdl - Pointer to the MDL containing the data to send
  309. PacketContext - Caller-supplied context for this packet that will be passed
  310. to the send complete handler when this packet has been sent.
  311. Return value:
  312. NDIS_STATUS_PENDING if the packet has been sent and is waiting to be completed,
  313. or an error code otherwise.
  314. --*/
  315. {
  316. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  317. PRCA_VC pRcaVc = (PRCA_VC)VcContext;
  318. PRCA_ADAPTER pAdapter;
  319. PNDIS_PACKET pPacket;
  320. RCADEBUGP(RCA_INFO, ("RCACoNdisSendFrame: Enter\n"));
  321. do {
  322. BOOL bVcIsClosing = FALSE;
  323. if (pRcaVc == NULL) {
  324. RCADEBUGP(RCA_ERROR,
  325. ("RCACoNdisSendFrame: VcContext was null, returing NDIS_STATUS_FAILURE\n"));
  326. Status = NDIS_STATUS_FAILURE;
  327. break;
  328. }
  329. pAdapter = pRcaVc->pAdapter;
  330. //
  331. // Check if the VC is closing. If it is, we
  332. // won't try to send a packet.
  333. //
  334. ACQUIRE_SPIN_LOCK(&pAdapter->SpinLock);
  335. if (pRcaVc->ClosingState & CLOSING_INCOMING_CLOSE) {
  336. bVcIsClosing = TRUE;
  337. }
  338. RELEASE_SPIN_LOCK(&pAdapter->SpinLock);
  339. if (bVcIsClosing) {
  340. RCADEBUGP(RCA_ERROR, ("RCACoNdisSendFrame: Can't send frame, VC is closing\n"));
  341. Status = STATUS_PORT_DISCONNECTED;
  342. break;
  343. }
  344. //
  345. // Allocate a packet from our sending pool.
  346. //
  347. #if PACKET_POOL_OPTIMIZATION
  348. // SendPPOpt - Start
  349. NdisAcquireSpinLock(&g_SendPPOptLock);
  350. g_alSendPPOptBuckets[g_lSendPPOptOutstanding]++;
  351. g_lSendPPOptOutstanding++;
  352. NdisReleaseSpinLock(&g_SendPPOptLock);
  353. // SendPPOpt - End
  354. #endif
  355. NdisAllocatePacket(&Status, &pPacket, pAdapter->SendPacketPool);
  356. if (Status != NDIS_STATUS_SUCCESS) {
  357. RCADEBUGP(RCA_ERROR, ("RCACoNdisSendFrame: "
  358. "Failed to allocate packet, Status == 0x%x\n", Status));
  359. break;
  360. }
  361. //
  362. // Initialize the packet and put the buffer into it.
  363. //
  364. NdisReinitializePacket(pPacket);
  365. NdisChainBufferAtFront(pPacket, (PNDIS_BUFFER)pMdl);
  366. //
  367. // Put the packet context in the protocol reserved field.
  368. //
  369. PKT_RSVD_FROM_PKT(pPacket)->PacketContext = PacketContext;
  370. //
  371. // Send it on it's way!
  372. //
  373. InterlockedIncrement(&pRcaVc->PendingSends);
  374. NdisCoSendPackets(pRcaVc->NdisVcHandle, &pPacket, 1);
  375. Status = NDIS_STATUS_PENDING;
  376. } while (FALSE);
  377. RCADEBUGP(RCA_INFO, ("RCACoNdisSendFrame: Exit - Returning Status == 0x%x\n", Status));
  378. return Status;
  379. }
  380. NDIS_STATUS
  381. RCACoNdisGetMdlFromPacket(
  382. IN PNDIS_PACKET pPacket,
  383. OUT PMDL *ppMdl
  384. )
  385. /*++
  386. Routine Description:
  387. Utility function that retrieves the data MDL from an NDIS packet.
  388. Arguments:
  389. pPacket - Pointer to an NDIS packet
  390. ppMdl - Address of an MDL pointer in which the address of the MDL will be returned.
  391. Return value:
  392. NDIS_STATUS_SUCCESS
  393. --*/
  394. {
  395. RCADEBUGP(RCA_INFO, ("RCACoNdisGetMdlFromPacket: Enter\n"));
  396. *ppMdl = (PMDL) pPacket->Private.Head;
  397. RCADEBUGP(RCA_INFO, ("RCACoNdisGetMdlFromPacket: Exit - Returning NDIS_STATUS_SUCCESS\n"));
  398. return NDIS_STATUS_SUCCESS;
  399. }
  400. VOID
  401. RCACoNdisReturnPacket(
  402. IN PNDIS_PACKET pPacket
  403. )
  404. /*++
  405. Routine Description:
  406. This routine should be called to return a packet to NDIS. Failure
  407. to call this routine when finished with a packet will cause a resource
  408. leak that will result in packets being dropped on the network.
  409. Arguments:
  410. pPacket - Pointer to the NDIS packet to return
  411. Return value:
  412. (None)
  413. --*/
  414. {
  415. RCADEBUGP(RCA_INFO, ("RCACoNdisReturnPacket: Enter\n"));
  416. if (WORK_ITEM_FROM_PKT(pPacket)->bFreeThisPacket) {
  417. //
  418. // This is our packet - free it.
  419. //
  420. RCADEBUGP(RCA_LOUD, ("RCACoNdisReturnPacket: Freeing locally allocated packet\n"));
  421. #if PACKET_POOL_OPTIMIZATION
  422. // RecvPPOpt - Start
  423. NdisAcquireSpinLock(&g_RecvPPOptLock);
  424. g_lRecvPPOptOutstanding--;
  425. NdisReleaseSpinLock(&g_RecvPPOptLock);
  426. // RecvPPOpt - End
  427. #endif
  428. RCAFreeCopyPacket(pPacket);
  429. } else {
  430. //
  431. // This is the miniport's packet - return it.
  432. //
  433. RCADEBUGP(RCA_LOUD, ("RCACoNdisReturnPacket: Returning packet to the miniport\n"));
  434. NdisReturnPackets(&pPacket, 1);
  435. }
  436. RCADEBUGP(RCA_INFO, ("RCACoNdisReturnPacket: Exit\n"));
  437. }
  438. NDIS_STATUS
  439. RCACoNdisGetMaxSduSizes(
  440. IN PVOID VcContext,
  441. OUT ULONG *RxMaxSduSize,
  442. OUT ULONG *TxMaxSduSize
  443. )
  444. /*++
  445. Routine Description:
  446. Utility function that retrieves the largest SDU sizes that a VC
  447. can support.
  448. Arguments:
  449. VcContext - The VC Context (returned by RCACoNdisGetVcContextForXXXX()).
  450. RxMaxSduSize - Pointer to ULONG variable in which to place the max receive
  451. SDU size.
  452. TxMaxSduSize - Pointer to ULONG variable in which to place the max transmit
  453. SDU size.
  454. Return value:
  455. (None)
  456. --*/
  457. {
  458. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  459. RCADEBUGP(RCA_INFO, ("RCACoNdisGetMaxSduSizes: Enter\n"));
  460. do {
  461. PRCA_VC pRcaVc = (PRCA_VC)VcContext;
  462. if (RxMaxSduSize) {
  463. *RxMaxSduSize = pRcaVc->CallParameters.CallMgrParameters->Receive.MaxSduSize;
  464. }
  465. if (TxMaxSduSize) {
  466. *TxMaxSduSize = pRcaVc->CallParameters.CallMgrParameters->Transmit.MaxSduSize;
  467. }
  468. } while (FALSE);
  469. RCADEBUGP(RCA_INFO, ("RCACoNdisGetMaxSduSizes: Exit - Returning Status 0x%x\n", Status));
  470. return Status;
  471. }