Annotation of ntddk/src/network/tdi/iframes.c, revision 1.1.1.1

1.1       root        1: /*++
                      2: 
                      3: Copyright (c) 1989-1993  Microsoft Corporation
                      4: 
                      5: Module Name:
                      6: 
                      7:     iframes.c
                      8: 
                      9: Abstract:
                     10: 
                     11:     This module contains routines called to handle i-frames received
                     12:     from the NDIS driver. Most of these routines are called at receive
                     13:     indication time.
                     14: 
                     15: Environment:
                     16: 
                     17:     Kernel mode, DISPATCH_LEVEL.
                     18: 
                     19: Revision History:
                     20: 
                     21: --*/
                     22: 
                     23: #include "st.h"
                     24: #if 27
                     25: ULONG StNoisyReceives = 0;
                     26: ULONG StRcvLoc = 0;
                     27: ULONG StRcvs[10];
                     28: #endif
                     29: 
                     30: 
                     31: 
                     32: NTSTATUS
                     33: StProcessIIndicate(
                     34:     IN PTP_CONNECTION Connection,
                     35:     IN PST_HEADER StHeader,
                     36:     IN UINT StIndicatedLength,
                     37:     IN UINT StTotalLength,
                     38:     IN NDIS_HANDLE ReceiveContext,
                     39:     IN BOOLEAN Last
                     40:     )
                     41: 
                     42: /*++
                     43: 
                     44: Routine Description:
                     45: 
                     46:     This routine processes a received I frame at indication time. It will do
                     47:     all necessary verification processing of the frame and pass those frames
                     48:     that are valid on to the proper handling routines.
                     49: 
                     50: Arguments:
                     51: 
                     52:     Connection - The connection that the data is destined for.
                     53: 
                     54:     StHeader - A pointer to the start of the ST header in the packet.
                     55: 
                     56:     StIndicatedLength - The length of the packet indicated, starting at
                     57:         StHeader.
                     58: 
                     59:     StTotalLength - The total length of the packet, starting at StHeader.
                     60: 
                     61:     ReceiveContext - A magic value for NDIS that indicates which packet we're
                     62:         talking about, used for calling TransferData
                     63: 
                     64:     Last - TRUE if this is the last packet in a send.
                     65: 
                     66: Return Value:
                     67: 
                     68:     STATUS_SUCCESS if we've consumed the packet, but
                     69:     STATUS_MORE_PROCESSING_REQUIRED if we did so and also
                     70:     activated a receive; this tells the caller not to
                     71:     remove the connection refcount.
                     72: 
                     73: --*/
                     74: 
                     75: {
                     76:     KIRQL oldirql;
                     77:     NTSTATUS status, tmpstatus;
                     78:     KIRQL cancelirql;
                     79:     PDEVICE_CONTEXT deviceContext;
                     80:     NDIS_STATUS ndisStatus;
                     81:     PNDIS_PACKET ndisPacket;
                     82:     PSINGLE_LIST_ENTRY linkage;
                     83:     PIRP irp;
                     84:     PIO_STACK_LOCATION irpSp;
                     85:     PNDIS_BUFFER ndisBuffer;
                     86:     ULONG destBytes;
                     87:     ULONG bufferChainLength;
                     88:     ULONG indicateBytesTransferred;
                     89:     ULONG ndisBytesTransferred;
                     90:     PUCHAR DataHeader;
                     91:     ULONG DataTotalLength;
                     92:     ULONG DataIndicatedLength;
                     93:     UINT BytesToTransfer;
                     94:     ULONG bytesIndicated;
                     95:     PRECEIVE_PACKET_TAG receiveTag;
                     96:     PTP_ADDRESS address;
                     97:     PTP_ADDRESS_FILE addressFile;
                     98:     PMDL SavedCurrentMdl;
                     99:     ULONG SavedCurrentByteOffset;
                    100:     LARGE_INTEGER time;
                    101:     ULONG DumpData[2];
                    102:     BOOLEAN CancelSpinLockHeld = FALSE;
                    103: #if 27
                    104:     if (StNoisyReceives) {
                    105:         DbgPrint ("Indicate %d, Total %d\n", StIndicatedLength, StTotalLength);
                    106:     }
                    107:     if (StTotalLength > 1000) {
                    108:         StRcvs[StRcvLoc] = StTotalLength;
                    109:         StRcvLoc = (StRcvLoc + 1) % 10;
                    110:     }
                    111: #endif
                    112: 
                    113: 
                    114:     //
                    115:     // copy this packet into our receive buffer.
                    116:     //
                    117: 
                    118:     deviceContext = Connection->Provider;
                    119:     addressFile = Connection->AddressFile;
                    120:     address = addressFile->Address;
                    121: 
                    122:     ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql);
                    123: 
                    124:     //
                    125:     // If we have a previous receive that is pending
                    126:     // completion, then we need to ignore this frame.
                    127:     // This may be common on MP.
                    128:     //
                    129: 
                    130:     if (Connection->Flags2 & CONNECTION_FLAGS2_RC_PENDING) {
                    131: 
                    132:         Connection->IndicationInProgress = FALSE;
                    133:         RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql);
                    134: 
                    135:         return STATUS_SUCCESS;
                    136:     }
                    137: 
                    138:     DataHeader = (PUCHAR)StHeader + sizeof(ST_HEADER);
                    139:     DataTotalLength = StTotalLength - sizeof(ST_HEADER);
                    140:     DataIndicatedLength = StIndicatedLength - sizeof(ST_HEADER);
                    141: 
                    142:     //
                    143:     // Initialize this to zero, in case we do not indicate or
                    144:     // the client does not fill it in.
                    145:     //
                    146: 
                    147:     indicateBytesTransferred = 0;
                    148: 
                    149:     if (!(Connection->Flags & CONNECTION_FLAGS_ACTIVE_RECEIVE)) {
                    150: 
                    151:         //
                    152:         // check first to see if there is a receive available. If there is,
                    153:         // use it before doing an indication.
                    154:         //
                    155: 
                    156:         if (Connection->ReceiveQueue.Flink != &Connection->ReceiveQueue) {
                    157: 
                    158:             //
                    159:             // Found a receive, so make it the active one and
                    160:             // cycle around again.
                    161:             //
                    162: 
                    163:             Connection->Flags |= CONNECTION_FLAGS_ACTIVE_RECEIVE;
                    164:             Connection->MessageBytesReceived = 0;
                    165:             Connection->MessageBytesAcked = 0;
                    166:             Connection->CurrentReceiveRequest =
                    167:                 CONTAINING_RECORD (Connection->ReceiveQueue.Flink,
                    168:                                    TP_REQUEST, Linkage);
                    169:             Connection->CurrentReceiveMdl =
                    170:                 Connection->CurrentReceiveRequest->Buffer2;
                    171:             Connection->ReceiveLength =
                    172:                 Connection->CurrentReceiveRequest->Buffer2Length;
                    173:             Connection->ReceiveByteOffset = 0;
                    174:             status = STATUS_SUCCESS;
                    175:             goto NormalReceive;
                    176:         }
                    177: 
                    178:         //
                    179:         // A receive is not active.  Post a receive event.
                    180:         //
                    181: 
                    182:         if (!addressFile->RegisteredReceiveHandler) {
                    183: 
                    184:             //
                    185:             // There is no receive posted to the Connection, and
                    186:             // no event handler. Set the RECEIVE_WAKEUP bit, so that when a
                    187:             // receive does become available, it will restart the
                    188:             // current send. Also send a NoReceive to tell the other
                    189:             // guy he needs to resynch.
                    190:             //
                    191: 
                    192:             Connection->IndicationInProgress = FALSE;
                    193:             return STATUS_SUCCESS;
                    194:         }
                    195: 
                    196:         if ((Connection->Flags & CONNECTION_FLAGS_READY) == 0) {
                    197:             Connection->IndicationInProgress = FALSE;
                    198:             RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql);
                    199: 
                    200:             return STATUS_SUCCESS;
                    201:         }
                    202: 
                    203:         RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql);
                    204: 
                    205:         //
                    206:         // Indicate to the user. For BytesAvailable we
                    207:         // always use DataTotalLength; for BytesIndicated we use
                    208:         // MIN (DataIndicatedLength, DataTotalLength).
                    209:         //
                    210:         // To clarify BytesIndicated, on an Ethernet packet
                    211:         // which is padded DataTotalLength will be shorter; on an
                    212:         // Ethernet packet which is not padded and which is
                    213:         // completely indicated, the two will be equal; and
                    214:         // on a long Ethernet packet DataIndicatedLength
                    215:         // will be shorter.
                    216:         //
                    217: 
                    218:         bytesIndicated = DataIndicatedLength;
                    219:         if (DataTotalLength < bytesIndicated) {
                    220:             bytesIndicated = DataTotalLength;
                    221:         }
                    222: 
                    223:         status = (*addressFile->ReceiveHandler)(
                    224:                     addressFile->ReceiveHandlerContext,
                    225:                     Connection->Context,
                    226:                     deviceContext->MacInfo.CopyLookahead ?
                    227:                         TDI_RECEIVE_COPY_LOOKAHEAD : 0,    // ReceiveFlags
                    228:                     bytesIndicated,
                    229:                     DataTotalLength,             // BytesAvailable
                    230:                     &indicateBytesTransferred,
                    231:                     DataHeader,
                    232:                     &irp);
                    233: 
                    234:         if (status == STATUS_SUCCESS) {
                    235: 
                    236:             //
                    237:             // The client has accepted some or all of the indicated data in
                    238:             // the event handler.  Update MessageBytesReceived variable in
                    239:             // the Connection.
                    240:             //
                    241: 
                    242:             Connection->MessageBytesReceived += indicateBytesTransferred;
                    243:             Connection->IndicationInProgress = FALSE;
                    244: 
                    245:             return STATUS_SUCCESS;
                    246: 
                    247:         } else if (status == STATUS_DATA_NOT_ACCEPTED) {
                    248: 
                    249:             //
                    250:             // Either there is no event handler installed (the default
                    251:             // handler returns this code) or the event handler is not
                    252:             // able to process the received data at this time.  If there
                    253:             // is a TdiReceive request outstanding on this Connection's
                    254:             // ReceiveQueue, then we may use it to receive this data.
                    255:             // If there is no request outstanding, then we must initiate
                    256:             // flow control at the transport level.
                    257:             //
                    258: 
                    259:             ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql);
                    260:             if (Connection->ReceiveQueue.Flink == &Connection->ReceiveQueue) {
                    261: 
                    262:                 //
                    263:                 // There is no receive posted to the Connection, and
                    264:                 // the event handler didn't want to accept the incoming
                    265:                 // data.
                    266:                 //
                    267: 
                    268:                 Connection->IndicationInProgress = FALSE;
                    269:                 return STATUS_SUCCESS;
                    270: 
                    271:             } else {
                    272: 
                    273:                 //
                    274:                 // Found a receive, so make it the active one. This will cause
                    275:                 // an NdisTransferData below, so we don't dereference the
                    276:                 // Connection here.
                    277:                 //
                    278: 
                    279:                 Connection->Flags |= CONNECTION_FLAGS_ACTIVE_RECEIVE;
                    280:                 Connection->MessageBytesReceived = 0;
                    281:                 Connection->MessageBytesAcked = 0;
                    282:                 Connection->CurrentReceiveRequest =
                    283:                     CONTAINING_RECORD (Connection->ReceiveQueue.Flink,
                    284:                                        TP_REQUEST, Linkage);
                    285:                 Connection->CurrentReceiveMdl =
                    286:                     Connection->CurrentReceiveRequest->Buffer2;
                    287:                 Connection->ReceiveLength =
                    288:                     Connection->CurrentReceiveRequest->Buffer2Length;
                    289:                 Connection->ReceiveByteOffset = 0;
                    290:             }
                    291: 
                    292:         } else if (status == STATUS_MORE_PROCESSING_REQUIRED) {
                    293: 
                    294:             PTP_REQUEST SpecialIrpRequest;
                    295:             ULONG SpecialIrpLength;
                    296: 
                    297:             //
                    298:             // The client's event handler has returned an IRP in the
                    299:             // form of a TdiReceive that is to be associated with this
                    300:             // data.  The request will be installed at the front of the
                    301:             // ReceiveQueue, and then made the active receive request.
                    302:             // This request will be used to accept the incoming data, which
                    303:             // will happen below.
                    304:             //
                    305: 
                    306:             //
                    307:             // Queueing a receive of any kind causes a Connection reference;
                    308:             // that's what we've just done here, so make the Connection stick
                    309:             // around. We create a request to keep a packets outstanding ref
                    310:             // count for the current IRP; we queue this on the connection's
                    311:             // receive queue so we can treat it like a normal receive. If
                    312:             // we can't get a request to describe this irp, we can't keep it
                    313:             // around hoping for better later; we simple fail it with
                    314:             // insufficient resources. Note this is only likely to happen if
                    315:             // we've completely run out of transport memory.
                    316:             //
                    317: 
                    318:             irp->IoStatus.Information = 0;  // byte transfer count.
                    319:             irp->IoStatus.Status = STATUS_PENDING;
                    320:             irpSp = IoGetCurrentIrpStackLocation (irp);
                    321: 
                    322:             ASSERT (irpSp->FileObject->FsContext == Connection);
                    323: 
                    324:             SpecialIrpLength =
                    325:                 ((PTDI_REQUEST_KERNEL_RECEIVE)&irpSp->Parameters)->ReceiveLength;
                    326: 
                    327:             //
                    328:             // The normal path, for longer receives.
                    329:             //
                    330: 
                    331:             time.HighPart = 0;
                    332:             time.LowPart = 0;
                    333: 
                    334:             status = StCreateRequest (
                    335:                         irp,
                    336:                         Connection,
                    337:                         REQUEST_FLAGS_CONNECTION | REQUEST_FLAGS_SEND_RCV,
                    338:                         irp->MdlAddress,
                    339:                         ((PTDI_REQUEST_KERNEL_RECEIVE )&irpSp->Parameters)->ReceiveLength,
                    340:                         time,
                    341:                         &SpecialIrpRequest);
                    342: 
                    343:             if (!NT_SUCCESS (status)) {
                    344:                 ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql);
                    345:                 Connection->ReceiveByteOffset = 0;
                    346:                 Connection->Flags |= CONNECTION_FLAGS_RECEIVE_WAKEUP;
                    347:                 RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql);
                    348: 
                    349:                 Connection->IndicationInProgress = FALSE;
                    350: 
                    351:                 irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                    352: 
                    353:                 IoCompleteRequest (irp, IO_NETWORK_INCREMENT);
                    354:                 return STATUS_INSUFFICIENT_RESOURCES;
                    355:             }
                    356: 
                    357:             //
                    358:             // If the Connection is stopping, abort this request.
                    359:             //
                    360: 
                    361:             IoAcquireCancelSpinLock(&cancelirql);
                    362:             ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql);
                    363: 
                    364:             if ((Connection->Flags & CONNECTION_FLAGS_STOPPING) != 0) {
                    365:                 Connection->IndicationInProgress = FALSE;
                    366:                 RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql);
                    367: 
                    368:                 IoReleaseCancelSpinLock(cancelirql);
                    369:                 StCompleteRequest (
                    370:                     SpecialIrpRequest,
                    371:                     Connection->Status,
                    372:                     0);
                    373:                 return STATUS_SUCCESS;    // we have consumed the packet
                    374: 
                    375:             }
                    376: 
                    377:             //
                    378:             // Insert the request on the head of the connection's
                    379:             // receive queue, so it can be handled like a normal
                    380:             // receive.
                    381:             //
                    382: 
                    383:             InsertHeadList (&Connection->ReceiveQueue, &SpecialIrpRequest->Linkage);
                    384: 
                    385:             Connection->Flags |= CONNECTION_FLAGS_ACTIVE_RECEIVE;
                    386:             Connection->ReceiveLength = ((PTDI_REQUEST_KERNEL_RECEIVE )&irpSp->Parameters)->ReceiveLength;
                    387:             Connection->MessageBytesReceived = indicateBytesTransferred;
                    388:             Connection->MessageBytesAcked = 0;
                    389:             Connection->CurrentReceiveRequest = SpecialIrpRequest;
                    390:             Connection->CurrentReceiveMdl = irp->MdlAddress;
                    391:             Connection->ReceiveByteOffset = 0;
                    392:             Connection->CurrentReceiveRequest->Owner = ConnectionType;
                    393: 
                    394:             //
                    395:             // If this IRP has been cancelled, then call the
                    396:             // cancel routine.
                    397:             //
                    398: 
                    399:             if (irp->Cancel) {
                    400: 
                    401:                 Connection->Flags |= CONNECTION_FLAGS_RECEIVE_WAKEUP;
                    402:                 Connection->IndicationInProgress = FALSE;
                    403:                 RELEASE_SPIN_LOCK (&Connection->SpinLock,oldirql);
                    404:                 irp->CancelIrql = cancelirql;
                    405:                 StCancelReceive((PDEVICE_OBJECT)deviceContext, irp);
                    406: 
                    407:                 return STATUS_SUCCESS;
                    408: 
                    409:             } else {
                    410: 
                    411:                 irp->CancelRoutine = StCancelReceive;
                    412: 
                    413:                 status = STATUS_MORE_PROCESSING_REQUIRED;
                    414: 
                    415:                 //
                    416:                 // Make a note so we know to release the cancel
                    417:                 // spinlock below.
                    418:                 //
                    419: 
                    420:                 CancelSpinLockHeld = TRUE;
                    421: 
                    422:             }
                    423: 
                    424:         } else {
                    425: 
                    426:             //
                    427:             // An unknown return code has been returned by the
                    428:             // client's event handler.  This is a client programming
                    429:             // error.  Because this can only occur when kernel-mode
                    430:             // clients have been coded incorrectly, we should beat
                    431:             // him with a stick.  We have to do SOMETHING, or this
                    432:             // Connection will HANG.
                    433:             //
                    434: 
                    435:             Connection->IndicationInProgress = FALSE;
                    436:             return STATUS_SUCCESS;
                    437: 
                    438:         }
                    439: 
                    440:     } else {
                    441: 
                    442:         //
                    443:         // A receive is active, set the status to show
                    444:         // that so far.
                    445:         //
                    446: 
                    447:         status = STATUS_SUCCESS;
                    448: 
                    449:     }
                    450: 
                    451: 
                    452: NormalReceive:;
                    453: 
                    454:     //
                    455:     // NOTE: The connection spinlock is held here.
                    456:     //
                    457:     // We should only get through here if a receive is active
                    458:     // and we have not released the lock since checking or
                    459:     // making one active.
                    460:     //
                    461: 
                    462:     ASSERT(Connection->Flags & CONNECTION_FLAGS_ACTIVE_RECEIVE);
                    463: 
                    464:     //
                    465:     // The status should be SUCCESS (we found an active receive)
                    466:     // or MORE_PROCESSING_REQUIRED (we made a new receive active).
                    467:     //
                    468: 
                    469:     ASSERT ((status == STATUS_SUCCESS) || (status == STATUS_MORE_PROCESSING_REQUIRED));
                    470: 
                    471:     destBytes = Connection->ReceiveLength - Connection->MessageBytesReceived;
                    472:     StReferenceRequest ("Transfer Data", Connection->CurrentReceiveRequest);
                    473: 
                    474:     RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql);
                    475:     if (CancelSpinLockHeld) {
                    476:         IoReleaseCancelSpinLock (cancelirql);
                    477:     }
                    478: 
                    479:     //
                    480:     // get a packet for the coming transfer
                    481:     //
                    482: 
                    483:     linkage = ExInterlockedPopEntryList(
                    484:         &deviceContext->ReceivePacketPool,
                    485:         &deviceContext->Interlock);
                    486: 
                    487:     if (linkage != NULL) {
                    488:         ndisPacket = CONTAINING_RECORD( linkage, NDIS_PACKET, ProtocolReserved[0] );
                    489:     } else {
                    490:         (VOID)ExInterlockedIncrementLong(
                    491:             (PLONG)&deviceContext->ReceivePacketExhausted,
                    492:             &deviceContext->Interlock);
                    493:         StDereferenceRequest ("No receive packet", Connection->CurrentReceiveRequest);
                    494: 
                    495:         // We could not get a receive packet.
                    496:         //
                    497: 
                    498:         Connection->IndicationInProgress = FALSE;
                    499:         return status;
                    500:     }
                    501: 
                    502:     //
                    503:     // Initialize the receive packet.
                    504:     //
                    505: 
                    506:     receiveTag = (PRECEIVE_PACKET_TAG)(ndisPacket->ProtocolReserved);
                    507:     receiveTag->PacketType = TYPE_AT_INDICATE;
                    508:     receiveTag->Connection = Connection;
                    509:     receiveTag->TransferDataPended = TRUE;
                    510: 
                    511: 
                    512:     //
                    513:     // Determine how much data remains to be transferred.
                    514:     //
                    515: 
                    516:     BytesToTransfer = DataTotalLength - indicateBytesTransferred;
                    517:     ASSERT (BytesToTransfer >= 0);
                    518: 
                    519:     if (destBytes < BytesToTransfer) {
                    520: 
                    521:         //
                    522:         // If the data overflows the current receive, then make a
                    523:         // note that we should complete the receive at the end of
                    524:         // transfer data, but with EOR false.
                    525:         //
                    526: 
                    527:         receiveTag->EndOfMessage = FALSE;
                    528:         receiveTag->CompleteReceive = TRUE;
                    529:         BytesToTransfer = destBytes;
                    530: 
                    531:     } else if (destBytes == BytesToTransfer) {
                    532: 
                    533:         //
                    534:         // If the data just fills the current receive, then complete
                    535:         // the receive; EOR depends on whether this is a DOL or not.
                    536:         //
                    537: 
                    538:         receiveTag->EndOfMessage = Last;
                    539:         receiveTag->CompleteReceive = TRUE;
                    540: 
                    541:     } else {
                    542: 
                    543:         //
                    544:         // Complete the receive if this is a DOL.
                    545:         //
                    546: 
                    547:         receiveTag->EndOfMessage = Last;
                    548:         receiveTag->CompleteReceive = Last;
                    549: 
                    550:     }
                    551: 
                    552:     //
                    553:     // if we've got zero bytes left, avoid the TransferData below and
                    554:     // just deliver.
                    555:     //
                    556: 
                    557:     if (BytesToTransfer <= 0) {
                    558:         Connection->IndicationInProgress = FALSE;
                    559:         receiveTag->NdisStatus = NDIS_STATUS_SUCCESS;
                    560:         receiveTag->TransferDataPended = FALSE;
                    561:         StTransferDataComplete (
                    562:                 deviceContext,
                    563:                 ndisPacket,
                    564:                 NDIS_STATUS_SUCCESS,
                    565:                 0);
                    566: 
                    567:         return status;
                    568:     }
                    569: 
                    570:     //
                    571:     // describe the right part of the user buffer to NDIS. If we can't get
                    572:     // the mdl for the packet, drop it. Bump the request reference count
                    573:     // so that we know we need to hold open receives until the NDIS transfer
                    574:     // data requests complete.
                    575:     //
                    576: 
                    577:     SavedCurrentMdl = Connection->CurrentReceiveMdl;
                    578:     SavedCurrentByteOffset = Connection->ReceiveByteOffset;
                    579: 
                    580:     if ((Connection->ReceiveByteOffset == 0) &&
                    581:         (receiveTag->CompleteReceive)) {
                    582: 
                    583:         //
                    584:         // If we are transferring into the beginning of
                    585:         // the current MDL, and we will be completing the
                    586:         // receive after the transfer, then we don't need to
                    587:         // copy it.
                    588:         //
                    589: 
                    590:         ndisBuffer = (PNDIS_BUFFER)Connection->CurrentReceiveMdl;
                    591:         bufferChainLength = BytesToTransfer;
                    592:         Connection->CurrentReceiveMdl = NULL;
                    593:         Connection->ReceiveByteOffset = 0;
                    594:         receiveTag->AllocatedNdisBuffer = FALSE;
                    595:         tmpstatus = STATUS_SUCCESS;
                    596: 
                    597:     } else {
                    598: 
                    599:         tmpstatus = BuildBufferChainFromMdlChain (
                    600:                     deviceContext->NdisBufferPoolHandle,
                    601:                     Connection->CurrentReceiveMdl,
                    602:                     Connection->ReceiveByteOffset,
                    603:                     BytesToTransfer,
                    604:                     &ndisBuffer,
                    605:                     &Connection->CurrentReceiveMdl,
                    606:                     &Connection->ReceiveByteOffset,
                    607:                     &bufferChainLength);
                    608: 
                    609:         receiveTag->AllocatedNdisBuffer = TRUE;
                    610: 
                    611:     }
                    612: 
                    613: 
                    614:     if ((!NT_SUCCESS (tmpstatus)) || (bufferChainLength != BytesToTransfer)) {
                    615: 
                    616:         DumpData[0] = bufferChainLength;
                    617:         DumpData[1] = BytesToTransfer;
                    618: 
                    619:         StWriteGeneralErrorLog(
                    620:             deviceContext,
                    621:             EVENT_TRANSPORT_TRANSFER_DATA,
                    622:             604,
                    623:             tmpstatus,
                    624:             NULL,
                    625:             2,
                    626:             DumpData);
                    627: 
                    628:         StDereferenceRequest ("No MDL chain", Connection->CurrentReceiveRequest);
                    629: 
                    630:         //
                    631:         // Restore our old state.
                    632:         //
                    633: 
                    634:         Connection->CurrentReceiveMdl = SavedCurrentMdl;
                    635:         Connection->ReceiveByteOffset = SavedCurrentByteOffset;
                    636: 
                    637:         Connection->IndicationInProgress = FALSE;
                    638: 
                    639:         ExInterlockedPushEntryList(
                    640:             &deviceContext->ReceivePacketPool,
                    641:             (PSINGLE_LIST_ENTRY)&receiveTag->Linkage,
                    642:             &deviceContext->Interlock);
                    643: 
                    644:         return status;
                    645:     }
                    646: 
                    647:     NdisChainBufferAtFront (ndisPacket, ndisBuffer);
                    648: 
                    649:     //
                    650:     // set up async return status so we can tell when it has happened;
                    651:     // can never get return of NDIS_STATUS_PENDING in synch completion routine
                    652:     // for NdisTransferData, so we know it has completed when this status
                    653:     // changes
                    654:     //
                    655: 
                    656:     receiveTag->NdisStatus = NDIS_STATUS_PENDING;
                    657: 
                    658:     //
                    659:     // update the number of bytes received; OK to do this
                    660:     // unprotected since IndicationInProgress is still FALSE.
                    661:     //
                    662:     //
                    663: 
                    664:     Connection->MessageBytesReceived += BytesToTransfer;
                    665: 
                    666:     //
                    667:     // We have now updated all the connection counters (BUG,
                    668:     // assuming the TransferData will succeed) and this
                    669:     // packet's location in the request is secured, so we
                    670:     // can be reentered.
                    671:     //
                    672: 
                    673:     Connection->IndicationInProgress = FALSE;
                    674: 
                    675:     NdisTransferData (
                    676:         &ndisStatus,
                    677:         deviceContext->NdisBindingHandle,
                    678:         ReceiveContext,
                    679:         sizeof (ST_HEADER) + indicateBytesTransferred,
                    680:         BytesToTransfer,
                    681:         ndisPacket,
                    682:         (PUINT)&ndisBytesTransferred);
                    683: 
                    684:     //
                    685:     // handle the various completion codes
                    686:     //
                    687: 
                    688:     switch (ndisStatus) {
                    689: 
                    690:     case NDIS_STATUS_SUCCESS:
                    691: 
                    692:         receiveTag->NdisStatus = NDIS_STATUS_SUCCESS;
                    693:         if (ndisBytesTransferred != BytesToTransfer) {       // Did we get the entire packet?
                    694: 
                    695:             DumpData[0] = ndisBytesTransferred;
                    696:             DumpData[1] = BytesToTransfer;
                    697: 
                    698:             StWriteGeneralErrorLog(
                    699:                 deviceContext,
                    700:                 EVENT_TRANSPORT_TRANSFER_DATA,
                    701:                 604,
                    702:                 ndisStatus,
                    703:                 NULL,
                    704:                 2,
                    705:                 DumpData);
                    706: 
                    707:             if (receiveTag->AllocatedNdisBuffer) {
                    708:                 NdisUnchainBufferAtFront (ndisPacket, &ndisBuffer);
                    709:                 while (ndisBuffer != NULL) {
                    710:                     NdisFreeBuffer (ndisBuffer);
                    711:                     NdisUnchainBufferAtFront (ndisPacket, &ndisBuffer);
                    712:                 }
                    713:             } else {
                    714:                 NdisReinitializePacket (ndisPacket);
                    715:             }
                    716: 
                    717:             ExInterlockedPushEntryList(
                    718:                 &deviceContext->ReceivePacketPool,
                    719:                 (PSINGLE_LIST_ENTRY)&receiveTag->Linkage,
                    720:                 &deviceContext->Interlock);
                    721: 
                    722:             StDereferenceRequest ("Bad byte count", Connection->CurrentReceiveRequest);
                    723: 
                    724:             //
                    725:             // Restore our old state.
                    726:             //
                    727: 
                    728:             Connection->CurrentReceiveMdl = SavedCurrentMdl;
                    729:             Connection->ReceiveByteOffset = SavedCurrentByteOffset;
                    730:             Connection->MessageBytesReceived -= BytesToTransfer;
                    731: 
                    732:             return status;
                    733:         }
                    734: 
                    735:         //
                    736:         // deallocate the buffers and such that we've used if at indicate
                    737:         //
                    738: 
                    739:         receiveTag->TransferDataPended = FALSE;
                    740: 
                    741:         StTransferDataComplete (
                    742:                 deviceContext,
                    743:                 ndisPacket,
                    744:                 ndisStatus,
                    745:                 BytesToTransfer);
                    746:         break;
                    747: 
                    748:     case NDIS_STATUS_PENDING:   // waiting async complete from NdisTransferData
                    749: 
                    750:         //
                    751:         // Because TransferDataPended stays TRUE, this reference will
                    752:         // be removed in TransferDataComplete. It is OK to do this
                    753:         // now, even though TransferDataComplete may already have been
                    754:         // called, because we also hold the ProcessIIndicate reference
                    755:         // so there will be no "bounce".
                    756:         //
                    757: 
                    758:         StReferenceConnection ("TransferData pended", Connection);
                    759:         break;
                    760: 
                    761:     default:
                    762: 
                    763:         //
                    764:         // Something broke; certainly we'll never get NdisTransferData
                    765:         // asynch completion.
                    766:         //
                    767:         // BUGBUG: The driver should recover from this situation.
                    768:         //
                    769: 
                    770:         StWriteGeneralErrorLog(
                    771:             deviceContext,
                    772:             EVENT_TRANSPORT_TRANSFER_DATA,
                    773:             604,
                    774:             ndisStatus,
                    775:             NULL,
                    776:             0,
                    777:             NULL);
                    778: 
                    779:         if (receiveTag->AllocatedNdisBuffer) {
                    780:             NdisUnchainBufferAtFront (ndisPacket, &ndisBuffer);
                    781:             while (ndisBuffer != NULL) {
                    782:                 NdisFreeBuffer (ndisBuffer);
                    783:                 NdisUnchainBufferAtFront (ndisPacket, &ndisBuffer);
                    784:             }
                    785:         } else {
                    786:             NdisReinitializePacket (ndisPacket);
                    787:         }
                    788: 
                    789:         ExInterlockedPushEntryList(
                    790:             &deviceContext->ReceivePacketPool,
                    791:             (PSINGLE_LIST_ENTRY)&receiveTag->Linkage,
                    792:             &deviceContext->Interlock);
                    793: 
                    794:         StDereferenceRequest ("TransferData failed", Connection->CurrentReceiveRequest);
                    795: 
                    796:         //
                    797:         // Restore our old state.
                    798:         //
                    799: 
                    800:         Connection->CurrentReceiveMdl = SavedCurrentMdl;
                    801:         Connection->ReceiveByteOffset = SavedCurrentByteOffset;
                    802:         Connection->MessageBytesReceived -= BytesToTransfer;
                    803: 
                    804:         return status;
                    805:     } // switch ndisStatus
                    806: 
                    807:     return status;  // which only means we've dealt with the packet
                    808: 
                    809: }   /* ProcessIIndicate */

unix.superglobalmegacorp.com

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