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