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