Leaked source code of windows server 2003
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.

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