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.

390 lines
7.7 KiB

  1. /*++
  2. Copyright (c) 1990-1998 Microsoft Corporation, All Rights Reserved.
  3. Module Name:
  4. sendrecv.c
  5. Abstract:
  6. This module contains the send and receive related routine for the driver.
  7. Author:
  8. Anil Francis Thomas (10/98)
  9. Environment:
  10. Kernel
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #define MODULE_ID MODULE_SEND
  16. VOID
  17. AtmSmSendPacketOnVc(
  18. IN PATMSM_VC pVc,
  19. IN PNDIS_PACKET pPacket
  20. )
  21. /*++
  22. Routine Description:
  23. Attempt to send a packet on a VC, if the VC is connecting, then
  24. queue the packet on it.
  25. Arguments:
  26. pVc - Pointer to the VC
  27. pPacket - Packet to be sent
  28. Return Value:
  29. None
  30. --*/
  31. {
  32. PATMSM_ADAPTER pAdapt = pVc->pAdapt;
  33. DbgInfo(("AtmSmSendPacketOnVc: Packet %x, pVc %lx\n",
  34. pPacket, pVc));
  35. // if we can add a reference to the VC and if its state is active
  36. // then we can send a packet on it
  37. if(!AtmSmReferenceVc(pVc)){
  38. NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_CLOSING);
  39. AtmSmCoSendComplete(NDIS_STATUS_CLOSING, (NDIS_HANDLE)pVc, pPacket);
  40. return;
  41. }
  42. if(ATMSM_GET_VC_STATE(pVc) == ATMSM_VC_ACTIVE){
  43. // we can send on the Vc
  44. NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_SUCCESS);
  45. NdisCoSendPackets(pVc->NdisVcHandle, &pPacket, 1);
  46. } else {
  47. // we will queue the packet on the Vc
  48. PPROTO_RSVD pPRsvd;
  49. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  50. pPRsvd = GET_PROTO_RSVD(pPacket);
  51. pPRsvd->pPktNext = NULL;
  52. if(pVc->pSendLastPkt){
  53. pPRsvd = GET_PROTO_RSVD(pVc->pSendLastPkt);
  54. pPRsvd->pPktNext = pPacket;
  55. } else
  56. pVc->pSendPktNext = pPacket;
  57. pVc->pSendLastPkt = pPacket;
  58. pVc->ulSendPktsCount++;
  59. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  60. }
  61. // remove the reference we added above
  62. AtmSmDereferenceVc(pVc);
  63. return;
  64. }
  65. VOID
  66. AtmSmSendQueuedPacketsOnVc(
  67. IN PATMSM_VC pVc
  68. )
  69. /*++
  70. Routine Description:
  71. When a P-P VC is connected or when a PMP VC has added all parties,
  72. this routine will start sending any queued packets on ths VC.
  73. Note: In this example we won't have any packets to send, since the
  74. app start sending only once the VC is connected.
  75. Arguments:
  76. pVc - pointer to the VC
  77. Return Value:
  78. None
  79. --*/
  80. {
  81. PATMSM_ADAPTER pAdapt = pVc->pAdapt;
  82. PPROTO_RSVD pPRsvd;
  83. PNDIS_PACKET pPacket;
  84. TraceIn(AtmSmSendQueuedPacketsOnVc);
  85. ASSERT(ATMSM_GET_VC_STATE(pVc) == ATMSM_VC_ACTIVE);
  86. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  87. while(pVc->pSendPktNext){
  88. pPacket = pVc->pSendPktNext;
  89. pPRsvd = GET_PROTO_RSVD(pPacket);
  90. pVc->pSendPktNext = pPRsvd->pPktNext;
  91. // this is the last packet
  92. if(pVc->pSendLastPkt == pPacket)
  93. pVc->pSendLastPkt = NULL;
  94. pVc->ulSendPktsCount--;
  95. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  96. // we can send the packet now
  97. NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_SUCCESS);
  98. NdisCoSendPackets(pVc->NdisVcHandle, &pPacket, 1);
  99. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  100. }
  101. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  102. TraceOut(AtmSmSendQueuedPacketsOnVc);
  103. return;
  104. }
  105. VOID
  106. AtmSmCoSendComplete(
  107. IN NDIS_STATUS Status,
  108. IN NDIS_HANDLE ProtocolVcContext,
  109. IN PNDIS_PACKET pPacket
  110. )
  111. /*++
  112. Routine Description:
  113. Completion routine for the previously pended send.
  114. Arguments:
  115. Status Status of Completion
  116. ProtocolVcContext Pointer to the Vc
  117. Packet The packet in question
  118. Return Value:
  119. --*/
  120. {
  121. PATMSM_VC pVc = (PATMSM_VC)ProtocolVcContext;
  122. PPROTO_RSVD pPRsvd;
  123. PIRP pIrp;
  124. pPRsvd = GET_PROTO_RSVD(pPacket);
  125. DbgInfo(("AtmSmCoSendComplete: Packet 0x%x, pVc 0x%lx Status - 0x%x\n",
  126. pPacket, pVc, Status));
  127. if (Status != NDIS_STATUS_SUCCESS){
  128. DbgErr(("AtmSmSCoSendComplete: Failed for Vc = %lx, status = %lx\n",
  129. pVc,Status));
  130. }
  131. pIrp = pPRsvd->pSendIrp;
  132. #ifdef BUG_IN_NEW_DMA
  133. {
  134. PNDIS_BUFFER pBuffer;
  135. NdisQueryPacket(pPacket,
  136. NULL,
  137. NULL,
  138. &pBuffer,
  139. NULL);
  140. NdisFreeBuffer(pBuffer);
  141. }
  142. #else // BUG_IN_NEW_DMA
  143. NdisFreePacket(pPacket);
  144. #endif // BUG_IN_NEW_DMA
  145. ASSERT(pIrp);
  146. if(pIrp){
  147. pIrp->IoStatus.Status = Status;
  148. // the number of bytes we sent
  149. if(NDIS_STATUS_SUCCESS == Status){
  150. pIrp->IoStatus.Information = MmGetMdlByteCount(pIrp->MdlAddress);
  151. } else {
  152. pIrp->IoStatus.Information = 0;
  153. }
  154. IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
  155. }
  156. return;
  157. }
  158. #undef MODULE_ID
  159. #define MODULE_ID MODULE_RECV
  160. UINT
  161. AtmSmCoReceivePacket(
  162. IN NDIS_HANDLE ProtocolBindingContext,
  163. IN NDIS_HANDLE ProtocolVcContext,
  164. IN PNDIS_PACKET pPacket
  165. )
  166. /*++
  167. Routine Description:
  168. When we recv a packet, see if we have anyone interested in received
  169. packets if so copy the info and return. Else see if miniport is ok
  170. with us holding the packet. In that case we will queue the packet
  171. otherwise return.
  172. Arguments:
  173. Status Status of Completion
  174. ProtocolVcContext Pointer to the Vc
  175. Packet The packet in question
  176. Return Value:
  177. --*/
  178. {
  179. PATMSM_ADAPTER pAdapt = (PATMSM_ADAPTER)ProtocolBindingContext;
  180. PATMSM_VC pVc = (PATMSM_VC)ProtocolVcContext;
  181. UINT uiRetVal = 0;
  182. BOOLEAN bLockReleased = FALSE;
  183. DbgInfo(("AtmSmCoReceivePacket - pVc - 0x%x, pPkt - 0x%x\n",
  184. pVc, pPacket));
  185. ASSERT(pAdapt == pVc->pAdapt);
  186. ACQUIRE_ADAPTER_GEN_LOCK(pAdapt);
  187. do { // break off loop
  188. if(ADAPT_SHUTTING_DOWN == pAdapt->ulFlags)
  189. break;
  190. // no one interested in receivg packet
  191. if(!pAdapt->fAdapterOpenedForRecv)
  192. break;
  193. if(pAdapt->pRecvIrp){
  194. PIRP pIrp = pAdapt->pRecvIrp;
  195. pAdapt->pRecvIrp = NULL;
  196. // release the lock
  197. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  198. bLockReleased = TRUE;
  199. // Copy the packet to the Irp buffer
  200. // Note this may be partial if the Irp buffer is not large enough
  201. pIrp->IoStatus.Information =
  202. CopyPacketToIrp(pIrp, pPacket);
  203. pIrp->IoStatus.Status = STATUS_SUCCESS;
  204. IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
  205. break;
  206. }
  207. // no pending irps to fill in.
  208. // so check if we can queue this packet
  209. if(NDIS_STATUS_RESOURCES == NDIS_GET_PACKET_STATUS(pPacket))
  210. break;
  211. // we can queue this packet
  212. {
  213. PPROTO_RSVD pPRsvd;
  214. pPRsvd = GET_PROTO_RSVD(pPacket);
  215. NdisGetSystemUpTime(&pPRsvd->ulTime);
  216. pPRsvd->pPktNext = NULL;
  217. if(pAdapt->pRecvLastPkt){
  218. pPRsvd = GET_PROTO_RSVD(pAdapt->pRecvLastPkt);
  219. pPRsvd->pPktNext = pPacket;
  220. } else
  221. pAdapt->pRecvPktNext = pPacket;
  222. pAdapt->pRecvLastPkt = pPacket;
  223. pAdapt->ulRecvPktsCount++;
  224. uiRetVal = 1;
  225. if(!pAdapt->fRecvTimerQueued){
  226. SET_ADAPTER_RECV_TIMER(pAdapt, RECV_BUFFERING_TIME);
  227. }
  228. break;
  229. }
  230. } while(FALSE);
  231. if(!bLockReleased){
  232. RELEASE_ADAPTER_GEN_LOCK(pAdapt);
  233. }
  234. return uiRetVal;
  235. }