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.

247 lines
9.5 KiB

  1. /*
  2. (C) Copyright 1998
  3. All rights reserved.
  4. Portions of this software are:
  5. (C) Copyright 1995, 1999 TriplePoint, Inc. -- http://www.TriplePoint.com
  6. License to use this software is granted under the terms outlined in
  7. the TriplePoint Software Services Agreement.
  8. (C) Copyright 1992 Microsoft Corp. -- http://www.Microsoft.com
  9. License to use this software is granted under the terms outlined in
  10. the Microsoft Windows Device Driver Development Kit.
  11. @doc INTERNAL Receive Receive_c
  12. @module Receive.c |
  13. This module implements the Miniport packet receive routines. Basically,
  14. the asynchronous receive processing routine. This module is very
  15. dependent on the hardware/firmware interface and should be looked at
  16. whenever changes to these interfaces occur.
  17. @head3 Contents |
  18. @index class,mfunc,func,msg,mdata,struct,enum | Receive_c
  19. @end
  20. */
  21. /* @doc EXTERNAL INTERNAL
  22. @topic 3.4 Receiving Packets General |
  23. A WAN miniport calls NdisMWanIndicateReceive to indicate that a
  24. packet has arrived and that the entire packet (there is no lookahead)
  25. is available for inspection. When this call is made, NDISWAN indicates
  26. the arrival of the packet to the ProtocolReceive handlers of bound
  27. higher-level drivers.
  28. <f Note>: Since the entire packet is always passed up, the miniport driver will
  29. never receive a transfer-data call (the data is copied by NDISWAN and
  30. then passed up to the next higher driver). The entire packet is always
  31. passed up due to compression and encryption that might have been applied
  32. to the packet. Also, because the link is point-to-point, at least one
  33. bound protocol will always want to look at the packet.
  34. The data contained in the header is the same as that received on the
  35. NIC. The NIC driver will not remove any headers or trailers from the
  36. data it receives. The transmitting driver cannot add padding to the
  37. packet.
  38. A WAN miniport calls NdisMWanIndicateReceiveComplete to indicate the
  39. end of one or more receive indications so that protocols can postprocess
  40. received packets. As a result, NDISWAN calls the ProtocolReceiveComplete
  41. handler(s) of bound protocols to notifying each protocol that it can
  42. now process the received data. In its receive-complete handler, a
  43. protocol need not operate under the severe time constraints that it
  44. does in its receive handler.
  45. The protocol should assume that interrupts are enabled during the
  46. call to ProtocolReceiveComplete. In an SMP machine, the receive
  47. handler and the receive complete handler can be running concurrently
  48. on different processors.
  49. Note that a WAN driver need not deliver NdisMWanIndicateReceiveComplete
  50. indications in one-to-one correspondence with NdisMWanIndicateReceive
  51. indications. It can issue a single receive-complete indication
  52. after several receive indications have occurred. For example, a
  53. WAN miniport could call NdisMWanIndicateReceiveComplete from its
  54. receive handler every ten packets or before exiting the handler,
  55. whichever occurs first.
  56. @topic 3.5 Receiving Packets Specific |
  57. Packets are recevied asynchronously by the Miniport from the driver's
  58. BChannel services as a stream of raw HDLC frames. See the Sending
  59. Packets section for details on the frame format.
  60. When a call is connected, the Miniport pre-loads the driver receive queue
  61. with the number of buffers defined by the registry parameter
  62. <p ReceiveBuffersPerLink>.
  63. When the driver has read an HDLC frame from the associated BChannel, it calls
  64. the Miniport routine <f BChannelEventHandler> with <t BREASON_RECEIVE_DONE>.
  65. The Miniport then calls <f CardNotifyReceive> which de-queues the buffer
  66. from the link's <p ReceivePendingList> and places it on the adapter's
  67. <p ReceiveCompleteList>. <f CardNotifyReceive> then schedules the routine
  68. <f MiniportTimer> to be called as soon as it is safe to process the
  69. event (i.e. the Miniport can be re-entered).
  70. When <f MiniportTimer> runs, it calls <f ReceivePacketHandler> to
  71. process ALL the packets on the <p ReceiveCompleteList>. Each packet is
  72. dequeued and passed up to <f NdisMWanIndicateReceive>. After the packet
  73. is copied by the WAN wrapper, the buffer is then reset and posted back to
  74. the driver so it can be used to receive another frame.
  75. After all packets have been processed by the <f ReceivePacketHandler>,
  76. before leaving <f MiniportTimer>, <f NdisMWanIndicateReceiveComplete>
  77. is called so the WAN wrapper can do its post-processing.
  78. @end
  79. */
  80. #define __FILEID__ RECEIVE_OBJECT_TYPE
  81. // Unique file ID for error logging
  82. #include "Miniport.h" // Defines all the miniport objects
  83. #if defined(NDIS_LCODE)
  84. # pragma NDIS_LCODE // Windows 95 wants this code locked down!
  85. # pragma NDIS_LDATA
  86. #endif
  87. /* @doc INTERNAL Receive Receive_c ReceivePacketHandler
  88. @func
  89. <f ReceivePacketHandler> is called from <f MiniportTimer> to handle
  90. a packet receive event. We enter here with interrupts enabled on
  91. the adapter and the processor, but the NDIS Wrapper holds a spin lock
  92. since we are executing on an NDIS timer thread.
  93. @comm
  94. We loop in here until all the available incoming packets have been passed
  95. up to the protocol stack. As we find each good packet, it is passed up
  96. to the protocol stack using <f NdisMWanIndicateReceive>. When NDIS
  97. returns control from this call, we resubmit the packet to the adapter
  98. so it can be used to receive another incoming packet. The link flag
  99. <p NeedReceiveCompleteIndication> is set TRUE if any packets are received
  100. on a particular link. This is used later, before returning from the
  101. async event handler, to notify NDIS of any ReceiveCompleteIndications.
  102. */
  103. void ReceivePacketHandler(
  104. IN PBCHANNEL_OBJECT pBChannel, // @parm
  105. // A Pointer to one of our <t BCHANNEL_OBJECT>'s.
  106. IN PUCHAR ReceiveBuffer, // @parm
  107. // Pointer to first byte received.
  108. IN ULONG BytesReceived // @parm
  109. // Number of bytes received.
  110. )
  111. {
  112. DBG_FUNC("ReceivePacketHandler")
  113. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  114. PMINIPORT_ADAPTER_OBJECT pAdapter;
  115. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  116. ASSERT(pBChannel && pBChannel->ObjectType == BCHANNEL_OBJECT_TYPE);
  117. pAdapter = GET_ADAPTER_FROM_BCHANNEL(pBChannel);
  118. DBG_ENTER(pAdapter);
  119. /*
  120. // I find it useful to do this nest check, just so I can make sure
  121. // I handle it correctly when it happens.
  122. */
  123. if (++(pAdapter->NestedDataHandler) > 1)
  124. {
  125. DBG_ERROR(pAdapter,("NestedDataHandler=%d > 1\n",
  126. pAdapter->NestedDataHandler));
  127. }
  128. /*
  129. // Is there someone up there who cares?
  130. */
  131. if (pBChannel->NdisLinkContext == NULL)
  132. {
  133. DBG_WARNING(pAdapter, ("Packet recvd on disconnected line #%d\n",pBChannel->BChannelIndex));
  134. }
  135. #ifdef NDISWAN_BUG // NDISWAN is sometimes setting this to zero - ignore it!
  136. /*
  137. // Return if we were told to expect nothing.
  138. */
  139. else if (pBChannel->WanLinkInfo.MaxRecvFrameSize == 0)
  140. {
  141. DBG_WARNING(pAdapter,("Packet size=%d > %d\n",
  142. BytesReceived, pBChannel->WanLinkInfo.MaxRecvFrameSize));
  143. }
  144. #endif // NDISWAN_BUG
  145. else
  146. {
  147. pAdapter->TotalRxBytes += BytesReceived;
  148. pAdapter->TotalRxPackets++;
  149. /*
  150. // We have to accept the frame if possible, I just want to know
  151. // if somebody has lied to us...
  152. */
  153. if (BytesReceived > pBChannel->WanLinkInfo.MaxRecvFrameSize)
  154. {
  155. DBG_NOTICE(pAdapter,("Packet size=%d > %d\n",
  156. BytesReceived, pBChannel->WanLinkInfo.MaxRecvFrameSize));
  157. }
  158. DBG_RX(pAdapter, pBChannel->BChannelIndex,
  159. BytesReceived, ReceiveBuffer);
  160. /*
  161. // Indiciate the packet up to the protocol stack.
  162. */
  163. NdisMWanIndicateReceive(
  164. &Status,
  165. pAdapter->MiniportAdapterHandle,
  166. pBChannel->NdisLinkContext,
  167. ReceiveBuffer,
  168. BytesReceived
  169. );
  170. if (Status == NDIS_STATUS_SUCCESS)
  171. {
  172. pBChannel->NeedReceiveCompleteIndication = TRUE;
  173. }
  174. else
  175. {
  176. DBG_WARNING(pAdapter,("NdisMWanIndicateReceive returned error 0x%X\n",
  177. Status));
  178. }
  179. }
  180. /*
  181. // I find it useful to do this nest check, just so I can make sure
  182. // I handle it correctly when it happens.
  183. */
  184. if (--(pAdapter->NestedDataHandler) < 0)
  185. {
  186. DBG_ERROR(pAdapter,("NestedDataHandler=%d < 0\n",
  187. pAdapter->NestedDataHandler));
  188. }
  189. DBG_LEAVE(pAdapter);
  190. }