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.

1079 lines
19 KiB

  1. //
  2. // Copyright (c) 1998-1999, Microsoft Corporation, all rights reserved
  3. //
  4. // util.c
  5. //
  6. // IEEE1394 mini-port/call-manager driver
  7. //
  8. // General utility routines
  9. //
  10. // 12/28/1998 JosephJ Created, adapted from the l2tp sources.
  11. //
  12. #include "precomp.h"
  13. //-----------------------------------------------------------------------------
  14. // General utility routines (alphabetically)
  15. //-----------------------------------------------------------------------------
  16. VOID
  17. nicSetFlags(
  18. IN OUT ULONG* pulFlags,
  19. IN ULONG ulMask )
  20. // Set 'ulMask' bits in '*pulFlags' flags as an interlocked operation.
  21. //
  22. {
  23. ULONG ulFlags;
  24. ULONG ulNewFlags;
  25. do
  26. {
  27. ulFlags = *pulFlags;
  28. ulNewFlags = ulFlags | ulMask;
  29. }
  30. while (InterlockedCompareExchange(
  31. pulFlags, ulNewFlags, ulFlags ) != (LONG )ulFlags);
  32. }
  33. VOID
  34. nicClearFlags(
  35. IN OUT ULONG* pulFlags,
  36. IN ULONG ulMask )
  37. // Set 'ulMask' bits in '*pulFlags' flags as an interlocked operation.
  38. //
  39. {
  40. ULONG ulFlags;
  41. ULONG ulNewFlags;
  42. do
  43. {
  44. ulFlags = *pulFlags;
  45. ulNewFlags = ulFlags & ~(ulMask);
  46. }
  47. while (InterlockedCompareExchange(
  48. pulFlags, ulNewFlags, ulFlags ) != (LONG )ulFlags);
  49. }
  50. ULONG
  51. nicReadFlags(
  52. IN ULONG* pulFlags )
  53. // Read the value of '*pulFlags' as an interlocked operation.
  54. //
  55. {
  56. return *pulFlags;
  57. }
  58. //
  59. // Reference And Dereference functions taken directly from Ndis
  60. //
  61. BOOLEAN
  62. nicReferenceRef(
  63. IN PREF RefP,
  64. OUT PLONG pNumber
  65. )
  66. /*++
  67. Routine Description:
  68. Adds a reference to an object.
  69. Arguments:
  70. RefP - A pointer to the REFERENCE portion of the object.
  71. Return Value:
  72. TRUE if the reference was added.
  73. FALSE if the object was closing.
  74. --*/
  75. {
  76. BOOLEAN rc = TRUE;
  77. KIRQL OldIrql;
  78. TRACE( TL_V, TM_Ref, ( "nicReferenceRef, %.8x", RefP ) );
  79. if (RefP->Closing)
  80. {
  81. rc = FALSE;
  82. }
  83. else
  84. {
  85. *pNumber = NdisInterlockedIncrement (&RefP->ReferenceCount);
  86. }
  87. TRACE( TL_V, TM_Ref, ( "nicReferenceRef, Bool %.2x, Ref %d", rc, RefP->ReferenceCount ) );
  88. return(rc);
  89. }
  90. BOOLEAN
  91. nicDereferenceRef(
  92. IN PREF RefP,
  93. IN PLONG pRefCount
  94. )
  95. /*++
  96. Routine Description:
  97. Removes a reference to an object.
  98. Arguments:
  99. RefP - A pointer to the REFERENCE portion of the object.
  100. Return Value:
  101. TRUE if the reference count is now 0.
  102. FALSE otherwise.
  103. --*/
  104. {
  105. BOOLEAN rc = FALSE;
  106. KIRQL OldIrql;
  107. ULONG NewRef;
  108. TRACE( TL_V, TM_Ref, ( "==>nicDeReferenceRef, %x", RefP ) );
  109. NewRef = NdisInterlockedDecrement (&RefP->ReferenceCount);
  110. if ((signed long)NewRef < 0)
  111. {
  112. ASSERT ( !"Ref Has Gone BELOW ZERO");
  113. }
  114. if (NewRef == 0)
  115. {
  116. rc = TRUE;
  117. NdisSetEvent (&RefP->RefZeroEvent);
  118. }
  119. *pRefCount = NewRef;
  120. TRACE( TL_V, TM_Ref, ( "<==nicDeReferenceRef, %.2x, RefCount %d", rc, NewRef ) );
  121. return(rc);
  122. }
  123. VOID
  124. nicInitializeRef(
  125. IN PREF RefP
  126. )
  127. /*++
  128. Routine Description:
  129. Initialize a reference count structure.
  130. Arguments:
  131. RefP - The structure to be initialized.
  132. Return Value:
  133. None.
  134. --*/
  135. {
  136. TRACE( TL_V, TM_Ref, ( "==>nicInitializeRef, %.8x", RefP ) );
  137. RefP->Closing = FALSE;
  138. RefP->ReferenceCount = 1;
  139. NdisInitializeEvent (&RefP->RefZeroEvent);
  140. TRACE( TL_V, TM_Ref, ( "<==nicInitializeRef, %.8x", RefP ) );
  141. }
  142. BOOLEAN
  143. nicCloseRef(
  144. IN PREF RefP
  145. )
  146. /*++
  147. Routine Description:
  148. Closes a reference count structure.
  149. Arguments:
  150. RefP - The structure to be closed.
  151. Return Value:
  152. FALSE if it was already closing.
  153. TRUE otherwise.
  154. --*/
  155. {
  156. KIRQL OldIrql;
  157. BOOLEAN rc = TRUE;
  158. TRACE( TL_N, TM_Ref, ( "==>ndisCloseRef, %.8x", RefP ) );
  159. if (RefP->Closing)
  160. {
  161. rc = FALSE;
  162. }
  163. else RefP->Closing = TRUE;
  164. TRACE( TL_N, TM_Ref, ( "<==ndisCloseRef, %.8x, RefCount %.8x", RefP, RefP->ReferenceCount ) );
  165. return(rc);
  166. }
  167. //
  168. // The following #define is used to track RemoteNode references in memory.
  169. //
  170. //
  171. #define LOG_REMOTE_NODE_REF 0
  172. #if LOG_REMOTE_NODE_REF
  173. typedef enum _REF_CHANGE
  174. {
  175. IncrementRef =1,
  176. DecrementRef
  177. }REF_CHANGE, *PREF_CHANGE;
  178. typedef struct _REMOTE_NODE_TRACKER
  179. {
  180. PREMOTE_NODE pRemoteNode;
  181. REMOTE_NODE_REF_CAUSE Cause;
  182. ULONG RefNumber;
  183. REF_CHANGE Change;
  184. }REMOTE_NODE_TRACKER, *PREMOTE_NODE_TRACKER;
  185. #define REMOTE_NODE_TRACKER_SIZE 5000
  186. REMOTE_NODE_TRACKER RemTracker[REMOTE_NODE_TRACKER_SIZE];
  187. ULONG RemTrackerIndex = 0;
  188. VOID
  189. nicFillRemoteNodeTracker(
  190. IN PREMOTE_NODE pRemoteNode,
  191. IN REMOTE_NODE_REF_CAUSE Cause,
  192. IN ULONG RefCount,
  193. IN REF_CHANGE Change
  194. )
  195. {
  196. LONG RemIndex= 0;
  197. RemIndex = NdisInterlockedIncrement (&RemTrackerIndex);
  198. if (RemIndex >= REMOTE_NODE_TRACKER_SIZE)
  199. {
  200. RemIndex = 0;
  201. RemTrackerIndex=0;
  202. }
  203. RemTracker[RemIndex].pRemoteNode = pRemoteNode;
  204. RemTracker[RemIndex].Cause = Cause;
  205. RemTracker[RemIndex].RefNumber = RefCount;
  206. RemTracker[RemIndex].Change = Change;
  207. }
  208. #endif
  209. //
  210. //
  211. // These are self expanatory Remote Node Reference functions
  212. // which will be turned into macros once we have functionality
  213. // working
  214. //
  215. BOOLEAN
  216. nicReferenceRemoteNode (
  217. IN REMOTE_NODE *pPdoCb,
  218. IN REMOTE_NODE_REF_CAUSE Cause
  219. )
  220. /*++
  221. Routine Description:
  222. Arguments:
  223. Return Value:
  224. --*/
  225. {
  226. BOOLEAN bRefClosing = FALSE;
  227. ULONG RefNumber =0;
  228. bRefClosing = nicReferenceRef (&pPdoCb->Ref, &RefNumber);
  229. #if LOG_REMOTE_NODE_REF
  230. nicFillRemoteNodeTracker(pPdoCb, Cause, RefNumber,IncrementRef);
  231. #endif
  232. TRACE( TL_V, TM_RemRef, ( "**nicReferenceRemoteNode pPdoCb %x, to %d, ret %x ",
  233. pPdoCb, pPdoCb->Ref.ReferenceCount, bRefClosing ) );
  234. return bRefClosing ;
  235. }
  236. BOOLEAN
  237. nicDereferenceRemoteNode (
  238. IN REMOTE_NODE *pPdoCb,
  239. IN REMOTE_NODE_REF_CAUSE Cause
  240. )
  241. /*++
  242. Routine Description:
  243. Arguments:
  244. Return Value:
  245. --*/
  246. {
  247. BOOLEAN bRet;
  248. ULONG RefCount = 0;
  249. TRACE( TL_V, TM_RemRef, ( "**nicDereferenceRemoteNode %x to %d",
  250. pPdoCb , pPdoCb->Ref.ReferenceCount -1 ) );
  251. bRet = nicDereferenceRef (&pPdoCb->Ref, &RefCount );
  252. #if LOG_REMOTE_NODE_REF
  253. nicFillRemoteNodeTracker(pPdoCb, Cause, RefCount,DecrementRef);
  254. #endif
  255. return bRet;
  256. }
  257. VOID
  258. nicInitalizeRefRemoteNode(
  259. IN REMOTE_NODE *pPdoCb
  260. )
  261. /*++
  262. Routine Description:
  263. Closes Ref on the remote node
  264. Arguments:
  265. IN REMOTE_NODE *pPdoCb - RemoteNode
  266. Return Value:
  267. None
  268. --*/
  269. {
  270. TRACE( TL_N, TM_Ref, ( "**nicinitalizeRefPdoCb pPdoCb %.8x", pPdoCb ) );
  271. nicInitializeRef (&pPdoCb->Ref);
  272. }
  273. BOOLEAN
  274. nicCloseRefRemoteNode(
  275. IN REMOTE_NODE *pPdoCb
  276. )
  277. /*++
  278. Routine Description:
  279. Closes Ref on the remote node
  280. Arguments:
  281. IN REMOTE_NODE *pPdoCb - RemoteNode
  282. Return Value:
  283. Return value of nicCloseRef
  284. --*/
  285. {
  286. TRACE( TL_N, TM_Ref, ( "**nicClosePdoCb pPdoCb %.8x", pPdoCb ) );
  287. return nicCloseRef (&pPdoCb->Ref);
  288. }
  289. NDIS_STATUS
  290. NtStatusToNdisStatus (
  291. NTSTATUS NtStatus
  292. )
  293. /*++
  294. Routine Description:
  295. Dumps the packet , if the appropriate Debuglevels are set
  296. Arguments:
  297. NTSTATUS NtStatus - NtStatus to be converted
  298. Return Value:
  299. NdisStatus - NtStatus' corresponding NdisStatus
  300. --*/
  301. {
  302. NDIS_STATUS NdisStatus;
  303. switch (NtStatus)
  304. {
  305. case STATUS_SUCCESS:
  306. {
  307. NdisStatus = NDIS_STATUS_SUCCESS;
  308. break;
  309. }
  310. case STATUS_UNSUCCESSFUL:
  311. {
  312. NdisStatus = NDIS_STATUS_FAILURE;
  313. break;
  314. }
  315. case STATUS_PENDING:
  316. {
  317. NdisStatus = NDIS_STATUS_PENDING;
  318. break;
  319. }
  320. case STATUS_INVALID_BUFFER_SIZE:
  321. {
  322. NdisStatus = NDIS_STATUS_INVALID_LENGTH;
  323. break;
  324. }
  325. case STATUS_INSUFFICIENT_RESOURCES:
  326. {
  327. NdisStatus = NDIS_STATUS_RESOURCES;
  328. break;
  329. }
  330. case STATUS_INVALID_GENERATION:
  331. {
  332. NdisStatus = NDIS_STATUS_DEST_OUT_OF_ORDER;
  333. break;
  334. }
  335. case STATUS_ALREADY_COMMITTED:
  336. {
  337. NdisStatus = NDIS_STATUS_RESOURCE_CONFLICT;
  338. break;
  339. }
  340. case STATUS_DEVICE_BUSY:
  341. {
  342. NdisStatus = NDIS_STATUS_MEDIA_BUSY;
  343. break;
  344. }
  345. case STATUS_INVALID_PARAMETER:
  346. {
  347. NdisStatus = NDIS_STATUS_INVALID_DATA;
  348. break;
  349. }
  350. case STATUS_DEVICE_DATA_ERROR:
  351. {
  352. NdisStatus = NDIS_STATUS_DEST_OUT_OF_ORDER;
  353. break;
  354. }
  355. case STATUS_TIMEOUT:
  356. {
  357. NdisStatus = NDIS_STATUS_FAILURE;
  358. break;
  359. }
  360. case STATUS_IO_DEVICE_ERROR:
  361. {
  362. NdisStatus = NDIS_STATUS_NETWORK_UNREACHABLE;
  363. break;
  364. }
  365. default:
  366. {
  367. NdisStatus = NDIS_STATUS_FAILURE;
  368. TRACE( TL_A, TM_Send, ( "Cause: Don't know, INVESTIGATE %x", NtStatus ) );
  369. }
  370. }
  371. return NdisStatus;
  372. }
  373. VOID
  374. nicAllocatePacket(
  375. OUT PNDIS_STATUS pNdisStatus,
  376. OUT PNDIS_PACKET *ppNdisPacket,
  377. IN PNIC_PACKET_POOL pPacketPool
  378. )
  379. /*++
  380. Routine Description:
  381. Calls the ndis API to allocate a packet.
  382. Arguments:
  383. pNdisStatus - pointer to NdisStatus
  384. *ppNdisPacket - Ndis packet Allocated by Ndis,
  385. pPacketPool - packet pool from which the packet is allocated
  386. Return Value:
  387. return value of the call to Ndis
  388. --*/
  389. {
  390. KIRQL OldIrql;
  391. NdisAllocatePacket (pNdisStatus,
  392. ppNdisPacket,
  393. pPacketPool->Handle );
  394. if (*pNdisStatus == NDIS_STATUS_SUCCESS)
  395. {
  396. PRSVD pRsvd = NULL;
  397. PINDICATE_RSVD pIndicateRsvd = NULL;
  398. pRsvd =(PRSVD)((*ppNdisPacket)->ProtocolReserved);
  399. pIndicateRsvd = &pRsvd->IndicateRsvd;
  400. pIndicateRsvd->Tag = NIC1394_TAG_ALLOCATED;
  401. NdisInterlockedIncrement (&pPacketPool->AllocatedPackets);
  402. }
  403. else
  404. {
  405. *ppNdisPacket = NULL;
  406. nicIncrementMallocFailure();
  407. }
  408. }
  409. VOID
  410. nicFreePacket(
  411. IN PNDIS_PACKET pNdisPacket,
  412. IN PNIC_PACKET_POOL pPacketPool
  413. )
  414. /*++
  415. Routine Description:
  416. Free the packet and decrements the outstanding Packet count.
  417. Arguments:
  418. IN PNDIS_PACKET pNdisPacket - Packet to be freed
  419. IN PNIC_PACKET_POOL pPacketPool - PacketPool to which the packet belongs
  420. Return Value:
  421. None
  422. --*/
  423. {
  424. KIRQL OldIrql;
  425. PRSVD pRsvd = NULL;
  426. PINDICATE_RSVD pIndicateRsvd = NULL;
  427. pRsvd =(PRSVD)(pNdisPacket->ProtocolReserved);
  428. pIndicateRsvd = &pRsvd->IndicateRsvd;
  429. pIndicateRsvd->Tag = NIC1394_TAG_FREED;
  430. NdisInterlockedDecrement (&pPacketPool->AllocatedPackets);
  431. NdisFreePacket (pNdisPacket);
  432. }
  433. VOID
  434. nicFreePacketPool (
  435. IN PNIC_PACKET_POOL pPacketPool
  436. )
  437. /*++
  438. Routine Description:
  439. frees the packet pool after waiting for the outstanding packet count to go to zero
  440. Arguments:
  441. IN PNIC_PACKET_POOL pPacketPool - PacketPool which is to be freed
  442. Return Value:
  443. None
  444. --*/
  445. {
  446. ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
  447. while (NdisPacketPoolUsage (pPacketPool->Handle)!=0)
  448. {
  449. TRACE( TL_V, TM_Cm, ( " Waiting PacketPool %x, AllocatedPackets %x",
  450. pPacketPool->Handle, pPacketPool->AllocatedPackets ) );
  451. NdisMSleep (10000);
  452. }
  453. NdisFreePacketPool (pPacketPool->Handle);
  454. pPacketPool->Handle = NULL;
  455. ASSERT (pPacketPool->AllocatedPackets == 0);
  456. }
  457. VOID
  458. nicAcquireSpinLock (
  459. IN PNIC_SPIN_LOCK pNicSpinLock,
  460. IN PUCHAR FileName,
  461. IN UINT LineNumber
  462. )
  463. /*++
  464. Routine Description:
  465. Acquires a spin lock and if the Dbg, then it will spew out the line and file
  466. Arguments:
  467. NIC_SPIN_LOCK - Lock to be acquired
  468. Return Value:
  469. None
  470. --*/
  471. {
  472. PKTHREAD pThread;
  473. TRACE (TL_V, TM_Lock, ("Lock %x, Acquired by File %s, Line %x" , pNicSpinLock, FileName, LineNumber)) ;
  474. NdisAcquireSpinLock(&(pNicSpinLock->NdisLock));
  475. #if TRACK_LOCKS
  476. pThread = KeGetCurrentThread();
  477. pNicSpinLock->OwnerThread = pThread;
  478. NdisMoveMemory(pNicSpinLock->TouchedByFileName, FileName, LOCK_FILE_NAME_LEN);
  479. pNicSpinLock->TouchedByFileName[LOCK_FILE_NAME_LEN - 1] = 0x0;
  480. pNicSpinLock->TouchedInLineNumber = LineNumber;
  481. pNicSpinLock->IsAcquired++;
  482. #endif
  483. }
  484. VOID
  485. nicReleaseSpinLock (
  486. IN PNIC_SPIN_LOCK pNicSpinLock,
  487. IN PUCHAR FileName,
  488. IN UINT LineNumber
  489. )
  490. /*++
  491. Routine Description:
  492. Release a spin lock and if Dbg is On, then it will spew out the line and file
  493. Arguments:
  494. pNicSpinLock - Lock to be Release
  495. FileName - File Name
  496. LineNumber - Line
  497. Return Value:
  498. None
  499. --*/
  500. {
  501. PKTHREAD pThread;
  502. TRACE (TL_V, TM_Lock, ("Lock %x, Released by File %s, Line %x" , pNicSpinLock, FileName, LineNumber)) ;
  503. #if TRACK_LOCKS
  504. pThread = KeGetCurrentThread();
  505. NdisMoveMemory(pNicSpinLock->TouchedByFileName, FileName, LOCK_FILE_NAME_LEN);
  506. pNicSpinLock->TouchedByFileName[LOCK_FILE_NAME_LEN - 1] = 0x0;
  507. pNicSpinLock->TouchedInLineNumber = LineNumber;
  508. pNicSpinLock->IsAcquired--;
  509. pNicSpinLock->OwnerThread = 0;
  510. #endif
  511. NdisReleaseSpinLock(&(pNicSpinLock->NdisLock));
  512. }
  513. VOID
  514. nicInitializeNicSpinLock (
  515. IN PNIC_SPIN_LOCK pNicSpinLock
  516. )
  517. /*++
  518. Routine Description:
  519. Initializes the lock in the SpinLock
  520. Arguments:
  521. pNicSpinLock - SpinLock
  522. Return Value:
  523. None
  524. --*/
  525. {
  526. NdisAllocateSpinLock (&pNicSpinLock->NdisLock);
  527. }
  528. VOID
  529. nicFreeNicSpinLock (
  530. IN PNIC_SPIN_LOCK pNicSpinLock
  531. )
  532. /*++
  533. Routine Description:
  534. Frees the spinlock
  535. Arguments:
  536. pNicSpinLock - SpinLock
  537. Return Value:
  538. None
  539. --*/
  540. {
  541. ASSERT ((ULONG)pNicSpinLock->NdisLock.SpinLock == 0);
  542. NdisFreeSpinLock (&pNicSpinLock->NdisLock);
  543. }
  544. UINT
  545. nicGetSystemTime(
  546. VOID
  547. )
  548. /*++
  549. Returns system time in seconds.
  550. Since it's in seconds, we won't overflow unless the system has been up
  551. for over
  552. a 100 years :-)
  553. --*/
  554. {
  555. LARGE_INTEGER Time;
  556. NdisGetCurrentSystemTime(&Time);
  557. Time.QuadPart /= 10000000; //100-nanoseconds to seconds.
  558. return Time.LowPart;
  559. }
  560. UINT
  561. nicGetSystemTimeMilliSeconds(
  562. VOID
  563. )
  564. /*++
  565. Returns system time in seconds.
  566. Since it's in seconds, we won't overflow unless the system has been up
  567. for over
  568. a 100 years :-)
  569. --*/
  570. {
  571. LARGE_INTEGER Time;
  572. NdisGetCurrentSystemTime(&Time);
  573. Time.QuadPart /= 10000; //10-nanoseconds to seconds.
  574. return Time.LowPart;
  575. }
  576. ULONG
  577. SwapBytesUlong(
  578. IN ULONG Val)
  579. {
  580. return ((((Val) & 0x000000ff) << 24) | (((Val) & 0x0000ff00) << 8) | (((Val) & 0x00ff0000) >> 8) | (((Val) & 0xff000000) >> 24) );
  581. }
  582. void
  583. nicTimeStamp(
  584. char *szFormatString,
  585. UINT Val
  586. )
  587. /*++
  588. Routine Description:
  589. Execute and print a time stamp
  590. Arguments:
  591. Return Value:
  592. --*/
  593. {
  594. UINT Minutes;
  595. UINT Seconds;
  596. UINT Milliseconds;
  597. LARGE_INTEGER Time;
  598. NdisGetCurrentSystemTime(&Time);
  599. Time.QuadPart /= 10000; //10-nanoseconds to milliseconds.
  600. Milliseconds = Time.LowPart; // don't care about highpart.
  601. Seconds = Milliseconds/1000;
  602. Milliseconds %= 1000;
  603. Minutes = Seconds/60;
  604. Seconds %= 60;
  605. DbgPrint( szFormatString, Minutes, Seconds, Milliseconds, Val);
  606. }
  607. VOID
  608. nicDumpPkt (
  609. IN PNDIS_PACKET pPacket,
  610. CHAR * str
  611. )
  612. /*++
  613. Routine Description:
  614. This functions is used for Debugging in runtime. If the global variable
  615. is set, then it will spew out the MDLs onto the debuggger.
  616. Arguments:
  617. Return Value:
  618. --*/
  619. {
  620. PNDIS_BUFFER pBuffer;
  621. extern BOOLEAN g_ulNicDumpPacket ;
  622. if ( g_ulNicDumpPacket == FALSE)
  623. {
  624. return ;
  625. }
  626. pBuffer = pPacket->Private.Head;
  627. DbgPrint (str);
  628. DbgPrint ("Packet %p TotLen %x", pPacket, pPacket->Private.TotalLength);
  629. do
  630. {
  631. ULONG Length = nicNdisBufferLength (pBuffer);
  632. PUCHAR pVa = nicNdisBufferVirtualAddress (pBuffer);
  633. DbgPrint ("pBuffer %p, Len %x \n", pBuffer, Length);
  634. Dump( pVa, Length, 0, 1 );
  635. pBuffer = pBuffer->Next;
  636. } while (pBuffer != NULL);
  637. }
  638. VOID
  639. nicDumpMdl (
  640. IN PMDL pMdl,
  641. IN ULONG LengthToPrint,
  642. IN CHAR *str
  643. )
  644. {
  645. ULONG MdlLength ;
  646. PUCHAR pVa;
  647. extern BOOLEAN g_ulNicDumpPacket ;
  648. if ( g_ulNicDumpPacket == FALSE )
  649. {
  650. return;
  651. }
  652. MdlLength = MmGetMdlByteCount(pMdl);
  653. //
  654. // if Length is zero then use MdlLength
  655. //
  656. if (LengthToPrint == 0)
  657. {
  658. LengthToPrint = MdlLength;
  659. }
  660. //
  661. // Check for invalid length
  662. //
  663. if (MdlLength < LengthToPrint)
  664. {
  665. return;
  666. }
  667. pVa = MmGetSystemAddressForMdlSafe(pMdl,LowPagePriority );
  668. if (pVa == NULL)
  669. {
  670. return;
  671. }
  672. DbgPrint (str);
  673. DbgPrint ("pMdl %p, Len %x\n", pMdl, LengthToPrint);
  674. Dump( pVa, LengthToPrint, 0, 1 );
  675. }
  676. NDIS_STATUS
  677. nicScheduleWorkItem (
  678. IN PADAPTERCB pAdapter,
  679. IN PNDIS_WORK_ITEM pWorkItem
  680. )
  681. /*++
  682. Routine Description:
  683. This function schedules a WorkItem to fire.
  684. It references the Adapter object by incrementing the number of
  685. outstanding workitems.
  686. In case of failure, it decrements the count.
  687. Arguments:
  688. Self explanatory
  689. Return Value:
  690. Success - appropriate failure code from NdisScheduleWorkItem
  691. --*/
  692. {
  693. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  694. NdisInterlockedIncrement(&pAdapter->OutstandingWorkItems);
  695. NdisStatus = NdisScheduleWorkItem (pWorkItem);
  696. if(NDIS_STATUS_SUCCESS != NdisStatus)
  697. {
  698. NdisInterlockedDecrement (&pAdapter->OutstandingWorkItems);
  699. }
  700. return NdisStatus;
  701. }