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.

327 lines
6.5 KiB

  1. #include "irsir.h"
  2. #pragma alloc_text(PAGE,InitializePacketQueue)
  3. VOID
  4. InitializePacketQueue(
  5. PPACKET_QUEUE PacketQueue,
  6. PVOID Context,
  7. PACKET_STARTER StarterRoutine
  8. )
  9. {
  10. NdisZeroMemory(PacketQueue,sizeof(*PacketQueue));
  11. NdisAllocateSpinLock(&PacketQueue->Lock);
  12. PacketQueue->Context=Context;
  13. PacketQueue->Starter=StarterRoutine;
  14. PacketQueue->Active=TRUE;
  15. KeInitializeEvent(&PacketQueue->InactiveEvent,NotificationEvent,FALSE);
  16. return;
  17. }
  18. VOID
  19. QueuePacket(
  20. PPACKET_QUEUE PacketQueue,
  21. PNDIS_PACKET Packet
  22. )
  23. {
  24. NDIS_STATUS Status;
  25. PPACKET_RESERVED_BLOCK Reserved=(PPACKET_RESERVED_BLOCK)&Packet->MiniportReservedEx[0];
  26. NdisAcquireSpinLock(&PacketQueue->Lock);
  27. if ((PacketQueue->CurrentPacket == NULL) && PacketQueue->Active && (PacketQueue->HeadOfList == NULL)) {
  28. //
  29. // not currently handling a packet and the queu is active and there are not other packets
  30. // queued, so handle it now
  31. //
  32. PacketQueue->CurrentPacket=Packet;
  33. NdisReleaseSpinLock(&PacketQueue->Lock);
  34. (*PacketQueue->Starter)(
  35. PacketQueue->Context,
  36. Packet
  37. );
  38. return;
  39. }
  40. //
  41. // need to queue the packet
  42. //
  43. Reserved->Next=NULL;
  44. if (PacketQueue->HeadOfList == NULL) {
  45. //
  46. // the list is empty
  47. //
  48. PacketQueue->HeadOfList=Packet;
  49. } else {
  50. Reserved=(PPACKET_RESERVED_BLOCK)&PacketQueue->TailOfList->MiniportReservedEx[0];
  51. Reserved->Next=Packet;
  52. }
  53. PacketQueue->TailOfList=Packet;
  54. NdisReleaseSpinLock(&PacketQueue->Lock);
  55. return;
  56. }
  57. VOID
  58. StartNextPacket(
  59. PPACKET_QUEUE PacketQueue
  60. )
  61. {
  62. NdisAcquireSpinLock(&PacketQueue->Lock);
  63. ASSERT(PacketQueue->CurrentPacket != NULL);
  64. //
  65. // done with this one
  66. //
  67. PacketQueue->CurrentPacket=NULL;
  68. if (!PacketQueue->InStartNext) {
  69. //
  70. // not already in this function
  71. //
  72. PacketQueue->InStartNext=TRUE;
  73. while ((PacketQueue->CurrentPacket == NULL) && PacketQueue->Active && (PacketQueue->HeadOfList != NULL)) {
  74. //
  75. // there is a packet queued
  76. //
  77. PNDIS_PACKET Packet;
  78. PPACKET_RESERVED_BLOCK Reserved;
  79. //
  80. // get the first packet on the list
  81. //
  82. Packet=PacketQueue->HeadOfList;
  83. //
  84. // Get a pointer to miniport reserved area
  85. //
  86. Reserved=(PPACKET_RESERVED_BLOCK)&Packet->MiniportReservedEx[0];
  87. //
  88. // move to the next one in the list
  89. //
  90. PacketQueue->HeadOfList=Reserved->Next;
  91. #if DBG
  92. Reserved->Next=NULL;
  93. if (PacketQueue->HeadOfList == NULL) {
  94. PacketQueue->TailOfList=NULL;
  95. }
  96. #endif
  97. //
  98. // now the current one
  99. //
  100. PacketQueue->CurrentPacket=Packet;
  101. NdisReleaseSpinLock(&PacketQueue->Lock);
  102. //
  103. // start the processing
  104. //
  105. (*PacketQueue->Starter)(
  106. PacketQueue->Context,
  107. Packet
  108. );
  109. NdisAcquireSpinLock(&PacketQueue->Lock);
  110. }
  111. if (!PacketQueue->Active && (PacketQueue->CurrentPacket == NULL)) {
  112. //
  113. // the queue has been paused and we don't have a current packet, signal the event
  114. //
  115. KeSetEvent(
  116. &PacketQueue->InactiveEvent,
  117. IO_NO_INCREMENT,
  118. FALSE
  119. );
  120. }
  121. PacketQueue->InStartNext=FALSE;
  122. }
  123. NdisReleaseSpinLock(&PacketQueue->Lock);
  124. return;
  125. }
  126. VOID
  127. PausePacketProcessing(
  128. PPACKET_QUEUE PacketQueue,
  129. BOOLEAN WaitForInactive
  130. )
  131. {
  132. BOOLEAN CurrentlyActive=FALSE;
  133. NdisAcquireSpinLock(&PacketQueue->Lock);
  134. PacketQueue->Active=FALSE;
  135. if (PacketQueue->CurrentPacket != NULL) {
  136. //
  137. // there is a packet currently being processed
  138. //
  139. CurrentlyActive=TRUE;
  140. KeClearEvent(&PacketQueue->InactiveEvent);
  141. }
  142. NdisReleaseSpinLock(&PacketQueue->Lock);
  143. if (WaitForInactive && CurrentlyActive) {
  144. //
  145. // the caller wants use to wait for the queue to inactive, and it was active when
  146. // theis was called
  147. //
  148. KeWaitForSingleObject(
  149. &PacketQueue->InactiveEvent,
  150. Executive,
  151. KernelMode,
  152. FALSE,
  153. NULL
  154. );
  155. }
  156. return;
  157. }
  158. VOID
  159. ActivatePacketProcessing(
  160. PPACKET_QUEUE PacketQueue
  161. )
  162. {
  163. NdisAcquireSpinLock(&PacketQueue->Lock);
  164. PacketQueue->Active=TRUE;
  165. if ((PacketQueue->CurrentPacket == NULL) && (PacketQueue->HeadOfList != NULL)) {
  166. //
  167. // there is a packet queued
  168. //
  169. PNDIS_PACKET Packet;
  170. PPACKET_RESERVED_BLOCK Reserved;
  171. Packet=PacketQueue->HeadOfList;
  172. //
  173. // get a pointer to the reserved area
  174. //
  175. Reserved=(PPACKET_RESERVED_BLOCK)&Packet->MiniportReservedEx[0];
  176. PacketQueue->HeadOfList=Reserved->Next;
  177. //
  178. // now the current one
  179. //
  180. PacketQueue->CurrentPacket=Packet;
  181. NdisReleaseSpinLock(&PacketQueue->Lock);
  182. //
  183. // start the processing
  184. //
  185. (*PacketQueue->Starter)(
  186. PacketQueue->Context,
  187. Packet
  188. );
  189. NdisAcquireSpinLock(&PacketQueue->Lock);
  190. }
  191. NdisReleaseSpinLock(&PacketQueue->Lock);
  192. return;
  193. }
  194. VOID
  195. FlushQueuedPackets(
  196. PPACKET_QUEUE PacketQueue,
  197. NDIS_HANDLE WrapperHandle
  198. )
  199. {
  200. //
  201. // dispose of all of the queue packets, don't touch the current one though
  202. //
  203. NdisAcquireSpinLock(&PacketQueue->Lock);
  204. while (PacketQueue->HeadOfList != NULL) {
  205. //
  206. // there is a packet queued
  207. //
  208. PNDIS_PACKET Packet;
  209. PPACKET_RESERVED_BLOCK Reserved;
  210. Packet=PacketQueue->HeadOfList;
  211. Reserved=(PPACKET_RESERVED_BLOCK)&Packet->MiniportReservedEx[0];
  212. PacketQueue->HeadOfList=Reserved->Next;
  213. NdisReleaseSpinLock(&PacketQueue->Lock);
  214. //
  215. // start the processing
  216. //
  217. NdisMSendComplete(
  218. WrapperHandle,
  219. Packet,
  220. NDIS_STATUS_REQUEST_ABORTED
  221. );
  222. NdisAcquireSpinLock(&PacketQueue->Lock);
  223. }
  224. NdisReleaseSpinLock(&PacketQueue->Lock);
  225. return;
  226. }