Annotation of ntddk/src/network/sonic/send.c, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.