Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3413 lines
87 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. common.c
  5. Abstract:
  6. NDIS wrapper functions common to miniports and full mac drivers
  7. Author:
  8. Adam Barr (adamba) 11-Jul-1990
  9. Environment:
  10. Kernel mode, FSD
  11. Revision History:
  12. 26-Feb-1991 JohnsonA Added Debugging Code
  13. 10-Jul-1991 JohnsonA Implement revised Ndis Specs
  14. 01-Jun-1995 JameelH Re-organization/optimization
  15. 09-Apr-1996 KyleB Added resource remove and acquisition routines.
  16. --*/
  17. #include <precomp.h>
  18. #pragma hdrstop
  19. #include <stdarg.h>
  20. //
  21. // Define the module number for debug code.
  22. //
  23. #define MODULE_NUMBER MODULE_COMMON
  24. //
  25. // Routines for dealing with making the PKG specific routines pagable
  26. //
  27. VOID FASTCALL
  28. ndisInitializePackage(
  29. IN PPKG_REF pPkg
  30. )
  31. {
  32. //
  33. // Lock and unlock the section to obtain the handle. Subsequent locks will be faster
  34. //
  35. pPkg->ImageHandle = MmLockPagableCodeSection(pPkg->Address);
  36. MmUnlockPagableImageSection(pPkg->ImageHandle);
  37. }
  38. VOID FASTCALL
  39. ndisReferencePackage(
  40. IN PPKG_REF pPkg
  41. )
  42. {
  43. ASSERT(CURRENT_IRQL < DISPATCH_LEVEL);
  44. MmLockPagableSectionByHandle(pPkg->ImageHandle);
  45. NdisInterlockedIncrement(&pPkg->ReferenceCount);
  46. }
  47. VOID FASTCALL
  48. ndisDereferencePackage(
  49. IN PPKG_REF pPkg
  50. )
  51. {
  52. ASSERT(CURRENT_IRQL < DISPATCH_LEVEL);
  53. MmUnlockPagableImageSection(pPkg->ImageHandle);
  54. NdisInterlockedDecrement(&pPkg->ReferenceCount);
  55. }
  56. NDIS_STATUS
  57. NdisAllocateMemory(
  58. OUT PVOID * VirtualAddress,
  59. IN UINT Length,
  60. IN UINT MemoryFlags,
  61. IN NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress
  62. )
  63. /*++
  64. Routine Description:
  65. Allocate memory for use by a protocol or a MAC driver
  66. Arguments:
  67. VirtualAddress - Returns a pointer to the allocated memory.
  68. Length - Size of requested allocation in bytes.
  69. MaximumPhysicalAddress - Highest addressable address of the allocated
  70. memory.. 0 means highest system memory possible.
  71. MemoryFlags - Bit mask that allows the caller to specify attributes
  72. of the allocated memory. 0 means standard memory.
  73. other options:
  74. NDIS_MEMORY_CONTIGUOUS
  75. NDIS_MEMORY_NONCACHED
  76. Return Value:
  77. NDIS_STATUS_SUCCESS if successful.
  78. NDIS_STATUS_FAILURE if not successful. *VirtualAddress will be NULL.
  79. --*/
  80. {
  81. //
  82. // Depending on the value of MemoryFlags, we allocate three different
  83. // types of memory.
  84. //
  85. if (MemoryFlags == 0)
  86. {
  87. *VirtualAddress = ALLOC_FROM_POOL(Length, NDIS_TAG_ALLOC_MEM);
  88. }
  89. else if (MemoryFlags & NDIS_MEMORY_NONCACHED)
  90. {
  91. *VirtualAddress = MmAllocateNonCachedMemory(Length);
  92. }
  93. else if (MemoryFlags & NDIS_MEMORY_CONTIGUOUS)
  94. {
  95. *VirtualAddress = MmAllocateContiguousMemory(Length, HighestAcceptableAddress);
  96. }
  97. else
  98. {
  99. //
  100. // invalid flags
  101. //
  102. *VirtualAddress = NULL;
  103. }
  104. return (*VirtualAddress == NULL) ? NDIS_STATUS_FAILURE : NDIS_STATUS_SUCCESS;
  105. }
  106. NDIS_STATUS
  107. NdisAllocateMemoryWithTag(
  108. OUT PVOID * VirtualAddress,
  109. IN UINT Length,
  110. IN ULONG Tag
  111. )
  112. /*++
  113. Routine Description:
  114. Allocate memory for use by a protocol or a MAC driver
  115. Arguments:
  116. VirtualAddress - Returns a pointer to the allocated memory.
  117. Length - Size of requested allocation in bytes.
  118. Tag - tag to associate with this memory.
  119. Return Value:
  120. NDIS_STATUS_SUCCESS if successful.
  121. NDIS_STATUS_FAILURE if not successful. *VirtualAddress will be NULL.
  122. --*/
  123. {
  124. *VirtualAddress = ALLOC_FROM_POOL(Length, Tag);
  125. return (*VirtualAddress == NULL) ? NDIS_STATUS_FAILURE : NDIS_STATUS_SUCCESS;
  126. }
  127. VOID
  128. NdisFreeMemory(
  129. IN PVOID VirtualAddress,
  130. IN UINT Length,
  131. IN UINT MemoryFlags
  132. )
  133. /*++
  134. Routine Description:
  135. Releases memory allocated using NdisAllocateMemory.
  136. Arguments:
  137. VirtualAddress - Pointer to the memory to be freed.
  138. Length - Size of allocation in bytes.
  139. MemoryFlags - Bit mask that allows the caller to specify attributes
  140. of the allocated memory. 0 means standard memory.
  141. other options:
  142. NDIS_MEMORY_CONTIGUOUS
  143. NDIS_MEMORY_NONCACHED
  144. Return Value:
  145. None.
  146. --*/
  147. {
  148. //
  149. // Depending on the value of MemoryFlags, we allocate three free 3
  150. // types of memory.
  151. //
  152. if (MemoryFlags == 0)
  153. {
  154. FREE_POOL(VirtualAddress);
  155. }
  156. else if (MemoryFlags & NDIS_MEMORY_NONCACHED)
  157. {
  158. MmFreeNonCachedMemory(VirtualAddress, Length);
  159. }
  160. else if (MemoryFlags & NDIS_MEMORY_CONTIGUOUS)
  161. {
  162. MmFreeContiguousMemory(VirtualAddress);
  163. }
  164. }
  165. UINT
  166. NdisPacketSize(
  167. IN UINT ProtocolReservedSize
  168. )
  169. /*++
  170. Routine Description:
  171. Returns the size of the packet given the amount of protocolreserved. This lets the caller
  172. do a better job with # of packets it allocates in a single pool.
  173. Arguments:
  174. ProtocolReservedSize - Size of protocol reserved in bytes
  175. Return Value:
  176. None.
  177. --*/
  178. {
  179. UINT PacketLength;
  180. PacketLength = SIZE_PACKET_STACKS + sizeof(NDIS_PACKET_OOB_DATA) + sizeof(NDIS_PACKET_EXTENSION);
  181. PacketLength += ((FIELD_OFFSET(NDIS_PACKET, ProtocolReserved) + ProtocolReservedSize + sizeof(ULONGLONG) - 1) & ~(sizeof(ULONGLONG) -1));
  182. //
  183. // Round the entire length up to a memory allocation alignment.
  184. //
  185. PacketLength = (PacketLength + MEMORY_ALLOCATION_ALIGNMENT - 1) & ~(MEMORY_ALLOCATION_ALIGNMENT - 1);
  186. return(PacketLength);
  187. }
  188. NDIS_HANDLE
  189. NdisGetPoolFromPacket(
  190. IN PNDIS_PACKET Packet
  191. )
  192. /*++
  193. Routine Description:
  194. Arguments:
  195. Packet - Packet in question
  196. Return Value:
  197. Pool handle corresponding to the packet
  198. --*/
  199. {
  200. PNDIS_PKT_POOL Pool = (PNDIS_PKT_POOL)Packet->Private.Pool;
  201. return(Pool);
  202. }
  203. PNDIS_PACKET_STACK
  204. NdisIMGetCurrentPacketStack(
  205. IN PNDIS_PACKET Packet,
  206. OUT BOOLEAN * StacksRemaining
  207. )
  208. /*++
  209. Routine Description:
  210. Arguments:
  211. Packet - Packet in question
  212. Return Value:
  213. Pointer to the new stack location or NULL if we are out of stacks
  214. --*/
  215. {
  216. PNDIS_PACKET_STACK pStack;
  217. GET_CURRENT_PACKET_STACK_X(Packet, &pStack, StacksRemaining);
  218. return(pStack);
  219. }
  220. VOID
  221. NdisAllocatePacketPool(
  222. OUT PNDIS_STATUS Status,
  223. OUT PNDIS_HANDLE PoolHandle,
  224. IN UINT NumberOfDescriptors,
  225. IN UINT ProtocolReservedLength
  226. )
  227. /*++
  228. Routine Description:
  229. See ndisAllocPacketPool.
  230. Arguments:
  231. Status - Returns the final status (always NDIS_STATUS_SUCCESS).
  232. PoolHandle - Returns a pointer to the pool.
  233. NumberOfDescriptors - Number of packet descriptors needed.
  234. ProtocolReservedLength - How long the ProtocolReserved field
  235. should be for packets in this pool.
  236. Return Value:
  237. None.
  238. --*/
  239. {
  240. PVOID Caller, CallersCaller;
  241. //
  242. // We save the address of the caller in the pool header, for debugging.
  243. //
  244. RtlGetCallersAddress(&Caller, &CallersCaller);
  245. NdisAllocatePacketPoolEx(Status,
  246. PoolHandle,
  247. NumberOfDescriptors,
  248. 0,
  249. ProtocolReservedLength);
  250. if (*Status == NDIS_STATUS_SUCCESS)
  251. {
  252. PNDIS_PKT_POOL Pool = *PoolHandle;
  253. Pool->Allocator = Caller;
  254. }
  255. }
  256. VOID
  257. NdisAllocatePacketPoolEx(
  258. OUT PNDIS_STATUS Status,
  259. OUT PNDIS_HANDLE PoolHandle,
  260. IN UINT NumberOfDescriptors,
  261. IN UINT NumberOfOverflowDescriptors,
  262. IN UINT ProtocolReservedLength
  263. )
  264. /*++
  265. Routine Description:
  266. Initializes a packet pool. All packets are the same size for a given pool
  267. (as determined by ProtocolReservedLength).
  268. Pool is organized as a pool-header and a number of page-size blocks
  269. Arguments:
  270. Status - Returns the final status (always NDIS_STATUS_SUCCESS).
  271. PoolHandle - Returns a pointer to the pool.
  272. NumberOfDescriptors - Number of packet descriptors needed.
  273. NumberOfOverflowDescriptors - Number of packet descriptors needed.
  274. ProtocolReservedLength - How long the ProtocolReserved field should be for packets in this pool.
  275. Return Value:
  276. None.
  277. --*/
  278. {
  279. PNDIS_PKT_POOL Pool;
  280. PNDIS_PACKET Packet;
  281. UINT i, NumPkts = (NumberOfDescriptors + NumberOfOverflowDescriptors);
  282. ULONG Tag = NDIS_TAG_PKT_POOL;
  283. NDIS_HANDLE tag = *PoolHandle;
  284. ULONG_PTR TmpTag;
  285. PVOID Caller, CallersCaller;
  286. KIRQL OldIrql;
  287. //
  288. // We save the address of the caller in the pool header, for debugging.
  289. //
  290. RtlGetCallersAddress(&Caller, &CallersCaller);
  291. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  292. ("==>NdisAllocatePacketPoolEx\n"));
  293. do
  294. {
  295. *PoolHandle = NULL;
  296. TmpTag = (ULONG_PTR)tag & 0xffffff;
  297. if ((TmpTag == '\0PDN') ||
  298. (TmpTag == '\0pDN'))
  299. {
  300. //
  301. // zero out the high order bit otherwise the verifier gets confused
  302. //
  303. Tag = (ULONG)((ULONG_PTR)tag & 0x7fffffff);
  304. }
  305. Pool = (PNDIS_PKT_POOL)ALLOC_FROM_POOL(sizeof(NDIS_PKT_POOL), Tag);
  306. if (Pool == NULL)
  307. {
  308. *Status = NDIS_STATUS_RESOURCES;
  309. return;
  310. }
  311. ZeroMemory(Pool, sizeof(NDIS_PKT_POOL));
  312. Pool->Tag = Tag;
  313. Pool->PacketLength = (USHORT)NdisPacketSize(ProtocolReservedLength);
  314. Pool->PktsPerBlock = (USHORT)((PAGE_SIZE - sizeof(NDIS_PKT_POOL_HDR))/Pool->PacketLength);
  315. if (Pool->PktsPerBlock != 0)
  316. {
  317. Pool->MaxBlocks = (NumPkts + Pool->PktsPerBlock - 1)/Pool->PktsPerBlock;
  318. Pool->BlockSize = PAGE_SIZE;
  319. }
  320. INITIALIZE_SPIN_LOCK(&Pool->Lock);
  321. if ((Pool->PktsPerBlock > NumPkts) || (Pool->PktsPerBlock == 0))
  322. {
  323. //
  324. // This is a pool which does not warrant a full-page or packet is too big to fit in
  325. // one page.
  326. //
  327. Pool->BlockSize = (ULONG)(sizeof(NDIS_PKT_POOL_HDR) + (NumPkts*Pool->PacketLength));
  328. Pool->PktsPerBlock = (USHORT)NumPkts;
  329. Pool->MaxBlocks = 1;
  330. }
  331. Pool->ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
  332. InitializeListHead(&Pool->AgingBlocks);
  333. InitializeListHead(&Pool->FreeBlocks);
  334. InitializeListHead(&Pool->UsedBlocks);
  335. ACQUIRE_SPIN_LOCK(&ndisGlobalPacketPoolListLock, &OldIrql);
  336. InsertHeadList(&ndisGlobalPacketPoolList, &Pool->GlobalPacketPoolList);
  337. RELEASE_SPIN_LOCK(&ndisGlobalPacketPoolListLock, OldIrql);
  338. //
  339. // Prime the pool by allocating a packet and freeing it.
  340. // Aging will ensure it is not immediately freed
  341. //
  342. NdisAllocatePacket(Status, &Packet, Pool);
  343. if (*Status != NDIS_STATUS_SUCCESS)
  344. {
  345. ACQUIRE_SPIN_LOCK(&ndisGlobalPacketPoolListLock, &OldIrql);
  346. RemoveEntryList(&Pool->GlobalPacketPoolList);
  347. RELEASE_SPIN_LOCK(&ndisGlobalPacketPoolListLock, OldIrql);
  348. FREE_POOL(Pool);
  349. break;
  350. }
  351. NdisFreePacket(Packet);
  352. *PoolHandle = Pool;
  353. Pool->Allocator = Caller;
  354. } while (FALSE);
  355. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  356. ("<==NdisAllocatePacketPoolEx, Status %.8x\n", *Status));
  357. }
  358. VOID
  359. NdisFreePacketPool(
  360. IN NDIS_HANDLE PoolHandle
  361. )
  362. {
  363. ndisFreePacketPool(PoolHandle, FALSE);
  364. }
  365. VOID
  366. ndisFreePacketPool(
  367. IN NDIS_HANDLE PoolHandle,
  368. IN BOOLEAN Verify
  369. )
  370. {
  371. PNDIS_PKT_POOL Pool = (PNDIS_PKT_POOL)PoolHandle;
  372. PNDIS_PKT_POOL_HDR Hdr;
  373. PLIST_ENTRY List;
  374. KIRQL OldIrql;
  375. ACQUIRE_SPIN_LOCK(&Pool->Lock, &OldIrql);
  376. if (Verify)
  377. ASSERTMSG("NdisFreePacketPool: Freeing non-empty pool\n", IsListEmpty(&Pool->UsedBlocks));
  378. while (!IsListEmpty(&Pool->AgingBlocks))
  379. {
  380. List = RemoveHeadList(&Pool->AgingBlocks);
  381. ASSERT(List != NULL);
  382. Hdr = CONTAINING_RECORD(List, NDIS_PKT_POOL_HDR, List);
  383. if (Verify)
  384. ASSERT(ExQueryDepthSList(&Hdr->FreeList) == Pool->PktsPerBlock);
  385. Pool->BlocksAllocated --;
  386. FREE_POOL(Hdr);
  387. }
  388. while (!IsListEmpty(&Pool->FreeBlocks))
  389. {
  390. List = RemoveHeadList(&Pool->FreeBlocks);
  391. ASSERT(List != NULL);
  392. Hdr = CONTAINING_RECORD(List, NDIS_PKT_POOL_HDR, List);
  393. if (Verify)
  394. ASSERT(ExQueryDepthSList(&Hdr->FreeList) == Pool->PktsPerBlock);
  395. Pool->BlocksAllocated --;
  396. FREE_POOL(Hdr);
  397. }
  398. //
  399. // We should never be executing the code below (see assertmsg() above). This should perhaps
  400. // be turned into a KeBugCheckEx()
  401. //
  402. while (!IsListEmpty(&Pool->UsedBlocks))
  403. {
  404. List = RemoveHeadList(&Pool->UsedBlocks);
  405. ASSERT(List != NULL);
  406. Hdr = CONTAINING_RECORD(List, NDIS_PKT_POOL_HDR, List);
  407. FREE_POOL(Hdr);
  408. Pool->BlocksAllocated --;
  409. }
  410. ASSERT(Pool->BlocksAllocated == 0);
  411. ACQUIRE_SPIN_LOCK_DPC(&ndisGlobalPacketPoolListLock);
  412. RemoveEntryList(&Pool->GlobalPacketPoolList);
  413. RELEASE_SPIN_LOCK_DPC(&ndisGlobalPacketPoolListLock);
  414. RELEASE_SPIN_LOCK(&Pool->Lock, OldIrql);
  415. FREE_POOL(Pool);
  416. }
  417. #define ndisInitializePacket(_Packet) \
  418. { \
  419. /* \
  420. * Set the current stack pointer to -1 \
  421. */ \
  422. CURR_STACK_LOCATION(_Packet) = -1; \
  423. CURR_XFER_DATA_STACK_LOCATION(_Packet) = -1; \
  424. NDIS_SET_ORIGINAL_PACKET(_Packet, _Packet); \
  425. (_Packet)->Private.Head = NULL; \
  426. (_Packet)->Private.ValidCounts = FALSE; \
  427. (_Packet)->Private.NdisPacketFlags = fPACKET_ALLOCATED_BY_NDIS; \
  428. }
  429. VOID
  430. NdisAllocatePacket(
  431. OUT PNDIS_STATUS Status,
  432. OUT PNDIS_PACKET * Packet,
  433. IN NDIS_HANDLE PoolHandle
  434. )
  435. /*++
  436. Routine Description:
  437. Allocates a packet out of a packet pool.
  438. Arguments:
  439. Status - Returns the final status.
  440. Packet - Return a pointer to the packet.
  441. PoolHandle - The packet pool to allocate from.
  442. Return Value:
  443. NDIS_STATUS_SUCCESS If we succeeded.
  444. NDIS_STATUS_RESOURCES On a failure to allocate or exceeded limit
  445. --*/
  446. {
  447. PNDIS_PKT_POOL Pool = (PNDIS_PKT_POOL)PoolHandle;
  448. PNDIS_PKT_POOL_HDR Hdr;
  449. PLIST_ENTRY List;
  450. PSINGLE_LIST_ENTRY SList;
  451. KIRQL OldIrql;
  452. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
  453. ("==> NdisAllocatePacket\n"));
  454. IF_DBG(DBG_COMP_CONFIG, DBG_LEVEL_ERR)
  455. {
  456. if (DbgIsNull(Pool))
  457. {
  458. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  459. ("NdisAllocatePacket: NULL Pool address\n"));
  460. DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR);
  461. }
  462. if (!DbgIsNonPaged(Pool))
  463. {
  464. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  465. ("NdisAllocatePacket: Not in NonPaged Memoryn"));
  466. DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR);
  467. }
  468. }
  469. do
  470. {
  471. SList = NULL;
  472. //
  473. // First check if we have any free packets readily available
  474. // but get a pointer to Flink before doing the check. this will save us aginst
  475. // the situations that List can become empty right after the check below.
  476. //
  477. List = Pool->FreeBlocks.Flink;
  478. if (List != &Pool->FreeBlocks)
  479. {
  480. Hdr = CONTAINING_RECORD(List, NDIS_PKT_POOL_HDR, List);
  481. SList = InterlockedPopEntrySList(&Hdr->FreeList);
  482. //
  483. // Another processor can exhaust the block between the check for non-empty and the pop
  484. //
  485. if (SList == NULL)
  486. {
  487. goto try_aging_block;
  488. }
  489. #ifdef NDIS_PKT_POOL_STATISTICS
  490. InterlockedIncrement(&Pool->cAllocatedFromFreeBlocks);
  491. #endif
  492. //
  493. // We got the packet, now see if some book-keeping is in order
  494. //
  495. if ((Pool->MaxBlocks > 1) &&
  496. ExQueryDepthSList(&Hdr->FreeList) == 0)
  497. {
  498. //
  499. // This block is now completely used up. Move it to the UsedBlocks list.
  500. // The sequence below guarantees that there is no race condition
  501. //
  502. ACQUIRE_SPIN_LOCK(&Pool->Lock, &OldIrql);
  503. RemoveEntryList(&Hdr->List);
  504. if (ExQueryDepthSList(&Hdr->FreeList) == 0)
  505. {
  506. InsertTailList(&Pool->UsedBlocks, List);
  507. Hdr->State = NDIS_PACKET_POOL_BLOCK_USED;
  508. #ifdef NDIS_PKT_POOL_STATISTICS
  509. InterlockedIncrement(&Pool->cMovedFreeBlocksToUsed);
  510. #endif
  511. }
  512. else
  513. {
  514. InsertHeadList(&Pool->FreeBlocks, &Hdr->List);
  515. Hdr->State = NDIS_PACKET_POOL_BLOCK_FREE;
  516. }
  517. RELEASE_SPIN_LOCK(&Pool->Lock, OldIrql);
  518. }
  519. break;
  520. }
  521. try_aging_block:
  522. //
  523. // Try taking an aging block and move it into the free block
  524. //
  525. ACQUIRE_SPIN_LOCK(&Pool->Lock, &OldIrql);
  526. if (!IsListEmpty(&Pool->AgingBlocks))
  527. {
  528. List = RemoveHeadList(&Pool->AgingBlocks);
  529. ASSERT (List != NULL);
  530. Hdr = CONTAINING_RECORD(List, NDIS_PKT_POOL_HDR, List);
  531. SList = InterlockedPopEntrySList(&Hdr->FreeList);
  532. ASSERT(SList != NULL);
  533. InsertHeadList(&Pool->FreeBlocks, List);
  534. Hdr->State = NDIS_PACKET_POOL_BLOCK_FREE;
  535. #ifdef NDIS_PKT_POOL_STATISTICS
  536. InterlockedIncrement(&Pool->cMovedAgedBlocksToFree);
  537. #endif
  538. if (!IsListEmpty(&Pool->AgingBlocks))
  539. {
  540. List = Pool->AgingBlocks.Flink;
  541. Hdr = CONTAINING_RECORD(List, NDIS_PKT_POOL_HDR, List);
  542. Pool->NextScavengeTick.QuadPart = Hdr->TimeStamp.QuadPart + PoolAgingTicks.QuadPart;
  543. }
  544. else
  545. {
  546. Pool->NextScavengeTick.QuadPart = 0;
  547. }
  548. RELEASE_SPIN_LOCK(&Pool->Lock, OldIrql);
  549. break;
  550. }
  551. //
  552. // See if have any head room to allocate more blocks
  553. //
  554. if (Pool->BlocksAllocated < Pool->MaxBlocks)
  555. {
  556. PUCHAR pTmp;
  557. ULONG i, j;
  558. Hdr = (PNDIS_PKT_POOL_HDR)ALLOC_FROM_POOL(Pool->BlockSize, Pool->Tag);
  559. if (Hdr == NULL)
  560. {
  561. RELEASE_SPIN_LOCK(&Pool->Lock, OldIrql);
  562. break;
  563. }
  564. NdisZeroMemory(Hdr, Pool->BlockSize);
  565. Pool->BlocksAllocated ++;
  566. InitializeListHead(&Hdr->List);
  567. ExInitializeSListHead(&Hdr->FreeList);
  568. pTmp = (PUCHAR)Hdr + sizeof(NDIS_PKT_POOL_HDR);
  569. for (i = Pool->PktsPerBlock; i > 0; i --)
  570. {
  571. PNDIS_PACKET p;
  572. PNDIS_STACK_RESERVED NSR;
  573. p = (PNDIS_PACKET)(pTmp + SIZE_PACKET_STACKS);
  574. p->Private.NdisPacketFlags = 0;
  575. pTmp += Pool->PacketLength;
  576. #ifdef _WIN64
  577. InterlockedPushEntrySList(&Hdr->FreeList,
  578. (PSINGLE_LIST_ENTRY)p);
  579. #else
  580. InterlockedPushEntrySList(&Hdr->FreeList,
  581. (PSINGLE_LIST_ENTRY)(&p->Private.Head));
  582. #endif
  583. p->Private.Pool = Pool;
  584. p->Private.Flags = Pool->ProtocolId;
  585. //
  586. // Set the offset to the out of band data.
  587. //
  588. p->Private.NdisPacketOobOffset = (USHORT)(Pool->PacketLength -
  589. (SIZE_PACKET_STACKS +
  590. sizeof(NDIS_PACKET_OOB_DATA) +
  591. sizeof(NDIS_PACKET_EXTENSION)));
  592. NDIS_SET_ORIGINAL_PACKET(p, p);
  593. //
  594. // initialize the spinlocks on packet stack
  595. //
  596. for (j = 0; j < ndisPacketStackSize; j++)
  597. {
  598. CURR_STACK_LOCATION(p) = j;
  599. NDIS_STACK_RESERVED_FROM_PACKET(p, &NSR);
  600. INITIALIZE_SPIN_LOCK(&NSR->Lock);
  601. }
  602. }
  603. SList = InterlockedPopEntrySList(&Hdr->FreeList);
  604. InsertHeadList(&Pool->FreeBlocks, &Hdr->List);
  605. Hdr->State = NDIS_PACKET_POOL_BLOCK_FREE;
  606. #ifdef NDIS_PKT_POOL_STATISTICS
  607. InterlockedIncrement(&Pool->cAllocatedNewBlocks);
  608. #endif
  609. RELEASE_SPIN_LOCK(&Pool->Lock, OldIrql);
  610. break;
  611. }
  612. RELEASE_SPIN_LOCK(&Pool->Lock, OldIrql);
  613. } while (FALSE);
  614. if (SList != NULL)
  615. {
  616. #ifdef _WIN64
  617. *Packet = (PNDIS_PACKET)SList;
  618. #else
  619. *Packet = CONTAINING_RECORD(SList, NDIS_PACKET, Private.Head);
  620. #endif
  621. *Status = NDIS_STATUS_SUCCESS;
  622. ndisInitializePacket(*Packet);
  623. }
  624. else
  625. {
  626. *Packet = NULL;
  627. *Status = NDIS_STATUS_RESOURCES;
  628. }
  629. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  630. ("<==NdisAllocatePacket, Status %.8x\n", *Status));
  631. }
  632. VOID
  633. NdisFreePacket(
  634. IN PNDIS_PACKET Packet
  635. )
  636. {
  637. PNDIS_PKT_POOL_HDR Hdr;
  638. PNDIS_PKT_POOL Pool;
  639. LARGE_INTEGER CurrTick;
  640. KIRQL OldIrql;
  641. LARGE_INTEGER HdrDeadTicks;
  642. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  643. ("==>NdisFreePacket\n"));
  644. ASSERT(Packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS);
  645. Packet->Private.NdisPacketFlags =0;
  646. Pool = Packet->Private.Pool;
  647. Hdr = (PNDIS_PKT_POOL_HDR)((ULONG_PTR)Packet & ~(PAGE_SIZE - 1));
  648. if (Pool->BlockSize != PAGE_SIZE)
  649. {
  650. PLIST_ENTRY List;
  651. //
  652. // This pool is not a page-sized pool and so the hdr is not page-aligned.
  653. // However we know that for such as pool, the Hdr is part of the FreeBlocks
  654. // list and is never moved to either Used or Aging blocks.
  655. //
  656. List = Pool->FreeBlocks.Flink;
  657. Hdr = CONTAINING_RECORD(List, NDIS_PKT_POOL_HDR, List);
  658. }
  659. #ifdef _WIN64
  660. ExInterlockedPushEntrySList(&Hdr->FreeList, (PSINGLE_LIST_ENTRY)Packet, &Pool->Lock);
  661. #else
  662. ExInterlockedPushEntrySList(&Hdr->FreeList,
  663. CONTAINING_RECORD(&Packet->Private.Head, SINGLE_LIST_ENTRY, Next),
  664. &Pool->Lock);
  665. #endif
  666. //
  667. // If this pool is a pool > 1 block and more than one has been allocated then ...
  668. //
  669. // If this hdr is completely free , then move it from the FreeBlocks list to the AgingBlocks and time-stamp it.
  670. // Add it at the tail since this makes it sorted in time.
  671. // While we are at it, check the head of the list and age out an entry if it needs to be.
  672. //
  673. if (Pool->MaxBlocks > 1)
  674. {
  675. if (((Pool->BlocksAllocated > 1) && (ExQueryDepthSList(&Hdr->FreeList) == Pool->PktsPerBlock))||
  676. (Hdr->State == NDIS_PACKET_POOL_BLOCK_USED))
  677. {
  678. ACQUIRE_SPIN_LOCK(&Pool->Lock, &OldIrql);
  679. if (ExQueryDepthSList(&Hdr->FreeList) == Pool->PktsPerBlock)
  680. {
  681. //
  682. // This block is completely free. Move it to the aged blocks list.
  683. //
  684. GET_CURRENT_TICK(&CurrTick);
  685. Hdr->TimeStamp = CurrTick;
  686. RemoveEntryList(&Hdr->List);
  687. InsertTailList(&Pool->AgingBlocks, &Hdr->List);
  688. Hdr->State = NDIS_PACKET_POOL_BLOCK_AGING;
  689. #ifdef NDIS_PKT_POOL_STATISTICS
  690. InterlockedIncrement(&Pool->cMovedFreeBlocksToAged);
  691. #endif
  692. }
  693. else if (Hdr->State == NDIS_PACKET_POOL_BLOCK_USED)
  694. {
  695. //
  696. // This block was completely used up but now has one or more
  697. // free packet. Move it to the tail of the free blocks list.
  698. //
  699. RemoveEntryList(&Hdr->List);
  700. InsertTailList(&Pool->FreeBlocks, &Hdr->List);
  701. Hdr->State = NDIS_PACKET_POOL_BLOCK_FREE;
  702. #ifdef NDIS_PKT_POOL_STATISTICS
  703. InterlockedIncrement(&Pool->cMovedUsedBlocksToFree);
  704. #endif
  705. }
  706. RELEASE_SPIN_LOCK(&Pool->Lock, OldIrql);
  707. }
  708. if (!IsListEmpty(&Pool->AgingBlocks))
  709. {
  710. GET_CURRENT_TICK(&CurrTick);
  711. if (CurrTick.QuadPart > Pool->NextScavengeTick.QuadPart)
  712. {
  713. ACQUIRE_SPIN_LOCK(&Pool->Lock, &OldIrql);
  714. while (!IsListEmpty(&Pool->AgingBlocks))
  715. {
  716. PLIST_ENTRY List = Pool->AgingBlocks.Flink;
  717. Hdr = CONTAINING_RECORD(List, NDIS_PKT_POOL_HDR, List);
  718. HdrDeadTicks.QuadPart = Hdr->TimeStamp.QuadPart + PoolAgingTicks.QuadPart;
  719. if (CurrTick.QuadPart > HdrDeadTicks.QuadPart)
  720. {
  721. RemoveHeadList(&Pool->AgingBlocks);
  722. if (ExQueryDepthSList(&Hdr->FreeList) != Pool->PktsPerBlock)
  723. {
  724. //
  725. // somehow we ended up allocating a packet from an aged block
  726. // put the block back on free list. this can happen if during
  727. // NdisAllocatePacket, right after getting a packet from a free
  728. // block list, the block moves to aging list.
  729. //
  730. #if DBG
  731. DbgPrint("Ndis: pool %p: aged packet pool block at %p contains allocated packets!\n", Pool, Hdr);
  732. #endif
  733. InsertHeadList(&Pool->FreeBlocks, &Hdr->List);
  734. Hdr->State = NDIS_PACKET_POOL_BLOCK_FREE;
  735. }
  736. else
  737. {
  738. FREE_POOL(Hdr);
  739. Pool->BlocksAllocated --;
  740. #ifdef NDIS_PKT_POOL_STATISTICS
  741. InterlockedIncrement(&Pool->cFreedAgedBlocks);
  742. #endif
  743. }
  744. }
  745. else
  746. {
  747. //
  748. // Compute the next tick value which represents the earliest time
  749. // that we will scavenge this pool again.
  750. //
  751. Pool->NextScavengeTick.QuadPart = HdrDeadTicks.QuadPart;
  752. break;
  753. }
  754. }
  755. RELEASE_SPIN_LOCK(&Pool->Lock, OldIrql);
  756. }
  757. }
  758. }
  759. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  760. ("<==NdisFreePacket\n"));
  761. }
  762. UINT
  763. NdisPacketPoolUsage(
  764. IN PNDIS_HANDLE PoolHandle
  765. )
  766. {
  767. PNDIS_PKT_POOL Pool = (PNDIS_PKT_POOL)PoolHandle;
  768. PNDIS_PKT_POOL_HDR Hdr;
  769. PLIST_ENTRY List;
  770. UINT i, NumUsed = 0;
  771. for (List = Pool->UsedBlocks.Flink; List != &Pool->UsedBlocks; List = List->Flink)
  772. {
  773. NumUsed += Pool->PktsPerBlock;
  774. }
  775. for (List = Pool->FreeBlocks.Flink; List != &Pool->FreeBlocks; List = List->Flink)
  776. {
  777. Hdr = CONTAINING_RECORD(List, NDIS_PKT_POOL_HDR, List);
  778. NumUsed += (Pool->PktsPerBlock - ExQueryDepthSList(&Hdr->FreeList));
  779. }
  780. return NumUsed;
  781. }
  782. VOID
  783. NdisSetPacketPoolProtocolId(
  784. IN NDIS_HANDLE PacketPoolHandle,
  785. IN UINT ProtocolId
  786. )
  787. /*++
  788. Routine Description:
  789. Set the protocol id in the pool and all the packets allocated to the pool. This api has to be called
  790. prior to any packets that are allocated out of the pool. The code below is linked to the NdisAllocatePacket
  791. code in that the first empty pool (Pool->BlocksAllocated == 1) is left at the FreeBlocks list and not
  792. moved to the AgingList.
  793. Arguments:
  794. Return Value:
  795. None.
  796. --*/
  797. {
  798. PNDIS_PKT_POOL Pool = (PNDIS_PKT_POOL)PacketPoolHandle;
  799. PNDIS_PKT_POOL_HDR Hdr;
  800. PLIST_ENTRY List;
  801. PNDIS_PACKET Packet;
  802. PUCHAR p;
  803. UINT j;
  804. Pool->ProtocolId = ProtocolId;
  805. ASSERT(IsListEmpty(&Pool->AgingBlocks));
  806. ASSERT(IsListEmpty(&Pool->UsedBlocks));
  807. for (List = Pool->FreeBlocks.Flink; List != &Pool->FreeBlocks; List = List->Flink)
  808. {
  809. Hdr = CONTAINING_RECORD(List, NDIS_PKT_POOL_HDR, List);
  810. p = (PUCHAR)Hdr + sizeof(NDIS_PKT_POOL_HDR);
  811. for (j = Pool->PktsPerBlock; j > 0; j--, p += Pool->PacketLength)
  812. {
  813. Packet = (PNDIS_PACKET)(p + SIZE_PACKET_STACKS);
  814. Packet->Private.Flags |= ProtocolId;
  815. }
  816. }
  817. }
  818. VOID
  819. NdisAllocateBufferPool(
  820. OUT PNDIS_STATUS Status,
  821. OUT PNDIS_HANDLE PoolHandle,
  822. IN UINT NumberOfDescriptors
  823. )
  824. /*++
  825. Routine Description:
  826. Initializes a block of storage so that buffer descriptors can be
  827. allocated.
  828. Arguments:
  829. Status - status of the request.
  830. PoolHandle - handle that is used to specify the pool
  831. NumberOfDescriptors - Number of buffer descriptors in the pool.
  832. Return Value:
  833. None.
  834. --*/
  835. {
  836. *PoolHandle = NULL;
  837. *Status = NDIS_STATUS_SUCCESS;
  838. }
  839. VOID
  840. NdisFreeBufferPool(
  841. IN NDIS_HANDLE PoolHandle
  842. )
  843. /*++
  844. Routine Description:
  845. Terminates usage of a buffer descriptor pool.
  846. Arguments:
  847. PoolHandle - handle that is used to specify the pool
  848. Return Value:
  849. None.
  850. --*/
  851. {
  852. return;
  853. }
  854. VOID
  855. NdisAllocateBuffer(
  856. OUT PNDIS_STATUS Status,
  857. OUT PNDIS_BUFFER * Buffer,
  858. IN NDIS_HANDLE PoolHandle,
  859. IN PVOID VirtualAddress,
  860. IN UINT Length
  861. )
  862. /*++
  863. Routine Description:
  864. Creates a buffer descriptor to describe a segment of virtual memory
  865. allocated via NdisAllocateMemory (which always allocates nonpaged).
  866. Arguments:
  867. Status - Status of the request.
  868. Buffer - Pointer to the allocated buffer descriptor.
  869. PoolHandle - Handle that is used to specify the pool.
  870. VirtualAddress - The virtual address of the buffer.
  871. Length - The Length of the buffer.
  872. Return Value:
  873. None.
  874. --*/
  875. {
  876. *Status = NDIS_STATUS_FAILURE;
  877. if ((*Buffer = IoAllocateMdl(VirtualAddress,
  878. Length,
  879. FALSE,
  880. FALSE,
  881. NULL)) != NULL)
  882. {
  883. MmBuildMdlForNonPagedPool(*Buffer);
  884. (*Buffer)->Next = NULL;
  885. *Status = NDIS_STATUS_SUCCESS;
  886. }
  887. }
  888. VOID
  889. NdisAdjustBufferLength(
  890. IN PNDIS_BUFFER Buffer,
  891. IN UINT Length
  892. )
  893. {
  894. Buffer->ByteCount = Length;
  895. }
  896. VOID
  897. NdisCopyBuffer(
  898. OUT PNDIS_STATUS Status,
  899. OUT PNDIS_BUFFER * Buffer,
  900. IN NDIS_HANDLE PoolHandle,
  901. IN PVOID MemoryDescriptor,
  902. IN UINT Offset,
  903. IN UINT Length
  904. )
  905. /*++
  906. Routine Description:
  907. Used to create a buffer descriptor given a memory descriptor.
  908. Arguments:
  909. Status - Status of the request.
  910. Buffer - Pointer to the allocated buffer descriptor.
  911. PoolHandle - Handle that is used to specify the pool.
  912. MemoryDescriptor - Pointer to the descriptor of the source memory.
  913. Offset - The Offset in the sources memory from which the copy is to begin
  914. Length - Number of Bytes to copy.
  915. Return Value:
  916. None.
  917. --*/
  918. {
  919. PNDIS_BUFFER SourceDescriptor = (PNDIS_BUFFER)MemoryDescriptor;
  920. PVOID BaseVa = (((PUCHAR)MDL_VA(SourceDescriptor)) + Offset);
  921. *Status = NDIS_STATUS_FAILURE;
  922. if ((*Buffer = IoAllocateMdl(BaseVa,
  923. Length,
  924. FALSE,
  925. FALSE,
  926. NULL)) != NULL)
  927. {
  928. IoBuildPartialMdl(SourceDescriptor,
  929. *Buffer,
  930. BaseVa,
  931. Length);
  932. (*Buffer)->Next = NULL;
  933. *Status = NDIS_STATUS_SUCCESS;
  934. }
  935. }
  936. VOID
  937. NdisUnchainBufferAtFront(
  938. IN OUT PNDIS_PACKET Packet,
  939. OUT PNDIS_BUFFER * Buffer
  940. )
  941. /*++
  942. Routine Description:
  943. Takes a buffer off the front of a packet.
  944. Arguments:
  945. Packet - The packet to be modified.
  946. Buffer - Returns the packet on the front, or NULL.
  947. Return Value:
  948. None.
  949. --*/
  950. {
  951. *Buffer = Packet->Private.Head;
  952. //
  953. // If packet is not empty, remove head buffer.
  954. //
  955. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  956. ("==>NdisUnchainBufferAtFront\n"));
  957. IF_DBG(DBG_COMP_CONFIG, DBG_LEVEL_ERR)
  958. {
  959. BOOLEAN f = FALSE;
  960. if (DbgIsNull(Packet))
  961. {
  962. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  963. ("UnchainBufferAtFront: Null Packet Pointer\n"));
  964. f = TRUE;
  965. }
  966. if (!DbgIsNonPaged(Packet))
  967. {
  968. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  969. ("UnchainBufferAtFront: Packet not in NonPaged Memory\n"));
  970. f = TRUE;
  971. }
  972. if (!DbgIsPacket(Packet))
  973. {
  974. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  975. ("UnchainBufferAtFront: Illegal Packet Size\n"));
  976. f = TRUE;
  977. }
  978. if (f)
  979. DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR);
  980. }
  981. if (*Buffer != (PNDIS_BUFFER)NULL)
  982. {
  983. Packet->Private.Head = (*Buffer)->Next; // may be NULL
  984. (*Buffer)->Next = (PNDIS_BUFFER)NULL;
  985. Packet->Private.ValidCounts = FALSE;
  986. }
  987. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  988. ("<==NdisUnchainBufferAtFront\n"));
  989. }
  990. VOID
  991. NdisUnchainBufferAtBack(
  992. IN OUT PNDIS_PACKET Packet,
  993. OUT PNDIS_BUFFER * Buffer
  994. )
  995. /*++
  996. Routine Description:
  997. Takes a buffer off the end of a packet.
  998. Arguments:
  999. Packet - The packet to be modified.
  1000. Buffer - Returns the packet on the end, or NULL.
  1001. Return Value:
  1002. None.
  1003. --*/
  1004. {
  1005. PNDIS_BUFFER BufP = Packet->Private.Head;
  1006. PNDIS_BUFFER Result;
  1007. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  1008. ("==>NdisUnchainBufferAtBack\n"));
  1009. IF_DBG(DBG_COMP_CONFIG, DBG_LEVEL_ERR)
  1010. {
  1011. BOOLEAN f = FALSE;
  1012. if (DbgIsNull(Packet))
  1013. {
  1014. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1015. ("UnchainBufferAtBack: Null Packet Pointer\n"));
  1016. f = TRUE;
  1017. }
  1018. if (!DbgIsNonPaged(Packet))
  1019. {
  1020. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1021. ("UnchainBufferAtBack: Packet not in NonPaged Memory\n"));
  1022. f = TRUE;
  1023. }
  1024. if (!DbgIsPacket(Packet))
  1025. {
  1026. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1027. ("UnchainBufferAtBack: Illegal Packet Size\n"));
  1028. f = TRUE;
  1029. }
  1030. if (f)
  1031. DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR);
  1032. }
  1033. if (BufP != (PNDIS_BUFFER)NULL)
  1034. {
  1035. //
  1036. // The packet is not empty, return the tail buffer.
  1037. //
  1038. Result = Packet->Private.Tail;
  1039. if (BufP == Result)
  1040. {
  1041. //
  1042. // There was only one buffer on the queue.
  1043. //
  1044. Packet->Private.Head = (PNDIS_BUFFER)NULL;
  1045. }
  1046. else
  1047. {
  1048. //
  1049. // Determine the new tail buffer.
  1050. //
  1051. while (BufP->Next != Result)
  1052. {
  1053. BufP = BufP->Next;
  1054. }
  1055. Packet->Private.Tail = BufP;
  1056. BufP->Next = NULL;
  1057. }
  1058. Result->Next = (PNDIS_BUFFER)NULL;
  1059. Packet->Private.ValidCounts = FALSE;
  1060. }
  1061. else
  1062. {
  1063. //
  1064. // Packet is empty.
  1065. //
  1066. Result = (PNDIS_BUFFER)NULL;
  1067. }
  1068. *Buffer = Result;
  1069. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  1070. ("<==NdisUnchainBufferAtBack\n"));
  1071. }
  1072. VOID
  1073. NdisCopyFromPacketToPacket(
  1074. IN PNDIS_PACKET Destination,
  1075. IN UINT DestinationOffset,
  1076. IN UINT BytesToCopy,
  1077. IN PNDIS_PACKET Source,
  1078. IN UINT SourceOffset,
  1079. OUT PUINT BytesCopied
  1080. )
  1081. /*++
  1082. Routine Description:
  1083. Copy from an ndis packet to an ndis packet.
  1084. Arguments:
  1085. Destination - The packet should be copied in to.
  1086. DestinationOffset - The offset from the beginning of the packet
  1087. into which the data should start being placed.
  1088. BytesToCopy - The number of bytes to copy from the source packet.
  1089. Source - The ndis packet from which to copy data.
  1090. SourceOffset - The offset from the start of the packet from which
  1091. to start copying data.
  1092. BytesCopied - The number of bytes actually copied from the source
  1093. packet. This can be less than BytesToCopy if the source or destination
  1094. packet is too short.
  1095. Return Value:
  1096. None
  1097. --*/
  1098. {
  1099. //
  1100. // Holds the count of the number of ndis buffers comprising the
  1101. // destination packet.
  1102. //
  1103. // UINT DestinationBufferCount;
  1104. //
  1105. // Holds the count of the number of ndis buffers comprising the
  1106. // source packet.
  1107. //
  1108. // UINT SourceBufferCount;
  1109. //
  1110. // Points to the buffer into which we are putting data.
  1111. //
  1112. PNDIS_BUFFER DestinationCurrentBuffer;
  1113. //
  1114. // Points to the buffer from which we are extracting data.
  1115. //
  1116. PNDIS_BUFFER SourceCurrentBuffer;
  1117. //
  1118. // Holds the virtual address of the current destination buffer.
  1119. //
  1120. PVOID DestinationVirtualAddress;
  1121. //
  1122. // Holds the virtual address of the current source buffer.
  1123. //
  1124. PVOID SourceVirtualAddress;
  1125. //
  1126. // Holds the length of the current destination buffer.
  1127. //
  1128. UINT DestinationCurrentLength;
  1129. //
  1130. // Holds the length of the current source buffer.
  1131. //
  1132. UINT SourceCurrentLength;
  1133. //
  1134. // Keep a local variable of BytesCopied so we aren't referencing
  1135. // through a pointer.
  1136. //
  1137. UINT LocalBytesCopied = 0;
  1138. //
  1139. // Take care of boundary condition of zero length copy.
  1140. //
  1141. *BytesCopied = 0;
  1142. if (!BytesToCopy)
  1143. return;
  1144. //
  1145. // Get the first buffer of the destination.
  1146. //
  1147. // NdisQueryPacket(Destination,
  1148. // NULL,
  1149. // &DestinationBufferCount,
  1150. // &DestinationCurrentBuffer,
  1151. // NULL);
  1152. DestinationCurrentBuffer = Destination->Private.Head;
  1153. if (DestinationCurrentBuffer == NULL)
  1154. return;
  1155. //
  1156. // Could have a null packet.
  1157. //
  1158. // if (!DestinationBufferCount)
  1159. // return;
  1160. // NdisQueryBuffer(DestinationCurrentBuffer,
  1161. // &DestinationVirtualAddress,
  1162. // &DestinationCurrentLength);
  1163. DestinationVirtualAddress = MDL_ADDRESS(DestinationCurrentBuffer);
  1164. DestinationCurrentLength = MDL_SIZE(DestinationCurrentBuffer);
  1165. //
  1166. // Get the first buffer of the source.
  1167. //
  1168. // NdisQueryPacket(Source,
  1169. // NULL,
  1170. // &SourceBufferCount,
  1171. // &SourceCurrentBuffer,
  1172. // NULL);
  1173. //
  1174. // Could have a null packet.
  1175. //
  1176. // if (!SourceBufferCount)
  1177. // return;
  1178. SourceCurrentBuffer = Source->Private.Head;
  1179. if (SourceCurrentBuffer == NULL)
  1180. return;
  1181. // NdisQueryBuffer(SourceCurrentBuffer,
  1182. // &SourceVirtualAddress,
  1183. // &SourceCurrentLength);
  1184. SourceVirtualAddress = MDL_ADDRESS(SourceCurrentBuffer);
  1185. SourceCurrentLength = MDL_SIZE(SourceCurrentBuffer);
  1186. while (LocalBytesCopied < BytesToCopy)
  1187. {
  1188. //
  1189. // Check to see whether we've exhausted the current destination
  1190. // buffer. If so, move onto the next one.
  1191. //
  1192. if (!DestinationCurrentLength)
  1193. {
  1194. // NdisGetNextBuffer(DestinationCurrentBuffer, &DestinationCurrentBuffer);
  1195. DestinationCurrentBuffer = DestinationCurrentBuffer->Next;
  1196. if (!DestinationCurrentBuffer)
  1197. {
  1198. //
  1199. // We've reached the end of the packet. We return
  1200. // with what we've done so far. (Which must be shorter
  1201. // than requested.)
  1202. //
  1203. break;
  1204. }
  1205. // NdisQueryBuffer(DestinationCurrentBuffer,
  1206. // &DestinationVirtualAddress,
  1207. // &DestinationCurrentLength);
  1208. DestinationVirtualAddress = MDL_ADDRESS(DestinationCurrentBuffer);
  1209. DestinationCurrentLength = MDL_SIZE(DestinationCurrentBuffer);
  1210. continue;
  1211. }
  1212. //
  1213. // Check to see whether we've exhausted the current source
  1214. // buffer. If so, move onto the next one.
  1215. //
  1216. if (!SourceCurrentLength)
  1217. {
  1218. // NdisGetNextBuffer(SourceCurrentBuffer, &SourceCurrentBuffer);
  1219. SourceCurrentBuffer = SourceCurrentBuffer->Next;
  1220. if (!SourceCurrentBuffer)
  1221. {
  1222. //
  1223. // We've reached the end of the packet. We return
  1224. // with what we've done so far. (Which must be shorter
  1225. // than requested.)
  1226. //
  1227. break;
  1228. }
  1229. // NdisQueryBuffer(SourceCurrentBuffer,
  1230. // &SourceVirtualAddress,
  1231. // &SourceCurrentLength);
  1232. SourceVirtualAddress = MDL_ADDRESS(SourceCurrentBuffer);
  1233. SourceCurrentLength = MDL_SIZE(SourceCurrentBuffer);
  1234. continue;
  1235. }
  1236. //
  1237. // Try to get us up to the point to start the copy.
  1238. //
  1239. if (DestinationOffset)
  1240. {
  1241. if (DestinationOffset > DestinationCurrentLength)
  1242. {
  1243. //
  1244. // What we want isn't in this buffer.
  1245. //
  1246. DestinationOffset -= DestinationCurrentLength;
  1247. DestinationCurrentLength = 0;
  1248. continue;
  1249. }
  1250. else
  1251. {
  1252. DestinationVirtualAddress = (PCHAR)DestinationVirtualAddress
  1253. + DestinationOffset;
  1254. DestinationCurrentLength -= DestinationOffset;
  1255. DestinationOffset = 0;
  1256. }
  1257. }
  1258. //
  1259. // Try to get us up to the point to start the copy.
  1260. //
  1261. if (SourceOffset)
  1262. {
  1263. if (SourceOffset > SourceCurrentLength)
  1264. {
  1265. //
  1266. // What we want isn't in this buffer.
  1267. //
  1268. SourceOffset -= SourceCurrentLength;
  1269. SourceCurrentLength = 0;
  1270. continue;
  1271. }
  1272. else
  1273. {
  1274. SourceVirtualAddress = (PCHAR)SourceVirtualAddress
  1275. + SourceOffset;
  1276. SourceCurrentLength -= SourceOffset;
  1277. SourceOffset = 0;
  1278. }
  1279. }
  1280. //
  1281. // Copy the data.
  1282. //
  1283. {
  1284. //
  1285. // Holds the amount of data to move.
  1286. //
  1287. UINT AmountToMove;
  1288. //
  1289. // Holds the amount desired remaining.
  1290. //
  1291. UINT Remaining = BytesToCopy - LocalBytesCopied;
  1292. AmountToMove = ((SourceCurrentLength <= DestinationCurrentLength) ?
  1293. (SourceCurrentLength) : (DestinationCurrentLength));
  1294. AmountToMove = ((Remaining < AmountToMove)?
  1295. (Remaining):(AmountToMove));
  1296. CopyMemory(DestinationVirtualAddress, SourceVirtualAddress, AmountToMove);
  1297. DestinationVirtualAddress =
  1298. (PCHAR)DestinationVirtualAddress + AmountToMove;
  1299. SourceVirtualAddress =
  1300. (PCHAR)SourceVirtualAddress + AmountToMove;
  1301. LocalBytesCopied += AmountToMove;
  1302. SourceCurrentLength -= AmountToMove;
  1303. DestinationCurrentLength -= AmountToMove;
  1304. }
  1305. }
  1306. *BytesCopied = LocalBytesCopied;
  1307. }
  1308. VOID
  1309. NdisUpdateSharedMemory(
  1310. IN NDIS_HANDLE NdisAdapterHandle,
  1311. IN ULONG Length,
  1312. IN PVOID VirtualAddress,
  1313. IN NDIS_PHYSICAL_ADDRESS PhysicalAddress
  1314. )
  1315. /*++
  1316. Routine Description:
  1317. Ensures that the data to be read from a shared memory region is
  1318. fully up-to-date.
  1319. Arguments:
  1320. NdisAdapterHandle - handle returned by NdisRegisterAdapter.
  1321. Length - The length of the shared memory.
  1322. VirtualAddress - Virtual address returned by NdisAllocateSharedMemory.
  1323. PhysicalAddress - The physical address returned by NdisAllocateSharedMemory.
  1324. Return Value:
  1325. None.
  1326. --*/
  1327. {
  1328. //
  1329. // There is no underlying HAL routine for this anymore,
  1330. // it is not needed.
  1331. //
  1332. }
  1333. BOOLEAN
  1334. ndisCheckPortUsage(
  1335. IN ULONG u32PortNumber,
  1336. IN PNDIS_MINIPORT_BLOCK Miniport,
  1337. OUT PULONG pTranslatedPort,
  1338. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR * pResourceDescriptor
  1339. )
  1340. /*++
  1341. Routine Description:
  1342. This routine checks if a port is currently in use somewhere in the
  1343. system via IoReportUsage -- which fails if there is a conflict.
  1344. Arguments:
  1345. BusNumber - Bus number in the system
  1346. PortNumber - Address of the port to access.
  1347. Return Value:
  1348. FALSE if there is a conflict, else TRUE
  1349. --*/
  1350. {
  1351. PHYSICAL_ADDRESS Port;
  1352. PHYSICAL_ADDRESS u64Port;
  1353. Port.QuadPart = u32PortNumber;
  1354. if (NDIS_STATUS_SUCCESS == ndisTranslateResources(Miniport,
  1355. CmResourceTypePort,
  1356. Port,
  1357. &u64Port,
  1358. pResourceDescriptor))
  1359. {
  1360. *pTranslatedPort = u64Port.LowPart;
  1361. return TRUE;
  1362. }
  1363. else
  1364. {
  1365. *pTranslatedPort = 0;
  1366. return FALSE;
  1367. }
  1368. }
  1369. NTSTATUS
  1370. ndisStartMapping(
  1371. IN INTERFACE_TYPE InterfaceType,
  1372. IN ULONG BusNumber,
  1373. IN ULONG InitialAddress,
  1374. IN ULONG Length,
  1375. IN ULONG AddressSpace,
  1376. OUT PVOID * InitialMapping,
  1377. OUT PBOOLEAN Mapped
  1378. )
  1379. /*++
  1380. Routine Description:
  1381. This routine initialize the mapping of a address into virtual
  1382. space dependent on the bus number, etc.
  1383. Arguments:
  1384. InterfaceType - The bus type (ISA)
  1385. BusNumber - Bus number in the system
  1386. InitialAddress - Address to access.
  1387. Length - Number of bytes from the base address to access.
  1388. InitialMapping - The virtual address space to use when accessing the
  1389. address.
  1390. Mapped - Did an MmMapIoSpace() take place.
  1391. Return Value:
  1392. The function value is the status of the operation.
  1393. --*/
  1394. {
  1395. PHYSICAL_ADDRESS TranslatedAddress;
  1396. PHYSICAL_ADDRESS InitialPhysAddress;
  1397. //
  1398. // Get the system physical address for this card. The card uses
  1399. // I/O space, except for "internal" Jazz devices which use
  1400. // memory space.
  1401. //
  1402. *Mapped = FALSE;
  1403. InitialPhysAddress.LowPart = InitialAddress;
  1404. InitialPhysAddress.HighPart = 0;
  1405. if (InterfaceType != -1)
  1406. {
  1407. if ((InterfaceType != Isa) &&
  1408. (InterfaceType != PCIBus))
  1409. {
  1410. InterfaceType = Isa;
  1411. }
  1412. if (!HalTranslateBusAddress(InterfaceType, // InterfaceType
  1413. BusNumber, // BusNumber
  1414. InitialPhysAddress, // Bus Address
  1415. &AddressSpace, // AddressSpace
  1416. &TranslatedAddress)) // Translated address
  1417. {
  1418. //
  1419. // It would be nice to return a better status here, but we only get
  1420. // TRUE/FALSE back from HalTranslateBusAddress.
  1421. //
  1422. return NDIS_STATUS_FAILURE;
  1423. }
  1424. }
  1425. else
  1426. {
  1427. TranslatedAddress = InitialPhysAddress;
  1428. }
  1429. if (AddressSpace == 0)
  1430. {
  1431. //
  1432. // memory space
  1433. //
  1434. *InitialMapping = MmMapIoSpace(TranslatedAddress, Length, FALSE);
  1435. if (*InitialMapping == NULL)
  1436. {
  1437. return STATUS_INSUFFICIENT_RESOURCES;
  1438. }
  1439. *Mapped = TRUE;
  1440. }
  1441. else
  1442. {
  1443. //
  1444. // I/O space
  1445. //
  1446. *(ULONG_PTR *)InitialMapping = TranslatedAddress.LowPart;
  1447. }
  1448. return STATUS_SUCCESS;
  1449. }
  1450. NTSTATUS
  1451. ndisEndMapping(
  1452. IN PVOID InitialMapping,
  1453. IN ULONG Length,
  1454. IN BOOLEAN Mapped
  1455. )
  1456. /*++
  1457. Routine Description:
  1458. This routine undoes the mapping of an address into virtual
  1459. space dependent on the bus number, etc.
  1460. Arguments:
  1461. InitialMapping - The virtual address space to use when accessing the
  1462. address.
  1463. Length - Number of bytes from the base address to access.
  1464. Mapped - Do we need to call MmUnmapIoSpace.
  1465. Return Value:
  1466. The function value is the status of the operation.
  1467. --*/
  1468. {
  1469. if (Mapped)
  1470. {
  1471. //
  1472. // memory space
  1473. //
  1474. MmUnmapIoSpace(InitialMapping, Length);
  1475. }
  1476. return STATUS_SUCCESS;
  1477. }
  1478. VOID
  1479. ndisImmediateReadWritePort(
  1480. IN NDIS_HANDLE WrapperConfigurationContext,
  1481. IN ULONG Port,
  1482. IN OUT PVOID Data,
  1483. IN ULONG Size,
  1484. IN BOOLEAN Read
  1485. )
  1486. /*++
  1487. Routine Description:
  1488. This routine reads from a port a UCHAR. It does all the mapping,
  1489. etc, to do the read here.
  1490. Arguments:
  1491. WrapperConfigurationContext - The handle used to call NdisOpenConfig.
  1492. Port - Port number to read from.
  1493. Data - Pointer to place to store the result.
  1494. Return Value:
  1495. None.
  1496. --*/
  1497. {
  1498. PRTL_QUERY_REGISTRY_TABLE KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
  1499. PNDIS_MINIPORT_BLOCK Miniport;
  1500. BOOLEAN Mapped = FALSE;
  1501. PVOID PortMapping;
  1502. NDIS_INTERFACE_TYPE BusType;
  1503. ULONG BusNumber;
  1504. NTSTATUS Status;
  1505. PCM_PARTIAL_RESOURCE_DESCRIPTOR pResourceDescriptor = NULL;
  1506. Miniport = (PNDIS_MINIPORT_BLOCK)KeyQueryTable[3].QueryRoutine;
  1507. BusType = Miniport->BusType;
  1508. BusNumber = Miniport->BusNumber;
  1509. ASSERT(Miniport != NULL);
  1510. do
  1511. {
  1512. if (Read)
  1513. {
  1514. switch (Size)
  1515. {
  1516. case sizeof (UCHAR):
  1517. *((PUCHAR)Data) = (UCHAR)0xFF;
  1518. break;
  1519. case sizeof (USHORT):
  1520. *((PUSHORT)Data) = (USHORT)0xFFFF;
  1521. break;
  1522. case sizeof (ULONG):
  1523. *((PULONG)Data) = (ULONG)0xFFFFFFFF;
  1524. break;
  1525. }
  1526. }
  1527. //
  1528. // Check that the port is available. If so map the space.
  1529. //
  1530. if (ndisCheckPortUsage(Port,
  1531. Miniport,
  1532. (PULONG)&PortMapping,
  1533. &pResourceDescriptor) == FALSE)
  1534. {
  1535. //
  1536. // the resource was not part of already allocated resources,
  1537. // nor could we allocate the resource
  1538. //
  1539. break;
  1540. }
  1541. if (pResourceDescriptor == NULL)
  1542. {
  1543. //
  1544. // the port is not part of allocated resources, try to
  1545. // temporray allocate the resource
  1546. //
  1547. if (!NT_SUCCESS(Status = ndisStartMapping(BusType,
  1548. BusNumber,
  1549. Port,
  1550. Size,
  1551. (BusType == Internal) ? 0 : 1,
  1552. &PortMapping,
  1553. &Mapped)))
  1554. {
  1555. break;
  1556. }
  1557. }
  1558. else
  1559. {
  1560. Mapped = FALSE;
  1561. }
  1562. if (Read)
  1563. {
  1564. //
  1565. // Read from the port
  1566. //
  1567. switch (Size)
  1568. {
  1569. case sizeof (UCHAR):
  1570. *((PUCHAR)Data) = READ_PORT_UCHAR((PUCHAR)PortMapping);
  1571. break;
  1572. case sizeof (USHORT):
  1573. *((PUSHORT)Data) = READ_PORT_USHORT((PUSHORT)PortMapping);
  1574. break;
  1575. case sizeof (ULONG):
  1576. *((PULONG)Data) = READ_PORT_ULONG((PULONG)PortMapping);
  1577. break;
  1578. }
  1579. }
  1580. else
  1581. {
  1582. //
  1583. // write to the port
  1584. //
  1585. switch (Size)
  1586. {
  1587. case sizeof (UCHAR):
  1588. WRITE_PORT_UCHAR((PUCHAR)PortMapping, *((PUCHAR)Data));
  1589. break;
  1590. case sizeof (USHORT):
  1591. WRITE_PORT_USHORT((PUSHORT)PortMapping, *((PUSHORT)Data));
  1592. break;
  1593. case sizeof (ULONG):
  1594. WRITE_PORT_ULONG((PULONG)PortMapping, *((PULONG)Data));
  1595. break;
  1596. }
  1597. }
  1598. if (Mapped)
  1599. {
  1600. //
  1601. // End port mapping
  1602. //
  1603. ndisEndMapping(PortMapping, Size, Mapped);
  1604. }
  1605. } while (FALSE);
  1606. }
  1607. VOID
  1608. NdisImmediateReadPortUchar(
  1609. IN NDIS_HANDLE WrapperConfigurationContext,
  1610. IN ULONG Port,
  1611. OUT PUCHAR Data
  1612. )
  1613. /*++
  1614. Routine Description:
  1615. This routine reads from a port a UCHAR. It does all the mapping,
  1616. etc, to do the read here.
  1617. Arguments:
  1618. WrapperConfigurationContext - The handle used to call NdisOpenConfig.
  1619. Port - Port number to read from.
  1620. Data - Pointer to place to store the result.
  1621. Return Value:
  1622. None.
  1623. --*/
  1624. {
  1625. #if DBG
  1626. PRTL_QUERY_REGISTRY_TABLE KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
  1627. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)KeyQueryTable[3].QueryRoutine;
  1628. NDIS_WARN(TRUE, Miniport, NDIS_GFLAG_WARN_LEVEL_1,
  1629. ("NdisImmediateReadPortUchar: this API is going away. use non-Immediate version\n", Miniport));
  1630. #endif
  1631. ndisImmediateReadWritePort(WrapperConfigurationContext,
  1632. Port,
  1633. (PVOID)Data,
  1634. sizeof (UCHAR),
  1635. TRUE);
  1636. }
  1637. VOID
  1638. NdisImmediateReadPortUshort(
  1639. IN NDIS_HANDLE WrapperConfigurationContext,
  1640. IN ULONG Port,
  1641. OUT PUSHORT Data
  1642. )
  1643. /*++
  1644. Routine Description:
  1645. This routine reads from a port a USHORT. It does all the mapping,
  1646. etc, to do the read here.
  1647. Arguments:
  1648. WrapperConfigurationContext - The handle used to call NdisOpenConfig.
  1649. Port - Port number to read from.
  1650. Data - Pointer to place to store the result.
  1651. Return Value:
  1652. None.
  1653. --*/
  1654. {
  1655. #if DBG
  1656. PRTL_QUERY_REGISTRY_TABLE KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
  1657. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)KeyQueryTable[3].QueryRoutine;
  1658. NDIS_WARN(TRUE, Miniport, NDIS_GFLAG_WARN_LEVEL_1,
  1659. ("NdisImmediateReadPortUshort: this API is going away. use non-Immediate version\n", Miniport));
  1660. #endif
  1661. ndisImmediateReadWritePort(WrapperConfigurationContext,
  1662. Port,
  1663. (PVOID)Data,
  1664. sizeof (USHORT),
  1665. TRUE);
  1666. }
  1667. VOID
  1668. NdisImmediateReadPortUlong(
  1669. IN NDIS_HANDLE WrapperConfigurationContext,
  1670. IN ULONG Port,
  1671. OUT PULONG Data
  1672. )
  1673. /*++
  1674. Routine Description:
  1675. This routine reads from a port a ULONG. It does all the mapping,
  1676. etc, to do the read here.
  1677. Arguments:
  1678. WrapperConfigurationContext - The handle used to call NdisOpenConfig.
  1679. Port - Port number to read from.
  1680. Data - Pointer to place to store the result.
  1681. Return Value:
  1682. None.
  1683. --*/
  1684. {
  1685. #if DBG
  1686. PRTL_QUERY_REGISTRY_TABLE KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
  1687. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)KeyQueryTable[3].QueryRoutine;
  1688. NDIS_WARN(TRUE, Miniport, NDIS_GFLAG_WARN_LEVEL_1,
  1689. ("NdisImmediateReadPortUlong: this API is going away. use non-Immediate version\n", Miniport));
  1690. #endif
  1691. ndisImmediateReadWritePort(WrapperConfigurationContext,
  1692. Port,
  1693. (PVOID)Data,
  1694. sizeof (ULONG),
  1695. TRUE);
  1696. }
  1697. VOID
  1698. NdisImmediateWritePortUchar(
  1699. IN NDIS_HANDLE WrapperConfigurationContext,
  1700. IN ULONG Port,
  1701. IN UCHAR Data
  1702. )
  1703. /*++
  1704. Routine Description:
  1705. This routine writes to a port a UCHAR. It does all the mapping,
  1706. etc, to do the write here.
  1707. Arguments:
  1708. WrapperConfigurationContext - The handle used to call NdisOpenConfig.
  1709. Port - Port number to read from.
  1710. Data - Pointer to place to store the result.
  1711. Return Value:
  1712. None.
  1713. --*/
  1714. {
  1715. #if DBG
  1716. PRTL_QUERY_REGISTRY_TABLE KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
  1717. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)KeyQueryTable[3].QueryRoutine;
  1718. NDIS_WARN(TRUE, Miniport, NDIS_GFLAG_WARN_LEVEL_1,
  1719. ("NdisImmediateWritePortUchar: this API is going away. use non-Immediate version\n", Miniport));
  1720. #endif
  1721. ndisImmediateReadWritePort(WrapperConfigurationContext,
  1722. Port,
  1723. (PVOID)&Data,
  1724. sizeof (UCHAR),
  1725. FALSE);
  1726. }
  1727. VOID
  1728. NdisImmediateWritePortUshort(
  1729. IN NDIS_HANDLE WrapperConfigurationContext,
  1730. IN ULONG Port,
  1731. IN USHORT Data
  1732. )
  1733. /*++
  1734. Routine Description:
  1735. This routine writes to a port a USHORT. It does all the mapping,
  1736. etc, to do the write here.
  1737. Arguments:
  1738. WrapperConfigurationContext - The handle used to call NdisOpenConfig.
  1739. Port - Port number to read from.
  1740. Data - Pointer to place to store the result.
  1741. Return Value:
  1742. None.
  1743. --*/
  1744. {
  1745. #if DBG
  1746. PRTL_QUERY_REGISTRY_TABLE KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
  1747. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)KeyQueryTable[3].QueryRoutine;
  1748. NDIS_WARN(TRUE, Miniport, NDIS_GFLAG_WARN_LEVEL_1,
  1749. ("NdisImmediateWritePortUshort: this API is going away. use non-Immediate version\n", Miniport));
  1750. #endif
  1751. ndisImmediateReadWritePort(WrapperConfigurationContext,
  1752. Port,
  1753. (PVOID)&Data,
  1754. sizeof (USHORT),
  1755. FALSE);
  1756. }
  1757. VOID
  1758. NdisImmediateWritePortUlong(
  1759. IN NDIS_HANDLE WrapperConfigurationContext,
  1760. IN ULONG Port,
  1761. IN ULONG Data
  1762. )
  1763. /*++
  1764. Routine Description:
  1765. This routine writes to a port a ULONG. It does all the mapping,
  1766. etc, to do the write here.
  1767. Arguments:
  1768. WrapperConfigurationContext - The handle used to call NdisOpenConfig.
  1769. Port - Port number to read from.
  1770. Data - Pointer to place to store the result.
  1771. Return Value:
  1772. None.
  1773. --*/
  1774. {
  1775. #if DBG
  1776. PRTL_QUERY_REGISTRY_TABLE KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
  1777. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)KeyQueryTable[3].QueryRoutine;
  1778. NDIS_WARN(TRUE, Miniport, NDIS_GFLAG_WARN_LEVEL_1,
  1779. ("NdisImmediateWritePortUlong: this API is going away. use non-Immediate version\n", Miniport));
  1780. #endif
  1781. ndisImmediateReadWritePort(WrapperConfigurationContext,
  1782. Port,
  1783. (PVOID)&Data,
  1784. sizeof (ULONG),
  1785. FALSE);
  1786. }
  1787. BOOLEAN
  1788. ndisCheckMemoryUsage(
  1789. IN ULONG u32Address,
  1790. IN PNDIS_MINIPORT_BLOCK Miniport,
  1791. OUT PULONG pTranslatedAddress,
  1792. OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR * pResourceDescriptor
  1793. )
  1794. /*++
  1795. Routine Description:
  1796. This routine checks if a range of memory is currently in use somewhere
  1797. in the system via IoReportUsage -- which fails if there is a conflict.
  1798. Arguments:
  1799. Address - Starting Address of the memory to access.
  1800. Length - Length of memory from the base address to access.
  1801. Return Value:
  1802. FALSE if there is a conflict, else TRUE
  1803. --*/
  1804. {
  1805. PHYSICAL_ADDRESS Address;
  1806. PHYSICAL_ADDRESS u64Address;
  1807. Address.QuadPart = u32Address;
  1808. if (NDIS_STATUS_SUCCESS == ndisTranslateResources(Miniport,
  1809. CmResourceTypeMemory,
  1810. Address,
  1811. &u64Address,
  1812. pResourceDescriptor))
  1813. {
  1814. *pTranslatedAddress = u64Address.LowPart;
  1815. return TRUE;
  1816. }
  1817. else
  1818. {
  1819. *pTranslatedAddress = 0;
  1820. return FALSE;
  1821. }
  1822. }
  1823. VOID
  1824. ndisImmediateReadWriteSharedMemory(
  1825. IN NDIS_HANDLE WrapperConfigurationContext,
  1826. IN ULONG SharedMemoryAddress,
  1827. OUT PUCHAR Buffer,
  1828. IN ULONG Length,
  1829. IN BOOLEAN Read
  1830. )
  1831. /*++
  1832. Routine Description:
  1833. This routine read into a buffer from shared ram. It does all the mapping,
  1834. etc, to do the read here.
  1835. Arguments:
  1836. WrapperConfigurationContext - The handle used to call NdisOpenConfig.
  1837. SharedMemoryAddress - The physical address to read from.
  1838. Buffer - The buffer to read into.
  1839. Length - Length of the buffer in bytes.
  1840. Return Value:
  1841. None.
  1842. --*/
  1843. {
  1844. PRTL_QUERY_REGISTRY_TABLE KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
  1845. PCM_PARTIAL_RESOURCE_DESCRIPTOR pResourceDescriptor = NULL;
  1846. NDIS_INTERFACE_TYPE BusType;
  1847. PNDIS_MINIPORT_BLOCK Miniport;
  1848. BOOLEAN Mapped;
  1849. PVOID MemoryMapping;
  1850. ULONG BusNumber;
  1851. Miniport = (PNDIS_MINIPORT_BLOCK)KeyQueryTable[3].QueryRoutine;
  1852. BusType = Miniport->BusType;
  1853. BusNumber = Miniport->BusNumber;
  1854. ASSERT(Miniport != NULL);
  1855. do
  1856. {
  1857. //
  1858. // Check that the memory is available. Map the space
  1859. //
  1860. if (ndisCheckMemoryUsage(SharedMemoryAddress,
  1861. Miniport,
  1862. (PULONG)&MemoryMapping,
  1863. &pResourceDescriptor
  1864. ) == FALSE)
  1865. {
  1866. //
  1867. // the resource was not part of already allocated resources,
  1868. // nor could we allocate the resource
  1869. //
  1870. break;
  1871. }
  1872. //
  1873. // the port is not part of allocated resources, try to
  1874. // temporray allocate the resource
  1875. //
  1876. if (!NT_SUCCESS(ndisStartMapping((pResourceDescriptor == NULL) ? BusType : -1,
  1877. BusNumber,
  1878. SharedMemoryAddress,
  1879. Length,
  1880. 0,
  1881. &MemoryMapping,
  1882. &Mapped)))
  1883. {
  1884. break;
  1885. }
  1886. if (Read)
  1887. {
  1888. //
  1889. // Read from memory
  1890. //
  1891. #ifdef _M_IX86
  1892. memcpy(Buffer, MemoryMapping, Length);
  1893. #else
  1894. READ_REGISTER_BUFFER_UCHAR(MemoryMapping,Buffer,Length);
  1895. #endif
  1896. }
  1897. else
  1898. {
  1899. //
  1900. // Write to memory
  1901. //
  1902. #ifdef _M_IX86
  1903. memcpy(MemoryMapping, Buffer, Length);
  1904. #else
  1905. WRITE_REGISTER_BUFFER_UCHAR(MemoryMapping,Buffer,Length);
  1906. #endif
  1907. }
  1908. //
  1909. // End mapping
  1910. //
  1911. ndisEndMapping(MemoryMapping,
  1912. Length,
  1913. Mapped);
  1914. } while (FALSE);
  1915. }
  1916. VOID
  1917. NdisImmediateReadSharedMemory(
  1918. IN NDIS_HANDLE WrapperConfigurationContext,
  1919. IN ULONG SharedMemoryAddress,
  1920. OUT PUCHAR Buffer,
  1921. IN ULONG Length
  1922. )
  1923. /*++
  1924. Routine Description:
  1925. This routine read into a buffer from shared ram. It does all the mapping,
  1926. etc, to do the read here.
  1927. Arguments:
  1928. WrapperConfigurationContext - The handle used to call NdisOpenConfig.
  1929. SharedMemoryAddress - The physical address to read from.
  1930. Buffer - The buffer to read into.
  1931. Length - Length of the buffer in bytes.
  1932. Return Value:
  1933. None.
  1934. --*/
  1935. {
  1936. #if DBG
  1937. PRTL_QUERY_REGISTRY_TABLE KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
  1938. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)KeyQueryTable[3].QueryRoutine;
  1939. NDIS_WARN(TRUE, Miniport, NDIS_GFLAG_WARN_LEVEL_1,
  1940. ("NdisImmediateReadSharedMemory: this API is going away. use non-Immediate version\n", Miniport));
  1941. #endif
  1942. ndisImmediateReadWriteSharedMemory(
  1943. WrapperConfigurationContext,
  1944. SharedMemoryAddress,
  1945. Buffer,
  1946. Length,
  1947. TRUE
  1948. );
  1949. }
  1950. VOID
  1951. NdisImmediateWriteSharedMemory(
  1952. IN NDIS_HANDLE WrapperConfigurationContext,
  1953. IN ULONG SharedMemoryAddress,
  1954. IN PUCHAR Buffer,
  1955. IN ULONG Length
  1956. )
  1957. /*++
  1958. Routine Description:
  1959. This routine writes a buffer to shared ram. It does all the mapping,
  1960. etc, to do the write here.
  1961. Arguments:
  1962. WrapperConfigurationContext - The handle used to call NdisOpenConfig.
  1963. SharedMemoryAddress - The physical address to write to.
  1964. Buffer - The buffer to write.
  1965. Length - Length of the buffer in bytes.
  1966. Return Value:
  1967. None.
  1968. --*/
  1969. {
  1970. #if DBG
  1971. PRTL_QUERY_REGISTRY_TABLE KeyQueryTable = (PRTL_QUERY_REGISTRY_TABLE)WrapperConfigurationContext;
  1972. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)KeyQueryTable[3].QueryRoutine;
  1973. NDIS_WARN(TRUE, Miniport, NDIS_GFLAG_WARN_LEVEL_1,
  1974. ("NdisImmediateWriteSharedMemory: this API is going away. use non-Immediate version\n", Miniport));
  1975. #endif
  1976. ndisImmediateReadWriteSharedMemory(
  1977. WrapperConfigurationContext,
  1978. SharedMemoryAddress,
  1979. Buffer,
  1980. Length,
  1981. FALSE
  1982. );
  1983. }
  1984. VOID
  1985. NdisOpenFile(
  1986. OUT PNDIS_STATUS Status,
  1987. OUT PNDIS_HANDLE FileHandle,
  1988. OUT PUINT FileLength,
  1989. IN PNDIS_STRING FileName,
  1990. IN NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress
  1991. )
  1992. /*++
  1993. Routine Description:
  1994. This routine opens a file for future mapping and reads its contents
  1995. into allocated memory.
  1996. Arguments:
  1997. Status - The status of the operation
  1998. FileHandle - A handle to be associated with this open
  1999. FileLength - Returns the length of the file
  2000. FileName - The name of the file
  2001. HighestAcceptableAddress - The highest physical address at which
  2002. the memory for the file can be allocated.
  2003. Return Value:
  2004. None.
  2005. --*/
  2006. {
  2007. NTSTATUS NtStatus;
  2008. IO_STATUS_BLOCK IoStatus;
  2009. HANDLE NtFileHandle;
  2010. OBJECT_ATTRIBUTES ObjectAttributes;
  2011. ULONG LengthOfFile;
  2012. #define PathPrefix L"\\SystemRoot\\system32\\drivers\\"
  2013. NDIS_STRING FullFileName;
  2014. PNDIS_FILE_DESCRIPTOR FileDescriptor;
  2015. PVOID FileImage;
  2016. FILE_STANDARD_INFORMATION StandardInfo;
  2017. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  2018. ("==>NdisOpenFile\n"));
  2019. do
  2020. {
  2021. //
  2022. // Insert the correct path prefix.
  2023. //
  2024. FullFileName.MaximumLength = sizeof(PathPrefix) + FileName->MaximumLength;
  2025. FullFileName.Buffer = ALLOC_FROM_POOL(FullFileName.MaximumLength, NDIS_TAG_FILE_NAME);
  2026. if (FullFileName.Buffer == NULL)
  2027. {
  2028. *Status = NDIS_STATUS_RESOURCES;
  2029. break;
  2030. }
  2031. FullFileName.Length = sizeof (PathPrefix) - sizeof(WCHAR);
  2032. CopyMemory(FullFileName.Buffer, PathPrefix, sizeof(PathPrefix));
  2033. RtlAppendUnicodeStringToString (&FullFileName, FileName);
  2034. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  2035. (" Attempting to open %Z\n", &FullFileName));
  2036. InitializeObjectAttributes(&ObjectAttributes,
  2037. &FullFileName,
  2038. OBJ_CASE_INSENSITIVE,
  2039. NULL,
  2040. NULL);
  2041. NtStatus = ZwCreateFile(&NtFileHandle,
  2042. SYNCHRONIZE | FILE_READ_DATA,
  2043. &ObjectAttributes,
  2044. &IoStatus,
  2045. NULL,
  2046. 0,
  2047. FILE_SHARE_READ,
  2048. FILE_OPEN,
  2049. FILE_SYNCHRONOUS_IO_NONALERT,
  2050. NULL,
  2051. 0);
  2052. FREE_POOL(FullFileName.Buffer);
  2053. if (!NT_SUCCESS(NtStatus))
  2054. {
  2055. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  2056. ("Error opening file %x\n", NtStatus));
  2057. *Status = NDIS_STATUS_FILE_NOT_FOUND;
  2058. break;
  2059. }
  2060. //
  2061. // Query the object to determine its length.
  2062. //
  2063. NtStatus = ZwQueryInformationFile(NtFileHandle,
  2064. &IoStatus,
  2065. &StandardInfo,
  2066. sizeof(FILE_STANDARD_INFORMATION),
  2067. FileStandardInformation);
  2068. if (!NT_SUCCESS(NtStatus))
  2069. {
  2070. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  2071. ("Error querying info on file %x\n", NtStatus));
  2072. ZwClose(NtFileHandle);
  2073. *Status = NDIS_STATUS_ERROR_READING_FILE;
  2074. break;
  2075. }
  2076. LengthOfFile = StandardInfo.EndOfFile.LowPart;
  2077. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_INFO,
  2078. ("File length is %d\n", LengthOfFile));
  2079. //
  2080. // Might be corrupted.
  2081. //
  2082. if (LengthOfFile < 1)
  2083. {
  2084. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  2085. ("Bad file length %d\n", LengthOfFile));
  2086. ZwClose(NtFileHandle);
  2087. *Status = NDIS_STATUS_ERROR_READING_FILE;
  2088. break;
  2089. }
  2090. //
  2091. // Allocate buffer for this file
  2092. //
  2093. FileImage = ALLOC_FROM_POOL(LengthOfFile, NDIS_TAG_FILE_IMAGE);
  2094. if (FileImage == NULL)
  2095. {
  2096. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  2097. ("Could not allocate buffer\n"));
  2098. ZwClose(NtFileHandle);
  2099. *Status = NDIS_STATUS_ERROR_READING_FILE;
  2100. break;
  2101. }
  2102. //
  2103. // Read the file into our buffer.
  2104. //
  2105. NtStatus = ZwReadFile(NtFileHandle,
  2106. NULL,
  2107. NULL,
  2108. NULL,
  2109. &IoStatus,
  2110. FileImage,
  2111. LengthOfFile,
  2112. NULL,
  2113. NULL);
  2114. ZwClose(NtFileHandle);
  2115. if ((!NT_SUCCESS(NtStatus)) || (IoStatus.Information != LengthOfFile))
  2116. {
  2117. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  2118. ("error reading file %x\n", NtStatus));
  2119. *Status = NDIS_STATUS_ERROR_READING_FILE;
  2120. FREE_POOL(FileImage);
  2121. break;
  2122. }
  2123. //
  2124. // Allocate a structure to describe the file.
  2125. //
  2126. FileDescriptor = ALLOC_FROM_POOL(sizeof(NDIS_FILE_DESCRIPTOR), NDIS_TAG_FILE_DESCRIPTOR);
  2127. if (FileDescriptor == NULL)
  2128. {
  2129. *Status = NDIS_STATUS_RESOURCES;
  2130. FREE_POOL(FileImage);
  2131. break;
  2132. }
  2133. FileDescriptor->Data = FileImage;
  2134. INITIALIZE_SPIN_LOCK (&FileDescriptor->Lock);
  2135. FileDescriptor->Mapped = FALSE;
  2136. *FileHandle = (NDIS_HANDLE)FileDescriptor;
  2137. *FileLength = LengthOfFile;
  2138. *Status = STATUS_SUCCESS;
  2139. } while (FALSE);
  2140. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  2141. ("<==NdisOpenFile, Status %.8x\n", *Status));
  2142. }
  2143. VOID
  2144. NdisCloseFile(
  2145. IN NDIS_HANDLE FileHandle
  2146. )
  2147. /*++
  2148. Routine Description:
  2149. This routine closes a file previously opened with NdisOpenFile.
  2150. The file is unmapped if needed and the memory is freed.
  2151. Arguments:
  2152. FileHandle - The handle returned by NdisOpenFile
  2153. Return Value:
  2154. None.
  2155. --*/
  2156. {
  2157. PNDIS_FILE_DESCRIPTOR FileDescriptor = (PNDIS_FILE_DESCRIPTOR)FileHandle;
  2158. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  2159. ("==>NdisCloseFile\n"));
  2160. FREE_POOL(FileDescriptor->Data);
  2161. FREE_POOL(FileDescriptor);
  2162. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  2163. ("<==NdisCloseFile\n"));
  2164. }
  2165. VOID
  2166. NdisMapFile(
  2167. OUT PNDIS_STATUS Status,
  2168. OUT PVOID * MappedBuffer,
  2169. IN NDIS_HANDLE FileHandle
  2170. )
  2171. /*++
  2172. Routine Description:
  2173. This routine maps an open file, so that the contents can be accessed.
  2174. Files can only have one active mapping at any time.
  2175. Arguments:
  2176. Status - The status of the operation
  2177. MappedBuffer - Returns the virtual address of the mapping.
  2178. FileHandle - The handle returned by NdisOpenFile.
  2179. Return Value:
  2180. None.
  2181. --*/
  2182. {
  2183. PNDIS_FILE_DESCRIPTOR FileDescriptor = (PNDIS_FILE_DESCRIPTOR)FileHandle;
  2184. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  2185. ("==>NdisMapFile\n"));
  2186. if (FileDescriptor->Mapped == TRUE)
  2187. {
  2188. *Status = NDIS_STATUS_ALREADY_MAPPED;
  2189. }
  2190. else
  2191. {
  2192. FileDescriptor->Mapped = TRUE;
  2193. *MappedBuffer = FileDescriptor->Data;
  2194. *Status = STATUS_SUCCESS;
  2195. }
  2196. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  2197. ("<==NdisMapFile, Status %.8x \n", *Status));
  2198. }
  2199. VOID
  2200. NdisUnmapFile(
  2201. IN NDIS_HANDLE FileHandle
  2202. )
  2203. /*++
  2204. Routine Description:
  2205. This routine unmaps a file previously mapped with NdisOpenFile.
  2206. The file is unmapped if needed and the memory is freed.
  2207. Arguments:
  2208. FileHandle - The handle returned by NdisOpenFile
  2209. Return Value:
  2210. None.
  2211. --*/
  2212. {
  2213. PNDIS_FILE_DESCRIPTOR FileDescriptor = (PNDIS_FILE_DESCRIPTOR)FileHandle;
  2214. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  2215. ("==>NdisUnmapFile\n"));
  2216. FileDescriptor->Mapped = FALSE;
  2217. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  2218. ("<==NdisUnmapFile\n"));
  2219. }
  2220. CCHAR
  2221. NdisSystemProcessorCount(
  2222. VOID
  2223. )
  2224. {
  2225. return KeNumberProcessors;
  2226. }
  2227. VOID
  2228. NdisGetSystemUpTime(
  2229. OUT PULONG pSystemUpTime
  2230. )
  2231. {
  2232. LARGE_INTEGER TickCount;
  2233. //
  2234. // Get tick count and convert to hundreds of nanoseconds.
  2235. //
  2236. KeQueryTickCount(&TickCount);
  2237. TickCount = RtlExtendedIntegerMultiply(TickCount, (LONG)ndisTimeIncrement);
  2238. TickCount.QuadPart /= 10000;
  2239. ASSERT(TickCount.HighPart == 0);
  2240. *pSystemUpTime = TickCount.LowPart;
  2241. }
  2242. VOID
  2243. NdisGetCurrentProcessorCpuUsage(
  2244. IN PULONG pCpuUsage
  2245. )
  2246. {
  2247. ExGetCurrentProcessorCpuUsage(pCpuUsage);
  2248. }
  2249. VOID
  2250. NdisGetCurrentProcessorCounts(
  2251. OUT PULONG pIdleCount,
  2252. OUT PULONG pKernelAndUser,
  2253. OUT PULONG pIndex
  2254. )
  2255. {
  2256. ExGetCurrentProcessorCounts(pIdleCount, pKernelAndUser, pIndex);
  2257. }
  2258. VOID
  2259. NdisGetCurrentSystemTime(
  2260. IN PLARGE_INTEGER pCurrentTime
  2261. )
  2262. {
  2263. KeQuerySystemTime(pCurrentTime);
  2264. }
  2265. NDIS_STATUS
  2266. NdisQueryMapRegisterCount(
  2267. IN NDIS_INTERFACE_TYPE BusType,
  2268. OUT PUINT MapRegisterCount
  2269. )
  2270. {
  2271. *MapRegisterCount = 0;
  2272. return NDIS_STATUS_NOT_SUPPORTED;
  2273. }
  2274. //
  2275. // NDIS Event support
  2276. //
  2277. VOID
  2278. NdisInitializeEvent(
  2279. IN PNDIS_EVENT Event
  2280. )
  2281. {
  2282. INITIALIZE_EVENT(&Event->Event);
  2283. }
  2284. VOID
  2285. NdisSetEvent(
  2286. IN PNDIS_EVENT Event
  2287. )
  2288. {
  2289. SET_EVENT(&Event->Event);
  2290. }
  2291. VOID
  2292. NdisResetEvent(
  2293. IN PNDIS_EVENT Event
  2294. )
  2295. {
  2296. RESET_EVENT(&Event->Event);
  2297. }
  2298. BOOLEAN
  2299. NdisWaitEvent(
  2300. IN PNDIS_EVENT Event,
  2301. IN UINT MsToWait
  2302. )
  2303. {
  2304. NTSTATUS Status;
  2305. TIME Time, *pTime;
  2306. pTime = NULL;
  2307. if (MsToWait != 0)
  2308. {
  2309. ASSERT(CURRENT_IRQL < DISPATCH_LEVEL);
  2310. Time.QuadPart = Int32x32To64(MsToWait, -10000);
  2311. pTime = &Time;
  2312. }
  2313. Status = WAIT_FOR_OBJECT(&Event->Event, pTime);
  2314. return(Status == NDIS_STATUS_SUCCESS);
  2315. }
  2316. NDIS_STATUS
  2317. NdisScheduleWorkItem(
  2318. IN PNDIS_WORK_ITEM WorkItem
  2319. )
  2320. {
  2321. INITIALIZE_WORK_ITEM((WORK_QUEUE_ITEM *)WorkItem->WrapperReserved,
  2322. ndisWorkItemHandler,
  2323. WorkItem);
  2324. XQUEUE_WORK_ITEM((WORK_QUEUE_ITEM *)WorkItem->WrapperReserved, CriticalWorkQueue);
  2325. return NDIS_STATUS_SUCCESS;
  2326. }
  2327. VOID
  2328. ndisWorkItemHandler(
  2329. IN PNDIS_WORK_ITEM WorkItem
  2330. )
  2331. {
  2332. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  2333. (*WorkItem->Routine)(WorkItem, WorkItem->Context);
  2334. ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
  2335. }
  2336. VOID
  2337. NdisInitializeString(
  2338. OUT PNDIS_STRING Destination,
  2339. IN PUCHAR Source
  2340. )
  2341. /*++
  2342. Routine Description:
  2343. Arguments:
  2344. Return Value:
  2345. --*/
  2346. {
  2347. WCHAR *strptr;
  2348. Destination->Length = strlen(Source) * sizeof(WCHAR);
  2349. Destination->MaximumLength = Destination->Length + sizeof(WCHAR);
  2350. Destination->Buffer = ALLOC_FROM_POOL(Destination->MaximumLength, NDIS_TAG_STRING);
  2351. if (Destination->Buffer != NULL)
  2352. {
  2353. strptr = Destination->Buffer;
  2354. while (*Source != '\0')
  2355. {
  2356. *strptr = (WCHAR)*Source;
  2357. Source++;
  2358. strptr++;
  2359. }
  2360. *strptr = UNICODE_NULL;
  2361. }
  2362. }
  2363. VOID
  2364. NdisSetPacketStatus(
  2365. IN PNDIS_PACKET Packet,
  2366. IN NDIS_STATUS Status,
  2367. IN NDIS_HANDLE Handle,
  2368. IN ULONG Code
  2369. )
  2370. {
  2371. #ifdef TRACK_RECEIVED_PACKETS
  2372. NDIS_STATUS OldStatus = NDIS_GET_PACKET_STATUS(Packet);
  2373. ndisRcvLogfile[ndisRcvLogfileIndex++] = (ULONG_PTR)Packet;
  2374. ndisRcvLogfile[ndisRcvLogfileIndex++] = (ULONG_PTR)Handle;
  2375. ndisRcvLogfile[ndisRcvLogfileIndex++] = (ULONG_PTR)PsGetCurrentThread();
  2376. ndisRcvLogfile[ndisRcvLogfileIndex++] = (ULONG_PTR)((Status<<24) |
  2377. ((OldStatus&0xff)<<16) |
  2378. (Code&0xffff)
  2379. );
  2380. #endif
  2381. NDIS_SET_PACKET_STATUS(Packet, Status);
  2382. }
  2383. VOID
  2384. NdisCopyFromPacketToPacketSafe(
  2385. IN PNDIS_PACKET Destination,
  2386. IN UINT DestinationOffset,
  2387. IN UINT BytesToCopy,
  2388. IN PNDIS_PACKET Source,
  2389. IN UINT SourceOffset,
  2390. OUT PUINT BytesCopied,
  2391. IN MM_PAGE_PRIORITY Priority
  2392. )
  2393. /*++
  2394. Routine Description:
  2395. Copy from an ndis packet to an ndis packet.
  2396. Arguments:
  2397. Destination - The packet should be copied in to.
  2398. DestinationOffset - The offset from the beginning of the packet
  2399. into which the data should start being placed.
  2400. BytesToCopy - The number of bytes to copy from the source packet.
  2401. Source - The ndis packet from which to copy data.
  2402. SourceOffset - The offset from the start of the packet from which
  2403. to start copying data.
  2404. BytesCopied - The number of bytes actually copied from the source
  2405. packet. This can be less than BytesToCopy if the source or destination
  2406. packet is too short.
  2407. Return Value:
  2408. None
  2409. --*/
  2410. {
  2411. //
  2412. // Points to the buffer into which we are putting data.
  2413. //
  2414. PNDIS_BUFFER DestinationCurrentBuffer;
  2415. //
  2416. // Points to the buffer from which we are extracting data.
  2417. //
  2418. PNDIS_BUFFER SourceCurrentBuffer;
  2419. //
  2420. // Holds the virtual address of the current destination buffer.
  2421. //
  2422. PVOID DestinationVirtualAddress;
  2423. //
  2424. // Holds the virtual address of the current source buffer.
  2425. //
  2426. PVOID SourceVirtualAddress;
  2427. //
  2428. // Holds the length of the current destination buffer.
  2429. //
  2430. UINT DestinationCurrentLength;
  2431. //
  2432. // Holds the length of the current source buffer.
  2433. //
  2434. UINT SourceCurrentLength;
  2435. //
  2436. // Keep a local variable of BytesCopied so we aren't referencing
  2437. // through a pointer.
  2438. //
  2439. UINT LocalBytesCopied = 0;
  2440. //
  2441. // Take care of boundary condition of zero length copy.
  2442. //
  2443. *BytesCopied = 0;
  2444. if (!BytesToCopy)
  2445. return;
  2446. //
  2447. // Get the first buffer of the destination.
  2448. //
  2449. // NdisQueryPacket(Destination,
  2450. // NULL,
  2451. // &DestinationBufferCount,
  2452. // &DestinationCurrentBuffer,
  2453. // NULL);
  2454. DestinationCurrentBuffer = Destination->Private.Head;
  2455. if (DestinationCurrentBuffer == NULL)
  2456. return;
  2457. // NdisQueryBuffer(DestinationCurrentBuffer,
  2458. // &DestinationVirtualAddress,
  2459. // &DestinationCurrentLength);
  2460. DestinationVirtualAddress = MmGetSystemAddressForMdlSafe(DestinationCurrentBuffer, Priority);
  2461. if (DestinationVirtualAddress == NULL)
  2462. return;
  2463. DestinationCurrentLength = MmGetMdlByteCount(DestinationCurrentBuffer);
  2464. //
  2465. // Get the first buffer of the source.
  2466. //
  2467. // NdisQueryPacket(Source,
  2468. // NULL,
  2469. // &SourceBufferCount,
  2470. // &SourceCurrentBuffer,
  2471. // NULL);
  2472. SourceCurrentBuffer = Source->Private.Head;
  2473. if (SourceCurrentBuffer == NULL)
  2474. return;
  2475. // NdisQueryBuffer(SourceCurrentBuffer,
  2476. // &SourceVirtualAddress,
  2477. // &SourceCurrentLength);
  2478. SourceVirtualAddress = MmGetSystemAddressForMdlSafe(SourceCurrentBuffer, Priority);
  2479. if (SourceVirtualAddress == NULL)
  2480. return;
  2481. SourceCurrentLength = MmGetMdlByteCount(SourceCurrentBuffer);
  2482. while (LocalBytesCopied < BytesToCopy)
  2483. {
  2484. //
  2485. // Check to see whether we've exhausted the current destination
  2486. // buffer. If so, move onto the next one.
  2487. //
  2488. if (!DestinationCurrentLength)
  2489. {
  2490. // NdisGetNextBuffer(DestinationCurrentBuffer, &DestinationCurrentBuffer);
  2491. DestinationCurrentBuffer = DestinationCurrentBuffer->Next;
  2492. if (!DestinationCurrentBuffer)
  2493. {
  2494. //
  2495. // We've reached the end of the packet. We return
  2496. // with what we've done so far. (Which must be shorter
  2497. // than requested.)
  2498. //
  2499. break;
  2500. }
  2501. // NdisQueryBuffer(DestinationCurrentBuffer,
  2502. // &DestinationVirtualAddress,
  2503. // &DestinationCurrentLength);
  2504. DestinationVirtualAddress = MmGetSystemAddressForMdlSafe(DestinationCurrentBuffer, Priority);
  2505. if (DestinationVirtualAddress == NULL)
  2506. break;
  2507. DestinationCurrentLength = MmGetMdlByteCount(DestinationCurrentBuffer);
  2508. continue;
  2509. }
  2510. //
  2511. // Check to see whether we've exhausted the current source
  2512. // buffer. If so, move onto the next one.
  2513. //
  2514. if (!SourceCurrentLength)
  2515. {
  2516. // NdisGetNextBuffer(SourceCurrentBuffer, &SourceCurrentBuffer);
  2517. SourceCurrentBuffer = SourceCurrentBuffer->Next;
  2518. if (!SourceCurrentBuffer)
  2519. {
  2520. //
  2521. // We've reached the end of the packet. We return
  2522. // with what we've done so far. (Which must be shorter
  2523. // than requested.)
  2524. //
  2525. break;
  2526. }
  2527. // NdisQueryBuffer(SourceCurrentBuffer,
  2528. // &SourceVirtualAddress,
  2529. // &SourceCurrentLength);
  2530. SourceVirtualAddress = MmGetSystemAddressForMdlSafe(SourceCurrentBuffer, Priority);
  2531. if (SourceVirtualAddress == NULL)
  2532. break;
  2533. SourceCurrentLength = MmGetMdlByteCount(SourceCurrentBuffer);
  2534. continue;
  2535. }
  2536. //
  2537. // Try to get us up to the point to start the copy.
  2538. //
  2539. if (DestinationOffset)
  2540. {
  2541. if (DestinationOffset > DestinationCurrentLength)
  2542. {
  2543. //
  2544. // What we want isn't in this buffer.
  2545. //
  2546. DestinationOffset -= DestinationCurrentLength;
  2547. DestinationCurrentLength = 0;
  2548. continue;
  2549. }
  2550. else
  2551. {
  2552. DestinationVirtualAddress = (PCHAR)DestinationVirtualAddress
  2553. + DestinationOffset;
  2554. DestinationCurrentLength -= DestinationOffset;
  2555. DestinationOffset = 0;
  2556. }
  2557. }
  2558. //
  2559. // Try to get us up to the point to start the copy.
  2560. //
  2561. if (SourceOffset)
  2562. {
  2563. if (SourceOffset > SourceCurrentLength)
  2564. {
  2565. //
  2566. // What we want isn't in this buffer.
  2567. //
  2568. SourceOffset -= SourceCurrentLength;
  2569. SourceCurrentLength = 0;
  2570. continue;
  2571. }
  2572. else
  2573. {
  2574. SourceVirtualAddress = (PCHAR)SourceVirtualAddress
  2575. + SourceOffset;
  2576. SourceCurrentLength -= SourceOffset;
  2577. SourceOffset = 0;
  2578. }
  2579. }
  2580. //
  2581. // Copy the data.
  2582. //
  2583. {
  2584. //
  2585. // Holds the amount of data to move.
  2586. //
  2587. UINT AmountToMove;
  2588. //
  2589. // Holds the amount desired remaining.
  2590. //
  2591. UINT Remaining = BytesToCopy - LocalBytesCopied;
  2592. AmountToMove = ((SourceCurrentLength <= DestinationCurrentLength) ?
  2593. (SourceCurrentLength) : (DestinationCurrentLength));
  2594. AmountToMove = ((Remaining < AmountToMove)?
  2595. (Remaining):(AmountToMove));
  2596. CopyMemory(DestinationVirtualAddress, SourceVirtualAddress, AmountToMove);
  2597. DestinationVirtualAddress =
  2598. (PCHAR)DestinationVirtualAddress + AmountToMove;
  2599. SourceVirtualAddress =
  2600. (PCHAR)SourceVirtualAddress + AmountToMove;
  2601. LocalBytesCopied += AmountToMove;
  2602. SourceCurrentLength -= AmountToMove;
  2603. DestinationCurrentLength -= AmountToMove;
  2604. }
  2605. }
  2606. *BytesCopied = LocalBytesCopied;
  2607. }