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.

1625 lines
60 KiB

  1. /***************************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. SEND.C
  5. Abstract:
  6. Multiple packet send routines for Remote NDIS Miniport driver
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13. PURPOSE.
  14. Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 5/13/99 : created
  17. Author:
  18. Tom Green
  19. ****************************************************************************/
  20. #include "precomp.h"
  21. ULONG MdlsAllocated = 0;
  22. ULONG PktWrapperAllocated = 0;
  23. ULONG SndPacketCount = 0;
  24. ULONG SndTimerCount = 0;
  25. ULONG SndMaxPackets = 0;
  26. BOOLEAN FirstDbg = FALSE;
  27. BOOLEAN PrintPkts = FALSE;
  28. /****************************************************************************/
  29. /* RndismpMultipleSend */
  30. /****************************************************************************/
  31. /* */
  32. /* Routine Description: */
  33. /* */
  34. /* NDIS Entry point to send an array of NDIS packets on the specified */
  35. /* adapter. */
  36. /* */
  37. /* Arguments: */
  38. /* */
  39. /* MiniportAdapterContext - a context version of our Adapter pointer */
  40. /* PacketArray - An array of pointers to NDIS packets */
  41. /* NumberOfPackets - Number of packets in array */
  42. /* */
  43. /* Return: */
  44. /* */
  45. /* VOID */
  46. /* */
  47. /****************************************************************************/
  48. VOID
  49. RndismpMultipleSend(IN NDIS_HANDLE MiniportAdapterContext,
  50. IN PPNDIS_PACKET PacketArray,
  51. IN UINT NumberOfPackets)
  52. {
  53. PRNDISMP_ADAPTER pAdapter;
  54. PNDIS_PACKET pNdisPacket;
  55. PRNDISMP_SEND_PKT_RESERVED_TEMP pSendRsvdTemp;
  56. ULONG i;
  57. // get adapter context
  58. pAdapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
  59. CHECK_VALID_ADAPTER(pAdapter);
  60. TRACE2(("RndismpMultipleSend\n"));
  61. if (pAdapter->bRunningOnWin9x)
  62. {
  63. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  64. for (i = 0; i < NumberOfPackets; i++)
  65. {
  66. pNdisPacket = PacketArray[i];
  67. pSendRsvdTemp = PRNDISMP_RESERVED_TEMP_FROM_SEND_PACKET(pNdisPacket);
  68. InsertTailList(&pAdapter->PendingSendProcessList, &pSendRsvdTemp->Link);
  69. }
  70. if (!pAdapter->SendProcessInProgress)
  71. {
  72. pAdapter->SendProcessInProgress = TRUE;
  73. NdisSetTimer(&pAdapter->SendProcessTimer, 0);
  74. }
  75. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  76. }
  77. else
  78. {
  79. //
  80. // Running on NT.
  81. //
  82. ASSERT(pAdapter->MultipleSendFunc != NULL);
  83. pAdapter->MultipleSendFunc(pAdapter,
  84. NULL,
  85. PacketArray,
  86. NumberOfPackets);
  87. }
  88. }
  89. /****************************************************************************/
  90. /* DoMultipleSend */
  91. /****************************************************************************/
  92. /* */
  93. /* Routine Description: */
  94. /* */
  95. /* NDIS Entry point to send an array of NDIS packets on the specified */
  96. /* adapter. Handles both connection-less and connection-oriented data. */
  97. /* */
  98. /* Arguments: */
  99. /* */
  100. /* pAdapter - pointer to Adapter structure */
  101. /* pVc - pointer to VC structure (NULL if CL send) */
  102. /* PacketArray - An array of pointers to NDIS packets */
  103. /* NumberOfPackets - Number of packets in array */
  104. /* */
  105. /* Return: */
  106. /* */
  107. /* VOID */
  108. /* */
  109. /****************************************************************************/
  110. VOID
  111. DoMultipleSend(IN PRNDISMP_ADAPTER pAdapter,
  112. IN PRNDISMP_VC pVc OPTIONAL,
  113. IN PPNDIS_PACKET PacketArray,
  114. IN UINT NumberOfPackets)
  115. {
  116. UINT PacketCount;
  117. PNDIS_PACKET pNdisPacket;
  118. PNDIS_PACKET * pPacketArray;
  119. PNDIS_PACKET * pPktPointer;
  120. PRNDISMP_SEND_PKT_RESERVED pResvd, pPrevResvd;
  121. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  122. PRNDISMP_PACKET_WRAPPER pPktWrapper;
  123. PMDL pMdl;
  124. ULONG TotalMessageLength; // of current message
  125. ULONG MessagePacketCount; // # of NDIS_PACKETS in this message
  126. ULONG CurPacketLength;
  127. PULONG pNextPacketOffset;
  128. NDIS_STATUS Status;
  129. ULONG i;
  130. BOOLEAN bMorePackets;
  131. pNextPacketOffset = NULL;
  132. pMsgFrame = NULL;
  133. Status = NDIS_STATUS_SUCCESS;
  134. PacketCount = 0;
  135. do
  136. {
  137. if (pAdapter->Halting)
  138. {
  139. Status = NDIS_STATUS_NOT_ACCEPTED;
  140. break;
  141. }
  142. pPacketArray = &PacketArray[0];
  143. #if DBG
  144. if (NumberOfPackets > 1)
  145. {
  146. if (FirstDbg)
  147. {
  148. FirstDbg = FALSE;
  149. PrintPkts = TRUE;
  150. }
  151. else
  152. {
  153. PrintPkts = FALSE;
  154. }
  155. }
  156. #endif
  157. for (PacketCount = 0;
  158. PacketCount < NumberOfPackets;
  159. NOTHING)
  160. {
  161. pNdisPacket = *pPacketArray;
  162. NdisQueryPacket(pNdisPacket, NULL, NULL, NULL, &CurPacketLength);
  163. TRACE2(("Send: Pkt %d bytes\n", CurPacketLength));
  164. bMorePackets = (pAdapter->bMultiPacketSupported &&
  165. (PacketCount < NumberOfPackets - 1));
  166. if (pMsgFrame == NULL)
  167. {
  168. //
  169. // Allocate a frame.
  170. //
  171. pMsgFrame = AllocateMsgFrame(pAdapter);
  172. if (pMsgFrame == NULL)
  173. {
  174. Status = NDIS_STATUS_RESOURCES;
  175. break;
  176. }
  177. pMsgFrame->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
  178. pMsgFrame->pVc = pVc;
  179. pMsgFrame->pNdisPacket = NULL;
  180. pPktPointer = &pMsgFrame->pNdisPacket;
  181. TotalMessageLength = 0;
  182. MessagePacketCount = 0;
  183. pPrevResvd = NULL;
  184. }
  185. //
  186. // Allocate and fill up the RNDIS message header for this packet.
  187. //
  188. pPktWrapper = PrepareDataMessage(
  189. pNdisPacket,
  190. pAdapter,
  191. pVc,
  192. &TotalMessageLength);
  193. if (pPktWrapper != NULL)
  194. {
  195. pPktWrapper->pMsgFrame = pMsgFrame;
  196. pMdl = pPktWrapper->pHeaderMdl;
  197. //
  198. // Initialize our context in this packet.
  199. //
  200. pResvd = PRNDISMP_RESERVED_FROM_SEND_PACKET(pNdisPacket);
  201. pResvd->pPktWrapper = pPktWrapper;
  202. pResvd->pNext = NULL;
  203. if (pMsgFrame->pMessageMdl == NULL)
  204. {
  205. pMsgFrame->pMessageMdl = pMdl;
  206. }
  207. //
  208. // Link this packet to the list.
  209. //
  210. *pPktPointer = pNdisPacket;
  211. MessagePacketCount++;
  212. if (pPrevResvd != NULL)
  213. {
  214. pPrevResvd->pPktWrapper->pTailMdl->Next = pMdl;
  215. }
  216. }
  217. if ((pPktWrapper == NULL) ||
  218. (!bMorePackets) ||
  219. (MessagePacketCount == pAdapter->MaxPacketsPerMessage))
  220. {
  221. //
  222. // Check if we have some data that we can send.
  223. //
  224. if (MessagePacketCount != 0)
  225. {
  226. //
  227. // Send this off to the microport.
  228. //
  229. #if DBG
  230. if (NumberOfPackets != 1)
  231. {
  232. TRACE2(("Send: MsgFrame %x, FirstPkt %x, %d/%d pkts\n",
  233. pMsgFrame,
  234. pMsgFrame->pNdisPacket,
  235. MessagePacketCount,
  236. NumberOfPackets));
  237. }
  238. {
  239. PMDL pTmpMdl;
  240. PUCHAR pBuf;
  241. ULONG Length;
  242. for (pTmpMdl = pMsgFrame->pMessageMdl;
  243. pTmpMdl != NULL;
  244. pTmpMdl = pTmpMdl->Next)
  245. {
  246. Length = RNDISMP_GET_MDL_LENGTH(pTmpMdl);
  247. pBuf = RNDISMP_GET_MDL_ADDRESS(pTmpMdl);
  248. if (pBuf != NULL)
  249. {
  250. TRACEDUMP(("MDL %x\n", pTmpMdl), pBuf, Length);
  251. }
  252. }
  253. }
  254. #endif // DBG
  255. {
  256. ULONG k;
  257. for (k = 0; k < MessagePacketCount; k++)
  258. {
  259. RNDISMP_INCR_STAT(pAdapter, XmitToMicroport);
  260. }
  261. }
  262. RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, FALSE, CompleteSendData);
  263. MessagePacketCount = 0;
  264. pMsgFrame = NULL;
  265. if (pPktWrapper != NULL)
  266. {
  267. PacketCount++;
  268. pPacketArray++;
  269. }
  270. continue;
  271. }
  272. else
  273. {
  274. TRACE1(("RndismpMultipleSend: Adapter %x, fail: PktWrp %x, bMore %d, MsgPktCount %d\n",
  275. pAdapter,
  276. pPktWrapper,
  277. bMorePackets,
  278. MessagePacketCount));
  279. Status = NDIS_STATUS_RESOURCES;
  280. break;
  281. }
  282. }
  283. pPktPointer = &pResvd->pNext;
  284. pPrevResvd = pResvd;
  285. PacketCount++;
  286. pPacketArray++;
  287. }
  288. if (PacketCount < NumberOfPackets)
  289. {
  290. break;
  291. }
  292. Status = NDIS_STATUS_SUCCESS;
  293. }
  294. while (FALSE);
  295. if (Status != NDIS_STATUS_SUCCESS)
  296. {
  297. TRACE1(("DoMultipleSend: Adapter %x, failure Status %x, PktCount %d, TotalPkts %d\n",
  298. pAdapter, Status, PacketCount, NumberOfPackets));
  299. //
  300. // Undo all we have done so far.
  301. //
  302. for (i = PacketCount; i < NumberOfPackets; i++)
  303. {
  304. RNDISMP_INCR_STAT(pAdapter, XmitError);
  305. if (pVc == NULL)
  306. {
  307. TRACE1(("DoMultipleSend: Adapter %x, failing pkt %x\n",
  308. pAdapter, PacketArray[i]));
  309. NdisMSendComplete(pAdapter->MiniportAdapterHandle,
  310. PacketArray[i],
  311. Status);
  312. }
  313. else
  314. {
  315. CompleteSendDataOnVc(pVc, PacketArray[i], Status);
  316. }
  317. }
  318. if (pMsgFrame)
  319. {
  320. pMsgFrame->pMessageMdl = NULL;
  321. DereferenceMsgFrame(pMsgFrame);
  322. }
  323. }
  324. return;
  325. }
  326. /****************************************************************************/
  327. /* DoMultipleSendRaw */
  328. /****************************************************************************/
  329. /* */
  330. /* Routine Description: */
  331. /* */
  332. /* NDIS Entry point to send an array of NDIS packets on the specified */
  333. /* adapter. Unlike DoMultipleSend, this handles raw encapsulation. */
  334. /* */
  335. /* Arguments: */
  336. /* */
  337. /* pAdapter - pointer to Adapter structure */
  338. /* pVc - pointer to VC structure (NULL if CL send) */
  339. /* PacketArray - An array of pointers to NDIS packets */
  340. /* NumberOfPackets - Number of packets in array */
  341. /* */
  342. /* Return: */
  343. /* */
  344. /* VOID */
  345. /* */
  346. /****************************************************************************/
  347. VOID
  348. DoMultipleSendRaw(IN PRNDISMP_ADAPTER pAdapter,
  349. IN PRNDISMP_VC pVc OPTIONAL,
  350. IN PPNDIS_PACKET PacketArray,
  351. IN UINT NumberOfPackets)
  352. {
  353. UINT PacketCount;
  354. PNDIS_PACKET pNdisPacket;
  355. PNDIS_PACKET * pPacketArray;
  356. PNDIS_PACKET * pPktPointer;
  357. PRNDISMP_SEND_PKT_RESERVED pResvd, pPrevResvd;
  358. PRNDISMP_MESSAGE_FRAME pMsgFrame;
  359. PRNDISMP_PACKET_WRAPPER pPktWrapper;
  360. PMDL pMdl;
  361. ULONG TotalMessageLength; // of current message
  362. ULONG MessagePacketCount; // # of NDIS_PACKETS in this message
  363. ULONG CurPacketLength;
  364. PULONG pNextPacketOffset;
  365. NDIS_STATUS Status;
  366. ULONG i;
  367. BOOLEAN bMorePackets;
  368. pNextPacketOffset = NULL;
  369. pMsgFrame = NULL;
  370. Status = NDIS_STATUS_SUCCESS;
  371. PacketCount = 0;
  372. if (pAdapter->Halting)
  373. {
  374. Status = NDIS_STATUS_NOT_ACCEPTED;
  375. } else
  376. {
  377. pPacketArray = &PacketArray[0];
  378. #if DBG
  379. if (NumberOfPackets > 1)
  380. {
  381. if (FirstDbg)
  382. {
  383. FirstDbg = FALSE;
  384. PrintPkts = TRUE;
  385. }
  386. else
  387. {
  388. PrintPkts = FALSE;
  389. }
  390. }
  391. #endif
  392. for (PacketCount = 0;
  393. PacketCount < NumberOfPackets;
  394. NOTHING)
  395. {
  396. pNdisPacket = *pPacketArray;
  397. NdisQueryPacket(pNdisPacket, NULL, NULL, NULL, &CurPacketLength);
  398. TRACE2(("Send: Pkt %d bytes\n", CurPacketLength));
  399. //
  400. // Allocate a frame.
  401. //
  402. pMsgFrame = AllocateMsgFrame(pAdapter);
  403. if (pMsgFrame == NULL)
  404. {
  405. Status = NDIS_STATUS_RESOURCES;
  406. break;
  407. }
  408. pMsgFrame->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
  409. pMsgFrame->pNdisPacket = pNdisPacket;
  410. NdisQueryPacket(pNdisPacket,NULL,NULL,&(pMsgFrame->pMessageMdl),NULL);
  411. TotalMessageLength = 0;
  412. pPktWrapper = PrepareDataMessageRaw(
  413. pNdisPacket,
  414. pAdapter,
  415. &TotalMessageLength);
  416. if (pPktWrapper != NULL)
  417. {
  418. pPktWrapper->pMsgFrame = pMsgFrame;
  419. pMdl = pPktWrapper->pHeaderMdl;
  420. pResvd = PRNDISMP_RESERVED_FROM_SEND_PACKET(pNdisPacket);
  421. pResvd->pPktWrapper = pPktWrapper;
  422. pResvd->pNext = NULL;
  423. pMsgFrame->pMessageMdl = pMdl;
  424. #ifdef DBG
  425. TRACE2(("Send: MsgFrame %x, Pkt %x\n",pMsgFrame, pMsgFrame->pNdisPacket));
  426. #endif
  427. RNDISMP_INCR_STAT(pAdapter,XmitToMicroport);
  428. RNDISMP_SEND_TO_MICROPORT(pAdapter,pMsgFrame,FALSE,CompleteSendData);
  429. }
  430. PacketCount++;
  431. }
  432. }
  433. if (Status != NDIS_STATUS_SUCCESS)
  434. {
  435. TRACE1(("DoMultipleSendRaw: Adapter %x, failure Status %x, PktCount %d, TotalPkts %d\n",
  436. pAdapter, Status, PacketCount, NumberOfPackets));
  437. //
  438. // Undo all we have done so far.
  439. //
  440. for (i = PacketCount; i < NumberOfPackets; i++)
  441. {
  442. RNDISMP_INCR_STAT(pAdapter, XmitError);
  443. TRACE1(("DoMultipleSendRaw: Adapter %x, failing pkt %x\n",
  444. pAdapter, PacketArray[i]));
  445. NdisMSendComplete(pAdapter->MiniportAdapterHandle,
  446. PacketArray[i],
  447. Status);
  448. }
  449. if (pMsgFrame)
  450. {
  451. pMsgFrame->pMessageMdl = NULL;
  452. DereferenceMsgFrame(pMsgFrame);
  453. }
  454. }
  455. return;
  456. }
  457. /****************************************************************************/
  458. /* PrepareDataMessage */
  459. /****************************************************************************/
  460. /* */
  461. /* Routine Description: */
  462. /* */
  463. /* Utility routine to prepare a complete or part of a data message. */
  464. /* */
  465. /* Arguments: */
  466. /* */
  467. /* pNdisPacket - the NDIS packet to be converted */
  468. /* pAdapter - Adapter on which the packet is being sent */
  469. /* pVc - VC on which the packet is sent (NULL if no VC context) */
  470. /* pTotalMessageLength - On input, contains the total message length */
  471. /* filled in so far. Updated on output. */
  472. /* */
  473. /* */
  474. /* Return: */
  475. /* */
  476. /* PRNDISMP_PACKET_WRAPPER */
  477. /* */
  478. /****************************************************************************/
  479. PRNDISMP_PACKET_WRAPPER
  480. PrepareDataMessage(IN PNDIS_PACKET pNdisPacket,
  481. IN PRNDISMP_ADAPTER pAdapter,
  482. IN PRNDISMP_VC pVc OPTIONAL,
  483. IN OUT PULONG pTotalMessageLength)
  484. {
  485. PMDL pMdl, pNextMdl;
  486. PMDL * ppNextMdl;
  487. PRNDISMP_PACKET_WRAPPER pPktWrapper;
  488. RNDIS_MESSAGE UNALIGNED * pRndisMessage;
  489. RNDIS_PACKET UNALIGNED * pPacketMsg;
  490. PNDIS_BUFFER pNdisBuffer;
  491. PNDIS_BUFFER pNextNdisBuffer;
  492. ULONG TotalMessageLength;
  493. ULONG PacketMsgLength;
  494. ULONG OobDataLength;
  495. ULONG PerPacketInfoLength;
  496. ULONG AlignedLength;
  497. ULONG AlignmentOffset;
  498. ULONG TotalDataLength;
  499. ULONG TcpipChecksum, TcpLargeSend, PacketPriority;
  500. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  501. pPktWrapper = NULL;
  502. pMdl = NULL;
  503. do
  504. {
  505. TotalMessageLength = 0;
  506. RNDISMP_GET_ALIGNED_LENGTH(AlignedLength, *pTotalMessageLength, pAdapter);
  507. AlignmentOffset = (AlignedLength - *pTotalMessageLength);
  508. //
  509. // Compute attachments. Zero for now.
  510. // TBD -- do the real thing.
  511. //
  512. OobDataLength = 0;
  513. PerPacketInfoLength = 0;
  514. //
  515. // Look for per-packet info elements, only on Win2K/Whistler.
  516. //
  517. if (!pAdapter->bRunningOnWin9x)
  518. {
  519. //
  520. // TCP/IP checksum offload?
  521. //
  522. TcpipChecksum = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(pNdisPacket, TcpIpChecksumPacketInfo));
  523. if (TcpipChecksum != 0)
  524. {
  525. PerPacketInfoLength += sizeof(RNDIS_PER_PACKET_INFO) + sizeof(ULONG);
  526. TRACE2(("Send: Pkt %p has TCP checksum %x\n",
  527. pNdisPacket, TcpipChecksum));
  528. }
  529. //
  530. // TCP large send offload?
  531. //
  532. TcpLargeSend = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(pNdisPacket, TcpLargeSendPacketInfo));
  533. if (TcpLargeSend != 0)
  534. {
  535. PerPacketInfoLength += sizeof(RNDIS_PER_PACKET_INFO) + sizeof(ULONG);
  536. TRACE2(("Send: Pkt %p has TCP large send %x\n",
  537. pNdisPacket, TcpLargeSend));
  538. }
  539. //
  540. // Packet priority?
  541. //
  542. PacketPriority = PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(pNdisPacket, Ieee8021pPriority));
  543. if (PacketPriority != 0)
  544. {
  545. PerPacketInfoLength += sizeof(RNDIS_PER_PACKET_INFO) + sizeof(ULONG);
  546. TRACE2(("Send: Pkt %p has priority %x\n",
  547. pNdisPacket, PacketPriority));
  548. }
  549. }
  550. PacketMsgLength = sizeof(*pPacketMsg) +
  551. OobDataLength +
  552. PerPacketInfoLength +
  553. AlignmentOffset;
  554. //
  555. // Need space for common RNDIS message header.
  556. //
  557. PacketMsgLength += (sizeof(RNDIS_MESSAGE) - sizeof(RNDIS_MESSAGE_CONTAINER));
  558. NdisQueryPacket(pNdisPacket, NULL, NULL, NULL, &TotalDataLength);
  559. //
  560. // We know the max transfer size of any message that we are allowed
  561. // to send to the device. Is this going beyond that limit?
  562. //
  563. if (*pTotalMessageLength + PacketMsgLength + TotalDataLength >
  564. pAdapter->MaxTransferSize)
  565. {
  566. TRACE2(("PrepareDataMessage: Adapter %x, pkt %x, length %d > device limit (%d)\n",
  567. pAdapter,
  568. pNdisPacket,
  569. *pTotalMessageLength + PacketMsgLength + TotalDataLength,
  570. pAdapter->MaxTransferSize));
  571. break;
  572. }
  573. //
  574. // Allocate an RNDIS_PACKET buffer.
  575. //
  576. pPktWrapper = AllocatePacketMsgWrapper(pAdapter, PacketMsgLength);
  577. if (pPktWrapper == NULL)
  578. {
  579. TRACE1(("PrepareDataMessage: failed to alloc wrapper, Adapter %x, Length %d\n", pAdapter, PacketMsgLength));
  580. ASSERT(FALSE);
  581. Status = NDIS_STATUS_RESOURCES;
  582. break;
  583. }
  584. pPktWrapper->pNdisPacket = pNdisPacket;
  585. pPktWrapper->pVc = pVc;
  586. pRndisMessage = (PRNDIS_MESSAGE)
  587. ((ULONG_PTR)&pPktWrapper->Packet[0] + AlignmentOffset);
  588. pPacketMsg = (PRNDIS_PACKET)(&pRndisMessage->Message);
  589. pRndisMessage->NdisMessageType = REMOTE_NDIS_PACKET_MSG;
  590. if (pVc == NULL)
  591. {
  592. pPacketMsg->VcHandle = 0;
  593. }
  594. else
  595. {
  596. pPacketMsg->VcHandle = pVc->DeviceVcContext;
  597. }
  598. #if DBG
  599. if (PrintPkts)
  600. {
  601. TRACE1((" Offs %d/x%x AlignOff %d/x%x, DataLen %d/x%x\n",
  602. *pTotalMessageLength, *pTotalMessageLength,
  603. AlignmentOffset, AlignmentOffset,
  604. TotalDataLength, TotalDataLength));
  605. }
  606. #endif // DBG
  607. //
  608. // Allocate MDLs for the RNDIS_PACKET header and for each
  609. // component NDIS buffer in the packet.
  610. //
  611. pMdl = IoAllocateMdl(
  612. &pPktWrapper->Packet[0],
  613. PacketMsgLength,
  614. FALSE,
  615. FALSE,
  616. NULL);
  617. if (pMdl == NULL)
  618. {
  619. TRACE1(("PrepareDataMsg: Adapter %x failed to alloc MDL for header\n", pAdapter));
  620. Status = NDIS_STATUS_RESOURCES;
  621. TRACE1(("PrepareDataMsg: outstanding MDL count %d, at %x\n", MdlsAllocated, &MdlsAllocated));
  622. ASSERT(FALSE);
  623. break;
  624. }
  625. NdisInterlockedIncrement(&MdlsAllocated);
  626. MmBuildMdlForNonPagedPool(pMdl);
  627. pMdl->Next = NULL;
  628. pPktWrapper->pHeaderMdl = pMdl;
  629. ppNextMdl = &pMdl->Next;
  630. TRACE2(("PrepareDataMsg: NdisPkt %x, PacketMsgLen %d, TotalDatalen %d, Mdl %x, pRndisMessage %x\n",
  631. pNdisPacket, PacketMsgLength, TotalDataLength, pMdl, pRndisMessage));
  632. TotalDataLength = 0;
  633. for (pNdisBuffer = pNdisPacket->Private.Head;
  634. pNdisBuffer != NULL;
  635. pNdisBuffer = pNextNdisBuffer)
  636. {
  637. PVOID VirtualAddress;
  638. UINT BufferLength;
  639. NdisGetNextBuffer(pNdisBuffer, &pNextNdisBuffer);
  640. #ifndef BUILD_WIN9X
  641. NdisQueryBufferSafe(pNdisBuffer, &VirtualAddress, &BufferLength, NormalPagePriority);
  642. if ((BufferLength != 0) && (VirtualAddress == NULL))
  643. {
  644. TRACE1(("PrepareDataMsg: Adapter %x failed to query buffer %p, Pkt %p\n",
  645. pAdapter, pNdisBuffer, pNdisPacket));
  646. Status = NDIS_STATUS_RESOURCES;
  647. break;
  648. }
  649. #else
  650. NdisQueryBuffer(pNdisBuffer, &VirtualAddress, &BufferLength);
  651. #endif // BUILD_WIN9X
  652. //
  653. // Skip any 0-length buffers given to us by IP or NDISTEST
  654. //
  655. if (BufferLength != 0)
  656. {
  657. TotalDataLength += BufferLength;
  658. pMdl = IoAllocateMdl(
  659. VirtualAddress,
  660. BufferLength,
  661. FALSE,
  662. FALSE,
  663. NULL);
  664. if (pMdl == NULL)
  665. {
  666. TRACE1(("PrepareDataMsg: Adapter %x failed to alloc MDL\n", pAdapter));
  667. Status = NDIS_STATUS_RESOURCES;
  668. TRACE1(("PrepareDataMsg: outstanding MDL count %d, at %x\n", MdlsAllocated, &MdlsAllocated));
  669. ASSERT(FALSE);
  670. break;
  671. }
  672. NdisInterlockedIncrement(&MdlsAllocated);
  673. MmBuildMdlForNonPagedPool(pMdl);
  674. *ppNextMdl = pMdl;
  675. ppNextMdl = &pMdl->Next;
  676. pMdl->Next = NULL;
  677. }
  678. }
  679. if (pNdisBuffer != NULL)
  680. {
  681. //
  682. // We bailed out before reaching the end of the list.
  683. //
  684. break;
  685. }
  686. *ppNextMdl = NULL;
  687. pPktWrapper->pTailMdl = pMdl;
  688. TotalMessageLength += (PacketMsgLength + TotalDataLength);
  689. pRndisMessage->MessageLength = PacketMsgLength + TotalDataLength;
  690. *pTotalMessageLength += TotalMessageLength;
  691. //
  692. // Fill in the RNDIS_PACKET message completely now.
  693. //
  694. pPacketMsg->DataOffset = sizeof(RNDIS_PACKET) + OobDataLength + PerPacketInfoLength;
  695. pPacketMsg->DataLength = TotalDataLength;
  696. if (PerPacketInfoLength)
  697. {
  698. PRNDIS_PER_PACKET_INFO pPerPacketInfo;
  699. pPacketMsg->PerPacketInfoOffset = sizeof(RNDIS_PACKET);
  700. pPacketMsg->PerPacketInfoLength = PerPacketInfoLength;
  701. pPerPacketInfo = (PRNDIS_PER_PACKET_INFO)((PUCHAR)pPacketMsg + sizeof(RNDIS_PACKET));
  702. if (TcpipChecksum)
  703. {
  704. pPerPacketInfo->Size = sizeof(RNDIS_PER_PACKET_INFO) + sizeof(ULONG);
  705. pPerPacketInfo->Type = TcpIpChecksumPacketInfo;
  706. pPerPacketInfo->PerPacketInformationOffset = sizeof(RNDIS_PER_PACKET_INFO);
  707. *(PULONG)(pPerPacketInfo + 1) = TcpipChecksum;
  708. pPerPacketInfo = (PRNDIS_PER_PACKET_INFO)((PUCHAR)pPerPacketInfo + pPerPacketInfo->Size);
  709. }
  710. if (TcpLargeSend)
  711. {
  712. pPerPacketInfo->Size = sizeof(RNDIS_PER_PACKET_INFO) + sizeof(ULONG);
  713. pPerPacketInfo->Type = TcpLargeSendPacketInfo;
  714. pPerPacketInfo->PerPacketInformationOffset = sizeof(RNDIS_PER_PACKET_INFO);
  715. *(PULONG)(pPerPacketInfo + 1) = TcpLargeSend;
  716. pPerPacketInfo = (PRNDIS_PER_PACKET_INFO)((PUCHAR)pPerPacketInfo + pPerPacketInfo->Size);
  717. //
  718. // Since we do not have a send-completion message, we fill up
  719. // the "ack" for large send right here.
  720. //
  721. NDIS_PER_PACKET_INFO_FROM_PACKET(pNdisPacket, TcpLargeSendPacketInfo) =
  722. UlongToPtr(TotalDataLength);
  723. }
  724. if (PacketPriority)
  725. {
  726. pPerPacketInfo->Size = sizeof(RNDIS_PER_PACKET_INFO) + sizeof(ULONG);
  727. pPerPacketInfo->Type = Ieee8021pPriority;
  728. pPerPacketInfo->PerPacketInformationOffset = sizeof(RNDIS_PER_PACKET_INFO);
  729. *(PULONG)(pPerPacketInfo + 1) = PacketPriority;
  730. pPerPacketInfo = (PRNDIS_PER_PACKET_INFO)((PUCHAR)pPerPacketInfo + pPerPacketInfo->Size);
  731. }
  732. }
  733. }
  734. while (FALSE);
  735. if (Status != NDIS_STATUS_SUCCESS)
  736. {
  737. TRACE1(("PrepareDataMessage: Adapter %x, failed %x\n", pAdapter, Status));
  738. //
  739. // Undo all we have done so far.
  740. //
  741. if (pPktWrapper)
  742. {
  743. for (pMdl = pPktWrapper->pHeaderMdl;
  744. pMdl != NULL;
  745. pMdl = pNextMdl)
  746. {
  747. pNextMdl = pMdl->Next;
  748. IoFreeMdl(pMdl);
  749. NdisInterlockedDecrement(&MdlsAllocated);
  750. }
  751. FreePacketMsgWrapper(pPktWrapper);
  752. pPktWrapper = NULL;
  753. }
  754. }
  755. TRACE2(("PrepareDataMessage (%08X)\n", pPktWrapper));
  756. return (pPktWrapper);
  757. }
  758. /****************************************************************************/
  759. /* PrepareDataMessageRaw */
  760. /****************************************************************************/
  761. /* */
  762. /* Routine Description: */
  763. /* */
  764. /* Utility routine to prepare a complete or part of a data message. */
  765. /* */
  766. /* Arguments: */
  767. /* */
  768. /* pNdisPacket - the NDIS packet to be converted */
  769. /* pAdapter - Adapter on which the packet is being sent */
  770. /* pVc - VC on which the packet is sent (NULL if no VC context) */
  771. /* pTotalMessageLength - On input, contains the total message length */
  772. /* filled in so far. Updated on output. */
  773. /* */
  774. /* */
  775. /* Return: */
  776. /* */
  777. /* PRNDISMP_PACKET_WRAPPER */
  778. /* */
  779. /****************************************************************************/
  780. PRNDISMP_PACKET_WRAPPER
  781. PrepareDataMessageRaw(IN PNDIS_PACKET pNdisPacket,
  782. IN PRNDISMP_ADAPTER pAdapter,
  783. IN OUT PULONG pTotalMessageLength)
  784. {
  785. PMDL pMdl, pNextMdl;
  786. PMDL * ppNextMdl;
  787. PRNDISMP_PACKET_WRAPPER pPktWrapper;
  788. RNDIS_MESSAGE UNALIGNED * pRndisMessage;
  789. PNDIS_BUFFER pNdisBuffer;
  790. PNDIS_BUFFER pNextNdisBuffer;
  791. ULONG TotalMessageLength;
  792. ULONG TotalDataLength;
  793. ULONG AlignedLength;
  794. ULONG AlignmentOffset;
  795. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  796. pPktWrapper = NULL;
  797. pMdl = NULL;
  798. RNDISMP_GET_ALIGNED_LENGTH(AlignedLength, *pTotalMessageLength, pAdapter);
  799. AlignmentOffset = (AlignedLength - *pTotalMessageLength);
  800. do
  801. {
  802. TotalMessageLength = 0;
  803. //
  804. // Allocate an RNDIS_PACKET buffer.
  805. //
  806. pPktWrapper = AllocatePacketMsgWrapper(pAdapter, 0);
  807. if (pPktWrapper == NULL)
  808. {
  809. TRACE1(("PrepareDataMessage: failed to alloc wrapper, Adapter %x\n", pAdapter));
  810. ASSERT(FALSE);
  811. Status = NDIS_STATUS_RESOURCES;
  812. break;
  813. }
  814. pPktWrapper->pNdisPacket = pNdisPacket;
  815. pPktWrapper->pVc = NULL;
  816. pPktWrapper->pHeaderMdl = NULL;
  817. TotalDataLength = 0;
  818. for (pNdisBuffer = pNdisPacket->Private.Head;
  819. pNdisBuffer != NULL;
  820. pNdisBuffer = pNextNdisBuffer)
  821. {
  822. PVOID VirtualAddress;
  823. UINT BufferLength;
  824. NdisGetNextBuffer(pNdisBuffer, &pNextNdisBuffer);
  825. #ifndef BUILD_WIN9X
  826. NdisQueryBufferSafe(pNdisBuffer, &VirtualAddress, &BufferLength, NormalPagePriority);
  827. if ((BufferLength != 0) && (VirtualAddress == NULL))
  828. {
  829. TRACE1(("PrepareDataMsg: Adapter %x failed to query buffer %p, Pkt %p\n",
  830. pAdapter, pNdisBuffer, pNdisPacket));
  831. Status = NDIS_STATUS_RESOURCES;
  832. break;
  833. }
  834. #else
  835. NdisQueryBuffer(pNdisBuffer, &VirtualAddress, &BufferLength);
  836. #endif // BUILD_WIN9X
  837. //
  838. // Skip any 0-length buffers given to us by IP or NDISTEST
  839. //
  840. if (BufferLength != 0)
  841. {
  842. TotalDataLength += BufferLength;
  843. pMdl = IoAllocateMdl(
  844. VirtualAddress,
  845. BufferLength,
  846. FALSE,
  847. FALSE,
  848. NULL);
  849. if (pMdl == NULL)
  850. {
  851. TRACE1(("PrepareDataMsg: Adapter %x failed to alloc MDL\n", pAdapter));
  852. Status = NDIS_STATUS_RESOURCES;
  853. TRACE1(("PrepareDataMsg: outstanding MDL count %d, at %x\n", MdlsAllocated, &MdlsAllocated));
  854. ASSERT(FALSE);
  855. break;
  856. }
  857. pMdl->Next = NULL;
  858. if (pPktWrapper->pHeaderMdl == NULL)
  859. {
  860. pPktWrapper->pHeaderMdl = pMdl;
  861. pPktWrapper->pTailMdl = pMdl;
  862. } else
  863. {
  864. pPktWrapper->pTailMdl->Next = pMdl;
  865. pPktWrapper->pTailMdl = pMdl;
  866. }
  867. NdisInterlockedIncrement(&MdlsAllocated);
  868. MmBuildMdlForNonPagedPool(pMdl);
  869. }
  870. }
  871. if (pNdisBuffer != NULL)
  872. {
  873. //
  874. // We bailed out before reaching the end of the list.
  875. //
  876. break;
  877. }
  878. *pTotalMessageLength += TotalDataLength;
  879. }
  880. while (FALSE);
  881. if (Status != NDIS_STATUS_SUCCESS)
  882. {
  883. TRACE1(("PrepareDataMessage: Adapter %x, failed %x\n", pAdapter, Status));
  884. //
  885. // Undo all we have done so far.
  886. //
  887. if (pPktWrapper)
  888. {
  889. for (pMdl = pPktWrapper->pHeaderMdl;
  890. pMdl != NULL;
  891. pMdl = pNextMdl)
  892. {
  893. pNextMdl = pMdl->Next;
  894. IoFreeMdl(pMdl);
  895. NdisInterlockedDecrement(&MdlsAllocated);
  896. }
  897. FreePacketMsgWrapper(pPktWrapper);
  898. pPktWrapper = NULL;
  899. }
  900. }
  901. TRACE2(("PrepareDataMessage (%08X)\n", pPktWrapper));
  902. return (pPktWrapper);
  903. }
  904. /****************************************************************************/
  905. /* AllocatePacketMsgWrapper */
  906. /****************************************************************************/
  907. /* */
  908. /* Routine Description: */
  909. /* */
  910. /* Allocate a structure to keep information about one NDIS packet sent */
  911. /* through the microport. */
  912. /* */
  913. /* Arguments: */
  914. /* */
  915. /* pAdapter - Adapter on which this packet is going to be sent. */
  916. /* MsgHeaderLength - Total length of the wrapper structure */
  917. /* */
  918. /* Return: */
  919. /* */
  920. /* PRNDISMP_PACKET_WRAPPER */
  921. /* */
  922. /****************************************************************************/
  923. PRNDISMP_PACKET_WRAPPER
  924. AllocatePacketMsgWrapper(IN PRNDISMP_ADAPTER pAdapter,
  925. IN ULONG MsgHeaderLength)
  926. {
  927. PRNDISMP_PACKET_WRAPPER pPktWrapper;
  928. NDIS_STATUS Status;
  929. ULONG TotalLength;
  930. TotalLength = sizeof(RNDISMP_PACKET_WRAPPER) + MsgHeaderLength;
  931. Status = MemAlloc(&pPktWrapper, TotalLength);
  932. if (Status == NDIS_STATUS_SUCCESS)
  933. {
  934. NdisZeroMemory(pPktWrapper, TotalLength);
  935. NdisInterlockedIncrement(&PktWrapperAllocated);
  936. }
  937. else
  938. {
  939. TRACE1(("AllocPacketMsgWrapper failed, adapter %x, alloc count %d at %x\n",
  940. pAdapter, PktWrapperAllocated, &PktWrapperAllocated));
  941. ASSERT(FALSE);
  942. pPktWrapper = NULL;
  943. }
  944. return (pPktWrapper);
  945. }
  946. /****************************************************************************/
  947. /* FreePacketMsgWrapper */
  948. /****************************************************************************/
  949. /* */
  950. /* Routine Description: */
  951. /* */
  952. /* Free a structure used to keep information about one NDIS packet sent */
  953. /* through the microport. */
  954. /* */
  955. /* Arguments: */
  956. /* */
  957. /* pPktWrapper - Pointer to wrapper structure. */
  958. /* */
  959. /* Return: */
  960. /* */
  961. /* VOID */
  962. /* */
  963. /****************************************************************************/
  964. VOID
  965. FreePacketMsgWrapper(IN PRNDISMP_PACKET_WRAPPER pPktWrapper)
  966. {
  967. MemFree(pPktWrapper, sizeof(RNDISMP_PACKET_WRAPPER));
  968. NdisInterlockedDecrement(&PktWrapperAllocated);
  969. }
  970. /****************************************************************************/
  971. /* CompleteSendData */
  972. /****************************************************************************/
  973. /* */
  974. /* Routine Description: */
  975. /* */
  976. /* Callback function to handle completion of send data message sent */
  977. /* down to microport */
  978. /* */
  979. /* Arguments: */
  980. /* */
  981. /* pMsgFrame - our frame structure holding information about a send */
  982. /* SendStatus - indicate status of send message */
  983. /* */
  984. /* Return: */
  985. /* */
  986. /* VOID */
  987. /* */
  988. /****************************************************************************/
  989. VOID
  990. CompleteSendData(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
  991. IN NDIS_STATUS SendStatus)
  992. {
  993. PRNDISMP_ADAPTER Adapter;
  994. PNDIS_PACKET Packet;
  995. PMDL pMdl, pNextMdl;
  996. PRNDISMP_PACKET_WRAPPER pPktWrapper, pNextPktWrapper;
  997. PRNDISMP_SEND_PKT_RESERVED pResvd;
  998. PNDIS_PACKET NextPacket;
  999. PRNDISMP_VC pVc;
  1000. Adapter = pMsgFrame->pAdapter;
  1001. TRACE2(("CompleteSendData: Adapter %x, MsgFrame %x, SendStatus %x\n",
  1002. Adapter, pMsgFrame, SendStatus));
  1003. #if DBG_TIME_STAMPS
  1004. {
  1005. ULONG NowTime;
  1006. ULONG PendedTime;
  1007. RNDISMP_GET_TIME_STAMP(&NowTime);
  1008. PendedTime = NowTime - pMsgFrame->TimeSent;
  1009. if (PendedTime > Adapter->MaxSendCompleteTime)
  1010. {
  1011. TRACE1(("CompleteSendData: Adapter %x: pend time %d millisec\n",
  1012. Adapter, PendedTime));
  1013. Adapter->MaxSendCompleteTime = PendedTime;
  1014. }
  1015. }
  1016. #endif // DBG_TIME_STAMPS
  1017. //
  1018. // free all MDLs we had allocated.
  1019. //
  1020. for (pMdl = pMsgFrame->pMessageMdl;
  1021. pMdl != NULL;
  1022. pMdl = pNextMdl)
  1023. {
  1024. pNextMdl = pMdl->Next;
  1025. IoFreeMdl(pMdl);
  1026. NdisInterlockedDecrement(&MdlsAllocated);
  1027. }
  1028. //
  1029. // we may have sent several NDIS packets in one message
  1030. // so we have to walk the list and complete each one
  1031. //
  1032. for (Packet = pMsgFrame->pNdisPacket;
  1033. Packet != NULL;
  1034. Packet = NextPacket)
  1035. {
  1036. pResvd = PRNDISMP_RESERVED_FROM_SEND_PACKET(Packet);
  1037. // get the next packet linked
  1038. NextPacket = pResvd->pNext;
  1039. pPktWrapper = pResvd->pPktWrapper;
  1040. #if DBG
  1041. if (NextPacket != NULL)
  1042. {
  1043. TRACE2(("CompleteSendData: multi: MsgFrame %x, tpkt %x, wrapper %x\n",
  1044. pMsgFrame, Packet,
  1045. // *(PULONG)((PUCHAR)Packet + 0x98),
  1046. pPktWrapper));
  1047. }
  1048. #endif // DBG
  1049. pVc = pPktWrapper->pVc;
  1050. // free the wrapper structure for this packet.
  1051. FreePacketMsgWrapper(pPktWrapper);
  1052. // send completion to upper layers
  1053. TRACE2(("CompleteSendData: Adapter %x, completing pkt %x\n", Adapter, Packet));
  1054. if (SendStatus == NDIS_STATUS_SUCCESS)
  1055. {
  1056. RNDISMP_INCR_STAT(Adapter, XmitOk);
  1057. }
  1058. else
  1059. {
  1060. RNDISMP_INCR_STAT(Adapter, XmitError);
  1061. }
  1062. if (pVc == NULL)
  1063. {
  1064. NdisMSendComplete(Adapter->MiniportAdapterHandle,
  1065. Packet,
  1066. SendStatus);
  1067. }
  1068. else
  1069. {
  1070. CompleteSendDataOnVc(pVc, Packet, SendStatus);
  1071. }
  1072. }
  1073. // free up frame and resources
  1074. pMsgFrame->pMessageMdl = NULL;
  1075. DereferenceMsgFrame(pMsgFrame);
  1076. } // CompleteSendData
  1077. /****************************************************************************/
  1078. /* FreeMsgAfterSend */
  1079. /****************************************************************************/
  1080. /* */
  1081. /* Routine Description: */
  1082. /* */
  1083. /* Called by microport to indicate completion of send data message sent */
  1084. /* down by miniport */
  1085. /* */
  1086. /* Arguments: */
  1087. /* */
  1088. /* pMsgFrame - our frame structure holding information about a send */
  1089. /* SendStatus - indicate status of send message */
  1090. /* */
  1091. /* Return: */
  1092. /* */
  1093. /* VOID */
  1094. /* */
  1095. /****************************************************************************/
  1096. VOID
  1097. FreeMsgAfterSend(IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
  1098. IN NDIS_STATUS SendStatus)
  1099. {
  1100. DereferenceMsgFrame(pMsgFrame);
  1101. }
  1102. #if THROTTLE_MESSAGES
  1103. /****************************************************************************/
  1104. /* QueueMessageToMicroport */
  1105. /****************************************************************************/
  1106. /* */
  1107. /* Routine Description: */
  1108. /* */
  1109. /* Queue the given message on the list of messages to be send to the */
  1110. /* microport, and start sending down these, if we haven't sent too many */
  1111. /* already. */
  1112. /* */
  1113. /* Arguments: */
  1114. /* */
  1115. /* pAdapter - our Adapter structure */
  1116. /* pMsgFrame - our frame structure holding information about a send */
  1117. /* bQueueMessageForResponse - add this message to the pending-response */
  1118. /* list on the adapter. We expect a response */
  1119. /* for this from the device. */
  1120. /* */
  1121. /* Return: */
  1122. /* */
  1123. /* VOID */
  1124. /* */
  1125. /****************************************************************************/
  1126. VOID
  1127. QueueMessageToMicroport(IN PRNDISMP_ADAPTER pAdapter,
  1128. IN PRNDISMP_MESSAGE_FRAME pMsgFrame,
  1129. IN BOOLEAN bQueueMessageForResponse)
  1130. {
  1131. PLIST_ENTRY pEnt;
  1132. PRNDISMP_MESSAGE_FRAME pFrame;
  1133. RM_CHANNEL_TYPE ChannelType;
  1134. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  1135. do
  1136. {
  1137. if (pMsgFrame)
  1138. {
  1139. //
  1140. // Add to waiting queue.
  1141. //
  1142. InsertTailList(&pAdapter->WaitingMessageList, &pMsgFrame->PendLink);
  1143. if (bQueueMessageForResponse)
  1144. {
  1145. InsertTailList(&pAdapter->PendingFrameList, &pMsgFrame->Link);
  1146. }
  1147. }
  1148. //
  1149. // Prevent more than one thread from executing below.
  1150. //
  1151. if (pAdapter->SendInProgress)
  1152. {
  1153. break;
  1154. }
  1155. pAdapter->SendInProgress = TRUE;
  1156. //
  1157. // Send as many messages to the microport as we can, without exceeding
  1158. // the high-water mark for messages pending at the microport.
  1159. //
  1160. while ((pAdapter->CurPendedMessages < pAdapter->HiWatPendedMessages) &&
  1161. !IsListEmpty(&pAdapter->WaitingMessageList))
  1162. {
  1163. //
  1164. // Take out the first message in the waiting queue.
  1165. //
  1166. pEnt = pAdapter->WaitingMessageList.Flink;
  1167. pFrame = CONTAINING_RECORD(pEnt, RNDISMP_MESSAGE_FRAME, PendLink);
  1168. RemoveEntryList(pEnt);
  1169. CHECK_VALID_FRAME(pFrame);
  1170. pAdapter->CurPendedMessages++;
  1171. InsertTailList(&pAdapter->PendingAtMicroportList, pEnt);
  1172. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  1173. RNDISMP_GET_TIME_STAMP(&pFrame->TimeSent);
  1174. DBG_LOG_SEND_MSG(pAdapter, pFrame);
  1175. //
  1176. // Check if we are halting the adapter, fail if so.
  1177. // NOTE: the only message we let thru is a HALT.
  1178. //
  1179. if (pAdapter->Halting &&
  1180. (pFrame->NdisMessageType != REMOTE_NDIS_HALT_MSG))
  1181. {
  1182. TRACE1(("QueueMsg: Adapter %x is halting, dropped msg 0x%x!\n",
  1183. pAdapter, pFrame->NdisMessageType));
  1184. RndisMSendComplete(
  1185. (NDIS_HANDLE)pAdapter,
  1186. pFrame,
  1187. NDIS_STATUS_NOT_ACCEPTED);
  1188. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  1189. continue;
  1190. }
  1191. //
  1192. // Send the message to the microport. The microport will
  1193. // call RndisMSendComplete when it is done with it.
  1194. //
  1195. #if DBG
  1196. {
  1197. ULONG Length;
  1198. PUCHAR pBuf;
  1199. Length = RNDISMP_GET_MDL_LENGTH(pFrame->pMessageMdl);
  1200. pBuf = RNDISMP_GET_MDL_ADDRESS(pFrame->pMessageMdl);
  1201. if (pBuf != NULL)
  1202. {
  1203. TRACEDUMP(("Sending msg type %x (%d bytes):\n",
  1204. pFrame->NdisMessageType, Length), pBuf, Length);
  1205. }
  1206. }
  1207. #endif
  1208. //
  1209. // Does this go on the data or control channel of the microport?
  1210. //
  1211. if (pFrame->NdisMessageType == REMOTE_NDIS_PACKET_MSG)
  1212. {
  1213. ChannelType = RMC_DATA;
  1214. }
  1215. else
  1216. {
  1217. ChannelType = RMC_CONTROL;
  1218. }
  1219. (pAdapter)->RmSendMessageHandler(pAdapter->MicroportAdapterContext,
  1220. pFrame->pMessageMdl,
  1221. (NDIS_HANDLE)pFrame,
  1222. ChannelType);
  1223. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  1224. }
  1225. pAdapter->SendInProgress = FALSE;
  1226. }
  1227. while (FALSE);
  1228. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  1229. }
  1230. /****************************************************************************/
  1231. /* FlushPendingMessages */
  1232. /****************************************************************************/
  1233. /* */
  1234. /* Routine Description: */
  1235. /* */
  1236. /* Remove and send-complete any messages pending to be sent to the */
  1237. /* microport. */
  1238. /* */
  1239. /* Arguments: */
  1240. /* */
  1241. /* pAdapter - our Adapter structure */
  1242. /* */
  1243. /* Return: */
  1244. /* */
  1245. /* VOID */
  1246. /* */
  1247. /****************************************************************************/
  1248. VOID
  1249. FlushPendingMessages(IN PRNDISMP_ADAPTER pAdapter)
  1250. {
  1251. PLIST_ENTRY pEnt;
  1252. PRNDISMP_MESSAGE_FRAME pFrame;
  1253. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  1254. //
  1255. // Prevent further sends to microport.
  1256. //
  1257. pAdapter->SendInProgress = TRUE;
  1258. while (!IsListEmpty(&pAdapter->WaitingMessageList))
  1259. {
  1260. //
  1261. // Take out the first message in the waiting queue.
  1262. //
  1263. pEnt = pAdapter->WaitingMessageList.Flink;
  1264. pFrame = CONTAINING_RECORD(pEnt, RNDISMP_MESSAGE_FRAME, PendLink);
  1265. RemoveEntryList(pEnt);
  1266. CHECK_VALID_FRAME(pFrame);
  1267. //
  1268. // Fake send to microport
  1269. //
  1270. pAdapter->CurPendedMessages++;
  1271. InsertTailList(&pAdapter->PendingAtMicroportList, pEnt);
  1272. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  1273. TRACE1(("Flush: Adapter %x, MsgFrame %x, MsgType %x\n",
  1274. pAdapter, pFrame, pFrame->NdisMessageType));
  1275. //
  1276. // Complete it right here.
  1277. //
  1278. RndisMSendComplete(
  1279. (NDIS_HANDLE)pAdapter,
  1280. pFrame,
  1281. NDIS_STATUS_NOT_ACCEPTED);
  1282. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  1283. }
  1284. pAdapter->SendInProgress = FALSE;
  1285. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  1286. TRACE1(("Flush done, adapter %x\n", pAdapter));
  1287. }
  1288. #endif // THROTTLE_MESSAGES
  1289. /****************************************************************************/
  1290. /* SendProcessTimeout */
  1291. /****************************************************************************/
  1292. /* */
  1293. /* Routine Description: */
  1294. /* */
  1295. /* Timeout callback routine to handle all sends. This is to avoid issues */
  1296. /* with TCP/IP stack preemption on WinME. */
  1297. /* */
  1298. /* Arguments: */
  1299. /* */
  1300. /* SystemSpecific[1-3] - Ignored */
  1301. /* Context - Pointer to our Adapter structure */
  1302. /* */
  1303. /* Return: */
  1304. /* */
  1305. /* VOID */
  1306. /* */
  1307. /****************************************************************************/
  1308. VOID
  1309. SendProcessTimeout(IN PVOID SystemSpecific1,
  1310. IN PVOID Context,
  1311. IN PVOID SystemSpecific2,
  1312. IN PVOID SystemSpecific3)
  1313. {
  1314. PRNDISMP_ADAPTER pAdapter;
  1315. PNDIS_PACKET pNdisPacket;
  1316. PRNDISMP_SEND_PKT_RESERVED_TEMP pSendResvdTemp;
  1317. PLIST_ENTRY pEntry;
  1318. NDIS_STATUS Status;
  1319. ULONG NumPkts;
  1320. ULONG CurPkts;
  1321. #define MAX_MULTI_SEND 20
  1322. PNDIS_PACKET PacketArray[MAX_MULTI_SEND];
  1323. pAdapter = (PRNDISMP_ADAPTER)Context;
  1324. CHECK_VALID_ADAPTER(pAdapter);
  1325. ASSERT(pAdapter->SendProcessInProgress == TRUE);
  1326. SndTimerCount++;
  1327. NumPkts = 0;
  1328. CurPkts = 0;
  1329. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  1330. while (!IsListEmpty(&pAdapter->PendingSendProcessList))
  1331. {
  1332. pEntry = RemoveHeadList(&pAdapter->PendingSendProcessList);
  1333. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  1334. SndPacketCount++;
  1335. CurPkts++;
  1336. pSendResvdTemp = CONTAINING_RECORD(pEntry, RNDISMP_SEND_PKT_RESERVED_TEMP, Link);
  1337. pNdisPacket = CONTAINING_RECORD(pSendResvdTemp, NDIS_PACKET, MiniportReserved);
  1338. PacketArray[NumPkts] = pNdisPacket;
  1339. NumPkts++;
  1340. if (NumPkts == MAX_MULTI_SEND)
  1341. {
  1342. pAdapter->MultipleSendFunc(pAdapter, NULL, PacketArray, NumPkts);
  1343. NumPkts = 0;
  1344. }
  1345. RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
  1346. }
  1347. pAdapter->SendProcessInProgress = FALSE;
  1348. SndMaxPackets = MAX(SndMaxPackets, CurPkts);
  1349. RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
  1350. if (NumPkts != 0)
  1351. {
  1352. pAdapter->MultipleSendFunc(pAdapter, NULL, PacketArray, NumPkts);
  1353. }
  1354. } // SendProcessTimeout