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