|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1990-1992 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: send.c ! 8: ! 9: Abstract: ! 10: ! 11: This file contains the code for putting a packet through the ! 12: staged allocation for transmission. ! 13: ! 14: This is a process of ! 15: ! 16: 1) Calculating the what would need to be done to the ! 17: packet so that the packet can be transmitted on the hardware. ! 18: ! 19: 2) Potentially allocating adapter buffers and copying user data ! 20: to those buffers so that the packet data is transmitted under ! 21: the hardware constraints. ! 22: ! 23: 3) Allocating enough hardware ring entries so that the packet ! 24: can be transmitted. ! 25: ! 26: 4) Relinquish thos ring entries to the hardware. ! 27: ! 28: The overall structure and most of the code is taken from ! 29: the Lance driver by Tony Ercolano. ! 30: ! 31: Author: ! 32: ! 33: Anthony V. Ercolano (Tonye) 12-Sept-1990 ! 34: Adam Barr (adamba) 16-Nov-1990 ! 35: ! 36: Environment: ! 37: ! 38: Kernel Mode - Or whatever is the equivalent. ! 39: ! 40: Revision History: ! 41: ! 42: ! 43: --*/ ! 44: ! 45: ! 46: #include <ndis.h> ! 47: ! 48: #include <efilter.h> ! 49: #include <sonichrd.h> ! 50: #include <sonicsft.h> ! 51: ! 52: ! 53: ! 54: // ! 55: // This macro will poke the sonic hardware into noticing that ! 56: // there is a packet available for transmit. ! 57: // ! 58: ! 59: #define START_TRANSMIT(_Adapter) \ ! 60: SONIC_WRITE_PORT(_Adapter, SONIC_COMMAND, SONIC_CR_TRANSMIT_PACKETS) ! 61: ! 62: ! 63: STATIC ! 64: BOOLEAN ! 65: DeterminePacketAddressing( ! 66: IN PNDIS_PACKET Packet ! 67: ); ! 68: ! 69: STATIC ! 70: VOID ! 71: StagedAllocation( ! 72: IN PSONIC_ADAPTER Adapter ! 73: ); ! 74: ! 75: STATIC ! 76: VOID ! 77: AssignPacketToDescriptor( ! 78: IN PSONIC_ADAPTER Adapter, ! 79: IN PNDIS_PACKET Packet, ! 80: IN UINT DescriptorIndex ! 81: ); ! 82: ! 83: STATIC ! 84: VOID ! 85: RelinquishPacket( ! 86: IN PSONIC_ADAPTER Adapter, ! 87: IN PNDIS_PACKET Packet, ! 88: IN UINT RingIndex ! 89: ); ! 90: ! 91: STATIC ! 92: VOID ! 93: CalculatePacketConstraints( ! 94: IN PSONIC_ADAPTER Adapter, ! 95: IN PNDIS_PACKET Packet ! 96: ); ! 97: ! 98: STATIC ! 99: BOOLEAN ! 100: ConstrainPacket( ! 101: IN PSONIC_ADAPTER Adapter, ! 102: IN PNDIS_PACKET Packet ! 103: ); ! 104: ! 105: ! 106: #ifdef CHECK_DUP_SENDS ! 107: ! 108: #define PACKET_LIST_SIZE 20 ! 109: ! 110: PNDIS_PACKET SonicPacketList[PACKET_LIST_SIZE]; ! 111: UINT SonicPacketListSize = 0; ! 112: ! 113: VOID ! 114: SonicAddPacketToList( ! 115: PSONIC_ADAPTER Adapter, ! 116: PNDIS_PACKET NewPacket ! 117: ) ! 118: { ! 119: INT i; ! 120: ! 121: for (i=0; i<SonicPacketListSize; i++) { ! 122: ! 123: if (SonicPacketList[i] == NewPacket) { ! 124: ! 125: DbgPrint("SONIC: dup send of %lx\n", NewPacket); ! 126: ! 127: } ! 128: ! 129: } ! 130: ! 131: SonicPacketList[SonicPacketListSize] = NewPacket; ! 132: ++SonicPacketListSize; ! 133: ! 134: } ! 135: ! 136: VOID ! 137: SonicRemovePacketFromList( ! 138: PSONIC_ADAPTER Adapter, ! 139: PNDIS_PACKET OldPacket ! 140: ) ! 141: { ! 142: INT i; ! 143: ! 144: for (i=0; i<SonicPacketListSize; i++) { ! 145: ! 146: if (SonicPacketList[i] == OldPacket) { ! 147: ! 148: break; ! 149: ! 150: } ! 151: ! 152: } ! 153: ! 154: if (i == SonicPacketListSize) { ! 155: ! 156: DbgPrint("SONIC: bad remove of %lx\n", OldPacket); ! 157: ! 158: } else { ! 159: ! 160: --SonicPacketListSize; ! 161: SonicPacketList[i] = SonicPacketList[SonicPacketListSize]; ! 162: ! 163: } ! 164: ! 165: } ! 166: #endif // CHECK_DUP_SENDS ! 167: ! 168: ! 169: extern ! 170: NDIS_STATUS ! 171: SonicSend( ! 172: IN NDIS_HANDLE MacBindingHandle, ! 173: IN PNDIS_PACKET Packet ! 174: ) ! 175: ! 176: /*++ ! 177: ! 178: Routine Description: ! 179: ! 180: The SonicSend request instructs a MAC to transmit a packet through ! 181: the adapter onto the medium. ! 182: ! 183: Arguments: ! 184: ! 185: MacBindingHandle - The context value returned by the MAC when the ! 186: adapter was opened. In reality, it is a pointer to SONIC_OPEN. ! 187: ! 188: Packet - A pointer to a descriptor for the packet that is to be ! 189: transmitted. ! 190: ! 191: Return Value: ! 192: ! 193: The function value is the status of the operation. ! 194: ! 195: --*/ ! 196: ! 197: { ! 198: ! 199: // ! 200: // Holds the status that should be returned to the caller. ! 201: // ! 202: NDIS_STATUS StatusToReturn = NDIS_STATUS_PENDING; ! 203: ! 204: // ! 205: // Pointer to the adapter. ! 206: // ! 207: PSONIC_ADAPTER Adapter; ! 208: ! 209: ! 210: Adapter = PSONIC_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle); ! 211: ! 212: NdisAcquireSpinLock(&Adapter->Lock); ! 213: ! 214: if (Adapter->Removed) { ! 215: ! 216: NdisReleaseSpinLock(&Adapter->Lock); ! 217: ! 218: return(NDIS_STATUS_FAILURE); ! 219: ! 220: } ! 221: ! 222: Adapter->References++; ! 223: ! 224: if (!Adapter->ResetInProgress) { ! 225: ! 226: PSONIC_OPEN Open; ! 227: PSONIC_PACKET_RESERVED Reserved; ! 228: ! 229: Open = PSONIC_OPEN_FROM_BINDING_HANDLE(MacBindingHandle); ! 230: ! 231: if (!Open->BindingShuttingDown) { ! 232: ! 233: // ! 234: // Increment the references on the open while we are ! 235: // accessing it in the interface. ! 236: // ! 237: ! 238: #ifdef CHECK_DUP_SENDS ! 239: SonicAddPacketToList(Adapter, Packet); ! 240: #endif ! 241: ! 242: Open->References++; ! 243: ! 244: // ! 245: // Check to see if the packet should even make it out to ! 246: // the media. The primary reason this shouldn't *actually* ! 247: // be sent is if the destination is equal to the source ! 248: // address. ! 249: // ! 250: // If it doesn't need to be placed on the wire then we can ! 251: // simply put it onto the loopback queue. ! 252: // ! 253: ! 254: Reserved = PSONIC_RESERVED_FROM_PACKET(Packet); ! 255: ! 256: ASSERT(sizeof(SONIC_PACKET_RESERVED) <= ! 257: sizeof(Packet->MacReserved)); ! 258: ! 259: Reserved->MacBindingHandle = MacBindingHandle; ! 260: ! 261: if (DeterminePacketAddressing(Packet)) { ! 262: ! 263: // ! 264: // The packet needs to be placed out on the wire. ! 265: // ! 266: // ! 267: // Determine if and how much adapter space would need to be allocated ! 268: // to meet hardware constraints. ! 269: // ! 270: ! 271: CalculatePacketConstraints( ! 272: Adapter, ! 273: Packet ! 274: ); ! 275: ! 276: // ! 277: // Put on the send stage queue. ! 278: // ! 279: ! 280: if (!Adapter->LastSendStagePacket) { ! 281: ! 282: Adapter->FirstSendStagePacket = Packet; ! 283: ! 284: } else { ! 285: ! 286: PSONIC_RESERVED_FROM_PACKET(Adapter->LastSendStagePacket)->Next = Packet; ! 287: ! 288: } ! 289: ! 290: Adapter->LastSendStagePacket = Packet; ! 291: ! 292: ++Adapter->GeneralOptional[GO_TRANSMIT_QUEUE_LENGTH - GO_ARRAY_START]; ! 293: ! 294: Reserved->Next = NULL; ! 295: ! 296: // ! 297: // Only try to push it through the send stage queue ! 298: // if somebody else isn't already doing it and ! 299: // there is some hope of moving some packets ! 300: // ahead. ! 301: // ! 302: ! 303: while ((!Adapter->AlreadyProcessingSendStage) && ! 304: Adapter->FirstSendStagePacket && ! 305: Adapter->SendStageOpen) { ! 306: ! 307: SonicStagedAllocation(Adapter); ! 308: ! 309: } ! 310: ! 311: } else { ! 312: ! 313: // ! 314: // It is a packet directed to ourselves. Put it directly ! 315: // on the loopback queue. ! 316: // ! 317: ! 318: SonicPutPacketOnLoopBack( ! 319: Adapter, ! 320: Packet, ! 321: TRUE ! 322: ); ! 323: ! 324: ! 325: // ! 326: // Tally statistics now; assume that loopback ! 327: // always "succeeds". These packets are always ! 328: // directed (to us), so add to those counts. ! 329: // ! 330: ! 331: ++Adapter->GeneralMandatory[GM_TRANSMIT_GOOD]; ! 332: ! 333: ++Adapter->GeneralOptionalFrameCount[GO_DIRECTED_TRANSMITS]; ! 334: ! 335: SonicAddUlongToLargeInteger( ! 336: &Adapter->GeneralOptionalByteCount[GO_DIRECTED_TRANSMITS], ! 337: Reserved->PacketLength); ! 338: ! 339: ! 340: } ! 341: ! 342: ! 343: } else { ! 344: ! 345: StatusToReturn = NDIS_STATUS_CLOSING; ! 346: ! 347: } ! 348: ! 349: } else { ! 350: ! 351: StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS; ! 352: ! 353: } ! 354: ! 355: ! 356: // ! 357: // This macro assumes it is called with the lock held, ! 358: // and releases it. ! 359: // ! 360: ! 361: SONIC_DO_DEFERRED(Adapter); ! 362: return StatusToReturn; ! 363: } ! 364: ! 365: STATIC ! 366: BOOLEAN ! 367: DeterminePacketAddressing( ! 368: IN PNDIS_PACKET Packet ! 369: ) ! 370: ! 371: /*++ ! 372: ! 373: Routine Description: ! 374: ! 375: Calculates the packet type for this packet. It also determines ! 376: if this packet should go out on the wire. ! 377: ! 378: Arguments: ! 379: ! 380: Packet - Packet whose source and destination addresses are tested. ! 381: ! 382: Return Value: ! 383: ! 384: Returns FALSE if the source is equal to the destination. ! 385: ! 386: ! 387: --*/ ! 388: ! 389: { ! 390: // ! 391: // MacReserved section of the packet. ! 392: // ! 393: PSONIC_PACKET_RESERVED Reserved = PSONIC_RESERVED_FROM_PACKET(Packet); ! 394: ! 395: // ! 396: // Hold the first Ndis buffer; ! 397: // ! 398: PNDIS_BUFFER FirstBuffer; ! 399: ! 400: // ! 401: // Holds the address of the data in the first buffer ! 402: // ! 403: PVOID BufferVirtualAddress; ! 404: ! 405: // ! 406: // Number of bytes in the first buffer. ! 407: // ! 408: UINT BufferLength; ! 409: ! 410: // ! 411: // Holds result of address check ! 412: // ! 413: UINT Result; ! 414: ! 415: NdisQueryPacket( ! 416: Packet, ! 417: NULL, ! 418: NULL, ! 419: &FirstBuffer, ! 420: NULL ! 421: ); ! 422: ! 423: // ! 424: // Get VA of first buffer ! 425: // ! 426: ! 427: NdisQueryBuffer( ! 428: FirstBuffer, ! 429: &BufferVirtualAddress, ! 430: &BufferLength ! 431: ); ! 432: ! 433: // ! 434: // Ndis spec says that the ethernet header must be in the first ! 435: // buffer. ! 436: // ! 437: ! 438: ASSERT(BufferLength >= 14); ! 439: ! 440: if (ETH_IS_MULTICAST(BufferVirtualAddress)) { ! 441: ! 442: if (ETH_IS_BROADCAST(BufferVirtualAddress)) { ! 443: ! 444: Reserved->PacketType = SONIC_BROADCAST; ! 445: ! 446: } else { ! 447: ! 448: Reserved->PacketType = SONIC_MULTICAST; ! 449: ! 450: } ! 451: ! 452: } else { ! 453: ! 454: Reserved->PacketType = SONIC_DIRECTED; ! 455: ! 456: ETH_COMPARE_NETWORK_ADDRESSES( ! 457: ((PUCHAR)BufferVirtualAddress) + ETH_LENGTH_OF_ADDRESS, ! 458: (PUCHAR)BufferVirtualAddress, ! 459: &Result ! 460: ); ! 461: ! 462: if (!Result) { ! 463: ! 464: Reserved->PacketType = SONIC_LOOPBACK; ! 465: ! 466: } ! 467: ! 468: } ! 469: ! 470: // ! 471: // If the two addresses are equal then the ! 472: // packet shouldn't go out on the wire. ! 473: // ! 474: ! 475: return ((Reserved->PacketType == SONIC_LOOPBACK) ? FALSE : TRUE); ! 476: ! 477: } ! 478: ! 479: extern ! 480: VOID ! 481: SonicStagedAllocation( ! 482: IN PSONIC_ADAPTER Adapter ! 483: ) ! 484: ! 485: /*++ ! 486: ! 487: Routine Description: ! 488: ! 489: This routine attempts to take a packet through a stage of allocation. ! 490: ! 491: NOTE : It is called with the lock held and returns with the lock held. ! 492: ! 493: NOTE : It is called with the stage open, a packet on the queue and ! 494: no one already processing the stage. ! 495: ! 496: Arguments: ! 497: ! 498: Adapter - The adapter that the packets are coming through. ! 499: ! 500: Return Value: ! 501: ! 502: None. ! 503: ! 504: --*/ ! 505: ! 506: { ! 507: // ! 508: // Holds whether the packet has been constrained ! 509: // to the hardware requirements. ! 510: // ! 511: BOOLEAN SuitableForHardware; ! 512: ! 513: // ! 514: // Packet to process ! 515: // ! 516: PNDIS_PACKET FirstPacket = Adapter->FirstSendStagePacket; ! 517: ! 518: // ! 519: // MacReserved section of the packet. ! 520: // ! 521: PSONIC_PACKET_RESERVED Reserved = PSONIC_RESERVED_FROM_PACKET(FirstPacket); ! 522: ! 523: // ! 524: // If we successfully acquire some ring entries, this ! 525: // is the index of the first one. ! 526: // ! 527: UINT DescriptorIndex; ! 528: ! 529: ASSERT(Adapter->SendStageOpen && ! 530: !Adapter->AlreadyProcessingSendStage && ! 531: Adapter->FirstSendStagePacket ! 532: ); ! 533: ! 534: ! 535: // ! 536: // We look to see if there are enough ring entries. ! 537: // If there aren't then stage will close. ! 538: // ! 539: ! 540: if (Adapter->NumberOfAvailableDescriptors > 1) { ! 541: ! 542: DescriptorIndex = Adapter->AllocateableDescriptor - Adapter->TransmitDescriptorArea; ! 543: ! 544: if (Adapter->AllocateableDescriptor == Adapter->LastTransmitDescriptor) { ! 545: ! 546: Adapter->AllocateableDescriptor = Adapter->TransmitDescriptorArea; ! 547: ! 548: } else { ! 549: ! 550: ++(Adapter->AllocateableDescriptor); ! 551: ! 552: } ! 553: ! 554: --(Adapter->NumberOfAvailableDescriptors); ! 555: ! 556: if (Reserved->UsedSonicBuffer == TRUE) { ! 557: ! 558: // ! 559: // ConstrainPacket returns FALSE if an adapter buffer ! 560: // is needed and none is available such that the ! 561: // spinlock will not have been release. It will also close ! 562: // stage in that case. ! 563: // ! 564: // If it did use an adapter buffer it will release the spinlock ! 565: // to do the copy to the buffer. ! 566: // ! 567: ! 568: Adapter->AlreadyProcessingSendStage = TRUE; ! 569: ! 570: SuitableForHardware = ConstrainPacket( ! 571: Adapter, ! 572: FirstPacket ! 573: ); ! 574: ! 575: Adapter->AlreadyProcessingSendStage = FALSE; ! 576: ! 577: if (!SuitableForHardware) { ! 578: ! 579: // ! 580: // Return transmit descriptor ! 581: // ! 582: ! 583: Adapter->AllocateableDescriptor = Adapter->TransmitDescriptorArea + ! 584: DescriptorIndex; ! 585: ! 586: ! 587: ++(Adapter->NumberOfAvailableDescriptors); ! 588: ! 589: return; ! 590: ! 591: ! 592: } ! 593: ! 594: } ! 595: ! 596: // ! 597: // Remove packet from wait queue and put it on transmit complete queue. ! 598: // ! 599: ! 600: if (Adapter->LastSendStagePacket == FirstPacket) { ! 601: ! 602: Adapter->FirstSendStagePacket = NULL; ! 603: Adapter->LastSendStagePacket = NULL; ! 604: ! 605: } else { ! 606: ! 607: Adapter->FirstSendStagePacket = Reserved->Next; ! 608: ! 609: } ! 610: ! 611: if (Adapter->FirstFinishTransmit == NULL) { ! 612: ! 613: Adapter->FirstFinishTransmit = FirstPacket; ! 614: ! 615: } else { ! 616: ! 617: PSONIC_RESERVED_FROM_PACKET(Adapter->LastFinishTransmit)->Next = FirstPacket; ! 618: ! 619: } ! 620: ! 621: Adapter->LastFinishTransmit = FirstPacket; ! 622: ! 623: Reserved->Next = NULL; ! 624: ! 625: --Adapter->GeneralOptional[GO_TRANSMIT_QUEUE_LENGTH - GO_ARRAY_START]; ! 626: ! 627: // ! 628: // We have the number of buffers that we need. ! 629: // We assign all of the buffers to the ring entries. ! 630: // ! 631: ! 632: AssignPacketToDescriptor( ! 633: Adapter, ! 634: FirstPacket, ! 635: DescriptorIndex ! 636: ); ! 637: ! 638: RelinquishPacket( ! 639: Adapter, ! 640: FirstPacket, ! 641: DescriptorIndex ! 642: ); ! 643: ! 644: } else { ! 645: ! 646: Adapter->SendStageOpen = FALSE; ! 647: ! 648: } ! 649: ! 650: } ! 651: ! 652: STATIC ! 653: BOOLEAN ! 654: ConstrainPacket( ! 655: IN PSONIC_ADAPTER Adapter, ! 656: IN PNDIS_PACKET Packet ! 657: ) ! 658: ! 659: /*++ ! 660: ! 661: Routine Description: ! 662: ! 663: Given a packet and necessary attempt to acquire adapter ! 664: buffer resources so that the packet meets sonic hardware ! 665: contraints. If a buffer is needed and is not available then ! 666: stage is closed. ! 667: ! 668: The constraints are that the packet must have SONIC_MAX_FRAGMENTS ! 669: or fewer physical pieces and no piece may be less than ! 670: SONIC_MIN_PIECE_SIZE bytes. The first constraint is based on ! 671: the size of the SONIC_TRANSMIT_DESCRIPTOR, and the second ! 672: is to prevent underflow in the Silo. ! 673: ! 674: If a packet violates either of the constraints then it ! 675: will be copied in its entirety into an adapter buffer. ! 676: ! 677: NOTE: Called with lock held!! ! 678: ! 679: Arguments: ! 680: ! 681: Adapter - The adapter the packet is coming through. ! 682: ! 683: Packet - The packet whose buffers are to be constrained. ! 684: The packet reserved section is filled with information ! 685: detailing how the packet needs to be adjusted. ! 686: ! 687: Return Value: ! 688: ! 689: Returns TRUE if the packet is suitable for the hardware. ! 690: ! 691: --*/ ! 692: ! 693: { ! 694: ! 695: // ! 696: // Pointer to the reserved section of the packet to be contrained. ! 697: // ! 698: PSONIC_PACKET_RESERVED Reserved = PSONIC_RESERVED_FROM_PACKET(Packet); ! 699: ! 700: // ! 701: // Holds the adapter buffer index available for allocation. ! 702: // ! 703: INT SonicBuffersIndex; ! 704: ! 705: // ! 706: // Points to a successfully allocated adapter buffer descriptor. ! 707: // ! 708: PSONIC_BUFFER_DESCRIPTOR BufferDescriptor; ! 709: ! 710: // ! 711: // Will point into the virtual address space addressed ! 712: // by the adapter buffer if one was successfully allocated. ! 713: // ! 714: PCHAR CurrentDestination; ! 715: ! 716: // ! 717: // Will hold the total amount of data copied to the ! 718: // adapter buffer. ! 719: // ! 720: UINT TotalDataMoved = 0; ! 721: ! 722: // ! 723: // Will point to the current source buffer. ! 724: // ! 725: PNDIS_BUFFER SourceBuffer; ! 726: ! 727: // ! 728: // Points to the virtual address of the source buffers data. ! 729: // ! 730: PVOID SourceData; ! 731: ! 732: // ! 733: // Will point to the number of bytes of data in the source ! 734: // buffer. ! 735: // ! 736: UINT SourceLength; ! 737: ! 738: // ! 739: // Simple iteration variable. ! 740: // ! 741: INT i; ! 742: ! 743: if (Reserved->PacketLength <= SONIC_SMALL_BUFFER_SIZE) { ! 744: ! 745: i = 1; ! 746: ! 747: } else if (Reserved->PacketLength <= SONIC_MEDIUM_BUFFER_SIZE) { ! 748: ! 749: i = 2; ! 750: ! 751: } else { ! 752: ! 753: i = 3; ! 754: ! 755: } ! 756: ! 757: ! 758: for ( ! 759: ; ! 760: i <= 3; ! 761: i++ ! 762: ) { ! 763: ! 764: if ((SonicBuffersIndex = Adapter->SonicBufferListHeads[i]) != -1) { ! 765: ! 766: BufferDescriptor = Adapter->SonicBuffers + SonicBuffersIndex; ! 767: Adapter->SonicBufferListHeads[i] = BufferDescriptor->Next; ! 768: break; ! 769: ! 770: } ! 771: ! 772: } ! 773: ! 774: if (SonicBuffersIndex == -1) { ! 775: ! 776: // ! 777: // Nothing available for the packet. ! 778: // ! 779: ! 780: Adapter->SendStageOpen = FALSE; ! 781: ! 782: return FALSE; ! 783: ! 784: } ! 785: ! 786: NdisReleaseSpinLock(&Adapter->Lock); ! 787: ! 788: // ! 789: // Save the list head index in the buffer descriptor ! 790: // to permit easy deallocation later. ! 791: // ! 792: ! 793: BufferDescriptor->Next = i; ! 794: ! 795: // ! 796: // Fill in the adapter buffer with the data from the users ! 797: // buffers. ! 798: // ! 799: ! 800: CurrentDestination = BufferDescriptor->VirtualSonicBuffer; ! 801: ! 802: NdisQueryPacket( ! 803: Packet, ! 804: NULL, ! 805: NULL, ! 806: &SourceBuffer, ! 807: NULL ! 808: ); ! 809: ! 810: while (SourceBuffer) { ! 811: ! 812: NdisQueryBuffer( ! 813: SourceBuffer, ! 814: &SourceData, ! 815: &SourceLength ! 816: ); ! 817: ! 818: SONIC_MOVE_MEMORY( ! 819: CurrentDestination, ! 820: SourceData, ! 821: SourceLength ! 822: ); ! 823: ! 824: CurrentDestination = (PCHAR)CurrentDestination + SourceLength; ! 825: ! 826: TotalDataMoved += SourceLength; ! 827: ! 828: NdisGetNextBuffer( ! 829: SourceBuffer, ! 830: &SourceBuffer ! 831: ); ! 832: ! 833: } ! 834: ! 835: // ! 836: // If the packet is less then the minimum size then we ! 837: // need to zero out the rest of the packet. ! 838: // ! 839: ! 840: if (TotalDataMoved < SONIC_MIN_PACKET_SIZE) { ! 841: ! 842: SONIC_ZERO_MEMORY( ! 843: CurrentDestination, ! 844: SONIC_MIN_PACKET_SIZE - TotalDataMoved ! 845: ); ! 846: ! 847: BufferDescriptor->DataLength = SONIC_MIN_PACKET_SIZE; ! 848: ! 849: } else { ! 850: ! 851: BufferDescriptor->DataLength = TotalDataMoved; ! 852: ! 853: } ! 854: ! 855: NdisAcquireSpinLock(&Adapter->Lock); ! 856: ! 857: // ! 858: // We need to save in the packet which adapter buffer descriptor ! 859: // it is using so that we can deallocate it later. ! 860: // ! 861: ! 862: Reserved->SonicBuffersIndex = SonicBuffersIndex; ! 863: ! 864: return TRUE; ! 865: } ! 866: ! 867: STATIC ! 868: VOID ! 869: CalculatePacketConstraints( ! 870: IN PSONIC_ADAPTER Adapter, ! 871: IN PNDIS_PACKET Packet ! 872: ) ! 873: ! 874: /*++ ! 875: ! 876: Routine Description: ! 877: ! 878: Given a packet calculate how the packet will have to be ! 879: adjusted to meet with hardware constraints. ! 880: ! 881: The constraints are that the packet must have SONIC_MAX_FRAGMENTS ! 882: or fewer physical pieces and no piece may be less than ! 883: SONIC_MIN_FRAGMENT_SIZE bytes. The first constraint is based on ! 884: the size of the SONIC_TRANSMIT_DESCRIPTOR, and the second ! 885: is to prevent underflow in the Silo. ! 886: ! 887: If the packet is found to violate the constraints, then ! 888: UsedSonicBuffer will be set to TRUE. This will cause the entire packet to ! 889: be copied into the adapter buffer (which is guaranteed ! 890: to be physically contiguous). ! 891: ! 892: Note: This is called with the lock held! Merely for convience to ! 893: reduce the number of times we acquire and release the spinlock. ! 894: ! 895: Arguments: ! 896: ! 897: Adapter - The adapter the packet is coming through. ! 898: ! 899: Packet - The packet whose buffers are to be reallocated. ! 900: The packet reserved section is filled with information ! 901: detailing how the packet needs to be adjusted. ! 902: ! 903: Return Value: ! 904: ! 905: None. ! 906: ! 907: --*/ ! 908: ! 909: { ! 910: ! 911: // ! 912: // Points to the MacReserved portion of the packet. ! 913: // ! 914: PSONIC_PACKET_RESERVED Reserved = PSONIC_RESERVED_FROM_PACKET(Packet); ! 915: ! 916: // ! 917: // The number of physical buffers in the entire packet. ! 918: // ! 919: UINT PacketPhysicalSegments; ! 920: ! 921: // ! 922: // Points to the current ndis buffer being walked. ! 923: // ! 924: PNDIS_BUFFER CurrentBuffer; ! 925: ! 926: // ! 927: // The virtual address of the current ndis buffer. ! 928: // ! 929: PVOID BufferVirtualAddress; ! 930: ! 931: // ! 932: // The length in bytes of the current ndis buffer. ! 933: // ! 934: UINT BufferVirtualLength; ! 935: ! 936: // ! 937: // The total amount of data contained within the ndis packet. ! 938: // ! 939: UINT PacketVirtualLength; ! 940: ! 941: // ! 942: // The number of physical buffers in a single buffer. ! 943: // ! 944: UINT BufferPhysicalSegments; ! 945: ! 946: // ! 947: // TRUE once we find a constraint violation ! 948: // ! 949: BOOLEAN ViolatedConstraints = FALSE; ! 950: ! 951: #ifndef NO_CHIP_FIXUP ! 952: // ! 953: // Used to keep track of the total number of fragments ! 954: // that the packet will occupy when assigned to a ! 955: // transmit descriptor (may be more than PacketPhysicalSegments ! 956: // if we have to worry about packets starting or ending ! 957: // on non-longword boundaries. ! 958: // ! 959: UINT TotalTransmitSegments = 0; ! 960: #endif ! 961: ! 962: ! 963: ! 964: // ! 965: // Get the first buffer in the packet. ! 966: // ! 967: ! 968: NdisQueryPacket( ! 969: Packet, ! 970: &PacketPhysicalSegments, ! 971: NULL, ! 972: &CurrentBuffer, ! 973: &PacketVirtualLength ! 974: ); ! 975: ! 976: // ! 977: // Save this value for later ! 978: // ! 979: ! 980: Reserved->PacketLength = PacketVirtualLength; ! 981: ! 982: // ! 983: // We only allow SONIC_MAX_FRAGMENTS physical pieces. ! 984: // ! 985: ! 986: if (PacketPhysicalSegments > SONIC_MAX_FRAGMENTS) { ! 987: ViolatedConstraints = TRUE; ! 988: goto DoneExamining; ! 989: } ! 990: ! 991: // ! 992: // For short packets we can only allow SONIC_MAX_FRAGMENTS-1 ! 993: // (to allow for the blank padding buffer). Also, we can't ! 994: // allow the padding itself to be less than the minimum ! 995: // fragment size. ! 996: // ! 997: ! 998: if (PacketVirtualLength < SONIC_MIN_PACKET_SIZE && ! 999: ((PacketPhysicalSegments > (SONIC_MAX_FRAGMENTS-1)) || ! 1000: (PacketVirtualLength > ! 1001: (SONIC_MIN_PACKET_SIZE - SONIC_MIN_FRAGMENT_SIZE)))) { ! 1002: ViolatedConstraints = TRUE; ! 1003: goto DoneExamining; ! 1004: } ! 1005: ! 1006: ! 1007: // ! 1008: // Now loop making sure no fragment is less than ! 1009: // SONIC_MIN_FRAGMENT_SIZE bytes. ! 1010: // ! 1011: ! 1012: while (CurrentBuffer) { ! 1013: ! 1014: NdisQueryBuffer( ! 1015: CurrentBuffer, ! 1016: &BufferVirtualAddress, ! 1017: &BufferVirtualLength ! 1018: ); ! 1019: ! 1020: ! 1021: // ! 1022: // See if there is only one piece in the buffer. ! 1023: // ! 1024: ! 1025: NdisGetBufferPhysicalArraySize( ! 1026: CurrentBuffer, ! 1027: &BufferPhysicalSegments ! 1028: ); ! 1029: ! 1030: if (BufferPhysicalSegments == 1) { ! 1031: ! 1032: // ! 1033: // Only one piece, make sure it is large enough. ! 1034: // ! 1035: ! 1036: if (BufferVirtualLength < SONIC_MIN_FRAGMENT_SIZE) { ! 1037: ViolatedConstraints = TRUE; ! 1038: goto DoneExamining; ! 1039: } ! 1040: ! 1041: #ifndef NO_CHIP_FIXUP ! 1042: ! 1043: // ! 1044: // See if the beginning AND end of this piece are ! 1045: // not longword-aligned. ! 1046: // ! 1047: ! 1048: if (((ULONG)BufferVirtualAddress & 0x03) && ! 1049: (((ULONG)BufferVirtualAddress + BufferVirtualLength) & 0x03)) { ! 1050: ! 1051: // ! 1052: // Now see if this piece is large enough to ! 1053: // be split into two. ! 1054: // ! 1055: ! 1056: if (BufferVirtualLength > ! 1057: (UINT)(4 - ((ULONG)BufferVirtualAddress & 0x03) + ! 1058: (2*SONIC_MIN_FRAGMENT_SIZE))) { ! 1059: ! 1060: // ! 1061: // Have enough to let the first fragment be ! 1062: // SONIC_MIN_FRAGMENT_SIZE plus the extra ! 1063: // few bytes at the beginning, and the ! 1064: // second piece SONIC_MIN_FRAGMENT_SIZE. ! 1065: // ! 1066: ! 1067: TotalTransmitSegments += 2; ! 1068: ! 1069: } else { ! 1070: ! 1071: ViolatedConstraints = TRUE; ! 1072: goto DoneExamining; ! 1073: ! 1074: } ! 1075: ! 1076: } else { ! 1077: ! 1078: // ! 1079: // This piece won't have to be split, so ! 1080: // just count it as one. ! 1081: // ! 1082: ! 1083: TotalTransmitSegments += 1; ! 1084: ! 1085: } ! 1086: ! 1087: #endif ! 1088: ! 1089: } else { ! 1090: ! 1091: // ! 1092: // Multiple pieces. We assume that the relevant low bits ! 1093: // will be the same in a physical and virtual address, so ! 1094: // we can check using the virtual address whether a ! 1095: // physical segment may be too short (we are being over- ! 1096: // cautious here, but this allows us to avoid actually ! 1097: // querying the physical addresses here. ! 1098: // ! 1099: ! 1100: // ! 1101: // See if this buffer starts less than MIN_FRAGMENT_SIZE ! 1102: // bytes before a page boundary. ! 1103: // ! 1104: ! 1105: if (PAGE_SIZE - ((ULONG)BufferVirtualAddress & (PAGE_SIZE-1)) < ! 1106: SONIC_MIN_FRAGMENT_SIZE) { ! 1107: ViolatedConstraints = TRUE; ! 1108: goto DoneExamining; ! 1109: } ! 1110: ! 1111: // ! 1112: // See if this buffer ends less than MIN_FRAGMENT_SIZE ! 1113: // bytes after a page boundary. ! 1114: // ! 1115: ! 1116: if (((ULONG)BufferVirtualAddress + BufferVirtualLength) & (PAGE_SIZE-1) < ! 1117: SONIC_MIN_FRAGMENT_SIZE) { ! 1118: ViolatedConstraints = TRUE; ! 1119: goto DoneExamining; ! 1120: } ! 1121: ! 1122: #ifndef NO_CHIP_FIXUP ! 1123: ! 1124: // ! 1125: // Add the number of fragments in this piece. ! 1126: // We assume that physical gaps will always be ! 1127: // on at least a 4 byte boundary, so we won't ! 1128: // need to split this piece. ! 1129: // ! 1130: ! 1131: TotalTransmitSegments += BufferPhysicalSegments; ! 1132: ! 1133: #endif ! 1134: ! 1135: } ! 1136: ! 1137: ! 1138: NdisGetNextBuffer( ! 1139: CurrentBuffer, ! 1140: &CurrentBuffer ! 1141: ); ! 1142: ! 1143: } ! 1144: ! 1145: ! 1146: #ifndef NO_CHIP_FIXUP ! 1147: ! 1148: // ! 1149: // If the packet is short, we have to allow for the ! 1150: // padding fragment at the end. ! 1151: // ! 1152: ! 1153: if (PacketVirtualLength < SONIC_MIN_PACKET_SIZE) { ! 1154: ! 1155: TotalTransmitSegments += 1; ! 1156: ! 1157: } ! 1158: ! 1159: #endif ! 1160: ! 1161: ! 1162: DoneExamining: ; ! 1163: ! 1164: #ifndef NO_CHIP_FIXUP ! 1165: if (ViolatedConstraints || (TotalTransmitSegments > SONIC_MAX_FRAGMENTS)) { ! 1166: #else ! 1167: if (ViolatedConstraints) { ! 1168: #endif ! 1169: ! 1170: Reserved->UsedSonicBuffer = TRUE; ! 1171: ! 1172: } else { ! 1173: ! 1174: Reserved->UsedSonicBuffer = FALSE; ! 1175: ! 1176: } ! 1177: ! 1178: } ! 1179: ! 1180: STATIC ! 1181: VOID ! 1182: AssignPacketToDescriptor( ! 1183: IN PSONIC_ADAPTER Adapter, ! 1184: IN PNDIS_PACKET Packet, ! 1185: IN UINT DescriptorIndex ! 1186: ) ! 1187: ! 1188: /*++ ! 1189: ! 1190: Routine Description: ! 1191: ! 1192: Given a packet and a ring index, assign all of the buffers ! 1193: in the packet to ring entries. ! 1194: ! 1195: NOTE : Called with lock held!! ! 1196: ! 1197: Arguments: ! 1198: ! 1199: Adapter - The adapter that the packets are coming through. ! 1200: ! 1201: Packet - The packet whose buffers are to be assigned ! 1202: ring entries. ! 1203: ! 1204: DescriptorIndex - The index of the start of the ring entries to ! 1205: be assigned buffers. ! 1206: ! 1207: Return Value: ! 1208: ! 1209: None. ! 1210: ! 1211: --*/ ! 1212: ! 1213: { ! 1214: ! 1215: // ! 1216: // Points to the reserved portion of the packet. ! 1217: // ! 1218: PSONIC_PACKET_RESERVED Reserved = PSONIC_RESERVED_FROM_PACKET(Packet); ! 1219: ! 1220: // ! 1221: // Pointer to the ring entry to be filled with buffer information. ! 1222: // ! 1223: PSONIC_TRANSMIT_DESCRIPTOR TransmitDescriptor = Adapter->TransmitDescriptorArea ! 1224: + DescriptorIndex; ! 1225: ! 1226: // ! 1227: // Pointer to the ring to packet entry that records the info about ! 1228: // this packet. ! 1229: // ! 1230: PSONIC_DESCRIPTOR_TO_PACKET DescriptorToPacket = Adapter->DescriptorToPacket + DescriptorIndex; ! 1231: ! 1232: // ! 1233: // The total amount of data in the ndis packet. ! 1234: // ! 1235: UINT TotalDataLength; ! 1236: ! 1237: // ! 1238: // Points to the current ndis buffer being walked. ! 1239: // ! 1240: PNDIS_BUFFER CurrentBuffer; ! 1241: ! 1242: // ! 1243: // The number of physical segments in this buffer. ! 1244: // ! 1245: UINT BufferPhysicalSegments; ! 1246: ! 1247: // ! 1248: // An array to hold the physical segments. ! 1249: // ! 1250: NDIS_PHYSICAL_ADDRESS_UNIT PhysicalSegmentArray[SONIC_MAX_FRAGMENTS]; ! 1251: ! 1252: // ! 1253: // We record the owning packet information in the ring packet packet ! 1254: // structure. ! 1255: // ! 1256: ! 1257: ! 1258: DescriptorToPacket->OwningPacket = Packet; ! 1259: DescriptorToPacket->UsedSonicBuffer = (BOOLEAN) ! 1260: Reserved->UsedSonicBuffer; ! 1261: DescriptorToPacket->SonicBuffersIndex = ! 1262: Reserved->SonicBuffersIndex; ! 1263: ! 1264: ! 1265: // ! 1266: // First initialize the fields that don't depend on ! 1267: // how many fragments there are in the packet. ! 1268: // ! 1269: ! 1270: TransmitDescriptor->TransmitStatus = 0; ! 1271: ! 1272: // ! 1273: // Set the programmable interrupt if it has been a long ! 1274: // time since transmit complete interrupts were processed. ! 1275: // ! 1276: ! 1277: if (Adapter->PacketsSinceLastInterrupt >= ! 1278: (SONIC_NUMBER_OF_TRANSMIT_DESCRIPTORS/2)) { ! 1279: ! 1280: TransmitDescriptor->TransmitConfiguration = (UINT)SONIC_TCR_PROG_INTERRUPT; ! 1281: Adapter->PacketsSinceLastInterrupt = 0; ! 1282: ! 1283: } else { ! 1284: ! 1285: TransmitDescriptor->TransmitConfiguration = 0; ! 1286: ++Adapter->PacketsSinceLastInterrupt; ! 1287: ! 1288: } ! 1289: ! 1290: ! 1291: // ! 1292: // Now check to see if the packet has been copied into an ! 1293: // adapter buffer. ! 1294: // ! 1295: ! 1296: if (Reserved->UsedSonicBuffer) { ! 1297: ! 1298: // ! 1299: // Points to the adapter buffer descriptor allocated ! 1300: // for this packet. ! 1301: // ! 1302: PSONIC_BUFFER_DESCRIPTOR BufferDescriptor; ! 1303: ! 1304: BufferDescriptor = Adapter->SonicBuffers ! 1305: + Reserved->SonicBuffersIndex; ! 1306: ! 1307: TransmitDescriptor->FragmentCount = 1; ! 1308: TransmitDescriptor->PacketSize = (UINT)BufferDescriptor->DataLength; ! 1309: ! 1310: SONIC_SET_TRANSMIT_FRAGMENT_ADDRESS( ! 1311: &(TransmitDescriptor->Fragments[0]), ! 1312: NdisGetPhysicalAddressLow(BufferDescriptor->PhysicalSonicBuffer) ! 1313: ); ! 1314: ! 1315: SONIC_SET_TRANSMIT_FRAGMENT_LENGTH( ! 1316: &(TransmitDescriptor->Fragments[0]), ! 1317: BufferDescriptor->DataLength ! 1318: ); ! 1319: ! 1320: ! 1321: // ! 1322: // This sets end-of-list for this descriptor. ! 1323: // ! 1324: ! 1325: SONIC_SET_TRANSMIT_LINK( ! 1326: &(TransmitDescriptor->Fragments[1]), ! 1327: TransmitDescriptor->Link ! 1328: ); ! 1329: ! 1330: DescriptorToPacket->LinkPointer = (SONIC_PHYSICAL_ADDRESS *) ! 1331: &(TransmitDescriptor->Fragments[1]); ! 1332: ! 1333: ! 1334: // ! 1335: // Flush the buffer that contains the packet. ! 1336: // ! 1337: ! 1338: SONIC_FLUSH_WRITE_BUFFER(BufferDescriptor->FlushBuffer); ! 1339: ! 1340: } else { ! 1341: ! 1342: // ! 1343: // The total length of the packet (including padding) ! 1344: // ! 1345: UINT TotalPacketLength; ! 1346: ! 1347: // ! 1348: // Which fragment we are filling; ! 1349: // ! 1350: UINT CurFragment; ! 1351: ! 1352: // ! 1353: // Which map register we use for this buffer. ! 1354: // ! 1355: UINT CurMapRegister; ! 1356: ! 1357: // ! 1358: // Simple iteration variable. ! 1359: // ! 1360: UINT i; ! 1361: ! 1362: ! 1363: CurFragment = 0; ! 1364: CurMapRegister = DescriptorIndex * SONIC_MAX_FRAGMENTS; ! 1365: ! 1366: NdisQueryPacket( ! 1367: Packet, ! 1368: NULL, ! 1369: NULL, ! 1370: &CurrentBuffer, ! 1371: &TotalDataLength ! 1372: ); ! 1373: ! 1374: ! 1375: while (CurrentBuffer) { ! 1376: ! 1377: NdisStartBufferPhysicalMapping( ! 1378: Adapter->NdisAdapterHandle, ! 1379: CurrentBuffer, ! 1380: CurMapRegister, ! 1381: TRUE, ! 1382: PhysicalSegmentArray, ! 1383: &BufferPhysicalSegments ! 1384: ); ! 1385: ! 1386: ++CurMapRegister; ! 1387: ! 1388: // ! 1389: // Put the physical segments for this buffer into ! 1390: // the transmit descriptors. ! 1391: // ! 1392: ! 1393: for (i=0; i<BufferPhysicalSegments; i++) { ! 1394: ! 1395: ASSERT (NdisGetPhysicalAddressHigh(PhysicalSegmentArray[i].PhysicalAddress) == 0); ! 1396: ! 1397: SONIC_SET_TRANSMIT_FRAGMENT_ADDRESS( ! 1398: &(TransmitDescriptor->Fragments[CurFragment]), ! 1399: NdisGetPhysicalAddressLow(PhysicalSegmentArray[i].PhysicalAddress) ! 1400: ); ! 1401: ! 1402: SONIC_SET_TRANSMIT_FRAGMENT_LENGTH( ! 1403: &(TransmitDescriptor->Fragments[CurFragment]), ! 1404: PhysicalSegmentArray[i].Length ! 1405: ); ! 1406: ! 1407: ++CurFragment; ! 1408: ! 1409: #ifndef NO_CHIP_FIXUP ! 1410: ! 1411: // ! 1412: // If the fragment starts and ends not on a longword ! 1413: // boundary, split it into two fragments, the first ! 1414: // being SONIC_MIN_FRAGMENT_SIZE plus the extra bits ! 1415: // at the beginning, the other the rest. ! 1416: // ! 1417: ! 1418: if ((NdisGetPhysicalAddressLow(PhysicalSegmentArray[i].PhysicalAddress) & 0x03) && ! 1419: ((NdisGetPhysicalAddressLow(PhysicalSegmentArray[i].PhysicalAddress) + PhysicalSegmentArray[i].Length) & 0x03)) { ! 1420: ! 1421: UINT FirstSegmentLength; ! 1422: ! 1423: FirstSegmentLength = (4 - ((NdisGetPhysicalAddressLow(PhysicalSegmentArray[i].PhysicalAddress) & 0x03))) + ! 1424: SONIC_MIN_FRAGMENT_SIZE; ! 1425: ! 1426: SONIC_SET_TRANSMIT_FRAGMENT_LENGTH( ! 1427: &(TransmitDescriptor->Fragments[CurFragment-1]), ! 1428: FirstSegmentLength ! 1429: ); ! 1430: ! 1431: SONIC_SET_TRANSMIT_FRAGMENT_ADDRESS( ! 1432: &(TransmitDescriptor->Fragments[CurFragment]), ! 1433: SONIC_GET_TRANSMIT_FRAGMENT_ADDRESS( ! 1434: &(TransmitDescriptor->Fragments[CurFragment-1])) + ! 1435: FirstSegmentLength ! 1436: ); ! 1437: ! 1438: SONIC_SET_TRANSMIT_FRAGMENT_LENGTH( ! 1439: &(TransmitDescriptor->Fragments[CurFragment]), ! 1440: PhysicalSegmentArray[i].Length - FirstSegmentLength ! 1441: ); ! 1442: ! 1443: ++CurFragment; ! 1444: ! 1445: } ! 1446: #endif ! 1447: } ! 1448: ! 1449: ! 1450: SONIC_FLUSH_WRITE_BUFFER (CurrentBuffer); ! 1451: ! 1452: NdisGetNextBuffer( ! 1453: CurrentBuffer, ! 1454: &CurrentBuffer ! 1455: ); ! 1456: ! 1457: } ! 1458: ! 1459: if (TotalDataLength < SONIC_MIN_PACKET_SIZE) { ! 1460: ! 1461: SONIC_SET_TRANSMIT_FRAGMENT_ADDRESS( ! 1462: &(TransmitDescriptor->Fragments[CurFragment]), ! 1463: NdisGetPhysicalAddressLow(Adapter->BlankBufferAddress) ! 1464: ); ! 1465: ! 1466: SONIC_SET_TRANSMIT_FRAGMENT_LENGTH( ! 1467: &(TransmitDescriptor->Fragments[CurFragment]), ! 1468: SONIC_MIN_PACKET_SIZE - TotalDataLength ! 1469: ); ! 1470: ! 1471: // ! 1472: // Note that BlankBuffer has already been flushed. ! 1473: // ! 1474: ! 1475: ++CurFragment; ! 1476: ! 1477: TotalPacketLength = SONIC_MIN_PACKET_SIZE; ! 1478: ! 1479: } else { ! 1480: ! 1481: TotalPacketLength = TotalDataLength; ! 1482: ! 1483: } ! 1484: ! 1485: // ! 1486: // Make sure we didn't mess up and use up too ! 1487: // many fragments. ! 1488: // ! 1489: ASSERT(CurFragment <= SONIC_MAX_FRAGMENTS); ! 1490: ! 1491: TransmitDescriptor->FragmentCount = (UINT)CurFragment; ! 1492: TransmitDescriptor->PacketSize = (UINT)TotalPacketLength; ! 1493: ! 1494: ! 1495: // ! 1496: // This sets end-of-list for this descriptor. ! 1497: // ! 1498: ! 1499: SONIC_SET_TRANSMIT_LINK( ! 1500: &(TransmitDescriptor->Fragments[CurFragment]), ! 1501: TransmitDescriptor->Link ! 1502: ); ! 1503: ! 1504: DescriptorToPacket->LinkPointer = (SONIC_PHYSICAL_ADDRESS *) ! 1505: &(TransmitDescriptor->Fragments[CurFragment]); ! 1506: ! 1507: } ! 1508: ! 1509: if (DescriptorIndex == (Adapter->NumberOfTransmitDescriptors-1)) { ! 1510: ! 1511: Adapter->DescriptorToPacket->PrevLinkPointer = DescriptorToPacket->LinkPointer; ! 1512: ! 1513: } else { ! 1514: ! 1515: (DescriptorToPacket+1)->PrevLinkPointer = DescriptorToPacket->LinkPointer; ! 1516: ! 1517: } ! 1518: ! 1519: Reserved->DescriptorIndex = DescriptorIndex; ! 1520: ! 1521: } ! 1522: ! 1523: STATIC ! 1524: VOID ! 1525: RelinquishPacket( ! 1526: IN PSONIC_ADAPTER Adapter, ! 1527: IN PNDIS_PACKET Packet, ! 1528: IN UINT RingIndex ! 1529: ) ! 1530: ! 1531: /*++ ! 1532: ! 1533: Routine Description: ! 1534: ! 1535: Relinquish the ring entries owned by the packet to the chip. ! 1536: We also update the first uncommitted ring pointer. ! 1537: ! 1538: NOTE: Called with the lock held!! ! 1539: ! 1540: Arguments: ! 1541: ! 1542: Adapter - The adapter that points to the ring entry structures. ! 1543: ! 1544: Packet - The packet contains the ring index of the ring ! 1545: entry for the packet. ! 1546: ! 1547: RingIndex - Holds the index of the ring entry used ! 1548: by this packet. ! 1549: ! 1550: Return Value: ! 1551: ! 1552: None. ! 1553: ! 1554: --*/ ! 1555: ! 1556: { ! 1557: ! 1558: // ! 1559: // Holds the previous link pointer, where we turn off ! 1560: // end-of-list. ! 1561: // ! 1562: ! 1563: PSONIC_PHYSICAL_ADDRESS PrevLinkPointer; ! 1564: ! 1565: #ifdef NDIS_NT ! 1566: ! 1567: // ! 1568: // NOTE: We have to raise the IRQL to POWER_LEVEL around the ! 1569: // calls to SONIC_REMOVE_END_OF_LIST and START_TRANSMIT. ! 1570: // This is to prevent a delay between these two instructions. ! 1571: // If a delay happens right after SONIC_REMOVE_END_OF_LIST, the ! 1572: // Sonic could transmit the packet and stop, then the call ! 1573: // to START_TRANSMIT would cause it to retransmit all the ! 1574: // packets in the descriptor ring. ! 1575: // ! 1576: KIRQL OldIrql; ! 1577: ! 1578: #endif ! 1579: ! 1580: ! 1581: PrevLinkPointer = Adapter->DescriptorToPacket[RingIndex].PrevLinkPointer; ! 1582: ! 1583: #ifdef NDIS_NT ! 1584: ! 1585: // ! 1586: // See NOTE above. ! 1587: // ! 1588: ! 1589: KeRaiseIrql(POWER_LEVEL, &OldIrql); ! 1590: ! 1591: #endif ! 1592: ! 1593: ! 1594: // ! 1595: // Turn off END_OF_LIST for the last one. ! 1596: // ! 1597: ! 1598: SONIC_REMOVE_END_OF_LIST(PrevLinkPointer); ! 1599: ! 1600: // ! 1601: // This turns on the correct bit in the SONIC_CONTROL ! 1602: // register. ! 1603: // ! 1604: ! 1605: START_TRANSMIT(Adapter); ! 1606: ! 1607: ! 1608: #ifdef NDIS_NT ! 1609: ! 1610: // ! 1611: // See NOTE above. ! 1612: // ! 1613: ! 1614: KeLowerIrql(OldIrql); ! 1615: ! 1616: #endif ! 1617: ! 1618: // ! 1619: // We want FirstUncommittedDescriptor to point to right after us. ! 1620: // ! 1621: ! 1622: if (RingIndex == (Adapter->NumberOfTransmitDescriptors-1)) { ! 1623: ! 1624: Adapter->FirstUncommittedDescriptor = Adapter->TransmitDescriptorArea; ! 1625: ! 1626: } else { ! 1627: ! 1628: Adapter->FirstUncommittedDescriptor = ! 1629: Adapter->TransmitDescriptorArea + (RingIndex + 1); ! 1630: ! 1631: } ! 1632: ! 1633: } ! 1634: ! 1635:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.