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

1.1       root        1: /*++
                      2: 
                      3: Copyright (c) 1989-1993  Microsoft Corporation
                      4: 
                      5: Module Name:
                      6: 
                      7:     ind.c
                      8: 
                      9: Abstract:
                     10: 
                     11:     This module contains code which implements the indication handler
                     12:     for the NT Sample transport provider.
                     13: 
                     14: Environment:
                     15: 
                     16:     Kernel mode
                     17: 
                     18: Revision History:
                     19: 
                     20: --*/
                     21: 
                     22: #include "st.h"
                     23: 
                     24: 
                     25: 
                     26: NDIS_STATUS
                     27: StReceiveIndication (
                     28:     IN NDIS_HANDLE BindingContext,
                     29:     IN NDIS_HANDLE ReceiveContext,
                     30:     IN PVOID HeaderBuffer,
                     31:     IN UINT HeaderBufferSize,
                     32:     IN PVOID LookaheadBuffer,
                     33:     IN UINT LookaheadBufferSize,
                     34:     IN UINT PacketSize
                     35:     )
                     36: 
                     37: /*++
                     38: 
                     39: Routine Description:
                     40: 
                     41:     This routine receives control from the physical provider as an
                     42:     indication that a frame has been received on the physical link.
                     43:     This routine is time critical, so we only allocate a
                     44:     buffer and copy the packet into it. We also perform minimal
                     45:     validation on this packet. It gets queued to the device context
                     46:     to allow for processing later.
                     47: 
                     48: Arguments:
                     49: 
                     50:     BindingContext - The Adapter Binding specified at initialization time.
                     51: 
                     52:     ReceiveContext - A magic cookie for the MAC.
                     53: 
                     54:     HeaderBuffer - pointer to a buffer containing the packet header.
                     55: 
                     56:     HeaderBufferSize - the size of the header.
                     57: 
                     58:     LookaheadBuffer - pointer to a buffer containing the negotiated minimum
                     59:         amount of buffer I get to look at (not including header).
                     60: 
                     61:     LookaheadBufferSize - the size of the above. May be less than asked
                     62:         for, if that's all there is.
                     63: 
                     64:     PacketSize - Overall size of the packet (not including header).
                     65: 
                     66: Return Value:
                     67: 
                     68:     NDIS_STATUS - status of operation, one of:
                     69: 
                     70:                  NDIS_STATUS_SUCCESS if packet accepted,
                     71:                  NDIS_STATUS_NOT_RECOGNIZED if not recognized by protocol,
                     72:                  NDIS_any_other_thing if I understand, but can't handle.
                     73: 
                     74: --*/
                     75: {
                     76:     PDEVICE_CONTEXT DeviceContext;
                     77:     HARDWARE_ADDRESS SourceAddressBuffer;
                     78:     PHARDWARE_ADDRESS SourceAddress;
                     79:     UINT RealPacketSize;
                     80:     PST_HEADER StHeader;
                     81: 
                     82:     DeviceContext = (PDEVICE_CONTEXT)BindingContext;
                     83: 
                     84:     RealPacketSize = 0;
                     85: 
                     86:     //
                     87:     // Obtain the packet length; this may optionally adjust
                     88:     // the lookahead buffer forward if the header we wish
                     89:     // to remove spills over into what the MAC considers
                     90:     // data. If it determines that the header is not
                     91:     // valid, it keeps RealPacketSize at 0.
                     92:     //
                     93: 
                     94:     MacReturnPacketLength(
                     95:         &DeviceContext->MacInfo,
                     96:         HeaderBuffer,
                     97:         HeaderBufferSize,
                     98:         PacketSize,
                     99:         &RealPacketSize
                    100:         );
                    101: 
                    102:     if (RealPacketSize < 2) {
                    103:         return NDIS_STATUS_NOT_RECOGNIZED;
                    104:     }
                    105: 
                    106:     //
                    107:     // We've negotiated at least a contiguous DLC header passed back in the
                    108:     // lookahead buffer. Check it to see if we want this packet.
                    109:     //
                    110: 
                    111:     StHeader = (PST_HEADER)LookaheadBuffer;
                    112: 
                    113:     if (StHeader->Signature != ST_SIGNATURE) {
                    114:         return NDIS_STATUS_NOT_RECOGNIZED;        // packet was processed.
                    115:     }
                    116: 
                    117: 
                    118:     //
                    119:     // Check that the packet is not too long.
                    120:     //
                    121: 
                    122:     if (PacketSize > DeviceContext->MaxReceivePacketSize) {
                    123: #if DBG
                    124:         StPrint2("StReceiveIndication: Ignoring packet length %d, max %d\n",
                    125:             PacketSize, DeviceContext->MaxReceivePacketSize);
                    126: #endif
                    127:         return NDIS_STATUS_NOT_RECOGNIZED;
                    128:     }
                    129: 
                    130:     MacReturnSourceAddress(
                    131:         &DeviceContext->MacInfo,
                    132:         HeaderBuffer,
                    133:         &SourceAddressBuffer,
                    134:         &SourceAddress
                    135:         );
                    136: 
                    137: 
                    138:     return StGeneralReceiveHandler(
                    139:                DeviceContext,
                    140:                ReceiveContext,
                    141:                SourceAddress,
                    142:                HeaderBuffer,                  // header
                    143:                RealPacketSize,                // total data length in packet
                    144:                (PST_HEADER)LookaheadBuffer,   // lookahead data
                    145:                LookaheadBufferSize            // lookahead data length
                    146:                );
                    147: 
                    148: }
                    149: 
                    150: 
                    151: NDIS_STATUS
                    152: StGeneralReceiveHandler (
                    153:     IN PDEVICE_CONTEXT DeviceContext,
                    154:     IN NDIS_HANDLE ReceiveContext,
                    155:     IN PHARDWARE_ADDRESS SourceAddress,
                    156:     IN PVOID HeaderBuffer,
                    157:     IN UINT PacketSize,
                    158:     IN PST_HEADER StHeader,
                    159:     IN UINT StSize
                    160:     )
                    161: 
                    162: /*++
                    163: 
                    164: Routine Description:
                    165: 
                    166:     This routine receives control from StReceiveIndication.
                    167:     It continues the processing of indicated data.
                    168: 
                    169:     This routine is time critical, so we only allocate a
                    170:     buffer and copy the packet into it. We also perform minimal
                    171:     validation on this packet. It gets queued to the device context
                    172:     to allow for processing later.
                    173: 
                    174: Arguments:
                    175: 
                    176:     DeviceContext - The device context of this adapter.
                    177: 
                    178:     ReceiveContext - A magic cookie for the MAC.
                    179: 
                    180:     SourceAddress - The source address of the packet.
                    181: 
                    182:     HeaderBuffer - pointer to the packet header.
                    183: 
                    184:     PacketSize - Overall size of the packet (not including header).
                    185: 
                    186:     DlcHeader - Points to the DLC header of the packet.
                    187: 
                    188:     DlcSize - The length of the packet indicated, starting from DlcHeader.
                    189: 
                    190: Return Value:
                    191: 
                    192:     NDIS_STATUS - status of operation, one of:
                    193: 
                    194:                  NDIS_STATUS_SUCCESS if packet accepted,
                    195:                  NDIS_STATUS_NOT_RECOGNIZED if not recognized by protocol,
                    196:                  NDIS_any_other_thing if I understand, but can't handle.
                    197: 
                    198: --*/
                    199: {
                    200: 
                    201:     KIRQL oldirql;
                    202:     NTSTATUS Status;
                    203:     NDIS_STATUS NdisStatus;
                    204:     PNDIS_PACKET NdisPacket;
                    205:     PNDIS_BUFFER NdisBuffer;
                    206:     PSINGLE_LIST_ENTRY linkage;
                    207:     UINT BytesTransferred;
                    208:     PRECEIVE_PACKET_TAG ReceiveTag;
                    209:     PBUFFER_TAG BufferTag;
                    210:     PUCHAR SourceRouting;
                    211:     UINT SourceRoutingLength;
                    212:     PTP_ADDRESS DatagramAddress;
                    213:     UINT NdisBufferLength;
                    214:     PTP_CONNECTION Connection;
                    215:     PVOID BufferPointer;
                    216: 
                    217: 
                    218:     INCREMENT_COUNTER (DeviceContext, PacketsReceived);
                    219: 
                    220:     Status = STATUS_SUCCESS;        // assume no further processing required
                    221: 
                    222: 
                    223:     //
                    224:     // See what type of frame this is.
                    225:     //
                    226: 
                    227:     if ((StHeader->Command == ST_CMD_CONNECT) ||
                    228:         (StHeader->Command == ST_CMD_DATAGRAM)) {
                    229: 
                    230:         MacReturnSourceRouting(
                    231:             &DeviceContext->MacInfo,
                    232:             HeaderBuffer,
                    233:             &SourceRouting,
                    234:             &SourceRoutingLength);
                    235: 
                    236:         Status = StProcessConnectionless (
                    237:                      DeviceContext,
                    238:                      SourceAddress,
                    239:                      StHeader,
                    240:                      StSize,
                    241:                      SourceRouting,
                    242:                      SourceRoutingLength,
                    243:                      &DatagramAddress);
                    244: 
                    245:     } else if ((StHeader->Command == ST_CMD_INFORMATION) ||
                    246:                (StHeader->Command == ST_CMD_DISCONNECT)) {
                    247: 
                    248:         //
                    249:         // If successful this adds a connection reference.
                    250:         //
                    251: 
                    252:         if (!(Connection = StFindConnection(DeviceContext, StHeader->Destination, StHeader->Source))) {
                    253:             return NDIS_STATUS_NOT_RECOGNIZED;
                    254:         }
                    255: 
                    256: 
                    257:         if (StHeader->Command == ST_CMD_INFORMATION) {
                    258: 
                    259:             Status = StProcessIIndicate (
                    260:                         Connection,
                    261:                         StHeader,
                    262:                         StSize,
                    263:                         PacketSize,
                    264:                         ReceiveContext,
                    265:                         (BOOLEAN)((StHeader->Flags & ST_FLAGS_LAST) != 0)
                    266:                         );
                    267: 
                    268:             if (Status != STATUS_MORE_PROCESSING_REQUIRED) {
                    269:                 StDereferenceConnection ("Information done", Connection);
                    270:             } else {
                    271:                 Status = STATUS_SUCCESS;
                    272:             }
                    273: 
                    274:         } else {
                    275: 
                    276:             StStopConnection (Connection, STATUS_REMOTE_DISCONNECT);
                    277:             StDereferenceConnection ("Disconnect done", Connection);
                    278:             Status = STATUS_SUCCESS;
                    279: 
                    280:         }
                    281: 
                    282:     } else {
                    283: 
                    284:         //
                    285:         // An unrecognized frame.
                    286:         //
                    287: 
                    288:         Status = STATUS_SUCCESS;
                    289: 
                    290:     }
                    291: 
                    292: 
                    293:     //
                    294:     // If the above routines return success, the packet has been processed
                    295:     // and can be discarded. If they return anything else, the packet needs
                    296:     // to be copied to local storage for handling in a more lesurely
                    297:     // fashion.
                    298:     //
                    299: 
                    300:     if (Status != STATUS_MORE_PROCESSING_REQUIRED) {
                    301:         return NDIS_STATUS_SUCCESS;
                    302:     }
                    303: 
                    304:     linkage = ExInterlockedPopEntryList(
                    305:         &DeviceContext->ReceivePacketPool,
                    306:         &DeviceContext->Interlock);
                    307: 
                    308:     if (linkage != NULL) {
                    309:         NdisPacket = CONTAINING_RECORD( linkage, NDIS_PACKET, ProtocolReserved[0] );
                    310:     } else {
                    311:         (VOID)ExInterlockedIncrementLong(
                    312:             (PLONG)&DeviceContext->ReceivePacketExhausted,
                    313:             &DeviceContext->Interlock);
                    314:         return NDIS_STATUS_RESOURCES;
                    315:     }
                    316:     ReceiveTag = (PRECEIVE_PACKET_TAG)(NdisPacket->ProtocolReserved);
                    317: 
                    318:     linkage = ExInterlockedPopEntryList(
                    319:        &DeviceContext->ReceiveBufferPool,
                    320:        &DeviceContext->Interlock);
                    321: 
                    322:     if (linkage != NULL) {
                    323:         BufferTag = CONTAINING_RECORD( linkage, BUFFER_TAG, Linkage);
                    324:     } else {
                    325:         ExInterlockedPushEntryList(
                    326:             &DeviceContext->ReceivePacketPool,
                    327:             (PSINGLE_LIST_ENTRY)&ReceiveTag->Linkage,
                    328:             &DeviceContext->Interlock);
                    329:         (VOID)ExInterlockedIncrementLong(
                    330:             (PLONG)&DeviceContext->ReceiveBufferExhausted,
                    331:             &DeviceContext->Interlock);
                    332:         return NDIS_STATUS_RESOURCES;
                    333:     }
                    334: 
                    335:     NdisAdjustBufferLength (BufferTag->NdisBuffer, PacketSize);
                    336:     NdisChainBufferAtFront (NdisPacket, (PNDIS_BUFFER)BufferTag->NdisBuffer);
                    337: 
                    338:     //
                    339:     // DatagramAddress has a reference added already.
                    340:     //
                    341: 
                    342:     BufferTag->Address = DatagramAddress;
                    343: 
                    344:     //
                    345:     // set up async return status so we can tell when it has happened;
                    346:     // can never get return of NDIS_STATUS_PENDING in synch completion routine
                    347:     // for NdisTransferData, so we know it has completed when this status
                    348:     // changes
                    349:     //
                    350: 
                    351:     ReceiveTag->NdisStatus = NDIS_STATUS_PENDING;
                    352:     ReceiveTag->PacketType = TYPE_AT_COMPLETE;
                    353: 
                    354:     ExInterlockedInsertTailList(
                    355:         &DeviceContext->ReceiveInProgress,
                    356:         &ReceiveTag->Linkage,
                    357:         &DeviceContext->SpinLock);
                    358: 
                    359:     //
                    360:     // receive packet is mapped at initalize
                    361:     //
                    362: 
                    363:     NdisTransferData (
                    364:         &NdisStatus,
                    365:         DeviceContext->NdisBindingHandle,
                    366:         ReceiveContext,
                    367:         0,
                    368:         PacketSize,
                    369:         NdisPacket,
                    370:         &BytesTransferred);
                    371: 
                    372:     //
                    373:     // handle the various error codes
                    374:     //
                    375: 
                    376:     switch (NdisStatus) {
                    377:     case NDIS_STATUS_SUCCESS: // received packet
                    378:         ReceiveTag->NdisStatus = NDIS_STATUS_SUCCESS;
                    379:         if (BytesTransferred == PacketSize) {  // Did we get the entire packet?
                    380:             return NDIS_STATUS_SUCCESS;
                    381:         }
                    382:         break;
                    383: 
                    384:     case NDIS_STATUS_PENDING:   // waiting async complete from NdisTransferData
                    385:         return NDIS_STATUS_SUCCESS;
                    386:         break;
                    387: 
                    388:     default:    // something broke; certainly we'll never get NdisTransferData
                    389:                 // asynch completion with this error status...
                    390:         break;
                    391:     }
                    392: 
                    393:     //
                    394:     // receive failed, for some reason; cleanup and fail return
                    395:     //
                    396: 
                    397: 
                    398:     ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
                    399:     RemoveEntryList (&ReceiveTag->Linkage);
                    400:     RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
                    401: 
                    402:     ReceiveTag->PacketType = TYPE_AT_INDICATE;
                    403: 
                    404:     ExInterlockedPushEntryList(
                    405:         &DeviceContext->ReceivePacketPool,
                    406:         (PSINGLE_LIST_ENTRY)&ReceiveTag->Linkage,
                    407:         &DeviceContext->Interlock);
                    408: 
                    409:     NdisUnchainBufferAtFront (NdisPacket, &NdisBuffer);
                    410:     NdisQueryBuffer (NdisBuffer, &BufferPointer, &NdisBufferLength);
                    411:     BufferTag = CONTAINING_RECORD (
                    412:                     BufferPointer,
                    413:                     BUFFER_TAG,
                    414:                     Buffer[0]
                    415:                     );
                    416:     NdisAdjustBufferLength (NdisBuffer, BufferTag->Length); // reset to good value
                    417: 
                    418:     ExInterlockedPushEntryList(
                    419:         &DeviceContext->ReceiveBufferPool,
                    420:         &BufferTag->Linkage,
                    421:         &DeviceContext->Interlock);
                    422: 
                    423:     if (DatagramAddress) {
                    424:         StDereferenceAddress ("DG TransferData failed", DatagramAddress);
                    425:     }
                    426: 
                    427:     return NDIS_STATUS_FAILURE;
                    428: 
                    429: } // StReceiveIndication
                    430: 
                    431: 
                    432: 
                    433: VOID
                    434: StTransferDataComplete (
                    435:     IN NDIS_HANDLE BindingContext,
                    436:     IN PNDIS_PACKET NdisPacket,
                    437:     IN NDIS_STATUS NdisStatus,
                    438:     IN UINT BytesTransferred
                    439:     )
                    440: 
                    441: /*++
                    442: 
                    443: Routine Description:
                    444: 
                    445:     This routine receives control from the physical provider as an
                    446:     indication that an NdisTransferData has completed. We use this indication
                    447:     to start stripping buffers from the receive queue.
                    448: 
                    449: Arguments:
                    450: 
                    451:     BindingContext - The Adapter Binding specified at initialization time.
                    452: 
                    453:     NdisPacket/RequestHandle - An identifier for the request that completed.
                    454: 
                    455:     NdisStatus - The completion status for the request.
                    456: 
                    457:     BytesTransferred - Number of bytes actually transferred.
                    458: 
                    459: 
                    460: Return Value:
                    461: 
                    462:     None.
                    463: 
                    464: --*/
                    465: 
                    466: {
                    467:     PDEVICE_CONTEXT DeviceContext;
                    468:     PRECEIVE_PACKET_TAG ReceiveTag;
                    469:     PTP_CONNECTION Connection;
                    470:     PNDIS_BUFFER NdisBuffer;
                    471:     KIRQL oldirql, cancelirql;
                    472: 
                    473:     //
                    474:     // Put the NDIS status into a place we can use in packet processing.
                    475:     // Note that this complete indication may be occuring during the call
                    476:     // to NdisTransferData in the receive indication.
                    477:     //
                    478: 
                    479:     ReceiveTag = (PRECEIVE_PACKET_TAG)(NdisPacket->ProtocolReserved);
                    480: 
                    481:     //
                    482:     // note that the processing below depends on having only one packet
                    483:     // transfer outstanding at a time. NDIS is supposed to guarentee this.
                    484:     //
                    485: 
                    486:     switch (ReceiveTag->PacketType) {
                    487: 
                    488:     case TYPE_AT_COMPLETE:          // normal handling
                    489:         ReceiveTag->NdisStatus = NdisStatus;
                    490:         break;
                    491: 
                    492:     case TYPE_AT_INDICATE:
                    493: 
                    494:         DeviceContext = (PDEVICE_CONTEXT)BindingContext;
                    495:         Connection = ReceiveTag->Connection;
                    496: 
                    497:         //
                    498:         // The transfer for this packet is complete. Was it successful??
                    499:         //
                    500: 
                    501:         if (NdisStatus != NDIS_STATUS_SUCCESS) {
                    502: 
                    503:             ULONG DumpData[1];
                    504:             DumpData[0] = BytesTransferred;
                    505: 
                    506:             StWriteGeneralErrorLog(
                    507:                 DeviceContext,
                    508:                 EVENT_TRANSPORT_TRANSFER_DATA,
                    509:                 603,
                    510:                 NdisStatus,
                    511:                 NULL,
                    512:                 1,
                    513:                 DumpData);
                    514: 
                    515:             //
                    516:             // Drop the packet. BUGBUG: The driver should recover
                    517:             // from this, but this transport has no way to cause
                    518:             // the remote to resend.
                    519:             //
                    520: 
                    521:         }
                    522: 
                    523:         //
                    524:         // Now dereference the request to say we've got no more local
                    525:         // references to the memory owned by it.
                    526:         //
                    527: 
                    528:         Connection->CurrentReceiveRequest->IoRequestPacket->IoStatus.Information += BytesTransferred;
                    529:         StDereferenceRequest ("TransferData complete", Connection->CurrentReceiveRequest);
                    530: 
                    531:         //
                    532:         // see if we've completed the current receive. If so, move to the next one.
                    533:         //
                    534: 
                    535:         if (ReceiveTag->CompleteReceive) {
                    536: 
                    537:             if (ReceiveTag->EndOfMessage) {
                    538: 
                    539:                 //
                    540:                 // The messages has been completely received, ack it.
                    541:                 //
                    542:                 // We set DEFERRED_ACK and DEFERRED_NOT_Q here, which
                    543:                 // will cause an ack to be piggybacked if any data is
                    544:                 // sent during the call to CompleteReceive. If this
                    545:                 // does not happen, then we will call AcknowledgeDataOnlyLast
                    546:                 // which will will send a DATA ACK or queue a request for
                    547:                 // a piggyback ack. We do this *after* calling CompleteReceive
                    548:                 // so we know that we will complete the receive back to
                    549:                 // the client before we ack the data, to prevent the
                    550:                 // next receive from being sent before this one is
                    551:                 // completed.
                    552:                 //
                    553: 
                    554: 
                    555:                 IoAcquireCancelSpinLock(&cancelirql);
                    556:                 ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql);
                    557: 
                    558:                 Connection->Flags2 |= CONNECTION_FLAGS2_RC_PENDING;
                    559: 
                    560:             } else {
                    561: 
                    562:                 //
                    563:                 // If there is a receive posted, make it current and
                    564:                 // send a receive outstanding.
                    565:                 //
                    566: 
                    567:                 ActivateReceive (Connection);
                    568: 
                    569:                 IoAcquireCancelSpinLock(&cancelirql);
                    570:                 ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql);
                    571: 
                    572:             }
                    573: 
                    574:             //
                    575:             // NOTE: This releases the cancel and connection locks.
                    576:             //
                    577: 
                    578:             CompleteReceive (Connection, ReceiveTag->EndOfMessage, oldirql, cancelirql);
                    579: 
                    580:         }
                    581: 
                    582:         //
                    583:         // dereference the connection to say we've done the I frame processing.
                    584:         // This reference was done before calling NdisTransferData.
                    585:         //
                    586: 
                    587:         if (ReceiveTag->TransferDataPended) {
                    588:             StDereferenceConnection("TransferData done", Connection);
                    589:         }
                    590: 
                    591: 
                    592:         //
                    593:         // rip all of the NDIS_BUFFERs we've used off the chain and return them.
                    594:         //
                    595: 
                    596:         if (ReceiveTag->AllocatedNdisBuffer) {
                    597:             NdisUnchainBufferAtFront (NdisPacket, &NdisBuffer);
                    598:             while (NdisBuffer != NULL) {
                    599:                 NdisFreeBuffer (NdisBuffer);
                    600:                 NdisUnchainBufferAtFront (NdisPacket, &NdisBuffer);
                    601:             }
                    602:         } else {
                    603:             NdisReinitializePacket (NdisPacket);
                    604:         }
                    605: 
                    606: 
                    607:         ExInterlockedPushEntryList(
                    608:             &DeviceContext->ReceivePacketPool,
                    609:             (PSINGLE_LIST_ENTRY)&ReceiveTag->Linkage,
                    610:             &DeviceContext->Interlock);
                    611: 
                    612:         break;
                    613: 
                    614:     default:
                    615: 
                    616:         break;
                    617:     }
                    618: 
                    619:     return;
                    620: 
                    621: }   /* StTransferDataComplete */
                    622: 
                    623: 
                    624: VOID
                    625: StReceiveComplete (
                    626:     IN NDIS_HANDLE BindingContext
                    627:     )
                    628: 
                    629: /*++
                    630: 
                    631: Routine Description:
                    632: 
                    633:     This routine receives control from the physical provider as an
                    634:     indication that a connection(less) frame has been received on the
                    635:     physical link.  We dispatch to the correct packet handler here.
                    636: 
                    637: Arguments:
                    638: 
                    639:     BindingContext - The Adapter Binding specified at initialization time.
                    640:                      ST uses the DeviceContext for this parameter.
                    641: 
                    642: Return Value:
                    643: 
                    644:     None
                    645: 
                    646: --*/
                    647: 
                    648: {
                    649:     PDEVICE_CONTEXT DeviceContext;
                    650:     NTSTATUS Status;
                    651:     KIRQL oldirql, oldirql1;
                    652:     PLIST_ENTRY linkage;
                    653:     PNDIS_PACKET NdisPacket;
                    654:     PNDIS_BUFFER NdisBuffer;
                    655:     UINT NdisBufferLength;
                    656:     PVOID BufferPointer;
                    657:     PRECEIVE_PACKET_TAG ReceiveTag;
                    658:     PBUFFER_TAG BufferTag;
                    659:     PTP_ADDRESS Address;
                    660:     PIRP Irp;
                    661:     PIO_STACK_LOCATION IrpSp;
                    662:     PTP_CONNECTION Connection;
                    663: 
                    664: 
                    665:     DeviceContext = (PDEVICE_CONTEXT) BindingContext;
                    666: 
                    667:     //
                    668:     // Complete all pending receives. Do a quick check
                    669:     // without the lock.
                    670:     //
                    671: 
                    672:     while (!IsListEmpty (&DeviceContext->IrpCompletionQueue)) {
                    673: 
                    674:         linkage = ExInterlockedRemoveHeadList(
                    675:                       &DeviceContext->IrpCompletionQueue,
                    676:                       &DeviceContext->SpinLock);
                    677: 
                    678:         if (linkage != NULL) {
                    679: 
                    680:             Irp = CONTAINING_RECORD (linkage, IRP, Tail.Overlay.ListEntry);
                    681:             IrpSp = IoGetCurrentIrpStackLocation (Irp);
                    682: 
                    683:             Connection = (PTP_CONNECTION)IrpSp->FileObject->FsContext;
                    684: 
                    685:             IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
                    686: 
                    687:             ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql1);
                    688: 
                    689:             if (Connection->Flags2 & CONNECTION_FLAGS2_RC_PENDING) {
                    690:                 Connection->Flags2 &= ~CONNECTION_FLAGS2_RC_PENDING;
                    691:             }
                    692: 
                    693:             RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql1);
                    694: 
                    695:             StDereferenceConnection ("receive completed", Connection);
                    696: 
                    697:         } else {
                    698: 
                    699:             //
                    700:             // ExInterlockedRemoveHeadList returned NULL, so don't
                    701:             // bother looping back.
                    702:             //
                    703: 
                    704:             break;
                    705: 
                    706:         }
                    707: 
                    708:     }
                    709: 
                    710: 
                    711:     //
                    712:     // Packetize all waiting connections
                    713:     //
                    714: 
                    715:     if (!IsListEmpty(&DeviceContext->PacketizeQueue)) {
                    716: 
                    717:         PacketizeConnections (DeviceContext);
                    718: 
                    719:     }
                    720: 
                    721: 
                    722:     //
                    723:     // Get every waiting packet, in order...
                    724:     //
                    725: 
                    726: 
                    727:     if (!IsListEmpty (&DeviceContext->ReceiveInProgress)) {
                    728: 
                    729:         ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
                    730: 
                    731:         while (!IsListEmpty (&DeviceContext->ReceiveInProgress)) {
                    732: 
                    733:             linkage = RemoveHeadList (&DeviceContext->ReceiveInProgress);
                    734:             NdisPacket = CONTAINING_RECORD( linkage, NDIS_PACKET, ProtocolReserved[0]);
                    735: 
                    736:             //
                    737:             // NdisTransferData may have failed at async completion; check and
                    738:             // see. If it did, then we discard this packet. If we're still waiting
                    739:             // for transfer to complete, go back to sleep and hope (no guarantee!)
                    740:             // we get waken up later.
                    741:             //
                    742: 
                    743:             ReceiveTag = (PRECEIVE_PACKET_TAG)(NdisPacket->ProtocolReserved);
                    744:             if (ReceiveTag->NdisStatus == NDIS_STATUS_PENDING) {
                    745:                 InsertHeadList (&DeviceContext->ReceiveInProgress, linkage);
                    746:                 RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
                    747:                 return;
                    748:             }
                    749: 
                    750:             RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
                    751: 
                    752:             if (ReceiveTag->NdisStatus != NDIS_STATUS_SUCCESS) {
                    753:                 goto FreePacket;   // skip the packet, continue with while loop
                    754:             }
                    755: 
                    756:             NdisQueryPacket (NdisPacket, NULL, NULL, &NdisBuffer, NULL);
                    757: 
                    758:             //
                    759:             // Have a packet. Since I allocated the storage for it, I know it's
                    760:             // virtually contiguous and can treat it that way, which I will
                    761:             // henceforth.
                    762:             //
                    763: 
                    764:             NdisQueryBuffer (NdisBuffer, &BufferPointer, &NdisBufferLength);
                    765: 
                    766:             //
                    767:             // Determine what address this is for, which is stored
                    768:             // in the buffer tag header.
                    769:             //
                    770: 
                    771:             BufferTag = CONTAINING_RECORD( BufferPointer, BUFFER_TAG, Buffer[0]);
                    772:             Address = BufferTag->Address;
                    773: 
                    774:             //
                    775:             // Process the frame as a UI frame; only datagrams should
                    776:             // be processed here. If Address is NULL then this datagram
                    777:             // is not needed for any bound address and should be given
                    778:             // to RAS only.
                    779:             //
                    780: 
                    781:             ASSERT (Address != NULL);
                    782: 
                    783:             //
                    784:             // Indicate it or complete posted datagrams.
                    785:             //
                    786: 
                    787:             Status = StIndicateDatagram (
                    788:                 DeviceContext,
                    789:                 Address,
                    790:                 BufferPointer,
                    791:                 NdisBufferLength);
                    792: 
                    793: 
                    794:             //
                    795:             // Dereference the address.
                    796:             //
                    797: 
                    798:             StDereferenceAddress ("Datagram done", Address);
                    799: 
                    800:             //
                    801:             // Finished with packet; return to pool.
                    802:             //
                    803: 
                    804: FreePacket:;
                    805: 
                    806:             NdisUnchainBufferAtFront (NdisPacket, &NdisBuffer);
                    807:             ReceiveTag->PacketType = TYPE_AT_INDICATE;
                    808: 
                    809:             ExInterlockedPushEntryList(
                    810:                 &DeviceContext->ReceivePacketPool,
                    811:                 (PSINGLE_LIST_ENTRY)&ReceiveTag->Linkage,
                    812:                 &DeviceContext->Interlock);
                    813: 
                    814:             NdisAdjustBufferLength (NdisBuffer, BufferTag->Length);
                    815:             ExInterlockedPushEntryList(
                    816:                 &DeviceContext->ReceiveBufferPool,
                    817:                 &BufferTag->Linkage,
                    818:                 &DeviceContext->Interlock);
                    819: 
                    820:             ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
                    821: 
                    822:         }
                    823: 
                    824:         RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
                    825: 
                    826:     } // if queue not empty
                    827: 
                    828:     return;
                    829: 
                    830: }   /* StReceiveComplete */
                    831: 

unix.superglobalmegacorp.com

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