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.

262 lines
6.7 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. spxsend.c
  5. Abstract:
  6. This module contains code that implements the send engine for the
  7. SPX transport provider.
  8. Author:
  9. Nikhil Kamkolkar (nikhilk) 11-November-1993
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. // Define module number for event logging entries
  17. #define FILENUM SPXSEND
  18. VOID
  19. SpxSendComplete(
  20. IN PNDIS_PACKET pNdisPkt,
  21. IN NDIS_STATUS NdisStatus
  22. )
  23. /*++
  24. Routine Description:
  25. This routine is called by the I/O system to indicate that a connection-
  26. oriented packet has been shipped and is no longer needed by the Physical
  27. Provider.
  28. Arguments:
  29. ProtocolBindingContext - The ADAPTER structure for this binding.
  30. NdisPacket/RequestHandle - A pointer to the NDIS_PACKET that we sent.
  31. NdisStatus - the completion status of the send.
  32. Return Value:
  33. none.
  34. --*/
  35. {
  36. PSPX_CONN_FILE pSpxConnFile;
  37. PSPX_SEND_RESD pSendResd;
  38. PNDIS_BUFFER pNdisBuffer;
  39. CTELockHandle lockHandle;
  40. UINT bufCount;
  41. PREQUEST pRequest = NULL;
  42. BOOLEAN completeReq = FALSE, freePkt = FALSE,
  43. orphaned = FALSE, lockHeld = FALSE;
  44. pSendResd = (PSPX_SEND_RESD)(pNdisPkt->ProtocolReserved);
  45. #if DBG
  46. if (NdisStatus != NDIS_STATUS_SUCCESS)
  47. {
  48. DBGPRINT(SEND, DBG,
  49. ("SpxSendComplete: For %lx with status **%lx**\n",
  50. pNdisPkt, NdisStatus));
  51. }
  52. #endif
  53. // IPX changes the length set for the first ndis buffer descriptor.
  54. // Change it back to its original value here.
  55. NdisQueryPacket(pNdisPkt, NULL, &bufCount, &pNdisBuffer, NULL);
  56. NdisAdjustBufferLength(pNdisBuffer, IpxMacHdrNeeded + MIN_IPXSPX2_HDRSIZE);
  57. do
  58. {
  59. pSpxConnFile = pSendResd->sr_ConnFile;
  60. CTEGetLock(&pSpxConnFile->scf_Lock, &lockHandle);
  61. lockHeld = TRUE;
  62. #if defined(__PNP)
  63. //
  64. // if IPX gave us a new LocalTarget, use for our next send.
  65. //
  66. // But if we are sending connect requests by iterating over NicIds,
  67. // dont update the local target bcoz that will mess up our iteration
  68. // logic.
  69. //
  70. if ( DEVICE_NETWORK_PATH_NOT_FOUND == NdisStatus
  71. &&
  72. !(
  73. SPX_CONN_CONNECTING(pSpxConnFile) &&
  74. (SPX_CONNECT_STATE(pSpxConnFile) == SPX_CONNECT_SENTREQ) &&
  75. (*((UNALIGNED ULONG *)(pSpxConnFile->scf_RemAddr)) == 0)
  76. ) ) {
  77. pSpxConnFile->scf_LocalTarget = pSendResd->LocalTarget;
  78. //
  79. // Renegotiate the max packet size if we have an active SPX2
  80. // session going on and we negotiated the max size originally.
  81. //
  82. if ( SPX_MAIN_STATE(pSpxConnFile) == SPX_CONNFILE_ACTIVE &&
  83. SPX_CONN_FLAG(pSpxConnFile, SPX_CONNFILE_SPX2) &&
  84. SPX_CONN_FLAG(pSpxConnFile, SPX_CONNFILE_NEG) ) {
  85. //
  86. // this call will get the local max size on this new local target
  87. // from IPX.
  88. //
  89. SPX_MAX_PKT_SIZE(pSpxConnFile, TRUE, TRUE, *((UNALIGNED ULONG *)pSpxConnFile->scf_RemAddr );
  90. SPX_SEND_SETSTATE(pSpxConnFile, SPX_SEND_RENEG);
  91. DBGPRINT(SEND, DBG3,
  92. ("SpxConnProcessAck: %lx CONNECTION ENTERING RENEG\n",
  93. pSpxConnFile));
  94. }
  95. }
  96. #endif __PNP
  97. CTEAssert((pSendResd->sr_State & SPX_SENDPKT_IPXOWNS) != 0);
  98. // IPX dont own this packet nomore.
  99. pSendResd->sr_State &= ~SPX_SENDPKT_IPXOWNS;
  100. // If a send packet has been aborted, then we need to call
  101. // abort send to go ahead and free up this packet, and deref associated
  102. // request, if there is one, potentially completing it.
  103. if ((pSendResd->sr_State & SPX_SENDPKT_ABORT) != 0)
  104. {
  105. spxConnAbortSendPkt(
  106. pSpxConnFile,
  107. pSendResd,
  108. SPX_CALL_TDILEVEL,
  109. lockHandle);
  110. lockHeld = FALSE;
  111. break;
  112. }
  113. // If there is an associated request, remove reference on it. BUT for a
  114. // sequenced packet only if it has been acked and is waiting for the request
  115. // to be dereferenced. It is already dequeued from queue, just free it up.
  116. if ((((pSendResd->sr_State & SPX_SENDPKT_REQ) != 0) &&
  117. ((pSendResd->sr_State & SPX_SENDPKT_SEQ) == 0)) ||
  118. ((pSendResd->sr_State & SPX_SENDPKT_ACKEDPKT) != 0))
  119. {
  120. freePkt = (BOOLEAN)((pSendResd->sr_State & SPX_SENDPKT_ACKEDPKT) != 0);
  121. pRequest = pSendResd->sr_Request;
  122. CTEAssert(pRequest != NULL);
  123. DBGPRINT(SEND, DBG,
  124. ("IpxSendComplete: ReqRef before dec %lx.%lx\n",
  125. pRequest, REQUEST_INFORMATION(pRequest)));
  126. // Deref the request and see if we complete it now. We always have our
  127. // own reference on the request.
  128. // !!! Status should already have been set in request...!!!
  129. if (--(REQUEST_INFORMATION(pRequest)) == 0)
  130. {
  131. CTEAssert(REQUEST_STATUS(pRequest) != STATUS_PENDING);
  132. completeReq = TRUE;
  133. // If this is acked already, request is not on list.
  134. // BUG #11626
  135. if ((pSendResd->sr_State & SPX_SENDPKT_ACKEDPKT) == 0)
  136. {
  137. RemoveEntryList(REQUEST_LINKAGE(pRequest));
  138. }
  139. }
  140. }
  141. // Do we destroy this packet?
  142. if ((pSendResd->sr_State & SPX_SENDPKT_DESTROY) != 0)
  143. {
  144. // Remove this packet from the send list in the connection.
  145. DBGPRINT(SEND, INFO,
  146. ("IpxSendComplete: destroy packet...\n"));
  147. SpxConnDequeueSendPktLock(pSpxConnFile, pNdisPkt);
  148. freePkt = TRUE;
  149. }
  150. } while (FALSE);
  151. if (lockHeld)
  152. {
  153. CTEFreeLock(&pSpxConnFile->scf_Lock, lockHandle);
  154. }
  155. if (freePkt)
  156. {
  157. DBGPRINT(SEND, INFO,
  158. ("IpxSendComplete: free packet...\n"));
  159. SpxPktSendRelease(pNdisPkt);
  160. }
  161. if (completeReq)
  162. {
  163. // If this is a send request, set info to data sent, else it will be
  164. // zero.
  165. if (REQUEST_MINOR_FUNCTION(pRequest) == TDI_SEND)
  166. {
  167. PTDI_REQUEST_KERNEL_SEND pParam;
  168. pParam = (PTDI_REQUEST_KERNEL_SEND)
  169. REQUEST_PARAMETERS(pRequest);
  170. REQUEST_INFORMATION(pRequest) = pParam->SendLength;
  171. DBGPRINT(SEND, DBG,
  172. ("IpxSendComplete: complete req %lx.%lx...\n",
  173. REQUEST_STATUS(pRequest),
  174. REQUEST_INFORMATION(pRequest)));
  175. CTEAssert(pRequest != NULL);
  176. CTEAssert(REQUEST_STATUS(pRequest) != STATUS_PENDING);
  177. SpxCompleteRequest(pRequest);
  178. }
  179. else
  180. {
  181. DBGPRINT(SEND, DBG,
  182. ("SpxSendComplete: %lx DISC Request %lx with %lx.%lx\n",
  183. pSpxConnFile, pRequest, REQUEST_STATUS(pRequest),
  184. REQUEST_INFORMATION(pRequest)));
  185. DBGPRINT(SEND, DBG,
  186. ("SpxSendComplete: %lx.%lx.%lx\n",
  187. pSpxConnFile->scf_RefCount,
  188. pSpxConnFile->scf_Flags,
  189. pSpxConnFile->scf_Flags2));
  190. // Set the request in the connection, and deref for it.
  191. InsertTailList(
  192. &pSpxConnFile->scf_DiscLinkage,
  193. REQUEST_LINKAGE(pRequest));
  194. }
  195. SpxConnFileDereference(pSpxConnFile, CFREF_VERIFY);
  196. }
  197. return;
  198. } // SpxSendComplete
  199.