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.

2628 lines
72 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. sendm.c
  5. Abstract:
  6. Author:
  7. Jameel Hyder (JameelH)
  8. Kyle Brandon (KyleB)
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include <precomp.h>
  14. #pragma hdrstop
  15. //
  16. // Define the module number for debug code.
  17. //
  18. #define MODULE_NUMBER MODULE_SENDM
  19. ///////////////////////////////////////////////////////////////////////////////////////
  20. //
  21. // UPPER-EDGE SEND HANDLERS
  22. //
  23. ///////////////////////////////////////////////////////////////////////////////////////
  24. VOID
  25. ndisMSendPackets(
  26. IN NDIS_HANDLE NdisBindingHandle,
  27. IN PPNDIS_PACKET PacketArray,
  28. IN UINT NumberOfPackets
  29. )
  30. {
  31. PNDIS_OPEN_BLOCK Open = (PNDIS_OPEN_BLOCK)NdisBindingHandle;
  32. PNDIS_STACK_RESERVED NSR;
  33. PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
  34. BOOLEAN LocalLock;
  35. NDIS_STATUS Status;
  36. KIRQL OldIrql;
  37. UINT c;
  38. PPNDIS_PACKET pPktArray;;
  39. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  40. ("==>ndisMSendPackets\n"));
  41. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  42. Status = NDIS_STATUS_SUCCESS;
  43. //
  44. // Place the packets on the miniport queue.
  45. //
  46. for (c = 0, pPktArray = PacketArray;
  47. c < NumberOfPackets;
  48. c++, pPktArray++)
  49. {
  50. PNDIS_PACKET Packet = *pPktArray;
  51. ASSERT(Packet != NULL);
  52. ASSERT(Packet->Private.Head != NULL);
  53. PUSH_PACKET_STACK(Packet);
  54. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  55. CHECK_FOR_DUPLICATE_PACKET(Miniport, Packet);
  56. if (MINIPORT_TEST_SEND_FLAG(Miniport, fMINIPORT_SEND_DO_NOT_MAP_MDLS))
  57. {
  58. ndisMCheckPacketAndGetStatsOutAlreadyMapped(Miniport, Packet);
  59. }
  60. else
  61. {
  62. ndisMCheckPacketAndGetStatsOut(Miniport, Packet, &Status);
  63. }
  64. NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_PENDING);
  65. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_SELF_DIRECTED);
  66. DBGPRINT(DBG_COMP_OPENREF, DBG_LEVEL_INFO,
  67. ("+ Open 0x%x Reference 0x%x\n", NdisBindingHandle, Open->References));
  68. M_OPEN_INCREMENT_REF_INTERLOCKED(Open);
  69. LINK_PACKET(Miniport, Packet, NSR, Open);
  70. if (Status != NDIS_STATUS_SUCCESS)
  71. {
  72. NDISM_COMPLETE_SEND(Miniport, Packet, NSR, Status, TRUE, 0);
  73. }
  74. else if (Miniport->FirstPendingPacket == NULL)
  75. {
  76. Miniport->FirstPendingPacket = Packet;
  77. }
  78. }
  79. //
  80. // Queue a workitem for the new sends.
  81. //
  82. NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemSend, NULL);
  83. LOCK_MINIPORT(Miniport, LocalLock);
  84. if (LocalLock)
  85. {
  86. //
  87. // We have the local lock
  88. //
  89. NDISM_PROCESS_DEFERRED(Miniport);
  90. UNLOCK_MINIPORT(Miniport, LocalLock);
  91. }
  92. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  93. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  94. ("<==ndisMSendPackets\n"));
  95. }
  96. VOID
  97. ndisMSendPacketsX(
  98. IN NDIS_HANDLE NdisBindingHandle,
  99. IN PPNDIS_PACKET PacketArray,
  100. IN UINT NumberOfPackets
  101. )
  102. {
  103. PNDIS_OPEN_BLOCK Open = (PNDIS_OPEN_BLOCK)NdisBindingHandle;
  104. PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
  105. PNDIS_STACK_RESERVED NSR;
  106. PPNDIS_PACKET pPktArray, pSend;
  107. NDIS_STATUS Status;
  108. UINT c, k = 0, Flags;
  109. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  110. ("==>ndisMSendPacketsX\n"));
  111. DBGPRINT(DBG_COMP_OPENREF, DBG_LEVEL_INFO,
  112. ("+ Open 0x%x Reference 0x%x\n", NdisBindingHandle, Open->References));
  113. Status = NDIS_STATUS_SUCCESS ;
  114. for (c = k = 0, pPktArray = pSend = PacketArray;
  115. c < NumberOfPackets;
  116. c++, pPktArray++)
  117. {
  118. PNDIS_PACKET Packet = *pPktArray;
  119. //
  120. // Initialize the packets with the Open
  121. //
  122. ASSERT(Packet != NULL);
  123. ASSERT(Packet->Private.Head != NULL);
  124. PUSH_PACKET_STACK(Packet);
  125. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  126. NSR->Open = Open;
  127. M_OPEN_INCREMENT_REF_INTERLOCKED(Open);
  128. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_SELF_DIRECTED);
  129. NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo) = NULL;
  130. if (MINIPORT_TEST_SEND_FLAG(Miniport, fMINIPORT_SEND_DO_NOT_MAP_MDLS))
  131. {
  132. ndisMCheckPacketAndGetStatsOutAlreadyMapped(Miniport, Packet);
  133. }
  134. else
  135. {
  136. ndisMCheckPacketAndGetStatsOut(Miniport, Packet, &Status);
  137. }
  138. if (Status == NDIS_STATUS_SUCCESS)
  139. {
  140. //
  141. // if PmodeOpens > 0 and NumOpens > 1, then check to see if we should
  142. // loop back the packet.
  143. //
  144. // we should also should loopback the packet if the protocol did not
  145. // explicitly asked for the packet not to be looped back and we have a miniport
  146. // that has indicated that it does not do loopback itself or it is in all_local
  147. // mode
  148. //
  149. if (NDIS_CHECK_FOR_LOOPBACK(Miniport, Packet))
  150. {
  151. //
  152. // Handle loopback
  153. //
  154. ndisMLoopbackPacketX(Miniport, Packet);
  155. }
  156. }
  157. //
  158. // Is this self-directed or if we should drop it due to low-resources?
  159. //
  160. if ((Status != NDIS_STATUS_SUCCESS) ||
  161. MINIPORT_TEST_PACKET_FLAG((Packet), fPACKET_SELF_DIRECTED))
  162. {
  163. //
  164. // Complete the packet back to the protocol.
  165. //
  166. ndisMSendCompleteX(Miniport, Packet, Status);
  167. if (k > 0)
  168. {
  169. ASSERT(MINIPORT_TEST_SEND_FLAG(Miniport, fMINIPORT_SEND_PACKET_ARRAY));
  170. //
  171. // Send down the packets so far and skip this one.
  172. //
  173. (Open->WSendPacketsHandler)(Miniport->MiniportAdapterContext,
  174. pSend,
  175. k);
  176. pSend = pPktArray + 1;
  177. k = 0;
  178. }
  179. }
  180. else
  181. {
  182. //
  183. // This needs to go on the wire
  184. //
  185. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SG_LIST))
  186. {
  187. ndisMAllocSGList(Miniport, Packet);
  188. }
  189. else if (MINIPORT_TEST_SEND_FLAG(Miniport, fMINIPORT_SEND_PACKET_ARRAY))
  190. {
  191. MINIPORT_SET_PACKET_FLAG(Packet, fPACKET_PENDING);
  192. k++;
  193. }
  194. else
  195. {
  196. NDIS_STATUS SendStatus;
  197. //
  198. // We need to send this down right away
  199. //
  200. NdisQuerySendFlags(Packet, &Flags);
  201. MINIPORT_SET_PACKET_FLAG(Packet, fPACKET_PENDING);
  202. SendStatus = (Open->WSendHandler)(Open->MiniportAdapterContext, Packet, Flags);
  203. //
  204. // If the packet is not pending then complete it.
  205. //
  206. if (SendStatus != NDIS_STATUS_PENDING)
  207. {
  208. ndisMSendCompleteX(Miniport, Packet, SendStatus);
  209. }
  210. }
  211. }
  212. }
  213. //
  214. // Pass the remaining packet array down to the miniport.
  215. //
  216. if (k > 0)
  217. {
  218. ASSERT(MINIPORT_TEST_SEND_FLAG(Miniport, fMINIPORT_SEND_PACKET_ARRAY));
  219. (Open->WSendPacketsHandler)(Miniport->MiniportAdapterContext,
  220. pSend,
  221. k);
  222. }
  223. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  224. ("<==ndisMSendPacketsX\n"));
  225. }
  226. NDIS_STATUS
  227. ndisMSend(
  228. IN NDIS_HANDLE NdisBindingHandle,
  229. IN PNDIS_PACKET Packet
  230. )
  231. {
  232. PNDIS_OPEN_BLOCK Open = ((PNDIS_OPEN_BLOCK)NdisBindingHandle);
  233. PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
  234. PNDIS_STACK_RESERVED NSR;
  235. PNDIS_PACKET_EXTENSION PktExt;
  236. NDIS_STATUS Status;
  237. BOOLEAN LocalLock;
  238. KIRQL OldIrql;
  239. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  240. ("==>ndisMSend\n"));
  241. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  242. ASSERT(Packet->Private.Head != NULL);
  243. CHECK_FOR_DUPLICATE_PACKET(Miniport, Packet);
  244. if (MINIPORT_TEST_SEND_FLAG(Miniport, fMINIPORT_SEND_DO_NOT_MAP_MDLS))
  245. {
  246. Status = NDIS_STATUS_SUCCESS;
  247. ndisMCheckPacketAndGetStatsOutAlreadyMapped(Miniport, Packet);
  248. }
  249. else
  250. {
  251. ndisMCheckPacketAndGetStatsOut(Miniport, Packet, &Status);
  252. }
  253. if (Status == NDIS_STATUS_SUCCESS)
  254. {
  255. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_SELF_DIRECTED);
  256. //
  257. // Increment the references on this open.
  258. //
  259. M_OPEN_INCREMENT_REF(Open);
  260. DBGPRINT(DBG_COMP_OPENREF, DBG_LEVEL_INFO,
  261. ("+ Open 0x%x Reference 0x%x\n", NdisBindingHandle, ((PNDIS_OPEN_BLOCK)NdisBindingHandle)->References));
  262. PUSH_PACKET_STACK(Packet);
  263. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  264. LINK_PACKET(Miniport, Packet, NSR, Open);
  265. if (Miniport->FirstPendingPacket == NULL)
  266. {
  267. Miniport->FirstPendingPacket = Packet;
  268. }
  269. //
  270. // If we have the local lock and there is no
  271. // packet pending, then fire off a send.
  272. //
  273. LOCK_MINIPORT(Miniport, LocalLock);
  274. NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemSend, NULL);
  275. if (LocalLock)
  276. {
  277. NDISM_PROCESS_DEFERRED(Miniport);
  278. }
  279. Status = NDIS_STATUS_PENDING;
  280. UNLOCK_MINIPORT(Miniport, LocalLock);
  281. }
  282. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  283. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  284. ("<==ndisMSend\n"));
  285. return Status;
  286. }
  287. NDIS_STATUS
  288. ndisMSendX(
  289. IN NDIS_HANDLE NdisBindingHandle,
  290. IN PNDIS_PACKET Packet
  291. )
  292. {
  293. PNDIS_OPEN_BLOCK Open = (PNDIS_OPEN_BLOCK)NdisBindingHandle;
  294. PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
  295. PNDIS_STACK_RESERVED NSR;
  296. UINT Flags;
  297. UINT OpenRef;
  298. NDIS_STATUS Status;
  299. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  300. ("==>ndisMSendX\n"));
  301. ASSERT(Packet->Private.Head != NULL);
  302. if (MINIPORT_TEST_SEND_FLAG(Miniport, fMINIPORT_SEND_DO_NOT_MAP_MDLS))
  303. {
  304. Status = NDIS_STATUS_SUCCESS;
  305. ndisMCheckPacketAndGetStatsOutAlreadyMapped(Miniport, Packet);
  306. }
  307. else
  308. {
  309. ndisMCheckPacketAndGetStatsOut(Miniport, Packet, &Status);
  310. }
  311. if (Status != NDIS_STATUS_SUCCESS)
  312. {
  313. return NDIS_STATUS_RESOURCES;
  314. }
  315. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_SELF_DIRECTED);
  316. NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo) = NULL;
  317. //
  318. // Initialize the packet info.
  319. //
  320. PUSH_PACKET_STACK(Packet);
  321. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  322. NSR->Open = Open;
  323. //
  324. // Increment the references on this open.
  325. //
  326. DBGPRINT(DBG_COMP_OPENREF, DBG_LEVEL_INFO,
  327. ("+ Open 0x%x Reference 0x%x\n", Open, Open->References));
  328. M_OPEN_INCREMENT_REF_INTERLOCKED(Open);
  329. //
  330. // HANDLE loopback
  331. //
  332. if (NDIS_CHECK_FOR_LOOPBACK(Miniport, Packet))
  333. {
  334. ndisMLoopbackPacketX(Miniport, Packet);
  335. }
  336. if (!MINIPORT_TEST_PACKET_FLAG(Packet, fPACKET_SELF_DIRECTED))
  337. {
  338. //
  339. // Does the driver support the SG method ?
  340. //
  341. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SG_LIST))
  342. {
  343. ndisMAllocSGList(Miniport, Packet);
  344. }
  345. //
  346. // Handle Send/SendPacket differently
  347. //
  348. else if (MINIPORT_TEST_SEND_FLAG(Miniport, fMINIPORT_SEND_PACKET_ARRAY))
  349. {
  350. //
  351. // Pass the packet down to the miniport.
  352. //
  353. (Open->WSendPacketsHandler)(Miniport->MiniportAdapterContext,
  354. &Packet,
  355. 1);
  356. }
  357. else
  358. {
  359. NdisQuerySendFlags(Packet, &Flags);
  360. MINIPORT_SET_PACKET_FLAG(Packet, fPACKET_PENDING);
  361. Status = (Open->WSendHandler)(Open->MiniportAdapterContext, Packet, Flags);
  362. if (Status != NDIS_STATUS_PENDING)
  363. {
  364. ndisMSendCompleteX(Miniport, Packet, Status);
  365. }
  366. }
  367. Status = NDIS_STATUS_PENDING;
  368. }
  369. else
  370. {
  371. //
  372. // Remove the reference added earlier.
  373. //
  374. DBGPRINT(DBG_COMP_OPENREF, DBG_LEVEL_INFO,
  375. ("- Open 0x%x Reference 0x%x\n", Open, Open->References));
  376. M_OPEN_DECREMENT_REF_INTERLOCKED(Open, OpenRef);
  377. /*
  378. * Make sure that an IM which shares send and receive packets on the same
  379. * pool works fine with the check in the receive path.
  380. */
  381. NSR->RefCount = 0;
  382. POP_PACKET_STACK(Packet);
  383. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_CLEAR_ITEMS);
  384. Status = NDIS_STATUS_SUCCESS;
  385. }
  386. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  387. ("<==ndisMSendX\n"));
  388. return(Status);
  389. }
  390. VOID
  391. NdisMSendComplete(
  392. IN NDIS_HANDLE MiniportAdapterHandle,
  393. IN PNDIS_PACKET Packet,
  394. IN NDIS_STATUS Status
  395. )
  396. /*++
  397. Routine Description:
  398. This function indicates the completion of a send.
  399. Arguments:
  400. MiniportAdapterHandle - points to the adapter block.
  401. Return Value:
  402. None.
  403. --*/
  404. {
  405. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  406. PNDIS_OPEN_BLOCK Open;
  407. PNDIS_STACK_RESERVED NSR;
  408. ASSERT_MINIPORT_LOCKED(Miniport);
  409. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  410. ("==>ndisMSendComplete\n"));
  411. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  412. ("packet 0x%x\n", Packet));
  413. ASSERT(Packet->Private.Head != NULL);
  414. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  415. ASSERT(VALID_OPEN(NSR->Open));
  416. ASSERT(MINIPORT_TEST_PACKET_FLAG(Packet, fPACKET_PENDING));
  417. //
  418. // Guard against double/bogus completions.
  419. //
  420. if (VALID_OPEN(NSR->Open) &&
  421. MINIPORT_TEST_PACKET_FLAG(Packet, fPACKET_PENDING))
  422. {
  423. ASSERT(Packet != Miniport->FirstPendingPacket);
  424. if (MINIPORT_TEST_PACKET_FLAG(Packet, fPACKET_DONT_COMPLETE))
  425. {
  426. //
  427. // If the packet completed in the context of a SendPackets, then
  428. // defer completion. It will get completed when we unwind.
  429. //
  430. NDIS_SET_PACKET_STATUS(Packet, Status);
  431. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_DONT_COMPLETE);
  432. }
  433. else
  434. {
  435. NDISM_COMPLETE_SEND(Miniport, Packet, NSR, Status, FALSE, 1);
  436. }
  437. }
  438. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  439. ("<==ndisMSendComplete\n"));
  440. }
  441. VOID
  442. ndisMSendCompleteX(
  443. IN NDIS_HANDLE MiniportAdapterHandle,
  444. IN PNDIS_PACKET Packet,
  445. IN NDIS_STATUS Status
  446. )
  447. /*++
  448. Routine Description:
  449. This function indicates the completion of a send.
  450. Arguments:
  451. MiniportAdapterHandle - points to the adapter block.
  452. Return Value:
  453. None.
  454. --*/
  455. {
  456. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  457. PNDIS_STACK_RESERVED NSR;
  458. PNDIS_OPEN_BLOCK Open;
  459. UINT OpenRef;
  460. KIRQL OldIrql;
  461. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  462. ("==>ndisMSendCompleteX\n"));
  463. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  464. ("packet 0x%x\n", Packet));
  465. ASSERT(Packet->Private.Head != NULL);
  466. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  467. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SG_LIST) &&
  468. (NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ScatterGatherListPacketInfo) != NULL))
  469. {
  470. ndisMFreeSGList(Miniport, Packet);
  471. }
  472. //
  473. // Indicate to Protocol;
  474. //
  475. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  476. POP_PACKET_STACK(Packet);
  477. Open = NSR->Open;
  478. ASSERT(VALID_OPEN(Open));
  479. NSR->Open = MAGIC_OPEN_I(6);
  480. #if ARCNET
  481. ASSERT (Miniport->MediaType != NdisMediumArcnet878_2);
  482. #endif
  483. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_CLEAR_ITEMS);
  484. /*
  485. * Make sure that an IM which shares send and receive packets on the same
  486. * pool works fine with the check in the receive path.
  487. */
  488. CLEAR_WRAPPER_RESERVED(NSR);
  489. (Open->SendCompleteHandler)(Open->ProtocolBindingContext,
  490. Packet,
  491. Status);
  492. DBGPRINT(DBG_COMP_OPENREF, DBG_LEVEL_INFO,
  493. ("- Open 0x%x Reference 0x%x\n", Open, Open->References));
  494. M_OPEN_DECREMENT_REF_INTERLOCKED(Open, OpenRef);
  495. DBGPRINT(DBG_COMP_OPENREF, DBG_LEVEL_INFO,
  496. ("==0 Open 0x%x Reference 0x%x\n", Open, Open->References));
  497. if (OpenRef == 0)
  498. {
  499. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  500. ndisMFinishClose(Open);
  501. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  502. }
  503. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  504. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  505. ("<==ndisMSendCompleteX\n"));
  506. }
  507. BOOLEAN
  508. FASTCALL
  509. ndisMStartSendPackets(
  510. IN PNDIS_MINIPORT_BLOCK Miniport
  511. )
  512. {
  513. PNDIS_PACKET Packet;
  514. NDIS_STATUS Status;
  515. PNDIS_STACK_RESERVED NSR;
  516. PPNDIS_PACKET pPktArray;
  517. PNDIS_PACKET PacketArray[SEND_PACKET_ARRAY];
  518. UINT MaxPkts = Miniport->MaxSendPackets;
  519. W_SEND_PACKETS_HANDLER SendPacketsHandler = Miniport->WSendPacketsHandler;
  520. BOOLEAN SelfDirected;
  521. ASSERT_MINIPORT_LOCKED(Miniport);
  522. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  523. ("==>ndisMStartSendPackets\n"));
  524. //
  525. // We could possibly end up with a situation (with intermediate serialized
  526. // miniports) where there are no packets down with the driver and we the
  527. // resource window is closed. In such a case open it fully. We are seeing this
  528. // with wlbs
  529. //
  530. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESOURCES_AVAILABLE) &&
  531. (Miniport->FirstPendingPacket == NULL))
  532. {
  533. ADD_RESOURCE(Miniport, 'X');
  534. }
  535. //
  536. // Work-around for a scenario we are hitting when PacketList is empty but FirstPendingPacket is NOT
  537. // Not sure how this can happen - yet.
  538. //
  539. if (IsListEmpty(&Miniport->PacketList))
  540. {
  541. ASSERT (Miniport->FirstPendingPacket == NULL);
  542. Miniport->FirstPendingPacket = NULL;
  543. }
  544. while ((Miniport->FirstPendingPacket != NULL) &&
  545. MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESOURCES_AVAILABLE))
  546. {
  547. UINT Count;
  548. UINT NumberOfPackets;
  549. ASSERT(!IsListEmpty(&Miniport->PacketList));
  550. //
  551. // Initialize the packet array.
  552. //
  553. pPktArray = PacketArray;
  554. //
  555. // Place as many packets as we can in the packet array to send
  556. // to the miniport.
  557. //
  558. for (NumberOfPackets = 0;
  559. (NumberOfPackets < MaxPkts) && (Miniport->FirstPendingPacket != NULL);
  560. NOTHING)
  561. {
  562. //
  563. // Grab the packet off of the pending queue.
  564. //
  565. ASSERT(!IsListEmpty(&Miniport->PacketList));
  566. Packet = Miniport->FirstPendingPacket;
  567. ASSERT(Packet->Private.Head != NULL);
  568. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  569. ASSERT(VALID_OPEN(NSR->Open));
  570. NEXT_PACKET_PENDING(Miniport, Packet, NSR);
  571. //
  572. // Indicate the packet loopback if necessary.
  573. //
  574. if (NDIS_CHECK_FOR_LOOPBACK(Miniport, Packet))
  575. {
  576. //
  577. // make sure the packet does not get looped back at lower levels.
  578. // we will restore the original flag on send completion
  579. //
  580. SelfDirected = ndisMLoopbackPacketX(Miniport, Packet);
  581. }
  582. else
  583. {
  584. SelfDirected = FALSE;
  585. }
  586. if (SelfDirected)
  587. {
  588. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  589. ("Packet 0x%x is self-directed.\n", Packet));
  590. //
  591. // Complete the packet back to the binding.
  592. //
  593. NDISM_COMPLETE_SEND(Miniport, Packet, NSR, NDIS_STATUS_SUCCESS, TRUE, 2);
  594. //
  595. // No, we don't want to increment the counter for the
  596. // miniport's packet array.
  597. //
  598. }
  599. else
  600. {
  601. //
  602. // We have to re-initialize this.
  603. //
  604. *pPktArray = Packet;
  605. MINIPORT_SET_PACKET_FLAG(Packet, (fPACKET_DONT_COMPLETE | fPACKET_PENDING));
  606. NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_SUCCESS);
  607. //
  608. // Increment the counter for the packet array index.
  609. //
  610. NumberOfPackets++;
  611. pPktArray++;
  612. }
  613. }
  614. //
  615. // Are there any packets to send?
  616. //
  617. if (NumberOfPackets == 0)
  618. {
  619. break;
  620. }
  621. pPktArray = PacketArray;
  622. {
  623. //
  624. // Pass the packet array down to the miniport.
  625. //
  626. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  627. (SendPacketsHandler)(Miniport->MiniportAdapterContext,
  628. pPktArray,
  629. NumberOfPackets);
  630. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  631. }
  632. //
  633. // Process the packet completion.
  634. //
  635. for (Count = 0; Count < NumberOfPackets; Count++, pPktArray++)
  636. {
  637. Packet = *pPktArray;
  638. ASSERT(Packet != NULL);
  639. Status = NDIS_GET_PACKET_STATUS(*pPktArray);
  640. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_DONT_COMPLETE);
  641. //
  642. // Process the packet based on it's return status.
  643. //
  644. if (NDIS_STATUS_PENDING == Status)
  645. {
  646. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  647. ("Complete is pending\n"));
  648. }
  649. else if (Status != NDIS_STATUS_RESOURCES)
  650. {
  651. //
  652. // Remove from the finish queue.
  653. //
  654. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  655. ("Completed packet 0x%x with status 0x%x\n",
  656. Packet, Status));
  657. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  658. if (VALID_OPEN(NSR->Open))
  659. {
  660. NDISM_COMPLETE_SEND(Miniport, Packet, NSR, Status, TRUE, 3);
  661. }
  662. }
  663. else
  664. {
  665. //
  666. // Once we hit a return code of NDIS_STATUS_RESOURCES
  667. // for a packet then we must break out and re-queue.
  668. //
  669. UINT i;
  670. Miniport->FirstPendingPacket = Packet;
  671. CLEAR_RESOURCE(Miniport, 'S');
  672. for (i = Count; i < NumberOfPackets; i++)
  673. {
  674. PNDIS_PACKET Packet = PacketArray[i];
  675. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_PENDING);
  676. VALIDATE_PACKET_OPEN(Packet);
  677. }
  678. break;
  679. }
  680. }
  681. }
  682. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  683. ("<==ndisMStartSendPackets\n"));
  684. return(FALSE);
  685. }
  686. BOOLEAN
  687. FASTCALL
  688. ndisMStartSends(
  689. IN PNDIS_MINIPORT_BLOCK Miniport
  690. )
  691. /*++
  692. Routine Description:
  693. Submits as many sends as possible to the mini-port.
  694. Arguments:
  695. Miniport - Miniport to send to.
  696. Return Value:
  697. If there are more packets to send but no resources to do it with
  698. the this is TRUE to keep a workitem queue'd.
  699. --*/
  700. {
  701. PNDIS_PACKET Packet;
  702. PNDIS_STACK_RESERVED NSR;
  703. NDIS_STATUS Status;
  704. PNDIS_OPEN_BLOCK Open;
  705. ASSERT_MINIPORT_LOCKED(Miniport);
  706. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  707. ("==>ndisMStartSends\n"));
  708. while ((Miniport->FirstPendingPacket != NULL) &&
  709. MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESOURCES_AVAILABLE))
  710. {
  711. //
  712. // Grab the packet off of the pending queue.
  713. //
  714. ASSERT(!IsListEmpty(&Miniport->PacketList));
  715. Packet = Miniport->FirstPendingPacket;
  716. ASSERT(Packet->Private.Head != NULL);
  717. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  718. NEXT_PACKET_PENDING(Miniport, Packet, NSR);
  719. Open = NSR->Open;
  720. ASSERT(VALID_OPEN(Open));
  721. #if ARCNET
  722. //
  723. // Is this arcnet using ethernet encapsulation ?
  724. //
  725. if (Miniport->MediaType == NdisMediumArcnet878_2)
  726. {
  727. //
  728. // Build the header for arcnet.
  729. //
  730. Status = ndisMBuildArcnetHeader(Miniport, Open, Packet);
  731. if (NDIS_STATUS_PENDING == Status)
  732. {
  733. break;
  734. }
  735. }
  736. #endif
  737. NDISM_SEND_PACKET(Miniport, Open, Packet, &Status);
  738. //
  739. // Process the packet pending completion status.
  740. //
  741. if (NDIS_STATUS_PENDING == Status)
  742. {
  743. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, ("Complete is pending\n"));
  744. }
  745. else
  746. {
  747. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_PENDING);
  748. //
  749. // Handle the completion and resources cases.
  750. //
  751. if (Status == NDIS_STATUS_RESOURCES)
  752. {
  753. NDISM_COMPLETE_SEND_RESOURCES(Miniport, NSR, Packet);
  754. }
  755. else
  756. {
  757. NDISM_COMPLETE_SEND(Miniport, Packet, NSR, Status, TRUE, 4);
  758. }
  759. }
  760. }
  761. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  762. ("<==ndisMStartSends\n"));
  763. return(FALSE);
  764. }
  765. BOOLEAN
  766. FASTCALL
  767. ndisMIsLoopbackPacket(
  768. IN PNDIS_MINIPORT_BLOCK Miniport,
  769. IN PNDIS_PACKET Packet,
  770. OUT PNDIS_PACKET * LoopbackPacket OPTIONAL
  771. )
  772. /*++
  773. Routine Description:
  774. This routine will determine if a packet needs to be looped back in
  775. software. if the packet is any kind of loopback packet then it
  776. will get placed on the loopback queue and a workitem will be queued
  777. to process it later.
  778. Arguments:
  779. Miniport- Pointer to the miniport block to send the packet on.
  780. Packet - Packet to check for loopback.
  781. Return Value:
  782. Returns TRUE if the packet is self-directed.
  783. --*/
  784. {
  785. PNDIS_BUFFER FirstBuffer;
  786. UINT Length;
  787. UINT Offset;
  788. PUCHAR BufferAddress;
  789. BOOLEAN Loopback;
  790. BOOLEAN SelfDirected, NotDirected;
  791. PNDIS_PACKET pNewPacket = NULL;
  792. PUCHAR Buffer;
  793. NDIS_STATUS Status;
  794. PNDIS_BUFFER pNdisBuffer;
  795. UINT HdrLength;
  796. LOCK_STATE LockState;
  797. //
  798. // We should not be here if the driver handles loopback.
  799. //
  800. Loopback = FALSE;
  801. SelfDirected = FALSE;
  802. FirstBuffer = Packet->Private.Head;
  803. BufferAddress = MDL_ADDRESS_SAFE(FirstBuffer, HighPagePriority);
  804. if (BufferAddress == NULL)
  805. {
  806. if (ARGUMENT_PRESENT(LoopbackPacket))
  807. *LoopbackPacket = NULL;
  808. return(FALSE);
  809. }
  810. //
  811. // If the card does not do loopback, then we check if we need to send it to ourselves,
  812. // then if that is the case we also check for it being self-directed.
  813. //
  814. switch (Miniport->MediaType)
  815. {
  816. case NdisMedium802_3:
  817. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SEND_LOOPBACK_DIRECTED))
  818. {
  819. if (!ETH_IS_MULTICAST(BufferAddress))
  820. {
  821. //
  822. // Packet is of type directed, now make sure that it
  823. // is not self-directed.
  824. //
  825. ETH_COMPARE_NETWORK_ADDRESSES_EQ(BufferAddress,
  826. Miniport->EthDB->AdapterAddress,
  827. &NotDirected);
  828. if (!NotDirected)
  829. {
  830. SelfDirected = Loopback = TRUE;
  831. break;
  832. }
  833. }
  834. //
  835. // since all_local is set we do loopback the packet
  836. // ourselves
  837. //
  838. Loopback = TRUE;
  839. break;
  840. }
  841. READ_LOCK_FILTER(Miniport, Miniport->EthDB, &LockState);
  842. //
  843. // Check for the miniports that don't do loopback.
  844. //
  845. EthShouldAddressLoopBackMacro(Miniport->EthDB,
  846. BufferAddress,
  847. &Loopback,
  848. &SelfDirected);
  849. READ_UNLOCK_FILTER(Miniport, Miniport->EthDB, &LockState);
  850. break;
  851. case NdisMedium802_5:
  852. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SEND_LOOPBACK_DIRECTED))
  853. {
  854. TR_IS_NOT_DIRECTED(BufferAddress + 2, &NotDirected);
  855. if (!NotDirected)
  856. {
  857. //
  858. // Packet is of type directed, now make sure that it
  859. // is not self-directed.
  860. //
  861. TR_COMPARE_NETWORK_ADDRESSES_EQ(BufferAddress + 2,
  862. Miniport->TrDB->AdapterAddress,
  863. &NotDirected);
  864. if (!NotDirected)
  865. {
  866. SelfDirected = Loopback = TRUE;
  867. break;
  868. }
  869. }
  870. //
  871. // since all_local is set we do loopback the packet
  872. // ourselves
  873. //
  874. Loopback = TRUE;
  875. break;
  876. }
  877. READ_LOCK_FILTER(Miniport, Miniport->TrDB, &LockState);
  878. TrShouldAddressLoopBackMacro(Miniport->TrDB,
  879. BufferAddress +2,
  880. BufferAddress +8,
  881. &Loopback,
  882. &SelfDirected);
  883. READ_UNLOCK_FILTER(Miniport, Miniport->TrDB, &LockState);
  884. break;
  885. case NdisMediumFddi:
  886. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SEND_LOOPBACK_DIRECTED))
  887. {
  888. BOOLEAN IsMulticast;
  889. FDDI_IS_MULTICAST(BufferAddress + 1,
  890. (BufferAddress[0] & 0x40) ?
  891. FDDI_LENGTH_OF_LONG_ADDRESS : FDDI_LENGTH_OF_SHORT_ADDRESS,
  892. &IsMulticast);
  893. if (!IsMulticast)
  894. {
  895. //
  896. // Packet is of type directed, now make sure that it
  897. // is not self-directed.
  898. //
  899. FDDI_COMPARE_NETWORK_ADDRESSES_EQ(BufferAddress + 1,
  900. (BufferAddress[0] & 0x40) ?
  901. Miniport->FddiDB->AdapterLongAddress : Miniport->FddiDB->AdapterShortAddress,
  902. (BufferAddress[0] & 0x40) ?
  903. FDDI_LENGTH_OF_LONG_ADDRESS : FDDI_LENGTH_OF_SHORT_ADDRESS,
  904. &NotDirected);
  905. if (!NotDirected)
  906. {
  907. SelfDirected = Loopback = TRUE;
  908. break;
  909. }
  910. }
  911. //
  912. // since all_local is set we do loopback the packet
  913. // ourselves
  914. //
  915. Loopback = TRUE;
  916. break;
  917. }
  918. READ_LOCK_FILTER(Miniport, Miniport->FddiDB, &LockState);
  919. FddiShouldAddressLoopBackMacro(Miniport->FddiDB,
  920. BufferAddress + 1, // Skip FC byte to dest address.
  921. (BufferAddress[0] & 0x40) ?
  922. FDDI_LENGTH_OF_LONG_ADDRESS :
  923. FDDI_LENGTH_OF_SHORT_ADDRESS,
  924. &Loopback,
  925. &SelfDirected);
  926. READ_UNLOCK_FILTER(Miniport, Miniport->FddiDB, &LockState);
  927. break;
  928. #if ARCNET
  929. case NdisMediumArcnet878_2:
  930. //
  931. // We just handle arcnet packets (encapsulated or not) in
  932. // a totally different manner...
  933. //
  934. SelfDirected = ndisMArcnetSendLoopback(Miniport, Packet);
  935. //
  936. // Mark the packet as having been looped back.
  937. //
  938. return(SelfDirected);
  939. break;
  940. #endif
  941. }
  942. if (Loopback && (NdisGetPacketFlags(Packet) & NDIS_FLAGS_LOOPBACK_ONLY))
  943. {
  944. SelfDirected = TRUE;
  945. }
  946. //
  947. // Mark packet with reserved bit to indicate that it is self-directed
  948. //
  949. if (SelfDirected)
  950. {
  951. MINIPORT_SET_PACKET_FLAG(Packet, fPACKET_SELF_DIRECTED);
  952. }
  953. //
  954. // If it is not a loopback packet then get out of here.
  955. //
  956. if (!Loopback)
  957. {
  958. ASSERT(!SelfDirected);
  959. return (NdisGetPacketFlags(Packet) & NDIS_FLAGS_LOOPBACK_ONLY) ? TRUE : FALSE;
  960. }
  961. do
  962. {
  963. PNDIS_STACK_RESERVED NSR;
  964. UINT PktSize;
  965. ULONG j;
  966. //
  967. //
  968. // Get the buffer length.
  969. //
  970. NdisQueryPacketLength(Packet, &Length);
  971. Offset = 0;
  972. //
  973. // Allocate a buffer for the packet.
  974. //
  975. PktSize = NdisPacketSize(PROTOCOL_RESERVED_SIZE_IN_PACKET);
  976. pNewPacket = (PNDIS_PACKET)ALLOC_FROM_POOL(Length + PktSize, NDIS_TAG_LOOP_PKT);
  977. if (NULL == pNewPacket)
  978. {
  979. Status = NDIS_STATUS_RESOURCES;
  980. break;
  981. }
  982. //
  983. // Get a pointer to the destination buffer.
  984. //
  985. ZeroMemory(pNewPacket, PktSize);
  986. Buffer = (PUCHAR)pNewPacket + PktSize;
  987. pNewPacket = (PNDIS_PACKET)((PUCHAR)pNewPacket + SIZE_PACKET_STACKS);
  988. for (j = 0; j < ndisPacketStackSize; j++)
  989. {
  990. CURR_STACK_LOCATION(pNewPacket) = j;
  991. NDIS_STACK_RESERVED_FROM_PACKET(pNewPacket, &NSR);
  992. INITIALIZE_SPIN_LOCK(&NSR->Lock);
  993. }
  994. CURR_STACK_LOCATION(pNewPacket) = -1;
  995. //
  996. // Allocate an MDL for the packet.
  997. //
  998. NdisAllocateBuffer(&Status, &pNdisBuffer, NULL, Buffer, Length);
  999. if (NDIS_STATUS_SUCCESS != Status)
  1000. {
  1001. break;
  1002. }
  1003. //
  1004. // NdisChainBufferAtFront()
  1005. //
  1006. pNewPacket->Private.Head = pNdisBuffer;
  1007. pNewPacket->Private.Tail = pNdisBuffer;
  1008. pNewPacket->Private.Pool = (PVOID)'pooL';
  1009. pNewPacket->Private.NdisPacketOobOffset = (USHORT)(PktSize - (SIZE_PACKET_STACKS +
  1010. sizeof(NDIS_PACKET_OOB_DATA) +
  1011. sizeof(NDIS_PACKET_EXTENSION)));
  1012. NDIS_SET_ORIGINAL_PACKET(pNewPacket, pNewPacket);
  1013. ndisMCopyFromPacketToBuffer(Packet, // Packet to copy from.
  1014. Offset, // Offset from beginning of packet.
  1015. Length, // Number of bytes to copy.
  1016. Buffer, // The destination buffer.
  1017. &HdrLength);// The number of bytes copied.
  1018. if (ARGUMENT_PRESENT(LoopbackPacket))
  1019. {
  1020. *LoopbackPacket = pNewPacket;
  1021. MINIPORT_SET_PACKET_FLAG(pNewPacket, fPACKET_IS_LOOPBACK);
  1022. pNewPacket->Private.Flags = NdisGetPacketFlags(Packet) & NDIS_FLAGS_DONT_LOOPBACK;
  1023. }
  1024. } while (FALSE);
  1025. if (NDIS_STATUS_SUCCESS != Status)
  1026. {
  1027. if (NULL != pNewPacket)
  1028. {
  1029. pNewPacket = (PNDIS_PACKET)((PUCHAR)pNewPacket - SIZE_PACKET_STACKS);
  1030. FREE_POOL(pNewPacket);
  1031. }
  1032. *LoopbackPacket = NULL;
  1033. SelfDirected = FALSE;
  1034. }
  1035. return SelfDirected;
  1036. }
  1037. BOOLEAN
  1038. FASTCALL
  1039. ndisMLoopbackPacketX(
  1040. IN PNDIS_MINIPORT_BLOCK Miniport,
  1041. IN PNDIS_PACKET Packet
  1042. )
  1043. {
  1044. PNDIS_PACKET LoopbackPacket = NULL;
  1045. PNDIS_PACKET_OOB_DATA pOob;
  1046. PNDIS_STACK_RESERVED NSR;
  1047. PUCHAR BufferAddress;
  1048. KIRQL OldIrql;
  1049. BOOLEAN fSelfDirected;
  1050. fSelfDirected = !MINIPORT_TEST_PACKET_FLAG(Packet, fPACKET_ALREADY_LOOPEDBACK) &&
  1051. ndisMIsLoopbackPacket(Miniport, Packet, &LoopbackPacket);
  1052. if ((LoopbackPacket != NULL) && (NdisMediumArcnet878_2 != Miniport->MediaType))
  1053. {
  1054. MINIPORT_SET_PACKET_FLAG(Packet, fPACKET_ALREADY_LOOPEDBACK);
  1055. pOob = NDIS_OOB_DATA_FROM_PACKET(LoopbackPacket);
  1056. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR);
  1057. pOob->Status = NDIS_STATUS_RESOURCES;
  1058. PNDIS_LB_REF_FROM_PNDIS_PACKET(LoopbackPacket)->Open = NSR->Open;
  1059. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  1060. {
  1061. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  1062. }
  1063. //
  1064. // For ethernet/token-ring/fddi/encapsulated arc-net, we want to
  1065. // indicate the packet using the receivepacket way.
  1066. //
  1067. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  1068. {
  1069. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1070. }
  1071. switch (Miniport->MediaType)
  1072. {
  1073. case NdisMedium802_3:
  1074. pOob->HeaderSize = 14;
  1075. ethFilterDprIndicateReceivePacket(Miniport, &LoopbackPacket, 1);
  1076. break;
  1077. case NdisMedium802_5:
  1078. pOob->HeaderSize = 14;
  1079. BufferAddress = (PUCHAR)LoopbackPacket + NdisPacketSize(PROTOCOL_RESERVED_SIZE_IN_PACKET) - SIZE_PACKET_STACKS;
  1080. if (BufferAddress[8] & 0x80)
  1081. {
  1082. pOob->HeaderSize += (BufferAddress[14] & 0x1F);
  1083. }
  1084. trFilterDprIndicateReceivePacket(Miniport, &LoopbackPacket, 1);
  1085. break;
  1086. case NdisMediumFddi:
  1087. BufferAddress = (PUCHAR)LoopbackPacket + NdisPacketSize(PROTOCOL_RESERVED_SIZE_IN_PACKET) - SIZE_PACKET_STACKS;
  1088. pOob->HeaderSize = (*BufferAddress & 0x40) ?
  1089. 2 * FDDI_LENGTH_OF_LONG_ADDRESS + 1:
  1090. 2 * FDDI_LENGTH_OF_SHORT_ADDRESS + 1;
  1091. fddiFilterDprIndicateReceivePacket(Miniport, &LoopbackPacket, 1);
  1092. break;
  1093. default:
  1094. ASSERT(0);
  1095. break;
  1096. }
  1097. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  1098. {
  1099. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1100. }
  1101. else
  1102. {
  1103. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  1104. }
  1105. ASSERT(NDIS_GET_PACKET_STATUS(LoopbackPacket) != NDIS_STATUS_PENDING);
  1106. NdisFreeBuffer(LoopbackPacket->Private.Head);
  1107. LoopbackPacket = (PNDIS_PACKET)((PUCHAR)LoopbackPacket - SIZE_PACKET_STACKS);
  1108. FREE_POOL(LoopbackPacket);
  1109. }
  1110. return(fSelfDirected);
  1111. }
  1112. VOID
  1113. NdisMSendResourcesAvailable(
  1114. IN NDIS_HANDLE MiniportAdapterHandle
  1115. )
  1116. /*++
  1117. Routine Description:
  1118. This function indicates that some send resources are available and are free for
  1119. processing more sends.
  1120. Arguments:
  1121. MiniportAdapterHandle - points to the adapter block.
  1122. Return Value:
  1123. None.
  1124. --*/
  1125. {
  1126. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  1127. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1128. ("==>ndisMSendResourcesAvailable\n"));
  1129. ASSERT(MINIPORT_AT_DPC_LEVEL);
  1130. ADD_RESOURCE(Miniport, 'V');
  1131. //
  1132. // Are there more sends to process?
  1133. //
  1134. if (Miniport->FirstPendingPacket != NULL)
  1135. {
  1136. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1137. ASSERT(!IsListEmpty(&Miniport->PacketList));
  1138. NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemSend, NULL);
  1139. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1140. }
  1141. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1142. ("<==ndisMSendResourcesAvailable\n"));
  1143. }
  1144. VOID
  1145. NdisMTransferDataComplete(
  1146. IN NDIS_HANDLE MiniportAdapterHandle,
  1147. IN PNDIS_PACKET Packet,
  1148. IN NDIS_STATUS Status,
  1149. IN UINT BytesTransferred
  1150. )
  1151. /*++
  1152. Routine Description:
  1153. This function indicates the completion of a transfer data request.
  1154. Arguments:
  1155. MiniportAdapterHandle - points to the adapter block.
  1156. Packet - The packet the data was copied into.
  1157. Status - Status of the operation.
  1158. BytesTransferred - Total number of bytes transferred.
  1159. Return Value:
  1160. None.
  1161. --*/
  1162. {
  1163. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  1164. PNDIS_OPEN_BLOCK Open = NULL;
  1165. KIRQL OldIrql;
  1166. ASSERT_MINIPORT_LOCKED(Miniport);
  1167. // GET_CURRENT_XFER_DATA_PACKET_STACK(Packet, Open);
  1168. GET_CURRENT_XFER_DATA_PACKET_STACK_AND_ZERO_OUT(Packet, Open);
  1169. if (Open)
  1170. {
  1171. POP_XFER_DATA_PACKET_STACK(Packet);
  1172. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  1173. {
  1174. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  1175. }
  1176. //
  1177. // Indicate to Protocol;
  1178. //
  1179. (Open->TransferDataCompleteHandler)(Open->ProtocolBindingContext,
  1180. Packet,
  1181. Status,
  1182. BytesTransferred);
  1183. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  1184. {
  1185. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  1186. }
  1187. }
  1188. }
  1189. NDIS_STATUS
  1190. ndisMTransferData(
  1191. IN NDIS_HANDLE NdisBindingHandle,
  1192. IN NDIS_HANDLE MacReceiveContext,
  1193. IN UINT ByteOffset,
  1194. IN UINT BytesToTransfer,
  1195. IN OUT PNDIS_PACKET Packet,
  1196. OUT PUINT BytesTransferred
  1197. )
  1198. {
  1199. PNDIS_OPEN_BLOCK Open = (PNDIS_OPEN_BLOCK)NdisBindingHandle;
  1200. PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
  1201. PNDIS_STACK_RESERVED NSR;
  1202. NDIS_STATUS Status;
  1203. ASSERT_MINIPORT_LOCKED(Miniport);
  1204. //
  1205. // Handle non-loopback (non-indicated) as the default case.
  1206. //
  1207. if ((MacReceiveContext == INDICATED_PACKET(Miniport)) &&
  1208. (INDICATED_PACKET(Miniport) != NULL))
  1209. {
  1210. PNDIS_PACKET_OOB_DATA pOob;
  1211. //
  1212. // This packet is a indicated (or possibly a loopback) packet
  1213. //
  1214. pOob = NDIS_OOB_DATA_FROM_PACKET((PNDIS_PACKET)MacReceiveContext);
  1215. NdisCopyFromPacketToPacketSafe(Packet,
  1216. 0,
  1217. BytesToTransfer,
  1218. (PNDIS_PACKET)MacReceiveContext,
  1219. ByteOffset + pOob->HeaderSize,
  1220. BytesTransferred,
  1221. NormalPagePriority);
  1222. Status = (*BytesTransferred == BytesToTransfer) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE;
  1223. }
  1224. else
  1225. {
  1226. PUSH_XFER_DATA_PACKET_STACK(Packet);
  1227. if (CONTAINING_RECORD(Packet, NDIS_PACKET_WRAPPER, Packet)->StackIndex.XferDataIndex >= 3 * ndisPacketStackSize)
  1228. {
  1229. POP_XFER_DATA_PACKET_STACK(Packet);
  1230. Status = NDIS_STATUS_RESOURCES;
  1231. }
  1232. else
  1233. {
  1234. PNDIS_BUFFER Buffer = Packet->Private.Head;
  1235. Status = NDIS_STATUS_SUCCESS;
  1236. if (!MINIPORT_TEST_SEND_FLAG(Miniport, fMINIPORT_SEND_DO_NOT_MAP_MDLS))
  1237. {
  1238. //
  1239. // miniport will not use safe APIs
  1240. // so map the buffers in destination packet
  1241. //
  1242. Buffer = Packet->Private.Head;
  1243. while (Buffer != NULL)
  1244. {
  1245. if (MDL_ADDRESS_SAFE(Buffer, HighPagePriority) == NULL)
  1246. {
  1247. Status = NDIS_STATUS_RESOURCES;
  1248. break;
  1249. }
  1250. Buffer = Buffer->Next;
  1251. }
  1252. }
  1253. if (Status == NDIS_STATUS_SUCCESS)
  1254. {
  1255. SET_CURRENT_XFER_DATA_PACKET_STACK(Packet, Open)
  1256. //
  1257. // Call Miniport.
  1258. //
  1259. Status = (Open->WTransferDataHandler)(Packet,
  1260. BytesTransferred,
  1261. Open->MiniportAdapterContext,
  1262. MacReceiveContext,
  1263. ByteOffset,
  1264. BytesToTransfer);
  1265. if (Status != NDIS_STATUS_PENDING)
  1266. {
  1267. SET_CURRENT_XFER_DATA_PACKET_STACK(Packet, 0);
  1268. POP_XFER_DATA_PACKET_STACK(Packet);
  1269. }
  1270. }
  1271. }
  1272. }
  1273. return Status;
  1274. }
  1275. NDIS_STATUS
  1276. ndisMWanSend(
  1277. IN NDIS_HANDLE NdisBindingHandle,
  1278. IN NDIS_HANDLE NdisLinkHandle,
  1279. IN PNDIS_WAN_PACKET Packet
  1280. )
  1281. {
  1282. PNDIS_OPEN_BLOCK Open = ((PNDIS_OPEN_BLOCK)NdisBindingHandle);
  1283. PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
  1284. NDIS_STATUS Status;
  1285. BOOLEAN LocalLock;
  1286. KIRQL OldIrql;
  1287. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1288. ("==>ndisMWanSend\n"));
  1289. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_PM_HALTING))
  1290. {
  1291. return NDIS_STATUS_FAILURE;
  1292. }
  1293. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  1294. {
  1295. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  1296. LOCK_MINIPORT(Miniport, LocalLock);
  1297. }
  1298. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE) || LocalLock)
  1299. {
  1300. //
  1301. // Call Miniport to send WAN packet
  1302. //
  1303. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  1304. {
  1305. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1306. }
  1307. Status = (Miniport->DriverHandle->MiniportCharacteristics.WanSendHandler)(
  1308. Miniport->MiniportAdapterContext,
  1309. NdisLinkHandle,
  1310. Packet);
  1311. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  1312. {
  1313. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1314. }
  1315. //
  1316. // Process the status of the send.
  1317. //
  1318. if (NDIS_STATUS_PENDING == Status)
  1319. {
  1320. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1321. ("ndisMWanSend: send is pending\n"));
  1322. }
  1323. else
  1324. {
  1325. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1326. ("ndisMWanSend: Completed 0x%x\n", Status));
  1327. }
  1328. }
  1329. else
  1330. {
  1331. LINK_WAN_PACKET(Miniport, Packet);
  1332. Packet->MacReserved1 = NdisLinkHandle;
  1333. NDISM_QUEUE_WORK_ITEM(Miniport, NdisWorkItemSend, NULL);
  1334. if (LocalLock)
  1335. {
  1336. NDISM_PROCESS_DEFERRED(Miniport);
  1337. }
  1338. Status = NDIS_STATUS_PENDING;
  1339. }
  1340. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  1341. {
  1342. UNLOCK_MINIPORT(Miniport, LocalLock);
  1343. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  1344. }
  1345. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1346. ("<==ndisMWanSend\n"));
  1347. return Status;
  1348. }
  1349. VOID
  1350. NdisMWanSendComplete(
  1351. IN NDIS_HANDLE MiniportAdapterHandle,
  1352. IN PNDIS_WAN_PACKET Packet,
  1353. IN NDIS_STATUS Status
  1354. )
  1355. /*++
  1356. Routine Description:
  1357. This function indicates the status is complete.
  1358. Arguments:
  1359. MiniportAdapterHandle - points to the adapter block.
  1360. Return Value:
  1361. None.
  1362. --*/
  1363. {
  1364. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  1365. PNDIS_OPEN_BLOCK Open;
  1366. KIRQL OldIrql;
  1367. ASSERT_MINIPORT_LOCKED(Miniport);
  1368. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1369. ("==>ndisMWanSendComplete\n"));
  1370. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1371. ("packet 0x%x\n", Packet));
  1372. ASSERT_MINIPORT_LOCKED(Miniport);
  1373. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  1374. {
  1375. RAISE_IRQL_TO_DISPATCH(&OldIrql);
  1376. }
  1377. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1378. for (Open = Miniport->OpenQueue; Open != NULL; Open = Open->MiniportNextOpen)
  1379. {
  1380. //
  1381. // Call Protocol to complete open
  1382. //
  1383. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1384. (Open->ProtocolHandle->ProtocolCharacteristics.WanSendCompleteHandler)(
  1385. Open->ProtocolBindingContext,
  1386. Packet,
  1387. Status);
  1388. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1389. }
  1390. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1391. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  1392. {
  1393. LOWER_IRQL(OldIrql, DISPATCH_LEVEL);
  1394. }
  1395. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1396. ("<==ndisMWanSendComplete\n"));
  1397. }
  1398. BOOLEAN
  1399. FASTCALL
  1400. ndisMStartWanSends(
  1401. IN PNDIS_MINIPORT_BLOCK Miniport
  1402. )
  1403. /*++
  1404. Routine Description:
  1405. Submits as many sends as possible to the WAN mini-port.
  1406. Arguments:
  1407. Miniport - Miniport to send to.
  1408. Return Value:
  1409. None
  1410. --*/
  1411. {
  1412. PNDIS_WAN_PACKET Packet;
  1413. PLIST_ENTRY Link;
  1414. NDIS_STATUS Status;
  1415. PNDIS_M_OPEN_BLOCK Open;
  1416. ASSERT_MINIPORT_LOCKED(Miniport);
  1417. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1418. ("==>ndisMStartSends\n"));
  1419. while (!IsListEmpty(&Miniport->PacketList))
  1420. {
  1421. Link = Miniport->PacketList.Flink;
  1422. Packet = CONTAINING_RECORD(Link, NDIS_WAN_PACKET, WanPacketQueue);
  1423. UNLINK_WAN_PACKET(Packet);
  1424. //
  1425. // Call Miniport to send WAN packet
  1426. //
  1427. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1428. Status = (Miniport->DriverHandle->MiniportCharacteristics.WanSendHandler)(
  1429. Miniport->MiniportAdapterContext,
  1430. Packet->MacReserved1,
  1431. Packet);
  1432. //
  1433. // Process the status of the send.
  1434. //
  1435. if (NDIS_STATUS_PENDING == Status)
  1436. {
  1437. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1438. ("ndisMWanSend: send is pending\n"));
  1439. }
  1440. else
  1441. {
  1442. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1443. ("ndisMWanSend: Completed 0x%x\n", Status));
  1444. NdisMWanSendComplete(Miniport, Packet, Status);
  1445. }
  1446. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1447. }
  1448. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1449. ("<==ndisMStartSends\n"));
  1450. return(FALSE);
  1451. }
  1452. VOID
  1453. ndisMCopyFromPacketToBuffer(
  1454. IN PNDIS_PACKET Packet,
  1455. IN UINT Offset,
  1456. IN UINT BytesToCopy,
  1457. OUT PCHAR Buffer,
  1458. OUT PUINT BytesCopied
  1459. )
  1460. /*++
  1461. Routine Description:
  1462. Copy from an ndis packet into a buffer.
  1463. Arguments:
  1464. Packet - The packet to copy from.
  1465. Offset - The offset from which to start the copy.
  1466. BytesToCopy - The number of bytes to copy from the packet.
  1467. Buffer - The destination of the copy.
  1468. BytesCopied - The number of bytes actually copied. Can be less then
  1469. BytesToCopy if the packet is shorter than BytesToCopy.
  1470. Return Value:
  1471. None
  1472. --*/
  1473. {
  1474. //
  1475. // Holds the number of ndis buffers comprising the packet.
  1476. //
  1477. UINT NdisBufferCount;
  1478. //
  1479. // Points to the buffer from which we are extracting data.
  1480. //
  1481. PNDIS_BUFFER CurrentBuffer;
  1482. //
  1483. // Holds the virtual address of the current buffer.
  1484. //
  1485. PVOID VirtualAddress;
  1486. //
  1487. // Holds the length of the current buffer of the packet.
  1488. //
  1489. UINT CurrentLength;
  1490. //
  1491. // Keep a local variable of BytesCopied so we aren't referencing
  1492. // through a pointer.
  1493. //
  1494. UINT LocalBytesCopied = 0;
  1495. //
  1496. // Take care of boundary condition of zero length copy.
  1497. //
  1498. *BytesCopied = 0;
  1499. if (!BytesToCopy)
  1500. return;
  1501. //
  1502. // Get the first buffer.
  1503. //
  1504. NdisQueryPacket(Packet,
  1505. NULL,
  1506. &NdisBufferCount,
  1507. &CurrentBuffer,
  1508. NULL);
  1509. //
  1510. // Could have a null packet.
  1511. //
  1512. if (!NdisBufferCount)
  1513. return;
  1514. VirtualAddress = MDL_ADDRESS_SAFE(CurrentBuffer, NormalPagePriority);
  1515. CurrentLength = MDL_SIZE(CurrentBuffer);
  1516. while (LocalBytesCopied < BytesToCopy)
  1517. {
  1518. if (CurrentLength == 0)
  1519. {
  1520. NdisGetNextBuffer(CurrentBuffer, &CurrentBuffer);
  1521. //
  1522. // We've reached the end of the packet. We return
  1523. // with what we've done so far. (Which must be shorter
  1524. // than requested.
  1525. //
  1526. if (!CurrentBuffer)
  1527. break;
  1528. NdisQueryBuffer(CurrentBuffer, &VirtualAddress, &CurrentLength);
  1529. continue;
  1530. }
  1531. //
  1532. // Try to get us up to the point to start the copy.
  1533. //
  1534. if (Offset)
  1535. {
  1536. if (Offset > CurrentLength)
  1537. {
  1538. //
  1539. // What we want isn't in this buffer.
  1540. //
  1541. Offset -= CurrentLength;
  1542. CurrentLength = 0;
  1543. continue;
  1544. }
  1545. else
  1546. {
  1547. VirtualAddress = (PCHAR)VirtualAddress + Offset;
  1548. CurrentLength -= Offset;
  1549. Offset = 0;
  1550. }
  1551. }
  1552. //
  1553. // Copy the data.
  1554. //
  1555. {
  1556. //
  1557. // Holds the amount of data to move.
  1558. //
  1559. UINT AmountToMove;
  1560. AmountToMove = ((CurrentLength <= (BytesToCopy - LocalBytesCopied)) ?
  1561. (CurrentLength):
  1562. (BytesToCopy - LocalBytesCopied));
  1563. MoveMemory(Buffer, VirtualAddress, AmountToMove);
  1564. Buffer = (PCHAR)Buffer + AmountToMove;
  1565. VirtualAddress = (PCHAR)VirtualAddress + AmountToMove;
  1566. LocalBytesCopied += AmountToMove;
  1567. CurrentLength -= AmountToMove;
  1568. }
  1569. }
  1570. *BytesCopied = LocalBytesCopied;
  1571. }
  1572. NDIS_STATUS
  1573. ndisMRejectSend(
  1574. IN NDIS_HANDLE NdisBindingHandle,
  1575. IN PNDIS_PACKET Packet
  1576. )
  1577. /*++
  1578. Routine Description:
  1579. This routine handles any error cases where a protocol binds to an Atm
  1580. miniport and tries to use the normal NdisSend() call.
  1581. Arguments:
  1582. NdisBindingHandle - Handle returned by NdisOpenAdapter.
  1583. Packet - the Ndis packet to send
  1584. Return Value:
  1585. NDIS_STATUS - always fails
  1586. --*/
  1587. {
  1588. return(NDIS_STATUS_NOT_SUPPORTED);
  1589. }
  1590. VOID
  1591. ndisMRejectSendPackets(
  1592. IN PNDIS_OPEN_BLOCK OpenBlock,
  1593. IN PPNDIS_PACKET Packet,
  1594. IN UINT NumberOfPackets
  1595. )
  1596. /*++
  1597. Routine Description:
  1598. This routine handles any error cases where a protocol binds to an Atm
  1599. miniport and tries to use the normal NdisSend() call.
  1600. Arguments:
  1601. OpenBlock - Pointer to the NdisOpenBlock
  1602. Packet - Pointer to the array of packets to send
  1603. NumberOfPackets - self-explanatory
  1604. Return Value:
  1605. None - SendCompleteHandler is called for the protocol calling this.
  1606. --*/
  1607. {
  1608. UINT i;
  1609. for (i = 0; i < NumberOfPackets; i++)
  1610. {
  1611. MINIPORT_CLEAR_PACKET_FLAG(Packet[i], fPACKET_CLEAR_ITEMS);
  1612. (*OpenBlock->SendCompleteHandler)(OpenBlock->ProtocolBindingContext,
  1613. Packet[i],
  1614. NDIS_STATUS_NOT_SUPPORTED);
  1615. }
  1616. }
  1617. VOID
  1618. NdisIMCopySendPerPacketInfo(
  1619. IN PNDIS_PACKET DstPacket,
  1620. IN PNDIS_PACKET SrcPacket
  1621. )
  1622. /*++
  1623. Routine Description:
  1624. This routine is used by IM miniport and copies all relevant per packet info from
  1625. the SrcPacket to the DstPacket. Used in the Send Code path
  1626. Arguments:
  1627. DstPacket - Pointer to the destination packet
  1628. SrcPacket - Pointer to the Source Packet
  1629. Return Value:
  1630. --*/
  1631. {
  1632. PVOID * pDstInfo;
  1633. PVOID * pSrcInfo;
  1634. pDstInfo = NDIS_PACKET_EXTENSION_FROM_PACKET(DstPacket)->NdisPacketInfo;
  1635. pSrcInfo = NDIS_PACKET_EXTENSION_FROM_PACKET(SrcPacket)->NdisPacketInfo;
  1636. pDstInfo[TcpIpChecksumPacketInfo] = pSrcInfo[TcpIpChecksumPacketInfo];
  1637. pDstInfo[IpSecPacketInfo] = pSrcInfo[IpSecPacketInfo];
  1638. pDstInfo[TcpLargeSendPacketInfo] = pSrcInfo[TcpLargeSendPacketInfo];
  1639. pDstInfo[ClassificationHandlePacketInfo] = pSrcInfo[ClassificationHandlePacketInfo];
  1640. pDstInfo[Ieee8021pPriority] = pSrcInfo[Ieee8021pPriority];
  1641. pDstInfo[PacketCancelId] = pSrcInfo[PacketCancelId];
  1642. DstPacket->Private.NdisPacketFlags &= ~fPACKET_WRAPPER_RESERVED;
  1643. DstPacket->Private.NdisPacketFlags |= SrcPacket->Private.NdisPacketFlags & fPACKET_WRAPPER_RESERVED;
  1644. }
  1645. EXPORT
  1646. VOID
  1647. NdisIMCopySendCompletePerPacketInfo(
  1648. IN PNDIS_PACKET DstPacket,
  1649. IN PNDIS_PACKET SrcPacket
  1650. )
  1651. /*++
  1652. Routine Description:
  1653. This routine is used by IM miniport and copies all relevant per packet info from
  1654. the SrcPacket to the DstPacket. Used in the SendComplete Code path
  1655. Arguments:
  1656. DstPacket - Pointer to the destination packet
  1657. SrcPacket - Pointer to the Source Packet
  1658. Return Value:
  1659. --*/
  1660. {
  1661. PVOID * pDstInfo;
  1662. pDstInfo = NDIS_PACKET_EXTENSION_FROM_PACKET(DstPacket)->NdisPacketInfo;
  1663. pDstInfo[TcpLargeSendPacketInfo] = NDIS_PER_PACKET_INFO_FROM_PACKET(SrcPacket, TcpLargeSendPacketInfo);
  1664. }
  1665. VOID
  1666. ndisMSendPacketsSG(
  1667. IN NDIS_HANDLE NdisBindingHandle,
  1668. IN PPNDIS_PACKET PacketArray,
  1669. IN UINT NumberOfPackets
  1670. )
  1671. {
  1672. PNDIS_OPEN_BLOCK Open = (PNDIS_OPEN_BLOCK)NdisBindingHandle;
  1673. PNDIS_STACK_RESERVED NSR;
  1674. PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
  1675. BOOLEAN LocalLock;
  1676. NDIS_STATUS Status;
  1677. KIRQL OldIrql;
  1678. UINT c;
  1679. PPNDIS_PACKET pPktArray;;
  1680. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1681. ("==>ndisMSendPacketsSG\n"));
  1682. ASSERT(MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SG_LIST));
  1683. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  1684. Status = NDIS_STATUS_SUCCESS;
  1685. //
  1686. // Place the packets on the miniport queue.
  1687. //
  1688. for (c = 0, pPktArray = PacketArray;
  1689. c < NumberOfPackets;
  1690. c++, pPktArray++)
  1691. {
  1692. PNDIS_PACKET Packet = *pPktArray;
  1693. ASSERT(Packet != NULL);
  1694. PUSH_PACKET_STACK(Packet);
  1695. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR);
  1696. NSR->Open = Open;
  1697. CHECK_FOR_DUPLICATE_PACKET(Miniport, Packet);
  1698. if (MINIPORT_TEST_SEND_FLAG(Miniport, fMINIPORT_SEND_DO_NOT_MAP_MDLS))
  1699. {
  1700. ndisMCheckPacketAndGetStatsOutAlreadyMapped(Miniport, Packet);
  1701. }
  1702. else
  1703. {
  1704. ndisMCheckPacketAndGetStatsOut(Miniport, Packet, &Status);
  1705. }
  1706. NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_PENDING);
  1707. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_SELF_DIRECTED);
  1708. DBGPRINT(DBG_COMP_OPENREF, DBG_LEVEL_INFO,
  1709. ("+ Open 0x%x Reference 0x%x\n", NdisBindingHandle, Open->References));
  1710. M_OPEN_INCREMENT_REF_INTERLOCKED(Open);
  1711. if (Status != NDIS_STATUS_SUCCESS)
  1712. {
  1713. NDISM_COMPLETE_SEND_SG(Miniport, Packet, NSR, Status, TRUE, 0, FALSE);
  1714. }
  1715. else
  1716. {
  1717. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  1718. ndisMAllocSGListS(Miniport, Packet);
  1719. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  1720. }
  1721. }
  1722. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  1723. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1724. ("<==ndisMSendPacketsSG\n"));
  1725. }
  1726. NDIS_STATUS
  1727. ndisMSendSG(
  1728. IN NDIS_HANDLE NdisBindingHandle,
  1729. IN PNDIS_PACKET Packet
  1730. )
  1731. /*++
  1732. Routine Description:
  1733. nsiaMSend for serialized drivers that handle SG lists
  1734. Arguments:
  1735. Return Value:
  1736. None.
  1737. --*/
  1738. {
  1739. PNDIS_OPEN_BLOCK Open = ((PNDIS_OPEN_BLOCK)NdisBindingHandle);
  1740. PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
  1741. PNDIS_STACK_RESERVED NSR;
  1742. PNDIS_PACKET_EXTENSION PktExt;
  1743. NDIS_STATUS Status;
  1744. BOOLEAN LocalLock;
  1745. KIRQL OldIrql;
  1746. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1747. ("==>ndisMSendSG\n"));
  1748. ASSERT(MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SG_LIST));
  1749. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  1750. CHECK_FOR_DUPLICATE_PACKET(Miniport, Packet);
  1751. if (MINIPORT_TEST_SEND_FLAG(Miniport, fMINIPORT_SEND_DO_NOT_MAP_MDLS))
  1752. {
  1753. Status = NDIS_STATUS_SUCCESS;
  1754. ndisMCheckPacketAndGetStatsOutAlreadyMapped(Miniport, Packet);
  1755. }
  1756. else
  1757. {
  1758. ndisMCheckPacketAndGetStatsOut(Miniport, Packet, &Status);
  1759. }
  1760. if (Status == NDIS_STATUS_SUCCESS)
  1761. {
  1762. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_SELF_DIRECTED);
  1763. //
  1764. // Increment the references on this open.
  1765. //
  1766. M_OPEN_INCREMENT_REF(Open);
  1767. DBGPRINT(DBG_COMP_OPENREF, DBG_LEVEL_INFO,
  1768. ("+ Open 0x%x Reference 0x%x\n", NdisBindingHandle, ((PNDIS_OPEN_BLOCK)NdisBindingHandle)->References));
  1769. PUSH_PACKET_STACK(Packet);
  1770. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  1771. NSR->Open = Open;
  1772. Status = NDIS_STATUS_PENDING;
  1773. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  1774. ndisMAllocSGListS(Miniport, Packet);
  1775. }
  1776. else
  1777. {
  1778. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  1779. }
  1780. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1781. ("<==ndisMSendSG\n"));
  1782. return Status;
  1783. }
  1784. VOID
  1785. ndisMSendCompleteSG(
  1786. IN NDIS_HANDLE MiniportAdapterHandle,
  1787. IN PNDIS_PACKET Packet,
  1788. IN NDIS_STATUS Status
  1789. )
  1790. /*++
  1791. Routine Description:
  1792. This function indicates the completion of a send.
  1793. Arguments:
  1794. MiniportAdapterHandle - points to the adapter block.
  1795. Return Value:
  1796. None.
  1797. --*/
  1798. {
  1799. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)MiniportAdapterHandle;
  1800. PNDIS_OPEN_BLOCK Open;
  1801. PNDIS_STACK_RESERVED NSR;
  1802. ASSERT_MINIPORT_LOCKED(Miniport);
  1803. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1804. ("==>ndisMSendCompleteSG\n"));
  1805. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1806. ("packet 0x%x\n", Packet));
  1807. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  1808. ASSERT(VALID_OPEN(NSR->Open));
  1809. ASSERT(MINIPORT_TEST_PACKET_FLAG(Packet, fPACKET_PENDING));
  1810. //
  1811. // Guard against double/bogus completions.
  1812. //
  1813. if (VALID_OPEN(NSR->Open) &&
  1814. MINIPORT_TEST_PACKET_FLAG(Packet, fPACKET_PENDING))
  1815. {
  1816. ASSERT(Packet != Miniport->FirstPendingPacket);
  1817. if (MINIPORT_TEST_PACKET_FLAG(Packet, fPACKET_DONT_COMPLETE))
  1818. {
  1819. //
  1820. // If the packet completed in the context of a SendPackets, then
  1821. // defer completion. It will get completed when we unwind.
  1822. //
  1823. NDIS_SET_PACKET_STATUS(Packet, Status);
  1824. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_DONT_COMPLETE);
  1825. }
  1826. else
  1827. {
  1828. NDISM_COMPLETE_SEND_SG(Miniport, Packet, NSR, Status, FALSE, 1, TRUE);
  1829. }
  1830. }
  1831. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1832. ("<==ndisMSendCompleteSG\n"));
  1833. }
  1834. BOOLEAN
  1835. FASTCALL
  1836. ndisMStartSendPacketsSG(
  1837. IN PNDIS_MINIPORT_BLOCK Miniport
  1838. )
  1839. {
  1840. PNDIS_PACKET Packet;
  1841. NDIS_STATUS Status;
  1842. PNDIS_STACK_RESERVED NSR;
  1843. PPNDIS_PACKET pPktArray;
  1844. PNDIS_PACKET PacketArray[SEND_PACKET_ARRAY];
  1845. UINT MaxPkts = Miniport->MaxSendPackets;
  1846. W_SEND_PACKETS_HANDLER SendPacketsHandler = Miniport->WSendPacketsHandler;
  1847. BOOLEAN SelfDirected;
  1848. ASSERT_MINIPORT_LOCKED(Miniport);
  1849. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1850. ("==>ndisMStartSendPacketsSG\n"));
  1851. //
  1852. // We could possibly end up with a situation (with intermediate serialized
  1853. // miniports) where there are no packets down with the driver and we the
  1854. // resource window is closed. In such a case open it fully. We are seeing this
  1855. // with wlbs
  1856. //
  1857. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESOURCES_AVAILABLE) &&
  1858. (Miniport->FirstPendingPacket == NULL))
  1859. {
  1860. ADD_RESOURCE(Miniport, 'X');
  1861. }
  1862. //
  1863. // Work-around for a scenario we are hitting when PacketList is empty but FirstPendingPacket is NOT
  1864. // Not sure how this can happen - yet.
  1865. //
  1866. if (IsListEmpty(&Miniport->PacketList))
  1867. {
  1868. ASSERT (Miniport->FirstPendingPacket == NULL);
  1869. Miniport->FirstPendingPacket = NULL;
  1870. }
  1871. while ((Miniport->FirstPendingPacket != NULL) &&
  1872. MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESOURCES_AVAILABLE))
  1873. {
  1874. UINT Count;
  1875. UINT NumberOfPackets;
  1876. ASSERT(!IsListEmpty(&Miniport->PacketList));
  1877. //
  1878. // Initialize the packet array.
  1879. //
  1880. pPktArray = PacketArray;
  1881. //
  1882. // Place as many packets as we can in the packet array to send
  1883. // to the miniport.
  1884. //
  1885. for (NumberOfPackets = 0;
  1886. (NumberOfPackets < MaxPkts) && (Miniport->FirstPendingPacket != NULL);
  1887. NOTHING)
  1888. {
  1889. //
  1890. // Grab the packet off of the pending queue.
  1891. //
  1892. ASSERT(!IsListEmpty(&Miniport->PacketList));
  1893. Packet = Miniport->FirstPendingPacket;
  1894. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  1895. ASSERT(VALID_OPEN(NSR->Open));
  1896. NEXT_PACKET_PENDING(Miniport, Packet, NSR);
  1897. //
  1898. // Indicate the packet loopback if necessary.
  1899. //
  1900. if (NDIS_CHECK_FOR_LOOPBACK(Miniport, Packet))
  1901. {
  1902. SelfDirected = ndisMLoopbackPacketX(Miniport, Packet);
  1903. }
  1904. else
  1905. {
  1906. SelfDirected = FALSE;
  1907. }
  1908. if (SelfDirected)
  1909. {
  1910. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1911. ("Packet 0x%x is self-directed.\n", Packet));
  1912. //
  1913. // Complete the packet back to the binding.
  1914. //
  1915. NDISM_COMPLETE_SEND_SG(Miniport, Packet, NSR, NDIS_STATUS_SUCCESS, TRUE, 2, TRUE);
  1916. //
  1917. // No, we don't want to increment the counter for the
  1918. // miniport's packet array.
  1919. //
  1920. }
  1921. else
  1922. {
  1923. //
  1924. // We have to re-initialize this.
  1925. //
  1926. *pPktArray = Packet;
  1927. MINIPORT_SET_PACKET_FLAG(Packet, (fPACKET_DONT_COMPLETE | fPACKET_PENDING));
  1928. NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_SUCCESS);
  1929. //
  1930. // Increment the counter for the packet array index.
  1931. //
  1932. NumberOfPackets++;
  1933. pPktArray++;
  1934. }
  1935. }
  1936. //
  1937. // Are there any packets to send?
  1938. //
  1939. if (NumberOfPackets == 0)
  1940. {
  1941. break;
  1942. }
  1943. pPktArray = PacketArray;
  1944. {
  1945. //
  1946. // Pass the packet array down to the miniport.
  1947. //
  1948. NDIS_RELEASE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1949. (SendPacketsHandler)(Miniport->MiniportAdapterContext,
  1950. pPktArray,
  1951. NumberOfPackets);
  1952. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK_DPC(Miniport);
  1953. }
  1954. //
  1955. // Process the packet completion.
  1956. //
  1957. for (Count = 0; Count < NumberOfPackets; Count++, pPktArray++)
  1958. {
  1959. Packet = *pPktArray;
  1960. ASSERT(Packet != NULL);
  1961. Status = NDIS_GET_PACKET_STATUS(*pPktArray);
  1962. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_DONT_COMPLETE);
  1963. //
  1964. // Process the packet based on it's return status.
  1965. //
  1966. if (NDIS_STATUS_PENDING == Status)
  1967. {
  1968. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1969. ("Complete is pending\n"));
  1970. }
  1971. else if (Status != NDIS_STATUS_RESOURCES)
  1972. {
  1973. //
  1974. // Remove from the finish queue.
  1975. //
  1976. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  1977. ("Completed packet 0x%x with status 0x%x\n",
  1978. Packet, Status));
  1979. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  1980. if (VALID_OPEN(NSR->Open))
  1981. {
  1982. NDISM_COMPLETE_SEND_SG(Miniport, Packet, NSR, Status, TRUE, 3, TRUE);
  1983. }
  1984. }
  1985. else
  1986. {
  1987. //
  1988. // Once we hit a return code of NDIS_STATUS_RESOURCES
  1989. // for a packet then we must break out and re-queue.
  1990. //
  1991. UINT i;
  1992. Miniport->FirstPendingPacket = Packet;
  1993. CLEAR_RESOURCE(Miniport, 'S');
  1994. for (i = Count; i < NumberOfPackets; i++)
  1995. {
  1996. PNDIS_PACKET Packet = PacketArray[i];
  1997. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_PENDING);
  1998. VALIDATE_PACKET_OPEN(Packet);
  1999. }
  2000. break;
  2001. }
  2002. }
  2003. }
  2004. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  2005. ("<==ndisMStartSendPacketsSG\n"));
  2006. return(FALSE);
  2007. }
  2008. BOOLEAN
  2009. FASTCALL
  2010. ndisMStartSendsSG(
  2011. IN PNDIS_MINIPORT_BLOCK Miniport
  2012. )
  2013. /*++
  2014. Routine Description:
  2015. Submits as many sends as possible to the mini-port.
  2016. Arguments:
  2017. Miniport - Miniport to send to.
  2018. Return Value:
  2019. If there are more packets to send but no resources to do it with
  2020. the this is TRUE to keep a workitem queue'd.
  2021. --*/
  2022. {
  2023. PNDIS_PACKET Packet;
  2024. PNDIS_STACK_RESERVED NSR;
  2025. NDIS_STATUS Status;
  2026. PNDIS_OPEN_BLOCK Open;
  2027. ASSERT_MINIPORT_LOCKED(Miniport);
  2028. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  2029. ("==>ndisMStartSendsSG\n"));
  2030. while ((Miniport->FirstPendingPacket != NULL) &&
  2031. MINIPORT_TEST_FLAG(Miniport, fMINIPORT_RESOURCES_AVAILABLE))
  2032. {
  2033. //
  2034. // Grab the packet off of the pending queue.
  2035. //
  2036. ASSERT(!IsListEmpty(&Miniport->PacketList));
  2037. Packet = Miniport->FirstPendingPacket;
  2038. NDIS_STACK_RESERVED_FROM_PACKET(Packet, &NSR)
  2039. NEXT_PACKET_PENDING(Miniport, Packet, NSR);
  2040. Open = NSR->Open;
  2041. ASSERT(VALID_OPEN(Open));
  2042. //
  2043. // we can use the same NDISM_SEND_PACKET we do for non SG miniports
  2044. //
  2045. NDISM_SEND_PACKET(Miniport, Open, Packet, &Status);
  2046. //
  2047. // Process the packet pending completion status.
  2048. //
  2049. if (NDIS_STATUS_PENDING == Status)
  2050. {
  2051. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, ("Complete is pending\n"));
  2052. }
  2053. else
  2054. {
  2055. MINIPORT_CLEAR_PACKET_FLAG(Packet, fPACKET_PENDING);
  2056. //
  2057. // Handle the completion and resources cases.
  2058. //
  2059. if (Status == NDIS_STATUS_RESOURCES)
  2060. {
  2061. NDISM_COMPLETE_SEND_RESOURCES(Miniport, NSR, Packet);
  2062. }
  2063. else
  2064. {
  2065. NDISM_COMPLETE_SEND_SG(Miniport, Packet, NSR, Status, TRUE, 4, TRUE);
  2066. }
  2067. }
  2068. }
  2069. DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
  2070. ("<==ndisMStartSendsSG\n"));
  2071. return(FALSE);
  2072. }