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