Annotation of ntddk/src/network/sonic/send.c, revision 1.1.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.