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.

948 lines
25 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. PURPOSE.
  7. Module Name:
  8. SendRCV.C
  9. Abstract:
  10. This module contains miniport functions for handling Send & Receive
  11. packets and other helper routines called by these miniport functions.
  12. In order to excercise the send and receive code path of this driver,
  13. you should install more than one instance of the miniport. If there
  14. is only one instance installed, the driver throws the send packet on
  15. the floor and completes the send successfully. If there are more
  16. instances present, it indicates the incoming send packet to the other
  17. instances. For example, if there 3 instances: A, B, & C installed.
  18. Packets coming in for A instance would be indicated to B & C; packets
  19. coming into B would be indicated to C, & A; and packets coming to C
  20. would be indicated to A & B.
  21. Revision History:
  22. Notes:
  23. --*/
  24. #include "miniport.h"
  25. VOID
  26. MPSendPackets(
  27. IN NDIS_HANDLE MiniportAdapterContext,
  28. IN PPNDIS_PACKET PacketArray,
  29. IN UINT NumberOfPackets)
  30. /*++
  31. Routine Description:
  32. Send Packet Array handler. Called by NDIS whenever a protocol
  33. bound to our miniport sends one or more packets.
  34. The input packet descriptor pointers have been ordered according
  35. to the order in which the packets should be sent over the network
  36. by the protocol driver that set up the packet array. The NDIS
  37. library preserves the protocol-determined ordering when it submits
  38. each packet array to MiniportSendPackets
  39. As a deserialized driver, we are responsible for holding incoming send
  40. packets in our internal queue until they can be transmitted over the
  41. network and for preserving the protocol-determined ordering of packet
  42. descriptors incoming to its MiniportSendPackets function.
  43. A deserialized miniport driver must complete each incoming send packet
  44. with NdisMSendComplete, and it cannot call NdisMSendResourcesAvailable.
  45. Runs at IRQL <= DISPATCH_LEVEL
  46. Arguments:
  47. MiniportAdapterContext Pointer to our adapter context
  48. PacketArray Set of packets to send
  49. NumberOfPackets Length of above array
  50. Return Value:
  51. None
  52. --*/
  53. {
  54. PMP_ADAPTER Adapter;
  55. NDIS_STATUS Status;
  56. UINT PacketCount;
  57. DEBUGP(MP_TRACE, ("---> MPSendPackets\n"));
  58. Adapter = (PMP_ADAPTER)MiniportAdapterContext;
  59. for(PacketCount=0;PacketCount < NumberOfPackets; PacketCount++)
  60. {
  61. //
  62. // Check for a zero pointer
  63. //
  64. ASSERT(PacketArray[PacketCount]);
  65. Status = NICSendPacket(Adapter, PacketArray[PacketCount]);
  66. }
  67. DEBUGP(MP_TRACE, ("<--- MPSendPackets\n"));
  68. return;
  69. }
  70. VOID
  71. MPReturnPacket(
  72. IN NDIS_HANDLE MiniportAdapterContext,
  73. IN PNDIS_PACKET Packet)
  74. /*++
  75. Routine Description:
  76. NDIS Miniport entry point called whenever protocols are done with
  77. a packet that we had indicated up and they had queued up for returning
  78. later.
  79. Arguments:
  80. MiniportAdapterContext - pointer to MP_ADAPTER structure
  81. Packet - packet being returned.
  82. Return Value:
  83. None.
  84. --*/
  85. {
  86. PMP_ADAPTER Adapter = (PMP_ADAPTER) MiniportAdapterContext;
  87. DEBUGP(MP_TRACE, ("---> MPReturnPacket\n"));
  88. NICFreeRecvPacket(Adapter, Packet);
  89. DEBUGP(MP_TRACE, ("<--- MPReturnPacket\n"));
  90. }
  91. NDIS_STATUS
  92. NICSendPacket(
  93. PMP_ADAPTER Adapter,
  94. PNDIS_PACKET Packet)
  95. /*++
  96. Routine Description:
  97. This routine copies the packet content to a TCB, gets a receive packet,
  98. associates the TCB buffer to this recive packet and queues
  99. receive packet with the same data on one or more miniport instances
  100. controlled by this driver. For receive path to be active, you have
  101. to install more than one instance of this miniport.
  102. Arguments:
  103. Adapter - pointer to the MP_ADAPTER structure
  104. Packet - packet to be transfered.
  105. Return Value:
  106. NDIS_STATUS_SUCCESS or NDIS_STATUS_PENDING
  107. --*/
  108. {
  109. PMP_ADAPTER DestAdapter;
  110. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  111. PTCB pTCB = NULL;
  112. DEBUGP(MP_TRACE, ("--> NICSendPacket, Packet= %p\n", Packet));
  113. //
  114. // Go through the adapter list and queue packet for
  115. // indication on them if there are any. Otherwise
  116. // just drop the packet on the floor and tell NDIS that
  117. // you have completed send.
  118. //
  119. NdisAcquireSpinLock(&GlobalData.Lock);
  120. DestAdapter = (PMP_ADAPTER) &GlobalData.AdapterList;
  121. while(MP_IS_READY(Adapter))
  122. {
  123. DestAdapter = (PMP_ADAPTER) DestAdapter->List.Flink;
  124. if((PLIST_ENTRY)DestAdapter == &GlobalData.AdapterList)
  125. {
  126. //
  127. // We have reached the end of the adapter list. So
  128. //
  129. break;
  130. }
  131. //
  132. // We wouldn't transmit the packet if:
  133. // a) The destination adapter is same as the Send Adapter.
  134. // b) The destination adapter is not ready to receive packets.
  135. // c) The packet itself is not worth transmitting.
  136. //
  137. if(DestAdapter == Adapter ||
  138. !MP_IS_READY(DestAdapter) ||
  139. !NICIsPacketTransmittable(DestAdapter, Packet))
  140. {
  141. continue;
  142. }
  143. DEBUGP(MP_LOUD, ("Packet is accepted...\n"));
  144. if(!pTCB)
  145. {
  146. pTCB = (PTCB) NdisInterlockedRemoveHeadList(
  147. &Adapter->SendFreeList,
  148. &Adapter->SendLock);
  149. if(pTCB == NULL)
  150. {
  151. DEBUGP(MP_WARNING, ("Can't allocate a TCB......!\n"));
  152. Status = NDIS_STATUS_PENDING;
  153. //
  154. // Not able to get TCB block for this send. So queue
  155. // it for later transmission and break out of the loop.
  156. //
  157. NdisInterlockedInsertTailList(
  158. &Adapter->SendWaitList,
  159. (PLIST_ENTRY)&Packet->MiniportReserved[0],
  160. &Adapter->SendLock);
  161. break;
  162. }
  163. else
  164. {
  165. NdisInterlockedIncrement(&Adapter->nBusySend);
  166. ASSERT(Adapter->nBusySend <= NIC_MAX_BUSY_SENDS);
  167. //
  168. // Copy the packet content into the TCB data buffer,
  169. // assuming the NIC is doing a common buffer DMA. For
  170. // scatter/gather DMA, this copy operation is not required.
  171. // For efficiency, I could have avoided the copy operation
  172. // in this driver and directly indicated the send buffers to
  173. // other miniport instances since I'm holding the send packet
  174. // until all the indicated packets are returned. Oh, well!
  175. //
  176. if(!NICCopyPacket(Adapter, pTCB, Packet)){
  177. DEBUGP(MP_ERROR, ("NICCopyPacket failed\n"));
  178. Status = NDIS_STATUS_FAILURE;
  179. break;
  180. }
  181. }
  182. }
  183. Status = NDIS_STATUS_PENDING;
  184. NICQueuePacketForRecvIndication(DestAdapter, pTCB);
  185. } // while
  186. NdisReleaseSpinLock(&GlobalData.Lock);
  187. NDIS_SET_PACKET_STATUS(Packet, Status);
  188. if(Status == NDIS_STATUS_SUCCESS ||
  189. (pTCB && (NdisInterlockedDecrement(&pTCB->Ref) == 0)))
  190. {
  191. DEBUGP(MP_LOUD, ("Calling NdisMSendComplete \n"));
  192. Status = NDIS_STATUS_SUCCESS;
  193. NdisMSendComplete(
  194. Adapter->AdapterHandle,
  195. Packet,
  196. Status);
  197. if(pTCB)
  198. {
  199. NICFreeSendTCB(Adapter, pTCB);
  200. }
  201. }
  202. DEBUGP(MP_TRACE, ("<-- NICSendPacket Status = 0x%08x\n", Status));
  203. return(Status);
  204. }
  205. VOID
  206. NICQueuePacketForRecvIndication(
  207. PMP_ADAPTER Adapter,
  208. PTCB pTCB)
  209. /*++
  210. Routine Description:
  211. This routine queues the send packet in to the destination
  212. adapters RecvWaitList and fires a timer DPC so that it
  213. cab be indicated as soon as possible.
  214. Arguments:
  215. Adapter - pointer to the destination adapter structure
  216. pTCB - pointer to TCB block
  217. Return Value:
  218. VOID
  219. --*/
  220. {
  221. PNDIS_PACKET SendPacket = pTCB->OrgSendPacket;
  222. PNDIS_PACKET RecvPacket = NULL;
  223. PNDIS_BUFFER CurrentBuffer = NULL;
  224. UINT NumPhysDesc, BufferCount, PacketLength, RecvPacketLength;
  225. PLIST_ENTRY pEntry;
  226. PRCB pRCB;
  227. NDIS_STATUS Status;
  228. DEBUGP(MP_TRACE, ("--> NICQueuePacketForRecvIndication\n"));
  229. //
  230. // Allocate memory for RCB.
  231. //
  232. pRCB = NdisAllocateFromNPagedLookasideList(&Adapter->RecvLookaside);
  233. if(!pRCB)
  234. {
  235. DEBUGP(MP_ERROR, ("Failed to allocate memory for RCB\n"));
  236. return;
  237. }
  238. //
  239. // Get a free recv packet descriptor from the list.
  240. //
  241. pEntry = (PLIST_ENTRY) NdisInterlockedRemoveHeadList(
  242. &Adapter->RecvFreeList,
  243. &Adapter->RecvLock);
  244. if(!pEntry)
  245. {
  246. ++Adapter->RcvResourceErrors;
  247. NdisFreeToNPagedLookasideList(&Adapter->RecvLookaside, pRCB);
  248. }
  249. else
  250. {
  251. ++Adapter->GoodReceives;
  252. RecvPacket = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
  253. //
  254. // Prepare the recv packet
  255. //
  256. NdisReinitializePacket(RecvPacket);
  257. *((PTCB *)RecvPacket->MiniportReserved) = pTCB;
  258. //
  259. // Chain the TCB buffers to the packet
  260. //
  261. NdisChainBufferAtBack(RecvPacket, pTCB->Buffer);
  262. #if DBG
  263. NdisQueryPacket(
  264. RecvPacket,
  265. NULL,
  266. NULL,
  267. &CurrentBuffer,
  268. &RecvPacketLength);
  269. ASSERT(CurrentBuffer == pTCB->Buffer);
  270. NdisQueryPacket(
  271. SendPacket,
  272. NULL,
  273. NULL,
  274. NULL,
  275. &PacketLength);
  276. if((RecvPacketLength != 60) && (RecvPacketLength != PacketLength))
  277. {
  278. DEBUGP(MP_ERROR, ("RecvPacketLength = %d, PacketLength = %d\n",
  279. RecvPacketLength, PacketLength));
  280. DEBUGP(MP_ERROR, ("RecvPacket = %p, Packet = %p\n",
  281. RecvPacket, SendPacket));
  282. ASSERT(FALSE);
  283. }
  284. #endif
  285. NDIS_SET_PACKET_STATUS(RecvPacket, NDIS_STATUS_SUCCESS);
  286. DEBUGP(MP_LOUD, ("RecvPkt= %p\n", RecvPacket));
  287. //
  288. // Initialize RCB
  289. //
  290. NdisInitializeListHead(&pRCB->List);
  291. pRCB->Packet = RecvPacket;
  292. //
  293. // Increment the Ref count on the TCB to denote that it's being
  294. // used. This reference will be removed when the indicated
  295. // Recv packet finally returns from the protocol.
  296. //
  297. NdisInterlockedIncrement(&pTCB->Ref);
  298. //
  299. // Insert the packet in the recv wait queue to be picked up by
  300. // the receive indication DPC.
  301. //
  302. NdisInterlockedIncrement(&Adapter->nBusyRecv);
  303. ASSERT(Adapter->nBusyRecv <= NIC_MAX_BUSY_RECVS);
  304. NdisInterlockedInsertTailList(
  305. &Adapter->RecvWaitList,
  306. &pRCB->List,
  307. &Adapter->RecvLock);
  308. //
  309. // Fire a timer DPC. By specifing zero timeout, the DPC will
  310. // be serviced whenever the next system timer interrupt arrives.
  311. //
  312. NdisMSetTimer(&Adapter->RecvTimer, 0);
  313. }
  314. DEBUGP(MP_TRACE, ("<-- NICQueuePacketForRecvIndication\n"));
  315. }
  316. VOID
  317. NICIndicateReceiveTimerDpc(
  318. IN PVOID SystemSpecific1,
  319. IN PVOID FunctionContext,
  320. IN PVOID SystemSpecific2,
  321. IN PVOID SystemSpecific3)
  322. /*++
  323. Routine Description:
  324. Timer callback function for Receive Indication. Please note that receive
  325. timer DPC is not required when you are talking to a real device. In real
  326. miniports, this DPC is usually provided by NDIS as MPHandleInterrupt
  327. callback whenever the device interrupts for receive indication.
  328. Arguments:
  329. FunctionContext - Pointer to our adapter
  330. Return Value:
  331. VOID
  332. --*/
  333. {
  334. PMP_ADAPTER Adapter = (PMP_ADAPTER)FunctionContext;
  335. PRCB pRCB = NULL;
  336. PLIST_ENTRY pEntry = NULL;
  337. DEBUGP(MP_TRACE, ("--->NICIndicateReceiveTimerDpc = %p\n", Adapter));
  338. //
  339. // Increment the ref count on the adapter to prevent the driver from
  340. // unloding while the DPC is running. The Halt handler waits for the
  341. // ref count to drop to zero before returning.
  342. //
  343. MP_INC_REF(Adapter);
  344. //
  345. // Remove the packet from waitlist and indicate it to the protocols
  346. // above us.
  347. //
  348. while (pEntry = (PLIST_ENTRY) NdisInterlockedRemoveHeadList(
  349. &Adapter->RecvWaitList,
  350. &Adapter->RecvLock)) {
  351. pRCB = CONTAINING_RECORD(pEntry, RCB, List);
  352. ASSERT(pRCB);
  353. ASSERT(pRCB->Packet);
  354. DEBUGP(MP_LOUD, ("Indicating packet = %p\n", pRCB->Packet));
  355. NdisMIndicateReceivePacket(
  356. Adapter->AdapterHandle,
  357. &pRCB->Packet,
  358. 1);
  359. //
  360. // We are done with RCB memory. So free it.
  361. //
  362. NdisFreeToNPagedLookasideList(&Adapter->RecvLookaside, pRCB);
  363. }
  364. MP_DEC_REF(Adapter);
  365. DEBUGP(MP_TRACE, ("<---NICIndicateReceiveTimerDpc\n"));
  366. }
  367. VOID
  368. NICFreeRecvPacket(
  369. PMP_ADAPTER Adapter,
  370. PNDIS_PACKET Packet)
  371. /*++
  372. Routine Description:
  373. Adapter - pointer to the adapter structure
  374. Packet - pointer to the receive packet
  375. Arguments:
  376. This is called by MPReturnPacket to free the Receive packet
  377. indicated above. Since we have used the send-side TCB, we
  378. will also carefully complete the pending SendPacket if we are
  379. the last one to use the TCB buffers.
  380. Return Value:
  381. VOID
  382. --*/
  383. {
  384. PTCB pTCB = *(PTCB *)Packet->MiniportReserved;
  385. PMP_ADAPTER SendAdapter = (PMP_ADAPTER)pTCB->Adapter;
  386. PNDIS_PACKET SendPacket = pTCB->OrgSendPacket;
  387. PLIST_ENTRY pEntry;
  388. DEBUGP(MP_TRACE, ("--> NICFreeRecvPacket\n"));
  389. DEBUGP(MP_INFO, ("Adapter= %p FreePkt= %p Ref=%d\n",
  390. SendAdapter, SendPacket, pTCB->Ref));
  391. ASSERT(pTCB->Ref > 0);
  392. ASSERT(Adapter);
  393. //
  394. // Put the packet back in the free list for reuse.
  395. //
  396. NdisInterlockedInsertTailList(
  397. &Adapter->RecvFreeList,
  398. (PLIST_ENTRY)&Packet->MiniportReserved[0],
  399. &Adapter->RecvLock);
  400. NdisInterlockedDecrement(&Adapter->nBusyRecv);
  401. ASSERT(Adapter->nBusyRecv >= 0);
  402. //
  403. // Check to see whether we are the last one to use the TCB
  404. // by decrementing the refcount. If so, complete the pending
  405. // Send packet and free the TCB block for reuse.
  406. //
  407. if(NdisInterlockedDecrement(&pTCB->Ref) == 0)
  408. {
  409. NdisMSendComplete(
  410. SendAdapter->AdapterHandle,
  411. SendPacket,
  412. NDIS_STATUS_SUCCESS);
  413. NICFreeSendTCB(SendAdapter, pTCB);
  414. //
  415. // Before we exit, since we have the control, let use see if there any
  416. // more packets waiting in the queue to be sent.
  417. //
  418. if(MP_IS_READY(SendAdapter))
  419. {
  420. pEntry = (PLIST_ENTRY) NdisInterlockedRemoveHeadList(
  421. &SendAdapter->SendWaitList,
  422. &SendAdapter->SendLock);
  423. if(pEntry)
  424. {
  425. SendPacket = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
  426. NICSendPacket(SendAdapter, SendPacket);
  427. }
  428. }
  429. }
  430. DEBUGP(MP_TRACE, ("<-- NICFreeRecvPacket\n"));
  431. }
  432. VOID
  433. NICFreeSendTCB(
  434. IN PMP_ADAPTER Adapter,
  435. IN PTCB pTCB)
  436. /*++
  437. Routine Description:
  438. Adapter - pointer to the adapter structure
  439. pTCB - pointer to TCB block
  440. Arguments:
  441. This routine reinitializes the TCB block and puts it back
  442. into the SendFreeList for reuse.
  443. Return Value:
  444. VOID
  445. --*/
  446. {
  447. DEBUGP(MP_TRACE, ("--> NICFreeSendTCB %p\n", pTCB));
  448. pTCB->OrgSendPacket = NULL;
  449. pTCB->Buffer->Next = NULL;
  450. ASSERT(!pTCB->Ref);
  451. //
  452. // Re adjust the length to the originl size
  453. //
  454. NdisAdjustBufferLength(pTCB->Buffer, NIC_BUFFER_SIZE);
  455. //
  456. // Insert the TCB back in the send free list
  457. //
  458. NdisAcquireSpinLock(&Adapter->SendLock);
  459. NdisInitializeListHead(&pTCB->List);
  460. InsertHeadList(&Adapter->SendFreeList, &pTCB->List);
  461. NdisReleaseSpinLock(&Adapter->SendLock);
  462. NdisInterlockedDecrement(&Adapter->nBusySend);
  463. ASSERT(Adapter->nBusySend >= 0);
  464. DEBUGP(MP_TRACE, ("<-- NICFreeSendTCB\n"));
  465. }
  466. VOID
  467. NICFreeQueuedSendPackets(
  468. PMP_ADAPTER Adapter
  469. )
  470. /*++
  471. Routine Description:
  472. This routine is called by the Halt or Reset handler to fail all
  473. the queued up SendPackets because the device is either
  474. gone, being stopped for resource rebalance, or reset.
  475. Arguments:
  476. Adapter - pointer to the adapter structure
  477. Return Value:
  478. VOID
  479. --*/
  480. {
  481. PLIST_ENTRY pEntry;
  482. PNDIS_PACKET Packet;
  483. DEBUGP(MP_TRACE, ("--> NICFreeQueuedSendPackets\n"));
  484. while(TRUE)
  485. {
  486. pEntry = (PLIST_ENTRY) NdisInterlockedRemoveHeadList(
  487. &Adapter->SendWaitList,
  488. &Adapter->SendLock);
  489. if(!pEntry)
  490. {
  491. break;
  492. }
  493. Packet = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReserved);
  494. NdisMSendComplete(
  495. Adapter->AdapterHandle,
  496. Packet,
  497. NDIS_STATUS_FAILURE);
  498. }
  499. DEBUGP(MP_TRACE, ("<-- NICFreeQueuedSendPackets\n"));
  500. }
  501. VOID
  502. NICFreeQueuedRecvPackets(
  503. PMP_ADAPTER Adapter
  504. )
  505. /*++
  506. Routine Description:
  507. This routine is called by the Halt handler to fail all
  508. the queued up RecvPackets if it succeeds in cancelling
  509. the RecvIndicate timer DPC.
  510. Arguments:
  511. Adapter - pointer to the adapter structure
  512. Return Value:
  513. VOID
  514. --*/
  515. {
  516. PLIST_ENTRY pEntry;
  517. PRCB pRCB = NULL;
  518. DEBUGP(MP_TRACE, ("--> NICFreeQueuedRecvPackets\n"));
  519. while(TRUE)
  520. {
  521. pEntry = (PLIST_ENTRY) NdisInterlockedRemoveHeadList(
  522. &Adapter->RecvWaitList,
  523. &Adapter->RecvLock);
  524. if(!pEntry)
  525. {
  526. break;
  527. }
  528. pRCB = CONTAINING_RECORD(pEntry, RCB, List);
  529. ASSERT(pRCB);
  530. ASSERT(pRCB->Packet);
  531. NICFreeRecvPacket(Adapter, pRCB->Packet);
  532. //
  533. // We are done with RCB memory. So free it.
  534. //
  535. NdisFreeToNPagedLookasideList(&Adapter->RecvLookaside, pRCB);
  536. }
  537. DEBUGP(MP_TRACE, ("<-- NICFreeQueuedRecvPackets\n"));
  538. }
  539. BOOLEAN
  540. NICIsPacketTransmittable(
  541. PMP_ADAPTER Adapter,
  542. PNDIS_PACKET Packet
  543. )
  544. /*++
  545. Routine Description:
  546. This routines checks to see whether the packet can be accepted
  547. for transmission based on the currently programmed filter type
  548. of the NIC and the mac address of the packet.
  549. Arguments:
  550. Adapter - pointer to the adapter structure
  551. Packet - pointer to the send packet
  552. Return Value:
  553. True or False
  554. --*/
  555. {
  556. int Equal;
  557. UINT PacketLength;
  558. PNDIS_BUFFER FirstBuffer;
  559. PUCHAR Address;
  560. UINT CurrentLength;
  561. ULONG index;
  562. BOOLEAN result = FALSE;
  563. NdisGetFirstBufferFromPacket(
  564. Packet,
  565. &FirstBuffer,
  566. &Address,
  567. &CurrentLength,
  568. &PacketLength);
  569. DEBUGP(MP_LOUD,
  570. ("DestAdapter=%p, PacketFilter = 0x%08x\n",
  571. Adapter,
  572. Adapter->PacketFilter));
  573. DEBUGP(MP_LOUD, ("Dest Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
  574. Address[0], Address[1], Address[2],
  575. Address[3], Address[4], Address[5]));
  576. do {
  577. //
  578. // If the NIC is in promiscuous mode, we will transmit anything
  579. // and everything.
  580. //
  581. if(Adapter->PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
  582. result = TRUE;
  583. break;
  584. }
  585. else if(ETH_IS_BROADCAST(Address)) {
  586. //
  587. // If it's a broadcast packet, check our filter settings to see
  588. // we can transmit that.
  589. //
  590. if(Adapter->PacketFilter & NDIS_PACKET_TYPE_BROADCAST) {
  591. result = TRUE;
  592. break;
  593. }
  594. }
  595. else if(ETH_IS_MULTICAST(Address)) {
  596. //
  597. // If it's a multicast packet, check our filter settings to see
  598. // we can transmit that.
  599. //
  600. if(Adapter->PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST) {
  601. result = TRUE;
  602. break;
  603. }
  604. else if(Adapter->PacketFilter & NDIS_PACKET_TYPE_MULTICAST) {
  605. //
  606. // Check to see if the multicast address is in our list
  607. //
  608. for(index=0; index < Adapter->ulMCListSize; index++) {
  609. ETH_COMPARE_NETWORK_ADDRESSES_EQ(
  610. Address,
  611. Adapter->MCList[index],
  612. &Equal);
  613. if(Equal == 0){ // 0 Implies equality
  614. result = TRUE;
  615. break;
  616. }
  617. }
  618. }
  619. }
  620. else if(Adapter->PacketFilter & NDIS_PACKET_TYPE_DIRECTED) {
  621. //
  622. // This has to be a directed packet. If so, does packet source
  623. // address match with the mac address of the NIC.
  624. //
  625. ETH_COMPARE_NETWORK_ADDRESSES_EQ(
  626. Address,
  627. Adapter->CurrentAddress,
  628. &Equal);
  629. if(Equal == 0){
  630. result = TRUE;
  631. break;
  632. }
  633. }
  634. //
  635. // This is a junk packet. We can't transmit this.
  636. //
  637. result = FALSE;
  638. }while(FALSE);
  639. return result;
  640. }
  641. BOOLEAN
  642. NICCopyPacket(
  643. PMP_ADAPTER Adapter,
  644. PTCB pTCB,
  645. PNDIS_PACKET Packet)
  646. /*++
  647. Routine Description:
  648. This routine copies the packet data into the TCB data block.
  649. Arguments:
  650. Adapter - pointer to the MP_ADAPTER structure
  651. pTCB - pointer to TCB block
  652. Packet - packet to be transfered.
  653. Return Value:
  654. VOID
  655. --*/
  656. {
  657. PNDIS_BUFFER MyBuffer;
  658. PNDIS_BUFFER CurrentBuffer;
  659. PVOID VirtualAddress;
  660. UINT CurrentLength;
  661. UINT BytesToCopy;
  662. UINT BytesCopied = 0;
  663. UINT BufferCount;
  664. UINT PacketLength;
  665. UINT DestBufferSize = NIC_BUFFER_SIZE;
  666. PUCHAR pDest;
  667. BOOLEAN bResult = TRUE;
  668. DEBUGP(MP_TRACE, ("--> NICCopyPacket\n"));
  669. pTCB->OrgSendPacket = Packet;
  670. pTCB->Ref = 1;
  671. MyBuffer = pTCB->Buffer;
  672. pDest = pTCB->pData;
  673. MyBuffer->Next = NULL;
  674. NdisQueryPacket(Packet,
  675. NULL,
  676. &BufferCount,
  677. &CurrentBuffer,
  678. &PacketLength);
  679. ASSERT(PacketLength <= NIC_BUFFER_SIZE);
  680. BytesToCopy = min(PacketLength, NIC_BUFFER_SIZE);
  681. if(BytesToCopy < ETH_MIN_PACKET_SIZE)
  682. {
  683. BytesToCopy = ETH_MIN_PACKET_SIZE; // padding
  684. }
  685. while(CurrentBuffer && DestBufferSize)
  686. {
  687. NdisQueryBufferSafe(
  688. CurrentBuffer,
  689. &VirtualAddress,
  690. &CurrentLength,
  691. NormalPagePriority);
  692. if(VirtualAddress == NULL){
  693. bResult = FALSE;
  694. break;
  695. }
  696. CurrentLength = min(CurrentLength, DestBufferSize);
  697. if(CurrentLength)
  698. {
  699. // Copy the data.
  700. NdisMoveMemory(pDest, VirtualAddress, CurrentLength);
  701. BytesCopied += CurrentLength;
  702. DestBufferSize -= CurrentLength;
  703. pDest += CurrentLength;
  704. }
  705. NdisGetNextBuffer(
  706. CurrentBuffer,
  707. &CurrentBuffer);
  708. }
  709. if(bResult) {
  710. if(BytesCopied < BytesToCopy)
  711. {
  712. //
  713. // This would be the case if the packet size is less than
  714. // ETH_MIN_PACKET_SIZE
  715. //
  716. BytesCopied = BytesToCopy;
  717. }
  718. NdisAdjustBufferLength(MyBuffer, BytesCopied);
  719. }
  720. DEBUGP(MP_TRACE, ("<-- NICCopyPacket\n"));
  721. return bResult;
  722. }