|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.