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.

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