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

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1990  Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     transfer.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This file contains the code to implement the MacTransferData
        !            12:     API for the ndis 3.0 interface.
        !            13: 
        !            14: Author:
        !            15: 
        !            16:     Anthony V. Ercolano (Tonye) 12-Sept-1990
        !            17: 
        !            18: Environment:
        !            19: 
        !            20:     Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
        !            21: 
        !            22: Revision History:
        !            23: 
        !            24: 
        !            25: --*/
        !            26: 
        !            27: #include <ndis.h>
        !            28: #include <efilter.h>
        !            29: #include <lancehrd.h>
        !            30: #include <lancesft.h>
        !            31: 
        !            32: 
        !            33: extern
        !            34: NDIS_STATUS
        !            35: LanceTransferData(
        !            36:     IN NDIS_HANDLE MacBindingHandle,
        !            37:     IN NDIS_HANDLE MacReceiveContext,
        !            38:     IN UINT ByteOffset,
        !            39:     IN UINT BytesToTransfer,
        !            40:     OUT PNDIS_PACKET Packet,
        !            41:     OUT PUINT BytesTransferred
        !            42:     )
        !            43: 
        !            44: /*++
        !            45: 
        !            46: Routine Description:
        !            47: 
        !            48:     A protocol calls the LanceTransferData request (indirectly via
        !            49:     NdisTransferData) from within its Receive event handler
        !            50:     to instruct the MAC to copy the contents of the received packet
        !            51:     a specified paqcket buffer.
        !            52: 
        !            53: Arguments:
        !            54: 
        !            55:     MacBindingHandle - The context value returned by the MAC when the
        !            56:     adapter was opened.  In reality this is a pointer to LANCE_OPEN.
        !            57: 
        !            58:     MacReceiveContext - The context value passed by the MAC on its call
        !            59:     to NdisIndicateReceive.  The MAC can use this value to determine
        !            60:     which packet, on which adapter, is being received.
        !            61: 
        !            62:     ByteOffset - An unsigned integer specifying the offset within the
        !            63:     received packet at which the copy is to begin.  If the entire packet
        !            64:     is to be copied, ByteOffset must be zero.
        !            65: 
        !            66:     BytesToTransfer - An unsigned integer specifying the number of bytes
        !            67:     to copy.  It is legal to transfer zero bytes; this has no effect.  If
        !            68:     the sum of ByteOffset and BytesToTransfer is greater than the size
        !            69:     of the received packet, then the remainder of the packet (starting from
        !            70:     ByteOffset) is transferred, and the trailing portion of the receive
        !            71:     buffer is not modified.
        !            72: 
        !            73:     Packet - A pointer to a descriptor for the packet storage into which
        !            74:     the MAC is to copy the received packet.
        !            75: 
        !            76:     BytesTransfered - A pointer to an unsigned integer.  The MAC writes
        !            77:     the actual number of bytes transferred into this location.  This value
        !            78:     is not valid if the return status is STATUS_PENDING.
        !            79: 
        !            80: Return Value:
        !            81: 
        !            82:     The function value is the status of the operation.
        !            83: 
        !            84: 
        !            85: --*/
        !            86: 
        !            87: {
        !            88: 
        !            89:     PLANCE_ADAPTER Adapter;
        !            90:     PLANCE_OPEN Open = PLANCE_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
        !            91:     NDIS_STATUS StatusToReturn;
        !            92: 
        !            93:     Adapter = PLANCE_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
        !            94: 
        !            95:     NdisAcquireSpinLock(&Adapter->Lock);
        !            96: 
        !            97:     Adapter->References++;
        !            98: 
        !            99:     ASSERT(!Adapter->ResetInitStarted);
        !           100: 
        !           101:     ByteOffset += LANCE_HEADER_SIZE;
        !           102: 
        !           103:     if (!Open->BindingShuttingDown) {
        !           104: 
        !           105:         Open->References++;
        !           106: 
        !           107:         NdisReleaseSpinLock(&Adapter->Lock);
        !           108: 
        !           109:         //
        !           110:         // The MacReceive context can be either of two things.
        !           111:         //
        !           112:         // If the low bit is != 1 then it is a pointer to the users
        !           113:         // ndis packet.  It would typically be the packet when the
        !           114:         // packet has been delivered via loopback.
        !           115:         //
        !           116:         // If the value has a 1 in the low bit, the value holds the
        !           117:         // first and last receive ring descriptor indices.
        !           118:         //
        !           119: 
        !           120:         if (!((UINT)MacReceiveContext & 1)) {
        !           121: 
        !           122:             LanceCopyFromPacketToPacket(
        !           123:                         Packet,
        !           124:                         0,
        !           125:                         BytesToTransfer,
        !           126:                         (PNDIS_PACKET)((PVOID)MacReceiveContext),
        !           127:                         ByteOffset,
        !           128:                         BytesTransferred
        !           129:                         );
        !           130: 
        !           131:         } else {
        !           132: 
        !           133:             //
        !           134:             // The code in this section is quite similar to the
        !           135:             // code in CopyFromPacketToPacket.  It could easily go
        !           136:             // into its own routine, except that it is not likely
        !           137:             // to be used in any other implementation.
        !           138:             //
        !           139: 
        !           140:             //
        !           141:             // Keep a local for the number of receive ring entries so
        !           142:             // that we aren't always accessing through the adapter.
        !           143:             //
        !           144:             const UINT TopReceiveIndex = Adapter->NumberOfReceiveRings - 1;
        !           145: 
        !           146:             //
        !           147:             // Used for only a short time to extract the context
        !           148:             // information from the parameter.
        !           149:             //
        !           150:             LANCE_RECEIVE_CONTEXT C;
        !           151: 
        !           152:             //
        !           153:             // Holds the first and last index of the first and last
        !           154:             // receive ring descriptors that hold the current packet.
        !           155:             //
        !           156:             UINT FirstBuffer;
        !           157:             UINT LastBuffer;
        !           158: 
        !           159:             //
        !           160:             // Pointer to the ring descriptor for the current buffer.
        !           161:             //
        !           162:             PLANCE_RECEIVE_ENTRY CurrentEntry;
        !           163: 
        !           164:             //
        !           165:             // Holds the count of the number of ndis buffers comprising
        !           166:             // the destination packet.
        !           167:             //
        !           168:             UINT DestinationBufferCount;
        !           169: 
        !           170:             //
        !           171:             // Points to the buffer into which we are putting data.
        !           172:             //
        !           173:             PNDIS_BUFFER DestinationCurrentBuffer;
        !           174: 
        !           175:             //
        !           176:             // Holds the virtual address of the current destination
        !           177:             // buffer.
        !           178:             //
        !           179:             PVOID DestinationVirtualAddress;
        !           180: 
        !           181:             //
        !           182:             // Holds the virtual address of the current source buffer.
        !           183:             //
        !           184:             PVOID SourceVirtualAddress;
        !           185: 
        !           186:             //
        !           187:             // Holds the length of the current destination buffer.
        !           188:             //
        !           189:             UINT DestinationCurrentLength;
        !           190: 
        !           191:             //
        !           192:             // Holds the length of the current source buffer.
        !           193:             //
        !           194:             UINT SourceCurrentLength;
        !           195: 
        !           196:             //
        !           197:             // Keep a local variable of BytesTransferred so we aren't
        !           198:             // referencing through a pointer.
        !           199:             //
        !           200:             UINT LocalBytesTransferred = 0;
        !           201: 
        !           202:             //
        !           203:             // Index in the ring of the current receive ring descriptor.
        !           204:             //
        !           205:             UINT CurrentSourceIndex;
        !           206: 
        !           207:             //
        !           208:             // Take care of boundary condition of zero length copy.
        !           209:             //
        !           210: 
        !           211:             *BytesTransferred = 0;
        !           212: 
        !           213:             ASSERT(sizeof(UINT) >= 2);
        !           214:             ASSERT(sizeof(UINT) == sizeof(NDIS_HANDLE));
        !           215: 
        !           216:             C.WholeThing = (UINT)MacReceiveContext;
        !           217:             FirstBuffer = C.INFO.FirstBuffer;
        !           218:             LastBuffer = C.INFO.LastBuffer;
        !           219: 
        !           220:             //
        !           221:             // Get the first buffer of the destination.
        !           222:             //
        !           223: 
        !           224:             NdisQueryPacket(
        !           225:                         Packet,
        !           226:                         NULL,
        !           227:                         &DestinationBufferCount,
        !           228:                         &DestinationCurrentBuffer,
        !           229:                         NULL
        !           230:                         );
        !           231: 
        !           232:             //
        !           233:             // Could have a null packet.
        !           234:             //
        !           235: 
        !           236:             if (DestinationBufferCount) {
        !           237: 
        !           238:                 NdisQueryBuffer(
        !           239:                             DestinationCurrentBuffer,
        !           240:                             &DestinationVirtualAddress,
        !           241:                             &DestinationCurrentLength
        !           242:                             );
        !           243: 
        !           244:                 //
        !           245:                 // Get the information for the first buffer of the source.
        !           246:                 //
        !           247: 
        !           248:                 SourceVirtualAddress = Adapter->ReceiveVAs[FirstBuffer];
        !           249:                 CurrentEntry = Adapter->ReceiveRing + FirstBuffer;
        !           250:                 CurrentSourceIndex = FirstBuffer;
        !           251: 
        !           252:                 if (CurrentSourceIndex == LastBuffer) {
        !           253: 
        !           254:                     //
        !           255:                     // The last buffer might only be partially filled with
        !           256:                     // transmitted data.  There is a field in the last
        !           257:                     // ring entry that has the total packet data length.
        !           258:                     //
        !           259:                     LANCE_GET_MESSAGE_SIZE(CurrentEntry, SourceCurrentLength);
        !           260:                     SourceCurrentLength -= LocalBytesTransferred;
        !           261: 
        !           262:                 } else {
        !           263: 
        !           264:                     SourceCurrentLength = Adapter->SizeOfReceiveBuffer;
        !           265: 
        !           266:                 }
        !           267: 
        !           268:                 while (LocalBytesTransferred < BytesToTransfer) {
        !           269: 
        !           270:                     //
        !           271:                     // Check to see whether we've exhausted the current
        !           272:                     // destination buffer.  If so, move onto the next one.
        !           273:                     //
        !           274: 
        !           275:                     if (!DestinationCurrentLength) {
        !           276: 
        !           277:                         NdisGetNextBuffer(
        !           278:                                         DestinationCurrentBuffer,
        !           279:                                         &DestinationCurrentBuffer
        !           280:                                         );
        !           281: 
        !           282:                         if (!DestinationCurrentBuffer) {
        !           283: 
        !           284:                             //
        !           285:                             // We've reached the end of the packet.  We
        !           286:                             // return with what we've done so far. (Which
        !           287:                             // must be shorter than requested.)
        !           288:                             //
        !           289: 
        !           290:                             break;
        !           291: 
        !           292:                         }
        !           293: 
        !           294:                         NdisQueryBuffer(
        !           295:                                         DestinationCurrentBuffer,
        !           296:                                         &DestinationVirtualAddress,
        !           297:                                         &DestinationCurrentLength
        !           298:                                         );
        !           299:                         continue;
        !           300: 
        !           301:                     }
        !           302: 
        !           303: 
        !           304:                     //
        !           305:                     // Check to see whether we've exhausted the current
        !           306:                     // source buffer.  If so, move onto the next one.
        !           307:                     //
        !           308: 
        !           309:                     if (!SourceCurrentLength) {
        !           310: 
        !           311:                         if (CurrentSourceIndex == LastBuffer) {
        !           312: 
        !           313:                             //
        !           314:                             // We've reached the end of the packet.  We
        !           315:                             // return with what we've done so far. (Which
        !           316:                             // must be shorter than requested.)
        !           317:                             //
        !           318: 
        !           319:                             break;
        !           320: 
        !           321:                         }
        !           322: 
        !           323:                         if (CurrentSourceIndex == TopReceiveIndex) {
        !           324: 
        !           325:                             CurrentSourceIndex = 0;
        !           326:                             CurrentEntry = Adapter->ReceiveRing;
        !           327: 
        !           328:                         } else {
        !           329: 
        !           330:                             CurrentSourceIndex++;
        !           331:                             CurrentEntry++;
        !           332: 
        !           333:                         }
        !           334: 
        !           335:                         if (CurrentSourceIndex == LastBuffer) {
        !           336: 
        !           337:                             //
        !           338:                             // The last buffer might only be partially
        !           339:                             // filled with transmitted data.  There is
        !           340:                             // a field in the last ring entry that has
        !           341:                             // the total packet data length.
        !           342:                             //
        !           343:                             LANCE_GET_MESSAGE_SIZE(CurrentEntry, SourceCurrentLength);
        !           344:                             SourceCurrentLength -= LocalBytesTransferred;
        !           345: 
        !           346:                         } else {
        !           347: 
        !           348:                             SourceCurrentLength =
        !           349:                                  Adapter->SizeOfReceiveBuffer;
        !           350: 
        !           351:                         }
        !           352: 
        !           353:                         SourceVirtualAddress =
        !           354:                                         Adapter->ReceiveVAs[CurrentSourceIndex];
        !           355:                         continue;
        !           356: 
        !           357:                     }
        !           358: 
        !           359:                     //
        !           360:                     // Try to get us up to the point to start the copy.
        !           361:                     //
        !           362: 
        !           363:                     if (ByteOffset) {
        !           364: 
        !           365:                         if (ByteOffset > SourceCurrentLength) {
        !           366: 
        !           367:                             //
        !           368:                             // What we want isn't in this buffer.
        !           369:                             //
        !           370: 
        !           371:                             ByteOffset -= SourceCurrentLength;
        !           372:                             SourceCurrentLength = 0;
        !           373:                             continue;
        !           374: 
        !           375:                         } else {
        !           376: 
        !           377:                             SourceVirtualAddress =
        !           378:                                             (PCHAR)SourceVirtualAddress + ByteOffset;
        !           379:                             SourceCurrentLength -= ByteOffset;
        !           380:                             ByteOffset = 0;
        !           381: 
        !           382:                         }
        !           383: 
        !           384:                     }
        !           385: 
        !           386:                     //
        !           387:                     // Copy the data.
        !           388:                     //
        !           389: 
        !           390:                     {
        !           391: 
        !           392:                         //
        !           393:                         // Holds the amount of data to move.
        !           394:                         //
        !           395:                         UINT AmountToMove;
        !           396: 
        !           397:                         //
        !           398:                         // Holds the amount desired remaining.
        !           399:                         //
        !           400:                         UINT Remaining = BytesToTransfer
        !           401:                                                      - LocalBytesTransferred;
        !           402: 
        !           403:                         AmountToMove =
        !           404:                                   ((SourceCurrentLength <= DestinationCurrentLength)?
        !           405:                                    (SourceCurrentLength):(DestinationCurrentLength));
        !           406: 
        !           407:                         AmountToMove = ((Remaining < AmountToMove)?
        !           408:                                                     (Remaining):(AmountToMove));
        !           409: 
        !           410:                         LANCE_MOVE_HARDWARE_TO_MEMORY(
        !           411:                                         DestinationVirtualAddress,
        !           412:                                         SourceVirtualAddress,
        !           413:                                         AmountToMove
        !           414:                                         );
        !           415: 
        !           416:                         DestinationVirtualAddress =
        !           417:                                       (PCHAR)DestinationVirtualAddress + AmountToMove;
        !           418:                         SourceVirtualAddress =
        !           419:                                         (PCHAR)SourceVirtualAddress + AmountToMove;
        !           420: 
        !           421:                         LocalBytesTransferred += AmountToMove;
        !           422:                         SourceCurrentLength -= AmountToMove;
        !           423:                         DestinationCurrentLength -= AmountToMove;
        !           424: 
        !           425:                     }
        !           426: 
        !           427:                 }
        !           428: 
        !           429:                 *BytesTransferred = LocalBytesTransferred;
        !           430: 
        !           431:             }
        !           432: 
        !           433:         }
        !           434: 
        !           435:         NdisAcquireSpinLock(&Adapter->Lock);
        !           436:         Open->References--;
        !           437:         StatusToReturn = NDIS_STATUS_SUCCESS;
        !           438: 
        !           439:     } else {
        !           440: 
        !           441:         StatusToReturn = NDIS_STATUS_REQUEST_ABORTED;
        !           442: 
        !           443:     }
        !           444: 
        !           445:     LANCE_DO_DEFERRED(Adapter);
        !           446:     return StatusToReturn;
        !           447: }

unix.superglobalmegacorp.com

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