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

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1990  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: Author:
        !            29: 
        !            30:     Anthony V. Ercolano (Tonye) 12-Sept-1990
        !            31: 
        !            32: Environment:
        !            33: 
        !            34:     Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
        !            35: 
        !            36: Revision History:
        !            37: 
        !            38:     31-Jul-1992  R.D. Lanser:
        !            39: 
        !            40:        Removed PhysicalBuffersContained and UsedLanceBuffer field from
        !            41:        _ADAPTER structure.  SeanSe says that the code related to this
        !            42:        field was used for adevice that is no longer supported.  I removed
        !            43:        the dependent code(or at least what was obvious) from 'send.c'.
        !            44:        This old code was generating an erroneous ring buffer count on the
        !            45:        MIPS R3000.  I did not test it on the MIPS R4000.  The problem goes
        !            46:        away with the removal of the offending code.
        !            47: 
        !            48: --*/
        !            49: 
        !            50: #include <ndis.h>
        !            51: #include <efilter.h>
        !            52: #include <lancehrd.h>
        !            53: #include <lancesft.h>
        !            54: 
        !            55: 
        !            56: //
        !            57: // Minimum packet size that a transport can send.  We subtract 4 bytes
        !            58: // because we add a 4 byte CRC on the end.
        !            59: //
        !            60: 
        !            61: #define MIN_SINGLE_BUFFER ((UINT)LANCE_SMALL_BUFFER_SIZE - 4)
        !            62: 
        !            63: 
        !            64: //
        !            65: // It will poke the lance hardware into noticing that there is a packet
        !            66: // available for transmit.
        !            67: //
        !            68: // Note that there is the assumption that the register address
        !            69: // port (RAP) is already set to zero.
        !            70: //
        !            71: #define PROD_TRANSMIT(A) \
        !            72:     LANCE_WRITE_RDP( \
        !            73:     A, \
        !            74:     LANCE_CSR0_TRANSMIT_DEMAND | LANCE_CSR0_INTERRUPT_ENABLE \
        !            75:     );
        !            76: 
        !            77: VOID
        !            78: SetupAllocate(
        !            79:     IN PLANCE_ADAPTER Adapter,
        !            80:     IN NDIS_HANDLE MacBindingHandle,
        !            81:     IN PNDIS_PACKET Packet
        !            82:     );
        !            83: 
        !            84: VOID
        !            85: StagedAllocation(
        !            86:     IN PLANCE_ADAPTER Adapter
        !            87:     );
        !            88: 
        !            89: VOID
        !            90: CopyPacketIntoBuffer(
        !            91:     IN PLANCE_ADAPTER Adapter,
        !            92:     IN PNDIS_PACKET Packet,
        !            93:     IN PLANCE_BUFFER_DESCRIPTOR BufferDescriptor
        !            94:     );
        !            95: 
        !            96: 
        !            97: 
        !            98: extern
        !            99: NDIS_STATUS
        !           100: LanceSend(
        !           101:     IN NDIS_HANDLE MacBindingHandle,
        !           102:     IN PNDIS_PACKET Packet
        !           103:     )
        !           104: 
        !           105: /*++
        !           106: 
        !           107: Routine Description:
        !           108: 
        !           109:     The LanceSend request instructs a MAC to transmit a packet through
        !           110:     the adapter onto the medium.
        !           111: 
        !           112: Arguments:
        !           113: 
        !           114:     MacBindingHandle - The context value returned by the MAC  when the
        !           115:     adapter was opened.  In reality, it is a pointer to LANCE_OPEN.
        !           116: 
        !           117:     Packet - A pointer to a descriptor for the packet that is to be
        !           118:     transmitted.
        !           119: 
        !           120: Return Value:
        !           121: 
        !           122:     The function value is the status of the operation.
        !           123: 
        !           124: 
        !           125: --*/
        !           126: 
        !           127: {
        !           128: 
        !           129:     //
        !           130:     // Holds the status that should be returned to the caller.
        !           131:     //
        !           132:     NDIS_STATUS StatusToReturn = NDIS_STATUS_PENDING;
        !           133: 
        !           134:     //
        !           135:     // Pointer to the adapter.
        !           136:     //
        !           137:     PLANCE_ADAPTER Adapter;
        !           138: 
        !           139:     PLANCE_OPEN Open;
        !           140: 
        !           141:     Open = PLANCE_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
        !           142: 
        !           143: #if LANCE_TRACE
        !           144:     DbgPrint("In LanceSend\n");
        !           145: #endif
        !           146: 
        !           147:     Adapter = PLANCE_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
        !           148: 
        !           149:     if (Adapter->HardwareFailure) {
        !           150: 
        !           151:         return(NDIS_STATUS_FAILURE);
        !           152: 
        !           153:     }
        !           154: 
        !           155:     NdisAcquireSpinLock(&Adapter->Lock);
        !           156:     Adapter->References++;
        !           157: 
        !           158:     LOG(IN_SEND);
        !           159: 
        !           160:     if (!Adapter->ResetInProgress) {
        !           161: 
        !           162:         if (!Open->BindingShuttingDown) {
        !           163: 
        !           164:             UINT TotalPacketSize;
        !           165: 
        !           166:             //
        !           167:             // Increment the references on the open while we are
        !           168:             // accessing it in the interface.
        !           169:             //
        !           170: 
        !           171:             Open->References++;
        !           172: 
        !           173:             //
        !           174:             // It is reasonable to do a quick check and fail if the packet
        !           175:             // is larger than the maximum an ethernet can handle.
        !           176:             //
        !           177: 
        !           178:             NdisQueryPacket(
        !           179:                 Packet,
        !           180:                 NULL,
        !           181:                 NULL,
        !           182:                 NULL,
        !           183:                 &TotalPacketSize
        !           184:                 );
        !           185: 
        !           186:             if ((!TotalPacketSize) ||
        !           187:                 (TotalPacketSize > LANCE_LARGE_BUFFER_SIZE)) {
        !           188: 
        !           189:                 StatusToReturn = NDIS_STATUS_RESOURCES;
        !           190: 
        !           191:             } else {
        !           192: 
        !           193:                 //
        !           194:                 // There is an assumption in the code that no pointer
        !           195:                 // (which are really handles) to an ndis packet will have
        !           196:                 // its low bit set. (Always have even byte alignment.)
        !           197:                 //
        !           198: 
        !           199:                 ASSERT(!((UINT)Packet & 1));
        !           200: 
        !           201:                 SetupAllocate(
        !           202:                     Adapter,
        !           203:                     MacBindingHandle,
        !           204:                     Packet
        !           205:                     );
        !           206: 
        !           207:                 //
        !           208:                 // Add a reference for the pending send
        !           209:                 //
        !           210: 
        !           211:                 Open->References++;
        !           212: 
        !           213:                 //
        !           214:                 // Only try to push it through the stage queues
        !           215:                 // if somebody else isn't already doing it and
        !           216:                 // there is some hope of moving some packets
        !           217:                 // ahead.
        !           218:                 //
        !           219: 
        !           220:                 while ((!Adapter->AlreadyProcessingStage
        !           221:                        ) &&
        !           222:                        (Adapter->FirstStage1Packet &&
        !           223:                         Adapter->StageOpen
        !           224:                        )
        !           225:                       ) {
        !           226: 
        !           227:                     LanceStagedAllocation(Adapter);
        !           228: 
        !           229:                 }
        !           230: 
        !           231:             }
        !           232: 
        !           233:             //
        !           234:             // The interface is no longer referencing the open.
        !           235:             //
        !           236: 
        !           237:             Open->References--;
        !           238: 
        !           239:         } else {
        !           240: 
        !           241:             StatusToReturn = NDIS_STATUS_CLOSING;
        !           242: 
        !           243:         }
        !           244: 
        !           245:     } else if (Adapter->ResetRequestType == NdisRequestGeneric1) {
        !           246: 
        !           247:         StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
        !           248: 
        !           249:     } else {
        !           250: 
        !           251:         //
        !           252:         // Reset is from a SetInfo or internal call and this packet needs
        !           253:         // to be pended.
        !           254:         //
        !           255: 
        !           256:         SetupAllocate(
        !           257:                         Adapter,
        !           258:                         MacBindingHandle,
        !           259:                         Packet
        !           260:                         );
        !           261: 
        !           262:         //
        !           263:         // Add one to reference fore pending send
        !           264:         //
        !           265:         Open->References++;
        !           266: 
        !           267:         StatusToReturn = NDIS_STATUS_PENDING;
        !           268: 
        !           269:     }
        !           270: 
        !           271:     LOG(OUT_SEND);
        !           272: 
        !           273:     LANCE_DO_DEFERRED(Adapter);
        !           274: 
        !           275: #if LANCE_TRACE
        !           276:     DbgPrint("Out LanceSend\n");
        !           277: #endif
        !           278: 
        !           279:     return StatusToReturn;
        !           280: }
        !           281: 
        !           282: VOID
        !           283: SetupAllocate(
        !           284:     IN PLANCE_ADAPTER Adapter,
        !           285:     IN NDIS_HANDLE MacBindingHandle,
        !           286:     IN PNDIS_PACKET Packet
        !           287:     )
        !           288: 
        !           289: /*++
        !           290: 
        !           291: Routine Description:
        !           292: 
        !           293:     This sets up the MAC reserved portion of the packet so that
        !           294:     later allocation routines can determine what is left to be
        !           295:     done in the allocation cycle.
        !           296: 
        !           297:     NOTE: This assumes it is called with the spinlock held!!
        !           298: 
        !           299: Arguments:
        !           300: 
        !           301:     Adapter - The adapter that this packet is coming through.
        !           302: 
        !           303:     MacBindingHandle - Points to the open binding structure.
        !           304: 
        !           305:     Packet - The packet that is to be transmitted.
        !           306: 
        !           307: Return Value:
        !           308: 
        !           309:     None.
        !           310: 
        !           311: --*/
        !           312: 
        !           313: {
        !           314: 
        !           315:     //
        !           316:     // Points to the MAC reserved portion of this packet.  This
        !           317:     // interpretation of the reserved section is only valid during
        !           318:     // the allocation phase of the packet.
        !           319:     //
        !           320:     PLANCE_RESERVED Reserved = PLANCE_RESERVED_FROM_PACKET(Packet);
        !           321: 
        !           322: 
        !           323:     ASSERT(sizeof(LANCE_RESERVED) <=
        !           324:            sizeof(Packet->MacReserved));
        !           325: 
        !           326:     Reserved->LanceBuffersIndex = 0;
        !           327:     Reserved->MacBindingHandle = MacBindingHandle;
        !           328: 
        !           329:     //
        !           330:     // Put on the stage 1 queue.
        !           331:     //
        !           332: 
        !           333:     if (!Adapter->LastStage1Packet) {
        !           334: 
        !           335:         Adapter->FirstStage1Packet = Packet;
        !           336: 
        !           337:     } else {
        !           338: 
        !           339:         PLANCE_RESERVED_FROM_PACKET(Adapter->LastStage1Packet)->Next = Packet;
        !           340: 
        !           341:     }
        !           342: 
        !           343:     Adapter->LastStage1Packet = Packet;
        !           344: 
        !           345:     Reserved->Next = NULL;
        !           346: 
        !           347: }
        !           348: 
        !           349: extern
        !           350: VOID
        !           351: LanceStagedAllocation(
        !           352:     IN PLANCE_ADAPTER Adapter
        !           353:     )
        !           354: 
        !           355: /*++
        !           356: 
        !           357: Routine Description:
        !           358: 
        !           359:     This routine attempts to take a packet through a stage of allocation.
        !           360: 
        !           361:     NOTE: THIS IS CALLED WITH THE LOCK HELD!!
        !           362: 
        !           363:     NOTE: MUST BE CALLED WITH
        !           364: 
        !           365:         Adapter->StageOpen &&
        !           366:         !Adapter->AlreadyProcessingStage &&
        !           367:         Adapter->FirstStage1Packet
        !           368: 
        !           369: 
        !           370: 
        !           371: Arguments:
        !           372: 
        !           373:     Adapter - The adapter that the packets are coming through.
        !           374: 
        !           375: Return Value:
        !           376: 
        !           377:     None.
        !           378: 
        !           379: --*/
        !           380: 
        !           381: {
        !           382:     //
        !           383:     // Pointer to the ring entry to be filled with buffer information.
        !           384:     //
        !           385:     PLANCE_TRANSMIT_ENTRY CurrentRingElement;
        !           386: 
        !           387:     //
        !           388:     // Pointer to the ring to packet entry that records the info about
        !           389:     // this packet.
        !           390:     //
        !           391:     PLANCE_RING_TO_PACKET RingToPacket;
        !           392: 
        !           393:     //
        !           394:     // Length of the packet
        !           395:     //
        !           396:     ULONG TotalVirtualLength;
        !           397: 
        !           398:     //
        !           399:     // Holds the adapter buffer index available for allocation.
        !           400:     //
        !           401:     INT LanceBuffersIndex;
        !           402: 
        !           403:     //
        !           404:     // Points to a successfully allocated adapter buffer descriptor.
        !           405:     //
        !           406:     PLANCE_BUFFER_DESCRIPTOR BufferDescriptor;
        !           407: 
        !           408:     //
        !           409:     // Simple iteration variable.
        !           410:     //
        !           411:     INT i;
        !           412: 
        !           413:     //
        !           414:     // Size of Lance Buffer needed (1==Small, 2==Medium, 3==Large)
        !           415:     //
        !           416:     UCHAR BufferSize;
        !           417: 
        !           418:     //
        !           419:     // If we successfully acquire some ring entries, this
        !           420:     // is the index of the first one.
        !           421:     //
        !           422:     UINT RingIndex;
        !           423: 
        !           424:     PNDIS_PACKET FirstPacket;
        !           425: 
        !           426:     PLANCE_RESERVED Reserved;
        !           427: 
        !           428: 
        !           429:     if (Adapter->NumberOfAvailableRings == 0) {
        !           430: 
        !           431:         Adapter->StageOpen = FALSE;
        !           432:         return ;
        !           433: 
        !           434:     }
        !           435: 
        !           436:     Adapter->AlreadyProcessingStage = TRUE;
        !           437: 
        !           438:     FirstPacket = Adapter->FirstStage1Packet;
        !           439: 
        !           440:     //
        !           441:     // Determine if and how much adapter space would need to be allocated
        !           442:     // to meet hardware constraints.
        !           443:     //
        !           444: 
        !           445:     NdisQueryPacket(
        !           446:         FirstPacket,
        !           447:         NULL,
        !           448:         NULL,
        !           449:         NULL,
        !           450:         &TotalVirtualLength
        !           451:         );
        !           452: 
        !           453:     //
        !           454:     // Certain hardware implementation (Decstation) use a dual ported
        !           455:     // memory to communicate with the hardware.  This is reasonable since
        !           456:     // it reduces bus contention.  When using the dual ported memory, all
        !           457:     // send data must be moved to buffers allocated from the dual ported
        !           458:     // memory.
        !           459:     //
        !           460: 
        !           461:     if (TotalVirtualLength <= LANCE_SMALL_BUFFER_SIZE) {
        !           462: 
        !           463:         BufferSize = 1;
        !           464: 
        !           465:     } else if (TotalVirtualLength <= LANCE_MEDIUM_BUFFER_SIZE) {
        !           466: 
        !           467:         BufferSize = 2;
        !           468: 
        !           469:     } else {
        !           470: 
        !           471:         BufferSize = 3;
        !           472: 
        !           473:     }
        !           474: 
        !           475:     //
        !           476:     // Find a buffer
        !           477:     //
        !           478:     for (
        !           479:         i = BufferSize;
        !           480:         i <= 3;
        !           481:         i++
        !           482:         ) {
        !           483: 
        !           484:         if ((LanceBuffersIndex = Adapter->LanceBufferListHeads[i]) != -1) {
        !           485: 
        !           486:             BufferDescriptor = Adapter->LanceBuffers + LanceBuffersIndex;
        !           487:             Adapter->LanceBufferListHeads[i] = BufferDescriptor->Next;
        !           488:             break;
        !           489: 
        !           490:         }
        !           491: 
        !           492:     }
        !           493: 
        !           494:     if (LanceBuffersIndex == -1) {
        !           495: 
        !           496:         //
        !           497:         // Nothing available for the packet.
        !           498:         //
        !           499: 
        !           500:         Adapter->StageOpen = FALSE;
        !           501:         Adapter->AlreadyProcessingStage = FALSE;
        !           502: 
        !           503:         return;
        !           504: 
        !           505:     }
        !           506: 
        !           507:     //
        !           508:     // We need to save in the packet which adapter buffere descriptor
        !           509:     // it is using so that we can deallocate it later.  We also store
        !           510:     // the number of buffers contained so that we can allocate ring
        !           511:     // entries.
        !           512:     //
        !           513: 
        !           514:     Reserved = PLANCE_RESERVED_FROM_PACKET(FirstPacket);
        !           515: 
        !           516:     Reserved->LanceBuffersIndex = LanceBuffersIndex;
        !           517: 
        !           518:     //
        !           519:     // Now remove this packet from the queue
        !           520:     //
        !           521: 
        !           522:     Adapter->FirstStage1Packet = Reserved->Next;
        !           523: 
        !           524:     if (Adapter->FirstStage1Packet == NULL) {
        !           525: 
        !           526:         Adapter->LastStage1Packet = NULL;
        !           527: 
        !           528:     }
        !           529: 
        !           530:     //
        !           531:     // Save the list head index in the buffer descriptor
        !           532:     // to permit easy deallocation later.
        !           533:     //
        !           534:     BufferDescriptor->Next = i;
        !           535: 
        !           536:     //
        !           537:     // Now Acquire the ring
        !           538:     //
        !           539:     RingIndex = Adapter->AllocateableRing - Adapter->TransmitRing;
        !           540: 
        !           541:     //
        !           542:     // Store the info
        !           543:     //
        !           544:     CurrentRingElement = Adapter->AllocateableRing;
        !           545: 
        !           546:     //
        !           547:     // NOTE NOTE NOTE NOTE NOTE NOTE
        !           548:     //
        !           549:     // We can do the next calculation because we know that the number
        !           550:     // or ring entries is a power of two!
        !           551:     //
        !           552: 
        !           553:     Adapter->AllocateableRing = Adapter->TransmitRing +
        !           554:             (((RingIndex) + 1) &
        !           555:              (Adapter->NumberOfTransmitRings-1));
        !           556: 
        !           557:     Adapter->NumberOfAvailableRings--;
        !           558: 
        !           559:     //
        !           560:     // Copy into buffer
        !           561:     //
        !           562:     CopyPacketIntoBuffer(Adapter, FirstPacket, BufferDescriptor);
        !           563: 
        !           564:     //
        !           565:     // Get the position for mapping ring entries to packets.
        !           566:     // We record the owning packet information in the ring packet packet
        !           567:     // structure.
        !           568:     //
        !           569:     RingToPacket = Adapter->RingToPacket + RingIndex;
        !           570:     RingToPacket->OwningPacket = FirstPacket;
        !           571:     RingToPacket->LanceBuffersIndex = Reserved->LanceBuffersIndex;
        !           572:     RingToPacket->RingIndex = RingIndex;
        !           573: 
        !           574:     //
        !           575:     // Make sure that the ring descriptor is clean.
        !           576:     //
        !           577: 
        !           578:     LANCE_ZERO_MEMORY_FOR_HARDWARE(CurrentRingElement,sizeof(LANCE_TRANSMIT_ENTRY));
        !           579: 
        !           580:     LANCE_SET_TRANSMIT_BUFFER_LENGTH(
        !           581:         CurrentRingElement,
        !           582:         BufferDescriptor->DataLength
        !           583:         );
        !           584: 
        !           585: 
        !           586:     LANCE_SET_TRANSMIT_BUFFER_ADDRESS(
        !           587:             Adapter,
        !           588:             CurrentRingElement,
        !           589:             BufferDescriptor->VirtualLanceBuffer
        !           590:             );
        !           591: 
        !           592:     LOG(TRANSMIT);
        !           593: 
        !           594:     //
        !           595:     // We update the ring ownership of the last packet under
        !           596:     // the protection of the lock so that the uncommitted packet
        !           597:     // pointer can be updated before the transmit post processing
        !           598:     // can examine it.
        !           599:     //
        !           600: 
        !           601:     LANCE_SET_RING_BITS(
        !           602:       CurrentRingElement->TransmitSummaryBits,
        !           603:       LANCE_TRANSMIT_START_OF_PACKET |
        !           604:       LANCE_TRANSMIT_OWNED_BY_CHIP |
        !           605:       LANCE_TRANSMIT_END_OF_PACKET
        !           606:       );
        !           607: 
        !           608: 
        !           609:     if (RingIndex == (Adapter->NumberOfTransmitRings-1)) {
        !           610: 
        !           611:         Adapter->FirstUncommittedRing = Adapter->TransmitRing ;
        !           612: 
        !           613:     } else {
        !           614: 
        !           615:         Adapter->FirstUncommittedRing = Adapter->TransmitRing + RingIndex + 1;
        !           616: 
        !           617:     }
        !           618: 
        !           619:     //
        !           620:     // Prod the chip into checking for packets to send.
        !           621:     //
        !           622: 
        !           623:     PROD_TRANSMIT(Adapter);
        !           624: 
        !           625:     if (Adapter->LastFinishTransmit) {
        !           626: 
        !           627:         PLANCE_RESERVED LastReserved =
        !           628:            PLANCE_RESERVED_FROM_PACKET(Adapter->LastFinishTransmit);
        !           629: 
        !           630:         LastReserved->Next = FirstPacket;
        !           631: 
        !           632:     }
        !           633: 
        !           634:     Reserved->Next = NULL;
        !           635: 
        !           636:     Adapter->LastFinishTransmit = FirstPacket;
        !           637: 
        !           638:     if (!Adapter->FirstFinishTransmit) {
        !           639: 
        !           640:         Adapter->FirstFinishTransmit = FirstPacket;
        !           641: 
        !           642:     }
        !           643: 
        !           644:     Adapter->AlreadyProcessingStage = FALSE;
        !           645: 
        !           646: }
        !           647: 
        !           648: 
        !           649: VOID
        !           650: CopyPacketIntoBuffer(
        !           651:     IN PLANCE_ADAPTER Adapter,
        !           652:     IN PNDIS_PACKET Packet,
        !           653:     IN PLANCE_BUFFER_DESCRIPTOR BufferDescriptor
        !           654:     )
        !           655: 
        !           656: /*++
        !           657: 
        !           658: Routine Description:
        !           659: 
        !           660:     Copy a packet down to the hardware.
        !           661: 
        !           662:     Note : MUST BE CALLED WITH LOCK HELD!
        !           663: 
        !           664: Arguments:
        !           665: 
        !           666:     Adapter - The adapter the packet is coming through.
        !           667: 
        !           668:     Packet - The packet whose buffers are to be copied.
        !           669: 
        !           670: Return Value:
        !           671: 
        !           672:     none
        !           673: 
        !           674: --*/
        !           675: 
        !           676: {
        !           677:     //
        !           678:     // Will point into the virtual address space addressed
        !           679:     // by the adapter buffer if one was successfully allocated.
        !           680:     //
        !           681:     PCHAR CurrentDestination;
        !           682: 
        !           683:     //
        !           684:     // Will hold the total amount of data copied to the
        !           685:     // adapter buffer.
        !           686:     //
        !           687:     UINT TotalVirtualLength;
        !           688: 
        !           689:     //
        !           690:     // Will point to the current source buffer.
        !           691:     //
        !           692:     PNDIS_BUFFER SourceBuffer;
        !           693: 
        !           694:     //
        !           695:     // Points to the virtual address of the source buffers data.
        !           696:     //
        !           697:     PVOID SourceData;
        !           698: 
        !           699:     //
        !           700:     // Will point to the number of bytes of data in the source
        !           701:     // buffer.
        !           702:     //
        !           703:     UINT SourceLength;
        !           704: 
        !           705:     NdisReleaseSpinLock(&Adapter->Lock);
        !           706: 
        !           707:     //
        !           708:     // Fill in the adapter buffer with the data from the users
        !           709:     // buffers.
        !           710:     //
        !           711: 
        !           712:     CurrentDestination = BufferDescriptor->VirtualLanceBuffer;
        !           713: 
        !           714:     NdisQueryPacket(
        !           715:         Packet,
        !           716:         NULL,
        !           717:         NULL,
        !           718:         &SourceBuffer,
        !           719:         &TotalVirtualLength
        !           720:         );
        !           721: 
        !           722:     while ( SourceBuffer != NULL ) {
        !           723: 
        !           724:         NdisQueryBuffer(
        !           725:                 SourceBuffer,
        !           726:                 &SourceData,
        !           727:                 &SourceLength
        !           728:                 );
        !           729: 
        !           730:         LANCE_MOVE_MEMORY_TO_HARDWARE(
        !           731:             CurrentDestination,
        !           732:             SourceData,
        !           733:             SourceLength
        !           734:             );
        !           735: 
        !           736:         CurrentDestination = (PCHAR)CurrentDestination + SourceLength;
        !           737: 
        !           738:         NdisGetNextBuffer(
        !           739:                 SourceBuffer,
        !           740:                 &SourceBuffer
        !           741:                 );
        !           742: 
        !           743:     }
        !           744: 
        !           745:     //
        !           746:     // If the packet is less then the minimum size then we
        !           747:     // need to zero out the rest of the packet.
        !           748:     //
        !           749: 
        !           750:     if (TotalVirtualLength < MIN_SINGLE_BUFFER) {
        !           751: 
        !           752:         LANCE_ZERO_MEMORY_FOR_HARDWARE(
        !           753:             CurrentDestination,
        !           754:             MIN_SINGLE_BUFFER - TotalVirtualLength
        !           755:             );
        !           756: 
        !           757:         BufferDescriptor->DataLength = MIN_SINGLE_BUFFER;
        !           758: 
        !           759:     } else {
        !           760: 
        !           761:         BufferDescriptor->DataLength = TotalVirtualLength;
        !           762: 
        !           763:     }
        !           764: 
        !           765:     NdisAcquireSpinLock(&Adapter->Lock);
        !           766: 
        !           767:     return;
        !           768: }
        !           769: 

unix.superglobalmegacorp.com

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