summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/lt200/ltloop.c
blob: 9baad5bd531bb94387d8aa0f21d8f05741dd329e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*++

Copyright (c) 1992  Microsoft Corporation

Module Name:

	ltloop.c

Abstract:

	This module contains the loopback queue processing routines.

Author:

	Stephen Hou			(stephh@microsoft.com)
	Nikhil 	Kamkolkar 	(nikhilk@microsoft.com)

Revision History:
	19 Jun 1992		Initial Version (dch@pacvax.pacersoft.com)

Notes:	Tab stop: 4
--*/

#include	"ltmain.h"

//	Define file id for errorlogging
#define		FILENUM		LTLOOP


VOID
LtLoopProcessQueue(
    IN PLT_ADAPTER	Adapter
    )
/*++

Routine Description:

    This routine is responsible for indicating *one* packet on
    the loopback queue either completing it or moving on to the
    finish send queue.

Arguments:

    Adapter - The adapter whose loopback queue we are processing.

Return Value:

    None.

--*/
{
	// Packet at the head of the loopback list.
	PNDIS_PACKET Packet;
	
	// The reserved portion of the above packet.
	PLT_PACKET_RESERVED Reserved;
	
	// Buffer for loopback.
	CHAR Loopback[LT_MAX_INDICATE_SIZE];
	
	// The first buffer in the ndis packet to be loopedback.
	PNDIS_BUFFER FirstBuffer;
	
	// The total amount of user data in the packet to be
	// loopedback.
	UINT PacketLength;
	
	// Eventually the address of the data to be indicated
	// to the transport.
	PCHAR BufferAddress, LinkAddress;
	
	// Eventually the length of the data to be indicated
	// to the transport.
	UINT 		BufferLength;
	PLIST_ENTRY p;
	PLT_OPEN	Binding;


	NdisAcquireSpinLock(&Adapter->Lock);
	while((!IsListEmpty(&Adapter->LoopBack)) &&
          ((Adapter->Flags & ADAPTER_RESET_IN_PROGRESS) == 0))
	{
		p = RemoveHeadList(&Adapter->LoopBack);
        Packet		= CONTAINING_RECORD(
						p,
						NDIS_PACKET,
						MacReserved);

		Reserved 	= (PLT_PACKET_RESERVED)Packet->MacReserved;

		//	Remember this in CurrentLoopbackPacket in Adapter.
		//	Used by Transfer data.
		Adapter->CurrentLoopbackPacket = Packet;
		NdisReleaseSpinLock(&Adapter->Lock);
		
		DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO,
				("LtLoopProcessLoopback: Dequeued %lx \n", Packet));
	
		// See if we need to copy the data from the packet
		// into the loopback buffer.
		//
		// We need to copy to the local loopback buffer if
		// the first buffer of the packet is less than the
		// minimum loopback size AND the first buffer isn't
		// the total packet.
		NdisQueryPacket(
			Packet,
			NULL,
			NULL,
			&FirstBuffer,
			&PacketLength);

		NdisQueryBuffer(
			FirstBuffer,
			&BufferAddress,
			&BufferLength);

		LinkAddress = BufferAddress;
		if (BufferLength != PacketLength)
		{
			//	!!!BUGBUG: What do the sizes mean?
			LtUtilsCopyFromPacketToBuffer(
				Packet,
				LT_DGRAM_OFFSET,
				LT_MAX_INDICATE_SIZE,
				Loopback,
				&BufferLength);

			BufferAddress = Loopback;

		}
		else
		{
			// Adjust the buffer to account for the link header
			// which is not part of the lookahead.
			BufferAddress += LT_DGRAM_OFFSET;
			BufferLength  -= LT_LINK_HEADER_LENGTH;
		}
		
		// Indicate the packet to every open binding
		// that could want it. Since loopback indications
		// are seralized, we use a NULL handle to indicate that it
		// is for a loopback packet. TransferData always gets the
		// first packet off the loopback queue.
		
		// Since we do not have an complicated filtering to do.
		// Just walk the list of Open bindings and Indicate the packet

		NdisAcquireSpinLock(&Adapter->Lock);
		LtRecvIndicatePacket(
			Adapter,
			LinkAddress,
			BufferAddress,
			BufferLength,
			PacketLength - LT_LINK_HEADER_LENGTH,
			(NDIS_HANDLE)NULL);
		NdisReleaseSpinLock(&Adapter->Lock);


		//	We have indicated the packet to all the binding. Now we just
		//	need to call send completion.

		DBGPRINT(DBG_COMP_LOOP, DBG_LEVEL_WARN,
				("LtLoopProcessLoopback: NdisSendComplete Packet = %p\n", Packet ));


		Binding = (PLT_OPEN)(Reserved->MacBindingHandle);
		NdisCompleteSend(
			Binding->NdisBindingContext,
			Packet,
			NDIS_STATUS_SUCCESS);

		//	Dereference the adapter and the binding for this completed
		//	send.
		LtDeReferenceBinding(Binding);
		LtDeReferenceAdapter(Adapter);

		NdisAcquireSpinLock(&Adapter->Lock);
	}
	NdisReleaseSpinLock(&Adapter->Lock);

	return;
}