Windows NT 4.0 source code leak
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.

523 lines
11 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. loopback.c
  5. Abstract:
  6. The routines here indicate packets on the loopback queue and are
  7. responsible for inserting and removing packets from the loopback
  8. queue and the send finishing queue.
  9. Author:
  10. Anthony V. Ercolano (Tonye) 12-Sept-1990
  11. Environment:
  12. Operates at dpc level - or the equivalent on os2 and dos.
  13. Revision History:
  14. --*/
  15. #include <ntos.h>
  16. #include <ndis.h>
  17. #include <filter.h>
  18. #include <pc586hrd.h>
  19. #include <pc586sft.h>
  20. extern
  21. VOID
  22. Pc586ProcessLoopback(
  23. IN PPC586_ADAPTER Adapter
  24. )
  25. /*++
  26. Routine Description:
  27. This routine is responsible for indicating *one* packet on
  28. the loopback queue either completing it or moving on to the
  29. finish send queue.
  30. Arguments:
  31. Adapter - The adapter whose loopback queue we are processing.
  32. Return Value:
  33. None.
  34. --*/
  35. {
  36. NdisAcquireSpinLock(&Adapter->Lock);
  37. if (Adapter->FirstLoopBack) {
  38. //
  39. // Packet at the head of the loopback list.
  40. //
  41. PNDIS_PACKET PacketToMove;
  42. //
  43. // The reserved portion of the above packet.
  44. //
  45. PPC586_RESERVED Reserved;
  46. //
  47. // Buffer for loopback.
  48. //
  49. CHAR Loopback[PC586_SIZE_OF_RECEIVE_BUFFERS];
  50. //
  51. // The first buffer in the ndis packet to be loopbacked.
  52. //
  53. PNDIS_BUFFER FirstBuffer;
  54. //
  55. // The total amount of user data in the packet to be
  56. // loopbacked.
  57. //
  58. UINT TotalPacketLength;
  59. //
  60. // Eventually the address of the data to be indicated
  61. // to the transport.
  62. //
  63. PVOID BufferAddress;
  64. //
  65. // Eventually the length of the data to be indicated
  66. // to the transport.
  67. //
  68. UINT BufferLength;
  69. PacketToMove = Adapter->FirstLoopBack;
  70. Pc586RemovePacketFromLoopBack(Adapter);
  71. NdisReleaseSpinLock(&Adapter->Lock);
  72. Reserved = PPC586_RESERVED_FROM_PACKET(PacketToMove);
  73. //
  74. // See if we need to copy the data from the packet
  75. // into the loopback buffer.
  76. //
  77. // We need to copy to the local loopback buffer if
  78. // the first buffer of the packet is less than the
  79. // minimum loopback size AND the first buffer isn't
  80. // the total packet.
  81. //
  82. NdisQueryPacket(
  83. PacketToMove,
  84. NULL,
  85. NULL,
  86. &FirstBuffer,
  87. &TotalPacketLength
  88. );
  89. NdisQueryBuffer(
  90. FirstBuffer,
  91. NULL,
  92. &BufferAddress,
  93. &BufferLength
  94. );
  95. if ((BufferLength < PC586_SIZE_OF_RECEIVE_BUFFERS) &&
  96. (BufferLength != TotalPacketLength)) {
  97. Pc586CopyFromPacketToBuffer(
  98. PacketToMove,
  99. 0,
  100. PC586_SIZE_OF_RECEIVE_BUFFERS,
  101. Loopback,
  102. &BufferLength
  103. );
  104. BufferAddress = Loopback;
  105. }
  106. //
  107. // Indicate the packet to every open binding
  108. // that could want it.
  109. //
  110. MacFilterIndicateReceive(
  111. Adapter->FilterDB,
  112. PacketToMove,
  113. ((PCHAR)BufferAddress),
  114. BufferAddress,
  115. BufferLength,
  116. TotalPacketLength
  117. );
  118. //
  119. // Remove the packet from the loopback queue and
  120. // either indicate that it is finished or put
  121. // it on the finishing up queue for the real transmits.
  122. //
  123. NdisAcquireSpinLock(&Adapter->Lock);
  124. if (!Reserved->STAGE.STAGE4.ReadyToComplete) {
  125. //
  126. // We can decrement the reference count on the open by one since
  127. // it is no longer being "referenced" by the packet on the
  128. // loopback queue.
  129. //
  130. PPC586_OPEN_FROM_BINDING_HANDLE(
  131. Reserved->MacBindingHandle
  132. )->References--;
  133. Pc586PutPacketOnFinishTrans(
  134. Adapter,
  135. PacketToMove
  136. );
  137. } else {
  138. PPC586_OPEN Open;
  139. //
  140. // Increment the reference count on the open so that
  141. // it will not be deleted out from under us while
  142. // where indicating it.
  143. //
  144. Open = PPC586_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
  145. Open->References++;
  146. NdisReleaseSpinLock(&Adapter->Lock);
  147. NdisCompleteSend(
  148. Open->NdisBindingContext,
  149. Reserved->RequestHandle,
  150. ((Reserved->STAGE.STAGE4.SuccessfulTransmit)?
  151. (NDIS_STATUS_SUCCESS):(NDIS_STATUS_FAILURE))
  152. );
  153. NdisAcquireSpinLock(&Adapter->Lock);
  154. //
  155. // We can decrement the reference count by two since it is
  156. // no longer being referenced to indicate and it is no longer
  157. // being "referenced" by the packet on the loopback queue.
  158. //
  159. Open->References -= 2;
  160. }
  161. //
  162. // If there is nothing else on the loopback queue
  163. // then indicate that reception is "done".
  164. //
  165. if (!Adapter->FirstLoopBack) {
  166. //
  167. // We need to signal every open binding that the
  168. // "receives" are complete. We increment the reference
  169. // count on the open binding while we're doing indications
  170. // so that the open can't be deleted out from under
  171. // us while we're indicating (recall that we can't own
  172. // the lock during the indication).
  173. //
  174. PPC586_OPEN Open;
  175. PLIST_ENTRY CurrentLink;
  176. CurrentLink = Adapter->OpenBindings.Flink;
  177. while (CurrentLink != &Adapter->OpenBindings) {
  178. Open = CONTAINING_RECORD(
  179. CurrentLink,
  180. PC586_OPEN,
  181. OpenList
  182. );
  183. Open->References++;
  184. NdisReleaseSpinLock(&Adapter->Lock);
  185. NdisIndicateReceiveComplete(Open->NdisBindingContext);
  186. NdisAcquireSpinLock(&Adapter->Lock);
  187. Open->References--;
  188. CurrentLink = CurrentLink->Flink;
  189. }
  190. }
  191. }
  192. NdisReleaseSpinLock(&Adapter->Lock);
  193. }
  194. extern
  195. VOID
  196. Pc586PutPacketOnFinishTrans(
  197. IN PPC586_ADAPTER Adapter,
  198. IN PNDIS_PACKET Packet
  199. )
  200. /*++
  201. Routine Description:
  202. Put the packet on the adapter wide queue for packets that
  203. are transmitting.
  204. NOTE: This routine assumes that the lock is held.
  205. NOTE: By definition any packet given to this routine is ready
  206. to complete.
  207. Arguments:
  208. Adapter - The adapter that contains the queue.
  209. Packet - The packet to be put on the queue.
  210. Return Value:
  211. None.
  212. --*/
  213. {
  214. PPC586_RESERVED Reserved, LastReserved;
  215. Reserved = PPC586_RESERVED_FROM_PACKET(Packet);
  216. Reserved->STAGE.ClearStage = 0;
  217. if (Adapter->LastFinishTransmit) {
  218. LastReserved =
  219. PPC586_RESERVED_FROM_PACKET(Adapter->LastFinishTransmit);
  220. LastReserved->Next = Packet;
  221. Reserved->STAGE.BackPointer = Adapter->LastFinishTransmit;
  222. } else {
  223. Reserved->STAGE.BackPointer = NULL;
  224. }
  225. Reserved->STAGE.STAGE4.ReadyToComplete = TRUE;
  226. Reserved->Next = NULL;
  227. Adapter->LastFinishTransmit = Packet;
  228. if (!Adapter->FirstFinishTransmit) {
  229. Adapter->FirstFinishTransmit = Packet;
  230. }
  231. }
  232. extern
  233. VOID
  234. Pc586RemovePacketOnFinishTrans(
  235. IN PPC586_ADAPTER Adapter,
  236. IN PNDIS_PACKET Packet
  237. )
  238. /*++
  239. Routine Description:
  240. Remove a packet on the adapter wide queue for packets that
  241. are transmitting.
  242. NOTE: This routine assumes that the lock is held.
  243. Arguments:
  244. Adapter - The adapter that contains the queue.
  245. Packet - The packet to be removed from the queue.
  246. Return Value:
  247. None.
  248. --*/
  249. {
  250. PPC586_RESERVED Reserved, RBack, RForward;
  251. PNDIS_PACKET Forward, Back;
  252. Reserved = PPC586_RESERVED_FROM_PACKET(Packet);
  253. //
  254. // Get rid of the low bits that is set in the backpointer by
  255. // the routine that inserted this packet on the finish
  256. // transmission list.
  257. //
  258. Reserved->STAGE.STAGE4.ReadyToComplete = 0;
  259. Reserved->STAGE.STAGE4.SuccessfulTransmit = 0;
  260. Forward = Reserved->Next;
  261. ASSERT(sizeof(UINT) == sizeof(PNDIS_PACKET));
  262. Back = Reserved->STAGE.BackPointer;
  263. if (!Back) {
  264. Adapter->FirstFinishTransmit = Forward;
  265. } else {
  266. RBack = PPC586_RESERVED_FROM_PACKET(Back);
  267. RBack->Next = Forward;
  268. }
  269. if (!Forward) {
  270. Adapter->LastFinishTransmit = Back;
  271. } else {
  272. RForward = PPC586_RESERVED_FROM_PACKET(Forward);
  273. RForward->STAGE.BackPointer = Back;
  274. RForward->STAGE.STAGE4.ReadyToComplete = TRUE;
  275. }
  276. }
  277. extern
  278. VOID
  279. Pc586PutPacketOnLoopBack(
  280. IN PPC586_ADAPTER Adapter,
  281. IN PNDIS_PACKET Packet,
  282. IN BOOLEAN ReadyToComplete
  283. )
  284. /*++
  285. Routine Description:
  286. Put the packet on the adapter wide loop back list.
  287. NOTE: This routine assumes that the lock is held.
  288. NOTE: This routine absolutely must be called before the packet
  289. is relinquished to the hardware.
  290. NOTE: This routine also increments the reference count on the
  291. open binding.
  292. Arguments:
  293. Adapter - The adapter that contains the loop back list.
  294. Packet - The packet to be put on loop back.
  295. ReadyToComplete - This value should be placed in the
  296. reserved section.
  297. NOTE: If ReadyToComplete == TRUE then the packets completion status
  298. field will also be set TRUE.
  299. Return Value:
  300. None.
  301. --*/
  302. {
  303. PPC586_RESERVED Reserved = PPC586_RESERVED_FROM_PACKET(Packet);
  304. if (!Adapter->FirstLoopBack) {
  305. Adapter->FirstLoopBack = Packet;
  306. } else {
  307. PPC586_RESERVED_FROM_PACKET(Adapter->LastLoopBack)->Next = Packet;
  308. }
  309. Reserved->STAGE.ClearStage = 0;
  310. Reserved->STAGE.STAGE4.ReadyToComplete = ReadyToComplete;
  311. if (ReadyToComplete) {
  312. Reserved->STAGE.STAGE4.SuccessfulTransmit = TRUE;
  313. }
  314. Reserved->Next = NULL;
  315. Adapter->LastLoopBack = Packet;
  316. //
  317. // Increment the reference count on the open since it will be
  318. // leaving a packet on the loopback queue.
  319. //
  320. PPC586_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle)->References++;
  321. }
  322. extern
  323. VOID
  324. Pc586RemovePacketFromLoopBack(
  325. IN PPC586_ADAPTER Adapter
  326. )
  327. /*++
  328. Routine Description:
  329. Remove the first packet on the adapter wide loop back list.
  330. NOTE: This routine assumes that the lock is held.
  331. Arguments:
  332. Adapter - The adapter that contains the loop back list.
  333. Return Value:
  334. None.
  335. --*/
  336. {
  337. PPC586_RESERVED Reserved =
  338. PPC586_RESERVED_FROM_PACKET(Adapter->FirstLoopBack);
  339. if (!Reserved->Next) {
  340. Adapter->LastLoopBack = NULL;
  341. }
  342. Adapter->FirstLoopBack = Reserved->Next;
  343. }