1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS NDIS library 4 * FILE: ndis/buffer.c 5 * PURPOSE: Buffer management routines 6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 7 * REVISIONS: 8 * CSH 01/08-2000 Created 9 */ 10 11 #include <ndissys.h> 12 13 __inline ULONG SkipToOffset( 14 IN PNDIS_BUFFER Buffer, 15 IN UINT Offset, 16 IN OUT PUCHAR *Data, 17 IN OUT PUINT Size) 18 /* 19 * FUNCTION: Skips Offset bytes into a buffer chain 20 * ARGUMENTS: 21 * Buffer = Pointer to NDIS buffer 22 * Offset = Number of bytes to skip 23 * Data = Address of a pointer that on return will contain the 24 * address of the offset in the buffer 25 * Size = Address of a pointer that on return will contain the 26 * size of the destination buffer 27 * RETURNS: 28 * Offset into buffer, -1 if buffer chain was smaller than Offset bytes 29 * NOTES: 30 * Buffer may be NULL 31 */ 32 { 33 for (;;) { 34 35 if (!Buffer) 36 return 0xFFFFFFFF; 37 38 NdisQueryBuffer(Buffer, (PVOID)Data, Size); 39 40 if (Offset < *Size) { 41 *Data = (PUCHAR) ((ULONG_PTR) *Data + Offset); 42 *Size -= Offset; 43 break; 44 } 45 46 Offset -= *Size; 47 48 NdisGetNextBuffer(Buffer, &Buffer); 49 } 50 51 return Offset; 52 } 53 54 UINT CopyBufferToBufferChain( 55 PNDIS_BUFFER DstBuffer, 56 UINT DstOffset, 57 PUCHAR SrcData, 58 UINT Length) 59 /* 60 * FUNCTION: Copies data from a buffer to an NDIS buffer chain 61 * ARGUMENTS: 62 * DstBuffer = Pointer to destination NDIS buffer 63 * DstOffset = Destination start offset 64 * SrcData = Pointer to source buffer 65 * Length = Number of bytes to copy 66 * RETURNS: 67 * Number of bytes copied to destination buffer 68 * NOTES: 69 * The number of bytes copied may be limited by the destination 70 * buffer size 71 */ 72 { 73 UINT BytesCopied, BytesToCopy, DstSize; 74 PUCHAR DstData; 75 76 NDIS_DbgPrint(MAX_TRACE, ("DstBuffer (0x%X) DstOffset (0x%X) SrcData (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcData, Length)); 77 78 /* Skip DstOffset bytes in the destination buffer chain */ 79 if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == 0xFFFFFFFF) 80 return 0; 81 82 /* Start copying the data */ 83 BytesCopied = 0; 84 for (;;) { 85 BytesToCopy = MIN(DstSize, Length); 86 87 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy); 88 BytesCopied += BytesToCopy; 89 SrcData = (PUCHAR) ((ULONG_PTR) SrcData + BytesToCopy); 90 91 Length -= BytesToCopy; 92 if (Length == 0) 93 break; 94 95 DstSize -= BytesToCopy; 96 if (DstSize == 0) { 97 /* No more bytes in desination buffer. Proceed to 98 the next buffer in the destination buffer chain */ 99 NdisGetNextBuffer(DstBuffer, &DstBuffer); 100 if (!DstBuffer) 101 break; 102 103 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); 104 } 105 } 106 107 return BytesCopied; 108 } 109 110 111 UINT CopyBufferChainToBuffer( 112 PUCHAR DstData, 113 PNDIS_BUFFER SrcBuffer, 114 UINT SrcOffset, 115 UINT Length) 116 /* 117 * FUNCTION: Copies data from an NDIS buffer chain to a buffer 118 * ARGUMENTS: 119 * DstData = Pointer to destination buffer 120 * SrcBuffer = Pointer to source NDIS buffer 121 * SrcOffset = Source start offset 122 * Length = Number of bytes to copy 123 * RETURNS: 124 * Number of bytes copied to destination buffer 125 * NOTES: 126 * The number of bytes copied may be limited by the source 127 * buffer size 128 */ 129 { 130 UINT BytesCopied, BytesToCopy, SrcSize; 131 PUCHAR SrcData; 132 133 NDIS_DbgPrint(MAX_TRACE, ("DstData 0x%X SrcBuffer 0x%X SrcOffset 0x%X Length %d\n",DstData,SrcBuffer, SrcOffset, Length)); 134 135 /* Skip SrcOffset bytes in the source buffer chain */ 136 if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == 0xFFFFFFFF) 137 return 0; 138 139 /* Start copying the data */ 140 BytesCopied = 0; 141 for (;;) { 142 BytesToCopy = MIN(SrcSize, Length); 143 144 NDIS_DbgPrint(MAX_TRACE, ("Copying (%d) bytes from 0x%X to 0x%X\n", BytesToCopy, SrcData, DstData)); 145 146 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy); 147 BytesCopied += BytesToCopy; 148 DstData = (PUCHAR)((ULONG_PTR) DstData + BytesToCopy); 149 150 Length -= BytesToCopy; 151 if (Length == 0) 152 break; 153 154 SrcSize -= BytesToCopy; 155 if (SrcSize == 0) { 156 /* No more bytes in source buffer. Proceed to 157 the next buffer in the source buffer chain */ 158 NdisGetNextBuffer(SrcBuffer, &SrcBuffer); 159 if (!SrcBuffer) 160 break; 161 162 NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize); 163 } 164 } 165 166 return BytesCopied; 167 } 168 169 170 UINT CopyPacketToBuffer( 171 PUCHAR DstData, 172 PNDIS_PACKET SrcPacket, 173 UINT SrcOffset, 174 UINT Length) 175 /* 176 * FUNCTION: Copies data from an NDIS packet to a buffer 177 * ARGUMENTS: 178 * DstData = Pointer to destination buffer 179 * SrcPacket = Pointer to source NDIS packet 180 * SrcOffset = Source start offset 181 * Length = Number of bytes to copy 182 * RETURNS: 183 * Number of bytes copied to destination buffer 184 * NOTES: 185 * The number of bytes copied may be limited by the source 186 * buffer size 187 */ 188 { 189 PNDIS_BUFFER FirstBuffer; 190 PVOID Address; 191 UINT FirstLength; 192 UINT TotalLength; 193 194 NDIS_DbgPrint(MAX_TRACE, ("DstData (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstData, SrcPacket, SrcOffset, Length)); 195 196 NdisGetFirstBufferFromPacket(SrcPacket, 197 &FirstBuffer, 198 &Address, 199 &FirstLength, 200 &TotalLength); 201 202 return CopyBufferChainToBuffer(DstData, FirstBuffer, SrcOffset, Length); 203 } 204 205 206 UINT CopyPacketToBufferChain( 207 PNDIS_BUFFER DstBuffer, 208 UINT DstOffset, 209 PNDIS_PACKET SrcPacket, 210 UINT SrcOffset, 211 UINT Length) 212 /* 213 * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain 214 * ARGUMENTS: 215 * DstBuffer = Pointer to destination NDIS buffer 216 * DstOffset = Destination start offset 217 * SrcPacket = Pointer to source NDIS packet 218 * SrcOffset = Source start offset 219 * Length = Number of bytes to copy 220 * RETURNS: 221 * Number of bytes copied to destination buffer 222 * NOTES: 223 * The number of bytes copied may be limited by the source and 224 * destination buffer sizes 225 */ 226 { 227 PNDIS_BUFFER SrcBuffer; 228 PUCHAR DstData, SrcData; 229 UINT DstSize, SrcSize; 230 UINT Count, Total; 231 232 NDIS_DbgPrint(MAX_TRACE, ("DstBuffer (0x%X) DstOffset (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcPacket, SrcOffset, Length)); 233 234 /* Skip DstOffset bytes in the destination buffer chain */ 235 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); 236 if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == 0xFFFFFFFF) 237 return 0; 238 /* Skip SrcOffset bytes in the source packet */ 239 NdisGetFirstBufferFromPacket(SrcPacket, &SrcBuffer, (PVOID*)&SrcData, &SrcSize, &Total); 240 if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == 0xFFFFFFFF) 241 return 0; 242 /* Copy the data */ 243 for (Total = 0;;) { 244 /* Find out how many bytes we can copy at one time */ 245 if (Length < SrcSize) 246 Count = Length; 247 else 248 Count = SrcSize; 249 if (DstSize < Count) 250 Count = DstSize; 251 252 RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count); 253 254 Total += Count; 255 Length -= Count; 256 if (Length == 0) 257 break; 258 259 DstSize -= Count; 260 if (DstSize == 0) { 261 /* No more bytes in destination buffer. Proceed to 262 the next buffer in the destination buffer chain */ 263 NdisGetNextBuffer(DstBuffer, &DstBuffer); 264 if (!DstBuffer) 265 break; 266 267 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); 268 } 269 270 SrcSize -= Count; 271 if (SrcSize == 0) { 272 /* No more bytes in source buffer. Proceed to 273 the next buffer in the source buffer chain */ 274 NdisGetNextBuffer(SrcBuffer, &SrcBuffer); 275 if (!SrcBuffer) 276 break; 277 278 NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize); 279 } 280 } 281 282 return Total; 283 } 284 285 286 /* 287 * @implemented 288 */ 289 #undef NdisAdjustBufferLength 290 VOID 291 EXPORT 292 NdisAdjustBufferLength( 293 IN PNDIS_BUFFER Buffer, 294 IN UINT Length) 295 /* 296 * FUNCTION: Modifies the length of an NDIS buffer 297 * ARGUMENTS: 298 * Buffer = Pointer to NDIS buffer descriptor 299 * Length = New size of buffer 300 */ 301 { 302 Buffer->ByteCount = Length; 303 } 304 305 306 /* 307 * @implemented 308 */ 309 #undef NDIS_BUFFER_TO_SPAN_PAGES 310 ULONG 311 EXPORT 312 NDIS_BUFFER_TO_SPAN_PAGES( 313 IN PNDIS_BUFFER Buffer) 314 /* 315 * FUNCTION: Determines how many physical pages a buffer is made of 316 * ARGUMENTS: 317 * Buffer = Pointer to NDIS buffer descriptor 318 */ 319 { 320 if (MmGetMdlByteCount(Buffer) == 0) 321 return 1; 322 323 return ADDRESS_AND_SIZE_TO_SPAN_PAGES( 324 MmGetMdlVirtualAddress(Buffer), 325 MmGetMdlByteCount(Buffer)); 326 } 327 328 329 /* 330 * @implemented 331 */ 332 VOID 333 EXPORT 334 NdisAllocateBuffer( 335 OUT PNDIS_STATUS Status, 336 OUT PNDIS_BUFFER * Buffer, 337 IN NDIS_HANDLE PoolHandle, 338 IN PVOID VirtualAddress, 339 IN UINT Length) 340 /* 341 * FUNCTION: Allocates an NDIS buffer descriptor 342 * ARGUMENTS: 343 * Status = Address of buffer for status 344 * Buffer = Address of buffer for NDIS buffer descriptor 345 * PoolHandle = Handle returned by NdisAllocateBufferPool 346 * VirtualAddress = Pointer to virtual address of data buffer 347 * Length = Number of bytes in data buffer 348 */ 349 { 350 ASSERT(VirtualAddress != NULL); 351 ASSERT(Length > 0); 352 353 *Buffer = IoAllocateMdl(VirtualAddress, Length, FALSE, FALSE, NULL); 354 if (*Buffer != NULL) { 355 MmBuildMdlForNonPagedPool(*Buffer); 356 (*Buffer)->Next = NULL; 357 *Status = NDIS_STATUS_SUCCESS; 358 } else { 359 NDIS_DbgPrint(MIN_TRACE, ("IoAllocateMdl failed (%x, %lx)\n", VirtualAddress, Length)); 360 *Status = NDIS_STATUS_FAILURE; 361 } 362 } 363 364 365 /* 366 * @implemented 367 */ 368 VOID 369 EXPORT 370 NdisAllocateBufferPool( 371 OUT PNDIS_STATUS Status, 372 OUT PNDIS_HANDLE PoolHandle, 373 IN UINT NumberOfDescriptors) 374 /* 375 * FUNCTION: Allocates storage for an NDIS buffer pool 376 * ARGUMENTS: 377 * Status = Address of buffer for status 378 * PoolHandle = Address of buffer for pool handle 379 * NumberOfDescriptors = Size of buffer pool in number of descriptors 380 */ 381 { 382 *Status = NDIS_STATUS_SUCCESS; 383 *PoolHandle = 0; 384 } 385 386 387 /* 388 * @implemented 389 */ 390 VOID 391 EXPORT 392 NdisAllocatePacket( 393 OUT PNDIS_STATUS Status, 394 OUT PNDIS_PACKET * Packet, 395 IN NDIS_HANDLE PoolHandle) 396 /* 397 * FUNCTION: Allocates an NDIS packet descriptor 398 * ARGUMENTS: 399 * Status = Address of buffer for status 400 * Packet = Address of buffer for packet descriptor 401 * PoolHandle = Handle returned by NdisAllocatePacketPool 402 */ 403 { 404 PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)PoolHandle; 405 406 KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &Pool->SpinLock.OldIrql); 407 NdisDprAllocatePacketNonInterlocked(Status, 408 Packet, 409 PoolHandle); 410 KeReleaseSpinLock(&Pool->SpinLock.SpinLock, Pool->SpinLock.OldIrql); 411 } 412 413 414 /* 415 * @implemented 416 */ 417 VOID 418 EXPORT 419 NdisAllocatePacketPool( 420 OUT PNDIS_STATUS Status, 421 OUT PNDIS_HANDLE PoolHandle, 422 IN UINT NumberOfDescriptors, 423 IN UINT ProtocolReservedLength) 424 /* 425 * FUNCTION: Allocates storage for an NDIS packet pool 426 * ARGUMENTS: 427 * Status = Address of buffer for status 428 * PoolHandle = Address of buffer for pool handle 429 * NumberOfDescriptors = Size of packet pool in number of descriptors 430 * ProtocolReservedLength = Size of protocol reserved area in bytes 431 */ 432 { 433 NdisAllocatePacketPoolEx( 434 Status, 435 PoolHandle, 436 NumberOfDescriptors, 437 0, 438 ProtocolReservedLength); 439 } 440 441 442 /* 443 * @implemented 444 */ 445 VOID 446 EXPORT 447 NdisAllocatePacketPoolEx( 448 OUT PNDIS_STATUS Status, 449 OUT PNDIS_HANDLE PoolHandle, 450 IN UINT NumberOfDescriptors, 451 IN UINT NumberOfOverflowDescriptors, 452 IN UINT ProtocolReservedLength) 453 /* 454 * FUNCTION: 455 * ARGUMENTS: 456 * NOTES: 457 * NDIS 5.0 458 */ 459 { 460 PNDISI_PACKET_POOL Pool; 461 UINT Size, Length, i; 462 PNDIS_PACKET Packet, NextPacket; 463 464 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) PoolHandle (0x%X) " 465 "NumberOfDescriptors (%d) ProtocolReservedLength (%d).\n", 466 Status, PoolHandle, NumberOfDescriptors, ProtocolReservedLength)); 467 468 *PoolHandle = NULL; 469 470 if (NumberOfDescriptors > 0xffff) 471 { 472 NDIS_DbgPrint(MIN_TRACE, ("Invalid number of descriptors (%lx)\n", NumberOfDescriptors)) 473 *Status = NDIS_STATUS_RESOURCES; 474 } 475 else 476 { 477 NumberOfDescriptors += NumberOfOverflowDescriptors; 478 if (NumberOfDescriptors > 0xffff) 479 { 480 NDIS_DbgPrint(MIN_TRACE, ("Total number of descriptors > 0xffff (%lx)\n", NumberOfDescriptors)); 481 NumberOfDescriptors = 0xffff; 482 } 483 484 Length = sizeof(NDIS_PACKET) + sizeof(NDIS_PACKET_OOB_DATA) + 485 sizeof(NDIS_PACKET_EXTENSION) + ProtocolReservedLength; 486 Size = sizeof(NDISI_PACKET_POOL) + Length * NumberOfDescriptors; 487 488 Pool = ExAllocatePool(NonPagedPool, Size); 489 if (Pool) 490 { 491 KeInitializeSpinLock(&Pool->SpinLock.SpinLock); 492 Pool->PacketLength = Length; 493 494 if (NumberOfDescriptors > 0) 495 { 496 Packet = (PNDIS_PACKET)&Pool->Buffer; 497 Pool->FreeList = Packet; 498 499 NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length); 500 for (i = 1; i < NumberOfDescriptors; i++) 501 { 502 Packet->Reserved[0] = (ULONG_PTR)NextPacket; 503 Packet = NextPacket; 504 NextPacket = (PNDIS_PACKET)((ULONG_PTR)Packet + Length); 505 } 506 Packet->Reserved[0] = 0; 507 } 508 else { 509 NDIS_DbgPrint(MIN_TRACE, ("Attempted to allocate a packet pool with 0 descriptors\n")); 510 Pool->FreeList = NULL; 511 } 512 513 *Status = NDIS_STATUS_SUCCESS; 514 *PoolHandle = (PNDIS_HANDLE)Pool; 515 } else { 516 *Status = NDIS_STATUS_RESOURCES; 517 } 518 } 519 } 520 521 522 /* 523 * @implemented 524 */ 525 #undef NdisBufferLength 526 ULONG 527 EXPORT 528 NdisBufferLength( 529 IN PNDIS_BUFFER Buffer) 530 /* 531 * FUNCTION: Modifies the length of an NDIS buffer 532 * ARGUMENTS: 533 * Buffer = Pointer to NDIS buffer descriptor 534 * Length = New size of buffer 535 * NOTES: 536 * NDIS 5.0 537 * RETURNS: 538 * Length of NDIS buffer 539 */ 540 { 541 return MmGetMdlByteCount(Buffer); 542 } 543 544 545 /* 546 * @implemented 547 */ 548 #undef NdisBufferVirtualAddress 549 PVOID 550 EXPORT 551 NdisBufferVirtualAddress( 552 IN PNDIS_BUFFER Buffer) 553 /* 554 * FUNCTION: 555 * ARGUMENTS: 556 * NOTES: 557 * NDIS 5.0 558 */ 559 { 560 return MmGetSystemAddressForMdl(Buffer); 561 } 562 563 564 /* 565 * @implemented 566 */ 567 VOID 568 EXPORT 569 NdisCopyFromPacketToPacket( 570 IN PNDIS_PACKET Destination, 571 IN UINT DestinationOffset, 572 IN UINT BytesToCopy, 573 IN PNDIS_PACKET Source, 574 IN UINT SourceOffset, 575 OUT PUINT BytesCopied) 576 /* 577 * FUNCTION: Copies data from one packet to another 578 * ARGUMENTS: 579 * Destination = Pointer to packet to copy data to 580 * DestinationOffset = Offset in destination packet to copy data to 581 * BytesToCopy = Number of bytes to copy 582 * Source = Pointer to packet descriptor to copy from 583 * SourceOffset = Offset in source packet to start copying from 584 * BytesCopied = Address of buffer to place number of bytes copied 585 */ 586 { 587 PNDIS_BUFFER SrcBuffer; 588 PNDIS_BUFFER DstBuffer; 589 PUCHAR DstData, SrcData; 590 UINT DstSize, SrcSize; 591 UINT Count, Total; 592 593 *BytesCopied = 0; 594 595 /* Skip DestinationOffset bytes in the destination packet */ 596 NdisGetFirstBufferFromPacket(Destination, &DstBuffer, (PVOID*)&DstData, &DstSize, &Total); 597 if (SkipToOffset(DstBuffer, DestinationOffset, &DstData, &DstSize) == 0xFFFFFFFF) 598 return; 599 600 /* Skip SourceOffset bytes in the source packet */ 601 NdisGetFirstBufferFromPacket(Source, &SrcBuffer, (PVOID*)&SrcData, &SrcSize, &Total); 602 if (SkipToOffset(SrcBuffer, SourceOffset, &SrcData, &SrcSize) == 0xFFFFFFFF) 603 return; 604 605 /* Copy the data */ 606 for (Total = 0;;) { 607 /* Find out how many bytes we can copy at one time */ 608 if (BytesToCopy < SrcSize) 609 Count = BytesToCopy; 610 else 611 Count = SrcSize; 612 if (DstSize < Count) 613 Count = DstSize; 614 615 RtlCopyMemory(DstData, SrcData, Count); 616 617 Total += Count; 618 BytesToCopy -= Count; 619 if (BytesToCopy == 0) 620 break; 621 622 DstSize -= Count; 623 if (DstSize == 0) { 624 /* No more bytes in destination buffer. Proceed to 625 the next buffer in the destination buffer chain */ 626 NdisGetNextBuffer(DstBuffer, &DstBuffer); 627 if (!DstBuffer) 628 break; 629 630 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); 631 } 632 633 SrcSize -= Count; 634 if (SrcSize == 0) { 635 /* No more bytes in source buffer. Proceed to 636 the next buffer in the source buffer chain */ 637 NdisGetNextBuffer(SrcBuffer, &SrcBuffer); 638 if (!SrcBuffer) 639 break; 640 641 NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize); 642 } 643 } 644 645 *BytesCopied = Total; 646 } 647 648 649 /* 650 * @implemented 651 */ 652 VOID 653 EXPORT 654 NdisDprAllocatePacket( 655 OUT PNDIS_STATUS Status, 656 OUT PNDIS_PACKET *Packet, 657 IN NDIS_HANDLE PoolHandle) 658 /* 659 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL 660 * ARGUMENTS: 661 * Status = Address of buffer to place status of operation 662 * Packet = Address of buffer to place a pointer to a packet descriptor 663 * PoolHandle = Handle returned by NdisAllocatePacketPool 664 */ 665 { 666 PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)PoolHandle; 667 668 KeAcquireSpinLockAtDpcLevel(&Pool->SpinLock.SpinLock); 669 NdisDprAllocatePacketNonInterlocked(Status, 670 Packet, 671 PoolHandle); 672 KeReleaseSpinLockFromDpcLevel(&Pool->SpinLock.SpinLock); 673 } 674 675 676 /* 677 * @implemented 678 */ 679 VOID 680 EXPORT 681 NdisDprAllocatePacketNonInterlocked( 682 OUT PNDIS_STATUS Status, 683 OUT PNDIS_PACKET *Packet, 684 IN NDIS_HANDLE PoolHandle) 685 /* 686 * FUNCTION: Allocates a packet at IRQL DISPATCH_LEVEL (w/o synchronization) 687 * ARGUMENTS: 688 * Status = Address of buffer to place status of operation 689 * Packet = Address of buffer to place a pointer to a packet descriptor 690 * PoolHandle = Handle returned by NdisAllocatePacketPool 691 */ 692 { 693 PNDIS_PACKET Temp; 694 PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)PoolHandle; 695 696 NDIS_DbgPrint(MAX_TRACE, ("Status (0x%X) Packet (0x%X) PoolHandle (0x%X).\n", 697 Status, Packet, PoolHandle)); 698 699 *Packet = NULL; 700 701 if (Pool == NULL) 702 { 703 *Status = NDIS_STATUS_FAILURE; 704 NDIS_DbgPrint(MIN_TRACE, ("Called passed a bad pool handle\n")); 705 return; 706 } 707 708 if (Pool->FreeList) { 709 Temp = Pool->FreeList; 710 Pool->FreeList = (PNDIS_PACKET)Temp->Reserved[0]; 711 712 RtlZeroMemory(Temp, Pool->PacketLength); 713 Temp->Private.Pool = Pool; 714 Temp->Private.ValidCounts = TRUE; 715 Temp->Private.NdisPacketFlags = fPACKET_ALLOCATED_BY_NDIS; 716 Temp->Private.NdisPacketOobOffset = Pool->PacketLength - 717 (sizeof(NDIS_PACKET_OOB_DATA) + 718 sizeof(NDIS_PACKET_EXTENSION)); 719 720 *Packet = Temp; 721 *Status = NDIS_STATUS_SUCCESS; 722 } else { 723 NDIS_DbgPrint(MIN_TRACE, ("No more free descriptors\n")); 724 *Status = NDIS_STATUS_RESOURCES; 725 } 726 } 727 728 729 /* 730 * @implemented 731 */ 732 VOID 733 EXPORT 734 NdisDprFreePacket( 735 IN PNDIS_PACKET Packet) 736 /* 737 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL 738 * ARGUMENTS: 739 * Packet = Pointer to packet to free 740 */ 741 { 742 PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)Packet->Private.Pool; 743 744 KeAcquireSpinLockAtDpcLevel(&Pool->SpinLock.SpinLock); 745 NdisDprFreePacketNonInterlocked(Packet); 746 KeReleaseSpinLockFromDpcLevel(&Pool->SpinLock.SpinLock); 747 } 748 749 750 /* 751 * @implemented 752 */ 753 VOID 754 EXPORT 755 NdisDprFreePacketNonInterlocked( 756 IN PNDIS_PACKET Packet) 757 /* 758 * FUNCTION: Frees a packet at IRQL DISPATCH_LEVEL (w/o synchronization) 759 * ARGUMENTS: 760 * Packet = Pointer to packet to free 761 */ 762 { 763 NDIS_DbgPrint(MAX_TRACE, ("Packet (0x%X).\n", Packet)); 764 765 Packet->Reserved[0] = (ULONG_PTR)((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList; 766 ((NDISI_PACKET_POOL*)Packet->Private.Pool)->FreeList = Packet; 767 } 768 769 770 /* 771 * @implemented 772 */ 773 VOID 774 EXPORT 775 NdisFreeBufferPool( 776 IN NDIS_HANDLE PoolHandle) 777 /* 778 * FUNCTION: Frees storage allocated for an NDIS buffer pool 779 * ARGUMENTS: 780 * PoolHandle = Handle returned by NdisAllocateBufferPool 781 */ 782 { 783 } 784 785 786 /* 787 * @implemented 788 */ 789 VOID 790 EXPORT 791 NdisFreePacketPool( 792 IN NDIS_HANDLE PoolHandle) 793 /* 794 * FUNCTION: Frees storage allocated for an NDIS packet pool 795 * ARGUMENTS: 796 * PoolHandle = Handle returned by NdisAllocatePacketPool 797 */ 798 { 799 ExFreePool((PVOID)PoolHandle); 800 } 801 802 803 /* 804 * @implemented 805 */ 806 #undef NdisFreeBuffer 807 VOID 808 EXPORT 809 NdisFreeBuffer( 810 IN PNDIS_BUFFER Buffer) 811 /* 812 * FUNCTION: Puts an NDIS buffer descriptor back in it's pool 813 * ARGUMENTS: 814 * Buffer = Pointer to buffer descriptor 815 */ 816 { 817 IoFreeMdl(Buffer); 818 } 819 820 821 /* 822 * @implemented 823 */ 824 VOID 825 EXPORT 826 NdisFreePacket( 827 IN PNDIS_PACKET Packet) 828 /* 829 * FUNCTION: Puts an NDIS packet descriptor back in it's pool 830 * ARGUMENTS: 831 * Packet = Pointer to packet descriptor 832 */ 833 { 834 PNDISI_PACKET_POOL Pool = (PNDISI_PACKET_POOL)Packet->Private.Pool; 835 836 KeAcquireSpinLock(&Pool->SpinLock.SpinLock, &Pool->SpinLock.OldIrql); 837 NdisDprFreePacketNonInterlocked(Packet); 838 KeReleaseSpinLock(&Pool->SpinLock.SpinLock, Pool->SpinLock.OldIrql); 839 } 840 841 842 /* 843 * @implemented 844 */ 845 #undef NdisGetBufferPhysicalArraySize 846 VOID 847 EXPORT 848 NdisGetBufferPhysicalArraySize( 849 IN PNDIS_BUFFER Buffer, 850 OUT PUINT ArraySize) 851 /* 852 * FUNCTION: Returns number of discontiguous physical blocks backing a buffer 853 * ARGUMENTS: 854 * Buffer = Pointer to buffer descriptor 855 * ArraySize = Address of buffer to place number of physical blocks 856 */ 857 { 858 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 859 ASSERT(Buffer && ArraySize); 860 861 *ArraySize = NDIS_BUFFER_TO_SPAN_PAGES(Buffer); 862 } 863 864 865 /* 866 * @implemented 867 */ 868 #undef NdisGetFirstBufferFromPacket 869 VOID 870 EXPORT 871 NdisGetFirstBufferFromPacket( 872 IN PNDIS_PACKET _Packet, 873 OUT PNDIS_BUFFER *_FirstBuffer, 874 OUT PVOID *_FirstBufferVA, 875 OUT PUINT _FirstBufferLength, 876 OUT PUINT _TotalBufferLength) 877 /* 878 * FUNCTION: Retrieves information about an NDIS packet 879 * ARGUMENTS: 880 * _Packet = Pointer to NDIS packet 881 * _FirstBuffer = Address of buffer for pointer to first NDIS buffer 882 * _FirstBufferVA = Address of buffer for address of first NDIS buffer 883 * _FirstBufferLength = Address of buffer for length of first buffer 884 * _TotalBufferLength = Address of buffer for total length of packet 885 */ 886 { 887 PNDIS_BUFFER Buffer; 888 889 Buffer = _Packet->Private.Head; 890 *_FirstBuffer = Buffer; 891 892 if (Buffer != NULL) { 893 *_FirstBufferLength = MmGetMdlByteCount(Buffer); 894 *_FirstBufferVA = MmGetSystemAddressForMdl(Buffer); 895 Buffer = Buffer->Next; 896 } else { 897 NDIS_DbgPrint(MID_TRACE, ("No buffers linked to this packet\n")); 898 *_FirstBufferLength = 0; 899 *_FirstBufferVA = NULL; 900 } 901 902 *_TotalBufferLength = *_FirstBufferLength; 903 904 while (Buffer != NULL) { 905 *_TotalBufferLength += MmGetMdlByteCount(Buffer); 906 Buffer = Buffer->Next; 907 } 908 } 909 910 #undef NdisGetFirstBufferFromPacketSafe 911 /* 912 * @implemented 913 */ 914 VOID 915 EXPORT 916 NdisGetFirstBufferFromPacketSafe( 917 IN PNDIS_PACKET _Packet, 918 OUT PNDIS_BUFFER *_FirstBuffer, 919 OUT PVOID *_FirstBufferVA, 920 OUT PUINT _FirstBufferLength, 921 OUT PUINT _TotalBufferLength, 922 IN MM_PAGE_PRIORITY Priority) 923 { 924 PNDIS_BUFFER Buffer; 925 926 Buffer = _Packet->Private.Head; 927 *_FirstBuffer = Buffer; 928 929 if (Buffer != NULL) { 930 *_FirstBufferLength = MmGetMdlByteCount(Buffer); 931 *_FirstBufferVA = MmGetSystemAddressForMdlSafe(Buffer, Priority); 932 Buffer = Buffer->Next; 933 } else { 934 NDIS_DbgPrint(MID_TRACE, ("No buffers linked to this packet\n")); 935 *_FirstBufferLength = 0; 936 *_FirstBufferVA = NULL; 937 } 938 939 *_TotalBufferLength = *_FirstBufferLength; 940 941 while (Buffer != NULL) { 942 *_TotalBufferLength += MmGetMdlByteCount(Buffer); 943 Buffer = Buffer->Next; 944 } 945 } 946 947 /* 948 * @implemented 949 */ 950 #undef NdisQueryBuffer 951 VOID 952 EXPORT 953 NdisQueryBuffer( 954 IN PNDIS_BUFFER Buffer, 955 OUT PVOID *VirtualAddress OPTIONAL, 956 OUT PUINT Length) 957 /* 958 * FUNCTION: 959 * Queries an NDIS buffer for information 960 * ARGUMENTS: 961 * Buffer = Pointer to NDIS buffer to query 962 * VirtualAddress = Address of buffer to place virtual address 963 * Length = Address of buffer to place length of buffer 964 */ 965 { 966 if (VirtualAddress != NULL) 967 *(PVOID*)VirtualAddress = MmGetSystemAddressForMdl(Buffer); 968 969 *Length = MmGetMdlByteCount(Buffer); 970 } 971 972 973 /* 974 * @implemented 975 */ 976 #undef NdisQueryBufferSafe 977 VOID 978 EXPORT 979 NdisQueryBufferSafe( 980 IN PNDIS_BUFFER Buffer, 981 OUT PVOID *VirtualAddress OPTIONAL, 982 OUT PUINT Length, 983 IN UINT Priority) 984 /* 985 * FUNCTION: 986 * ARGUMENTS: 987 * NOTES: 988 * NDIS 5.0 989 */ 990 { 991 if (VirtualAddress != NULL) 992 *VirtualAddress = MmGetSystemAddressForMdlSafe(Buffer, Priority); 993 *Length = MmGetMdlByteCount(Buffer); 994 } 995 996 997 /* 998 * @implemented 999 */ 1000 #undef NdisQueryBufferOffset 1001 VOID 1002 EXPORT 1003 NdisQueryBufferOffset( 1004 IN PNDIS_BUFFER Buffer, 1005 OUT PUINT Offset, 1006 OUT PUINT Length) 1007 { 1008 *((PUINT)Offset) = MmGetMdlByteOffset(Buffer); 1009 *((PUINT)Length) = MmGetMdlByteCount(Buffer); 1010 } 1011 1012 1013 /* 1014 * @implemented 1015 */ 1016 VOID 1017 EXPORT 1018 NdisUnchainBufferAtBack( 1019 IN OUT PNDIS_PACKET Packet, 1020 OUT PNDIS_BUFFER *Buffer) 1021 /* 1022 * FUNCTION: 1023 * Removes the last buffer in a packet 1024 * ARGUMENTS: 1025 * Packet = Pointer to NDIS packet 1026 * Buffer = Address of buffer to place pointer to removed NDIS buffer 1027 */ 1028 { 1029 PNDIS_BUFFER NdisBuffer, Previous; 1030 1031 NdisQueryPacket(Packet, 1032 NULL, 1033 NULL, 1034 &NdisBuffer, 1035 NULL); 1036 if (!NdisBuffer) { 1037 NDIS_DbgPrint(MID_TRACE, ("No buffer to unchain\n")); 1038 *Buffer = NULL; 1039 return; 1040 } 1041 1042 Previous = NULL; 1043 while (NdisBuffer->Next) { 1044 Previous = NdisBuffer; 1045 NdisBuffer = NdisBuffer->Next; 1046 } 1047 1048 if (Previous) { 1049 Previous->Next = NULL; 1050 Packet->Private.Tail = Previous; 1051 } else { 1052 Packet->Private.Head = NULL; 1053 Packet->Private.Tail = NULL; 1054 } 1055 1056 Packet->Private.ValidCounts = FALSE; 1057 1058 *Buffer = NdisBuffer; 1059 } 1060 1061 1062 /* 1063 * @implemented 1064 */ 1065 VOID 1066 EXPORT 1067 NdisUnchainBufferAtFront( 1068 IN OUT PNDIS_PACKET Packet, 1069 OUT PNDIS_BUFFER *Buffer) 1070 /* 1071 * FUNCTION: 1072 * Removes the first buffer in a packet 1073 * ARGUMENTS: 1074 * Packet = Pointer to NDIS packet 1075 * Buffer = Address of buffer to place pointer to removed NDIS buffer 1076 */ 1077 { 1078 PNDIS_BUFFER NdisBuffer; 1079 1080 NdisQueryPacket(Packet, 1081 NULL, 1082 NULL, 1083 &NdisBuffer, 1084 NULL); 1085 if (!NdisBuffer) { 1086 NDIS_DbgPrint(MID_TRACE, ("No buffer to unchain\n")); 1087 *Buffer = NULL; 1088 return; 1089 } 1090 1091 Packet->Private.Head = NdisBuffer->Next; 1092 1093 if (!NdisBuffer->Next) 1094 Packet->Private.Tail = NULL; 1095 1096 NdisBuffer->Next = NULL; 1097 1098 Packet->Private.ValidCounts = FALSE; 1099 1100 *Buffer = NdisBuffer; 1101 } 1102 1103 /* 1104 * @implemented 1105 */ 1106 VOID 1107 EXPORT 1108 NdisCopyBuffer( 1109 OUT PNDIS_STATUS Status, 1110 OUT PNDIS_BUFFER *Buffer, 1111 IN NDIS_HANDLE PoolHandle, 1112 IN PVOID MemoryDescriptor, 1113 IN UINT Offset, 1114 IN UINT Length) 1115 /* 1116 * FUNCTION: Returns a new buffer descriptor for a (partial) buffer 1117 * ARGUMENTS: 1118 * Status = Address of a buffer to place status of operation 1119 * Buffer = Address of a buffer to place new buffer descriptor 1120 * PoolHandle = Handle returned by NdisAllocateBufferPool 1121 * MemoryDescriptor = Pointer to a memory descriptor (possibly NDIS_BUFFER) 1122 * Offset = Offset in buffer to start copying 1123 * Length = Number of bytes to copy 1124 */ 1125 { 1126 PVOID CurrentVa = (PUCHAR)(MmGetMdlVirtualAddress((PNDIS_BUFFER)MemoryDescriptor)) + Offset; 1127 1128 NDIS_DbgPrint(MAX_TRACE, ("Called\n")); 1129 1130 *Buffer = IoAllocateMdl(CurrentVa, Length, FALSE, FALSE, NULL); 1131 if (!*Buffer) 1132 { 1133 NDIS_DbgPrint(MIN_TRACE, ("IoAllocateMdl failed (%x, %lx)\n", CurrentVa, Length)); 1134 *Status = NDIS_STATUS_FAILURE; 1135 return; 1136 } 1137 1138 IoBuildPartialMdl((PNDIS_BUFFER)MemoryDescriptor, 1139 *Buffer, 1140 CurrentVa, 1141 Length); 1142 1143 (*Buffer)->Next = NULL; 1144 *Status = NDIS_STATUS_SUCCESS; 1145 } 1146 1147 /* 1148 * @implemented 1149 */ 1150 NDIS_HANDLE 1151 EXPORT 1152 NdisGetPoolFromPacket( 1153 IN PNDIS_PACKET Packet) 1154 { 1155 return Packet->Private.Pool; 1156 } 1157 1158 /* 1159 * @implemented 1160 */ 1161 UINT 1162 EXPORT 1163 NdisPacketSize( 1164 IN UINT ProtocolReservedSize) 1165 { 1166 return sizeof(NDIS_PACKET) + sizeof(NDIS_PACKET_OOB_DATA) + 1167 sizeof(NDIS_PACKET_EXTENSION) + ProtocolReservedSize; 1168 } 1169 1170 /* 1171 * @implemented 1172 */ 1173 #undef NdisGetPacketCancelId 1174 PVOID 1175 EXPORT 1176 NdisGetPacketCancelId( 1177 IN PNDIS_PACKET Packet) 1178 { 1179 return NDIS_GET_PACKET_CANCEL_ID(Packet); 1180 } 1181 1182 /* 1183 * @implemented 1184 */ 1185 #undef NdisSetPacketCancelId 1186 VOID 1187 EXPORT 1188 NdisSetPacketCancelId( 1189 IN PNDIS_PACKET Packet, 1190 IN PVOID CancelId) 1191 { 1192 NDIS_SET_PACKET_CANCEL_ID(Packet, CancelId); 1193 } 1194 1195 /* 1196 * @implemented 1197 */ 1198 VOID 1199 EXPORT 1200 NdisCopyFromPacketToPacketSafe( 1201 IN PNDIS_PACKET Destination, 1202 IN UINT DestinationOffset, 1203 IN UINT BytesToCopy, 1204 IN PNDIS_PACKET Source, 1205 IN UINT SourceOffset, 1206 OUT PUINT BytesCopied, 1207 IN MM_PAGE_PRIORITY Priority) 1208 { 1209 PNDIS_BUFFER SrcBuffer; 1210 PNDIS_BUFFER DstBuffer; 1211 PUCHAR DstData, SrcData; 1212 UINT DstSize, SrcSize; 1213 UINT Count, Total; 1214 1215 *BytesCopied = 0; 1216 1217 /* Skip DestinationOffset bytes in the destination packet */ 1218 NdisGetFirstBufferFromPacketSafe(Destination, &DstBuffer, (PVOID*)&DstData, &DstSize, &Total, Priority); 1219 if (!DstData || SkipToOffset(DstBuffer, DestinationOffset, &DstData, &DstSize) == 0xFFFFFFFF) 1220 return; 1221 1222 /* Skip SourceOffset bytes in the source packet */ 1223 NdisGetFirstBufferFromPacketSafe(Source, &SrcBuffer, (PVOID*)&SrcData, &SrcSize, &Total, Priority); 1224 if (!SrcData || SkipToOffset(SrcBuffer, SourceOffset, &SrcData, &SrcSize) == 0xFFFFFFFF) 1225 return; 1226 1227 /* Copy the data */ 1228 for (Total = 0;;) { 1229 /* Find out how many bytes we can copy at one time */ 1230 if (BytesToCopy < SrcSize) 1231 Count = BytesToCopy; 1232 else 1233 Count = SrcSize; 1234 if (DstSize < Count) 1235 Count = DstSize; 1236 1237 RtlCopyMemory(DstData, SrcData, Count); 1238 1239 Total += Count; 1240 BytesToCopy -= Count; 1241 if (BytesToCopy == 0) 1242 break; 1243 1244 DstSize -= Count; 1245 if (DstSize == 0) { 1246 /* No more bytes in destination buffer. Proceed to 1247 the next buffer in the destination buffer chain */ 1248 NdisGetNextBuffer(DstBuffer, &DstBuffer); 1249 if (!DstBuffer) 1250 break; 1251 1252 NdisQueryBufferSafe(DstBuffer, (PVOID)&DstData, &DstSize, Priority); 1253 if (!DstData) 1254 break; 1255 } 1256 1257 SrcSize -= Count; 1258 if (SrcSize == 0) { 1259 /* No more bytes in source buffer. Proceed to 1260 the next buffer in the source buffer chain */ 1261 NdisGetNextBuffer(SrcBuffer, &SrcBuffer); 1262 if (!SrcBuffer) 1263 break; 1264 1265 NdisQueryBufferSafe(SrcBuffer, (PVOID)&SrcData, &SrcSize, Priority); 1266 if (!SrcData) 1267 break; 1268 } 1269 } 1270 1271 *BytesCopied = Total; 1272 } 1273 1274 /* 1275 * @implemented 1276 */ 1277 VOID 1278 EXPORT 1279 NdisIMCopySendCompletePerPacketInfo( 1280 IN PNDIS_PACKET DstPacket, 1281 IN PNDIS_PACKET SrcPacket) 1282 /* 1283 * FUNCTION: 1284 * ARGUMENTS: 1285 * NOTES: 1286 * NDIS 5.0 1287 */ 1288 { 1289 /* FIXME: What is the difference between NdisIMCopySendPerPacketInfo and 1290 * NdisIMCopySendCompletePerPacketInfo? 1291 */ 1292 1293 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 1294 1295 RtlCopyMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(DstPacket), 1296 NDIS_PACKET_EXTENSION_FROM_PACKET(SrcPacket), 1297 sizeof(NDIS_PACKET_EXTENSION)); 1298 } 1299 1300 1301 /* 1302 * @implemented 1303 */ 1304 VOID 1305 EXPORT 1306 NdisIMCopySendPerPacketInfo( 1307 IN PNDIS_PACKET DstPacket, 1308 IN PNDIS_PACKET SrcPacket) 1309 /* 1310 * FUNCTION: 1311 * ARGUMENTS: 1312 * NOTES: 1313 * NDIS 5.0 1314 */ 1315 { 1316 /* FIXME: What is the difference between NdisIMCopySendPerPacketInfo and 1317 * NdisIMCopySendCompletePerPacketInfo? 1318 */ 1319 1320 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 1321 1322 RtlCopyMemory(NDIS_PACKET_EXTENSION_FROM_PACKET(DstPacket), 1323 NDIS_PACKET_EXTENSION_FROM_PACKET(SrcPacket), 1324 sizeof(NDIS_PACKET_EXTENSION)); 1325 } 1326 1327 /* EOF */ 1328