|
|
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: Adam Barr (adamba) 15-Mar-1991
18:
19: Environment:
20:
21: Kernel Mode - Or whatever is the equivalent.
22:
23: Revision History:
24:
25:
26: --*/
27:
28: #pragma optimize("",off)
29:
30: #include <ndis.h>
31:
32: #include <tfilter.h>
33: #include <tokhrd.h>
34: #include <toksft.h>
35:
36:
37: extern
38: NDIS_STATUS
39: IbmtokTransferData(
40: IN NDIS_HANDLE MacBindingHandle,
41: IN NDIS_HANDLE MacReceiveContext,
42: IN UINT ByteOffset,
43: IN UINT BytesToTransfer,
44: OUT PNDIS_PACKET Packet,
45: OUT PUINT BytesTransferred
46: )
47:
48: /*++
49:
50: Routine Description:
51:
52: A protocol calls the IbmtokTransferData request (indirectly via
53: NdisTransferData) from within its Receive event handler
54: to instruct the MAC to copy the contents of the received packet
55: a specified packet buffer.
56:
57: Arguments:
58:
59: MacBindingHandle - The context value returned by the MAC when the
60: adapter was opened. In reality this is a pointer to IBMTOK.
61:
62: MacReceiveContext - The context value passed by the MAC on its call
63: to NdisIndicateReceive. The MAC can use this value to determine
64: which packet, on which adapter, is being received.
65:
66: ByteOffset - An unsigned integer specifying the offset within the
67: received packet at which the copy is to begin. If the entire packet
68: is to be copied, ByteOffset must be zero.
69:
70: BytesToTransfer - An unsigned integer specifying the number of bytes
71: to copy. It is legal to transfer zero bytes; this has no effect. If
72: the sum of ByteOffset and BytesToTransfer is greater than the size
73: of the received packet, then the remainder of the packet (starting from
74: ByteOffset) is transferred, and the trailing portion of the receive
75: buffer is not modified.
76:
77: Packet - A pointer to a descriptor for the packet storage into which
78: the MAC is to copy the received packet.
79:
80: BytesTransfered - A pointer to an unsigned integer. The MAC writes
81: the actual number of bytes transferred into this location. This value
82: is not valid if the return status is STATUS_PENDING.
83:
84: Return Value:
85:
86: The function value is the status of the operation.
87:
88:
89: --*/
90:
91: {
92:
93: PIBMTOK_ADAPTER Adapter;
94:
95: NDIS_STATUS StatusToReturn;
96:
97: Adapter = PIBMTOK_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
98:
99: NdisAcquireSpinLock(&Adapter->Lock);
100: Adapter->References++;
101:
102: if (!Adapter->NotAcceptingRequests) {
103:
104: PIBMTOK_OPEN Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
105:
106: if (!Open->BindingShuttingDown) {
107:
108: //
109: // The code in this section is quite similar to the
110: // code in CopyFromPacketToPacket. It could easily go
111: // into its own routine, except that it is not likely
112: // to be used in any other implementation.
113: //
114: SRAM_PTR SourceReceiveBuffer =
115: Adapter->IndicatedReceiveBuffer;
116:
117: //
118: // Holds the count of the number of ndis buffers comprising
119: // the destination packet.
120: //
121: UINT DestinationBufferCount;
122:
123: //
124: // Points to the buffer into which we are putting data.
125: //
126: PNDIS_BUFFER DestinationCurrentBuffer;
127:
128: //
129: // Holds the virtual address of the current destination
130: // buffer.
131: //
132: PVOID DestinationVirtualAddress;
133:
134: //
135: // Holds the virtual address of the current source buffer.
136: //
137: PRECEIVE_BUFFER SourceBufferAddress;
138:
139: //
140: // Holds the address of the data in the current source buffer.
141: //
142: PVOID SourceVirtualAddress;
143:
144: //
145: // Holds the length of the current destination buffer.
146: //
147: UINT DestinationCurrentLength;
148:
149: //
150: // Holds the length of the current source buffer.
151: //
152: UINT SourceCurrentLength;
153:
154: //
155: // Keep a local variable of BytesTransferred so we aren't
156: // referencing through a pointer.
157: //
158: UINT LocalBytesTransferred = 0;
159:
160: USHORT PortValue;
161:
162: Open->References++;
163:
164: NdisReleaseSpinLock(&Adapter->Lock);
165:
166: *BytesTransferred = 0;
167:
168: ASSERT(sizeof(UINT) >= 2);
169: ASSERT(sizeof(UINT) == sizeof(NDIS_HANDLE));
170:
171: //
172: // Get the first buffer of the destination.
173: //
174:
175: NdisQueryPacket(
176: Packet,
177: NULL,
178: &DestinationBufferCount,
179: &DestinationCurrentBuffer,
180: NULL
181: );
182:
183: //
184: // Could have a null packet.
185: //
186:
187: if (DestinationBufferCount != 0) {
188:
189: NdisQueryBuffer(
190: DestinationCurrentBuffer,
191: &DestinationVirtualAddress,
192: &DestinationCurrentLength
193: );
194:
195: //
196: // Get the information for the first buffer of the source.
197: //
198:
199: SourceBufferAddress = (PRECEIVE_BUFFER)
200: ((PUCHAR)SRAM_PTR_TO_PVOID(Adapter,
201: SourceReceiveBuffer) + 2);
202:
203: //
204: // Adjust the address and length to account for the
205: // header for this frame.
206: //
207:
208: SourceVirtualAddress =
209: SourceBufferAddress->FrameData +
210: Adapter->IndicatedHeaderLength;
211:
212: NdisReadRegisterUshort(&SourceBufferAddress->BufferLength,
213: &PortValue
214: );
215:
216: SourceCurrentLength = IBMSHORT_TO_USHORT(PortValue) -
217: Adapter->IndicatedHeaderLength;
218:
219:
220:
221: //
222: // Take care of boundary condition of zero length copy.
223: //
224:
225: while (LocalBytesTransferred < BytesToTransfer) {
226:
227: //
228: // Check to see whether we've exhausted the current
229: // destination buffer. If so, move onto the next one.
230: //
231:
232: if (!DestinationCurrentLength) {
233:
234: NdisGetNextBuffer(
235: DestinationCurrentBuffer,
236: &DestinationCurrentBuffer
237: );
238:
239: if (!DestinationCurrentBuffer) {
240:
241: //
242: // We've reached the end of the packet. We
243: // return with what we've done so far. (Which
244: // must be shorter than requested.)
245: //
246:
247: break;
248:
249: }
250:
251: NdisQueryBuffer(
252: DestinationCurrentBuffer,
253: &DestinationVirtualAddress,
254: &DestinationCurrentLength
255: );
256: continue;
257:
258: }
259:
260:
261: //
262: // Check to see whether we've exhausted the current
263: // source buffer. If so, move onto the next one.
264: //
265:
266: if (!SourceCurrentLength) {
267:
268: NdisReadRegisterUshort(
269: &SourceBufferAddress->NextBuffer,
270: &SourceReceiveBuffer
271: );
272:
273: if (SourceReceiveBuffer == NULL_SRAM_PTR) {
274:
275: //
276: // We've reached the end of the frame. We
277: // return with what we've done so far. (Which
278: // must be shorter than requested.)
279: //
280:
281: break;
282:
283: }
284:
285: SourceBufferAddress = (PRECEIVE_BUFFER)
286: SRAM_PTR_TO_PVOID(Adapter, SourceReceiveBuffer);
287:
288: SourceVirtualAddress =
289: (PVOID)SourceBufferAddress->FrameData;
290:
291: NdisReadRegisterUshort(
292: &SourceBufferAddress->BufferLength,
293: &SourceCurrentLength
294: );
295:
296: SourceCurrentLength = IBMSHORT_TO_USHORT(
297: SourceCurrentLength
298: );
299:
300: continue;
301:
302: }
303:
304: //
305: // Try to get us up to the point to start the copy.
306: //
307:
308: if (ByteOffset) {
309:
310: if (ByteOffset > SourceCurrentLength) {
311:
312: //
313: // What we want isn't in this buffer.
314: //
315:
316: ByteOffset -= SourceCurrentLength;
317: SourceCurrentLength = 0;
318: continue;
319:
320: } else {
321:
322: SourceVirtualAddress =
323: (PCHAR)SourceVirtualAddress + ByteOffset;
324: SourceCurrentLength -= ByteOffset;
325: ByteOffset = 0;
326:
327: }
328:
329: }
330:
331: //
332: // Copy the data.
333: //
334:
335: {
336:
337: //
338: // Holds the amount of data to move.
339: //
340: UINT AmountToMove;
341:
342: //
343: // Holds the amount desired remaining.
344: //
345: UINT Remaining = BytesToTransfer
346: - LocalBytesTransferred;
347:
348: AmountToMove =
349: ((SourceCurrentLength <= DestinationCurrentLength)?
350: (SourceCurrentLength):(DestinationCurrentLength));
351:
352: AmountToMove = ((Remaining < AmountToMove)?
353: (Remaining):(AmountToMove));
354:
355: IBMTOK_MOVE_FROM_MAPPED_MEMORY(
356: DestinationVirtualAddress,
357: SourceVirtualAddress,
358: AmountToMove
359: );
360:
361: DestinationVirtualAddress =
362: (PCHAR)DestinationVirtualAddress + AmountToMove;
363: SourceVirtualAddress =
364: (PCHAR)SourceVirtualAddress + AmountToMove;
365:
366: LocalBytesTransferred += AmountToMove;
367: SourceCurrentLength -= AmountToMove;
368: DestinationCurrentLength -= AmountToMove;
369:
370: }
371:
372: }
373:
374: *BytesTransferred = LocalBytesTransferred;
375:
376: }
377:
378: NdisAcquireSpinLock(&Adapter->Lock);
379: Open->References--;
380: StatusToReturn = NDIS_STATUS_SUCCESS;
381:
382: } else {
383:
384: StatusToReturn = NDIS_STATUS_REQUEST_ABORTED;
385:
386: }
387:
388: } else {
389:
390: if (Adapter->ResetInProgress) {
391:
392: StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
393:
394: } else if (Adapter->OpenInProgress) {
395:
396: StatusToReturn = NDIS_STATUS_FAILURE;
397:
398: } else {
399:
400: NdisWriteErrorLogEntry(
401: Adapter->NdisAdapterHandle,
402: NDIS_ERROR_CODE_DRIVER_FAILURE,
403: 2,
404: IBMTOK_ERRMSG_INVALID_STATE,
405: 1
406: );
407:
408: }
409:
410: }
411:
412: IBMTOK_DO_DEFERRED(Adapter);
413: return StatusToReturn;
414: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.