|
|
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.