|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1990 Microsoft Corporation
4:
5: Module Name:
6:
7: transfer.c
8:
9: Abstract:
10:
11: This file contains the code to implement the MacTransferData
12: API for the ndis 3.0 interface.
13:
14: Author:
15:
16: Anthony V. Ercolano (Tonye) 12-Sept-1990
17:
18: Environment:
19:
20: Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
21:
22: Revision History:
23:
24:
25: --*/
26:
27: #include <ndis.h>
28: #include <efilter.h>
29: #include <lancehrd.h>
30: #include <lancesft.h>
31:
32:
33: extern
34: NDIS_STATUS
35: LanceTransferData(
36: IN NDIS_HANDLE MacBindingHandle,
37: IN NDIS_HANDLE MacReceiveContext,
38: IN UINT ByteOffset,
39: IN UINT BytesToTransfer,
40: OUT PNDIS_PACKET Packet,
41: OUT PUINT BytesTransferred
42: )
43:
44: /*++
45:
46: Routine Description:
47:
48: A protocol calls the LanceTransferData request (indirectly via
49: NdisTransferData) from within its Receive event handler
50: to instruct the MAC to copy the contents of the received packet
51: a specified paqcket buffer.
52:
53: Arguments:
54:
55: MacBindingHandle - The context value returned by the MAC when the
56: adapter was opened. In reality this is a pointer to LANCE_OPEN.
57:
58: MacReceiveContext - The context value passed by the MAC on its call
59: to NdisIndicateReceive. The MAC can use this value to determine
60: which packet, on which adapter, is being received.
61:
62: ByteOffset - An unsigned integer specifying the offset within the
63: received packet at which the copy is to begin. If the entire packet
64: is to be copied, ByteOffset must be zero.
65:
66: BytesToTransfer - An unsigned integer specifying the number of bytes
67: to copy. It is legal to transfer zero bytes; this has no effect. If
68: the sum of ByteOffset and BytesToTransfer is greater than the size
69: of the received packet, then the remainder of the packet (starting from
70: ByteOffset) is transferred, and the trailing portion of the receive
71: buffer is not modified.
72:
73: Packet - A pointer to a descriptor for the packet storage into which
74: the MAC is to copy the received packet.
75:
76: BytesTransfered - A pointer to an unsigned integer. The MAC writes
77: the actual number of bytes transferred into this location. This value
78: is not valid if the return status is STATUS_PENDING.
79:
80: Return Value:
81:
82: The function value is the status of the operation.
83:
84:
85: --*/
86:
87: {
88:
89: PLANCE_ADAPTER Adapter;
90: PLANCE_OPEN Open = PLANCE_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
91: NDIS_STATUS StatusToReturn;
92:
93: Adapter = PLANCE_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
94:
95: NdisAcquireSpinLock(&Adapter->Lock);
96:
97: Adapter->References++;
98:
99: ASSERT(!Adapter->ResetInitStarted);
100:
101: ByteOffset += LANCE_HEADER_SIZE;
102:
103: if (!Open->BindingShuttingDown) {
104:
105: Open->References++;
106:
107: NdisReleaseSpinLock(&Adapter->Lock);
108:
109: //
110: // The MacReceive context can be either of two things.
111: //
112: // If the low bit is != 1 then it is a pointer to the users
113: // ndis packet. It would typically be the packet when the
114: // packet has been delivered via loopback.
115: //
116: // If the value has a 1 in the low bit, the value holds the
117: // first and last receive ring descriptor indices.
118: //
119:
120: if (!((UINT)MacReceiveContext & 1)) {
121:
122: LanceCopyFromPacketToPacket(
123: Packet,
124: 0,
125: BytesToTransfer,
126: (PNDIS_PACKET)((PVOID)MacReceiveContext),
127: ByteOffset,
128: BytesTransferred
129: );
130:
131: } else {
132:
133: //
134: // The code in this section is quite similar to the
135: // code in CopyFromPacketToPacket. It could easily go
136: // into its own routine, except that it is not likely
137: // to be used in any other implementation.
138: //
139:
140: //
141: // Keep a local for the number of receive ring entries so
142: // that we aren't always accessing through the adapter.
143: //
144: const UINT TopReceiveIndex = Adapter->NumberOfReceiveRings - 1;
145:
146: //
147: // Used for only a short time to extract the context
148: // information from the parameter.
149: //
150: LANCE_RECEIVE_CONTEXT C;
151:
152: //
153: // Holds the first and last index of the first and last
154: // receive ring descriptors that hold the current packet.
155: //
156: UINT FirstBuffer;
157: UINT LastBuffer;
158:
159: //
160: // Pointer to the ring descriptor for the current buffer.
161: //
162: PLANCE_RECEIVE_ENTRY CurrentEntry;
163:
164: //
165: // Holds the count of the number of ndis buffers comprising
166: // the destination packet.
167: //
168: UINT DestinationBufferCount;
169:
170: //
171: // Points to the buffer into which we are putting data.
172: //
173: PNDIS_BUFFER DestinationCurrentBuffer;
174:
175: //
176: // Holds the virtual address of the current destination
177: // buffer.
178: //
179: PVOID DestinationVirtualAddress;
180:
181: //
182: // Holds the virtual address of the current source buffer.
183: //
184: PVOID SourceVirtualAddress;
185:
186: //
187: // Holds the length of the current destination buffer.
188: //
189: UINT DestinationCurrentLength;
190:
191: //
192: // Holds the length of the current source buffer.
193: //
194: UINT SourceCurrentLength;
195:
196: //
197: // Keep a local variable of BytesTransferred so we aren't
198: // referencing through a pointer.
199: //
200: UINT LocalBytesTransferred = 0;
201:
202: //
203: // Index in the ring of the current receive ring descriptor.
204: //
205: UINT CurrentSourceIndex;
206:
207: //
208: // Take care of boundary condition of zero length copy.
209: //
210:
211: *BytesTransferred = 0;
212:
213: ASSERT(sizeof(UINT) >= 2);
214: ASSERT(sizeof(UINT) == sizeof(NDIS_HANDLE));
215:
216: C.WholeThing = (UINT)MacReceiveContext;
217: FirstBuffer = C.INFO.FirstBuffer;
218: LastBuffer = C.INFO.LastBuffer;
219:
220: //
221: // Get the first buffer of the destination.
222: //
223:
224: NdisQueryPacket(
225: Packet,
226: NULL,
227: &DestinationBufferCount,
228: &DestinationCurrentBuffer,
229: NULL
230: );
231:
232: //
233: // Could have a null packet.
234: //
235:
236: if (DestinationBufferCount) {
237:
238: NdisQueryBuffer(
239: DestinationCurrentBuffer,
240: &DestinationVirtualAddress,
241: &DestinationCurrentLength
242: );
243:
244: //
245: // Get the information for the first buffer of the source.
246: //
247:
248: SourceVirtualAddress = Adapter->ReceiveVAs[FirstBuffer];
249: CurrentEntry = Adapter->ReceiveRing + FirstBuffer;
250: CurrentSourceIndex = FirstBuffer;
251:
252: if (CurrentSourceIndex == LastBuffer) {
253:
254: //
255: // The last buffer might only be partially filled with
256: // transmitted data. There is a field in the last
257: // ring entry that has the total packet data length.
258: //
259: LANCE_GET_MESSAGE_SIZE(CurrentEntry, SourceCurrentLength);
260: SourceCurrentLength -= LocalBytesTransferred;
261:
262: } else {
263:
264: SourceCurrentLength = Adapter->SizeOfReceiveBuffer;
265:
266: }
267:
268: while (LocalBytesTransferred < BytesToTransfer) {
269:
270: //
271: // Check to see whether we've exhausted the current
272: // destination buffer. If so, move onto the next one.
273: //
274:
275: if (!DestinationCurrentLength) {
276:
277: NdisGetNextBuffer(
278: DestinationCurrentBuffer,
279: &DestinationCurrentBuffer
280: );
281:
282: if (!DestinationCurrentBuffer) {
283:
284: //
285: // We've reached the end of the packet. We
286: // return with what we've done so far. (Which
287: // must be shorter than requested.)
288: //
289:
290: break;
291:
292: }
293:
294: NdisQueryBuffer(
295: DestinationCurrentBuffer,
296: &DestinationVirtualAddress,
297: &DestinationCurrentLength
298: );
299: continue;
300:
301: }
302:
303:
304: //
305: // Check to see whether we've exhausted the current
306: // source buffer. If so, move onto the next one.
307: //
308:
309: if (!SourceCurrentLength) {
310:
311: if (CurrentSourceIndex == LastBuffer) {
312:
313: //
314: // We've reached the end of the packet. We
315: // return with what we've done so far. (Which
316: // must be shorter than requested.)
317: //
318:
319: break;
320:
321: }
322:
323: if (CurrentSourceIndex == TopReceiveIndex) {
324:
325: CurrentSourceIndex = 0;
326: CurrentEntry = Adapter->ReceiveRing;
327:
328: } else {
329:
330: CurrentSourceIndex++;
331: CurrentEntry++;
332:
333: }
334:
335: if (CurrentSourceIndex == LastBuffer) {
336:
337: //
338: // The last buffer might only be partially
339: // filled with transmitted data. There is
340: // a field in the last ring entry that has
341: // the total packet data length.
342: //
343: LANCE_GET_MESSAGE_SIZE(CurrentEntry, SourceCurrentLength);
344: SourceCurrentLength -= LocalBytesTransferred;
345:
346: } else {
347:
348: SourceCurrentLength =
349: Adapter->SizeOfReceiveBuffer;
350:
351: }
352:
353: SourceVirtualAddress =
354: Adapter->ReceiveVAs[CurrentSourceIndex];
355: continue;
356:
357: }
358:
359: //
360: // Try to get us up to the point to start the copy.
361: //
362:
363: if (ByteOffset) {
364:
365: if (ByteOffset > SourceCurrentLength) {
366:
367: //
368: // What we want isn't in this buffer.
369: //
370:
371: ByteOffset -= SourceCurrentLength;
372: SourceCurrentLength = 0;
373: continue;
374:
375: } else {
376:
377: SourceVirtualAddress =
378: (PCHAR)SourceVirtualAddress + ByteOffset;
379: SourceCurrentLength -= ByteOffset;
380: ByteOffset = 0;
381:
382: }
383:
384: }
385:
386: //
387: // Copy the data.
388: //
389:
390: {
391:
392: //
393: // Holds the amount of data to move.
394: //
395: UINT AmountToMove;
396:
397: //
398: // Holds the amount desired remaining.
399: //
400: UINT Remaining = BytesToTransfer
401: - LocalBytesTransferred;
402:
403: AmountToMove =
404: ((SourceCurrentLength <= DestinationCurrentLength)?
405: (SourceCurrentLength):(DestinationCurrentLength));
406:
407: AmountToMove = ((Remaining < AmountToMove)?
408: (Remaining):(AmountToMove));
409:
410: LANCE_MOVE_HARDWARE_TO_MEMORY(
411: DestinationVirtualAddress,
412: SourceVirtualAddress,
413: AmountToMove
414: );
415:
416: DestinationVirtualAddress =
417: (PCHAR)DestinationVirtualAddress + AmountToMove;
418: SourceVirtualAddress =
419: (PCHAR)SourceVirtualAddress + AmountToMove;
420:
421: LocalBytesTransferred += AmountToMove;
422: SourceCurrentLength -= AmountToMove;
423: DestinationCurrentLength -= AmountToMove;
424:
425: }
426:
427: }
428:
429: *BytesTransferred = LocalBytesTransferred;
430:
431: }
432:
433: }
434:
435: NdisAcquireSpinLock(&Adapter->Lock);
436: Open->References--;
437: StatusToReturn = NDIS_STATUS_SUCCESS;
438:
439: } else {
440:
441: StatusToReturn = NDIS_STATUS_REQUEST_ABORTED;
442:
443: }
444:
445: LANCE_DO_DEFERRED(Adapter);
446: return StatusToReturn;
447: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.