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.

839 lines
19 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. util.c
  5. Abstract:
  6. ATMEPVC - utilities
  7. Author:
  8. Revision History:
  9. Who When What
  10. -------- -------- ----
  11. ADube 03-23-00 created, .
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #if DO_TIMESTAMPS
  16. void
  17. epvcTimeStamp(
  18. char *szFormatString,
  19. UINT Val
  20. )
  21. {
  22. UINT Minutes;
  23. UINT Seconds;
  24. UINT Milliseconds;
  25. LARGE_INTEGER Time;
  26. NdisGetCurrentSystemTime(&Time);
  27. Time.QuadPart /= 10000; //10-nanoseconds to milliseconds.
  28. Milliseconds = Time.LowPart; // don't care about highpart.
  29. Seconds = Milliseconds/1000;
  30. Milliseconds %= 1000;
  31. Minutes = Seconds/60;
  32. Seconds %= 60;
  33. DbgPrint( szFormatString, Minutes, Seconds, Milliseconds, Val);
  34. }
  35. #endif // DO_TIMESTAMPS
  36. //------------------------------------------------------------------------
  37. // //
  38. // Task Data structures and functions begin here //
  39. // //
  40. //----------------------------------------------------------------------//
  41. //
  42. // EpvcTasks_StaticInfo contains static information about
  43. // objects of type EPVC_TASK;
  44. //
  45. RM_STATIC_OBJECT_INFO
  46. EpvcTasks_StaticInfo =
  47. {
  48. 0, // TypeUID
  49. 0, // TypeFlags
  50. "ATM Epvc Task", // TypeName
  51. 0, // Timeout
  52. NULL, // pfnCreate
  53. epvcTaskDelete, // pfnDelete
  54. NULL, // LockVerifier
  55. 0, // length of resource table
  56. NULL // Resource Table
  57. };
  58. VOID
  59. epvcTaskDelete (
  60. PRM_OBJECT_HEADER pObj,
  61. PRM_STACK_RECORD psr
  62. )
  63. /*++
  64. Routine Description:
  65. Free an object of type EPVC_TASK.
  66. Arguments:
  67. pHdr - Actually a pointer to the EPVC_TASK to be deleted.
  68. --*/
  69. {
  70. EPVC_FREE(pObj);
  71. }
  72. NDIS_STATUS
  73. epvcAllocateTask(
  74. IN PRM_OBJECT_HEADER pParentObject,
  75. IN PFN_RM_TASK_HANDLER pfnHandler,
  76. IN UINT Timeout,
  77. IN const char * szDescription, OPTIONAL
  78. OUT PRM_TASK *ppTask,
  79. IN PRM_STACK_RECORD pSR
  80. )
  81. /*++
  82. Routine Description:
  83. Allocates and initializes a task of subtype ARP1394_TASK.
  84. Arguments:
  85. pParentObject - Object that is to be the parent of the allocated task.
  86. pfnHandler - The task handler for the task.
  87. Timeout - Unused.
  88. szDescription - Text describing this task.
  89. ppTask - Place to store pointer to the new task.
  90. Return Value:
  91. NDIS_STATUS_SUCCESS if we could allocate and initialize the task.
  92. NDIS_STATUS_RESOURCES otherwise
  93. --*/
  94. {
  95. EPVC_TASK *pATask;
  96. NDIS_STATUS Status;
  97. Status = EPVC_ALLOCSTRUCT(pATask, TAG_TASK); // TODO use lookaside lists.
  98. *ppTask = NULL;
  99. if (pATask != NULL && (FAIL(Status)== FALSE))
  100. {
  101. EPVC_ZEROSTRUCT(pATask);
  102. RmInitializeTask(
  103. &(pATask->TskHdr),
  104. pParentObject,
  105. pfnHandler,
  106. &EpvcTasks_StaticInfo,
  107. szDescription,
  108. Timeout,
  109. pSR
  110. );
  111. *ppTask = &(pATask->TskHdr);
  112. Status = NDIS_STATUS_SUCCESS;
  113. }
  114. else
  115. {
  116. Status = NDIS_STATUS_RESOURCES;
  117. }
  118. return Status;
  119. }
  120. NDIS_STATUS
  121. epvcAllocateTaskUsingLookasideList(
  122. IN PRM_OBJECT_HEADER pParentObject,
  123. IN PEPVC_NPAGED_LOOKASIDE_LIST pList,
  124. IN PFN_RM_TASK_HANDLER pfnHandler,
  125. IN UINT Timeout,
  126. IN const char * szDescription, OPTIONAL
  127. OUT PRM_TASK *ppTask,
  128. IN PRM_STACK_RECORD pSR
  129. )
  130. /*++
  131. Routine Description:
  132. Allocates and initializes a task of subtype ARP1394_TASK.
  133. Arguments:
  134. pParentObject - Object that is to be the parent of the allocated task.
  135. pfnHandler - The task handler for the task.
  136. Timeout - Unused.
  137. szDescription - Text describing this task.
  138. ppTask - Place to store pointer to the new task.
  139. Return Value:
  140. NDIS_STATUS_SUCCESS if we could allocate and initialize the task.
  141. NDIS_STATUS_RESOURCES otherwise
  142. --*/
  143. {
  144. EPVC_TASK *pATask;
  145. NDIS_STATUS Status;
  146. pATask = epvcGetLookasideBuffer (pList);
  147. Status = EPVC_ALLOCSTRUCT(pATask, TAG_TASK); // TODO use lookaside lists.
  148. *ppTask = NULL;
  149. if (pATask != NULL && (FAIL(Status)== FALSE))
  150. {
  151. EPVC_ZEROSTRUCT(pATask);
  152. RmInitializeTask(
  153. &(pATask->TskHdr),
  154. pParentObject,
  155. pfnHandler,
  156. &EpvcTasks_StaticInfo,
  157. szDescription,
  158. Timeout,
  159. pSR
  160. );
  161. *ppTask = &(pATask->TskHdr);
  162. Status = NDIS_STATUS_SUCCESS;
  163. }
  164. else
  165. {
  166. Status = NDIS_STATUS_RESOURCES;
  167. }
  168. return Status;
  169. }
  170. VOID
  171. epvcSetPrimaryAdapterTask(
  172. PEPVC_ADAPTER pAdapter, // LOCKIN LOCKOUT
  173. PRM_TASK pTask,
  174. ULONG PrimaryState,
  175. PRM_STACK_RECORD pSR
  176. )
  177. {
  178. ENTER("epvcSetPrimaryAdapterTask", 0x49c9e2d5)
  179. RM_ASSERT_OBJLOCKED(&pAdapter->Hdr, pSR);
  180. ASSERT(pAdapter->bind.pPrimaryTask==NULL);
  181. #if DBG
  182. // Veriy that this is a valid primary task. Also verify that PrimaryState
  183. // is a valid primary state.
  184. //
  185. {
  186. PFN_RM_TASK_HANDLER pfn = pTask->pfnHandler;
  187. ASSERT(
  188. ((pfn == epvcTaskInitializeAdapter) && (PrimaryState == EPVC_AD_PS_INITING))
  189. || ((pfn == epvcTaskShutdownAdapter) && (PrimaryState == EPVC_AD_PS_DEINITING))
  190. );
  191. }
  192. #endif // DBG
  193. //
  194. // Although it's tempting to put pTask as entity1 and pRask->Hdr.szDescption as
  195. // entity2 below, we specify NULL for both so that we can be sure that ONLY one
  196. // primary task can be active at any one time.
  197. //
  198. DBG_ADDASSOC(
  199. &pAdapter->Hdr,
  200. NULL, // Entity1
  201. NULL, // Entity2
  202. EPVC_ASSOC_AD_PRIMARY_TASK,
  203. " Primary task\n",
  204. pSR
  205. );
  206. pAdapter->bind.pPrimaryTask = pTask;
  207. SET_AD_PRIMARY_STATE(pAdapter, PrimaryState);
  208. EXIT()
  209. }
  210. VOID
  211. epvcClearPrimaryAdapterTask(
  212. PEPVC_ADAPTER pAdapter, // LOCKIN LOCKOUT
  213. PRM_TASK pTask,
  214. ULONG PrimaryState,
  215. PRM_STACK_RECORD pSR
  216. )
  217. {
  218. ENTER("epvcClearPrimaryAdapterTask", 0x593087b1)
  219. RM_ASSERT_OBJLOCKED(&pAdapter->Hdr, pSR);
  220. ASSERT(pAdapter->bind.pPrimaryTask==pTask);
  221. // Veriy that PrimaryState is a valid primary state.
  222. //
  223. ASSERT(
  224. (PrimaryState == EPVC_AD_PS_INITED)
  225. || (PrimaryState == EPVC_AD_PS_FAILEDINIT)
  226. || (PrimaryState == EPVC_AD_PS_DEINITED)
  227. );
  228. // Delete the association added when setting the primary IF task
  229. //
  230. DBG_DELASSOC(
  231. &pAdapter->Hdr,
  232. NULL,
  233. NULL,
  234. EPVC_ASSOC_AD_PRIMARY_TASK,
  235. pSR
  236. );
  237. pAdapter->bind.pPrimaryTask = NULL;
  238. SET_AD_PRIMARY_STATE(pAdapter, PrimaryState);
  239. EXIT()
  240. }
  241. VOID
  242. epvcSetSecondaryAdapterTask(
  243. PEPVC_ADAPTER pAdapter, // LOCKIN LOCKOUT
  244. PRM_TASK pTask,
  245. ULONG SecondaryState,
  246. PRM_STACK_RECORD pSR
  247. )
  248. {
  249. ENTER("epvcSetSecondaryAdapterTask", 0x56bbb567)
  250. RM_ASSERT_OBJLOCKED(&pAdapter->Hdr, pSR);
  251. if (pAdapter->bind.pSecondaryTask != NULL)
  252. {
  253. ASSERT(FALSE);
  254. return; // EARLY RETURN
  255. }
  256. #if DBG
  257. // Veriy that this is a valid act/deact task. Also verify that SecondaryState
  258. // is a valid state.
  259. //
  260. {
  261. PFN_RM_TASK_HANDLER pfn = pTask->pfnHandler;
  262. ASSERT(
  263. ((pfn == epvcTaskActivateAdapter) && (SecondaryState == EPVC_AD_AS_ACTIVATING))
  264. || ((pfn == epvcTaskDeactivateAdapter) && (SecondaryState == EPVC_AD_AS_DEACTIVATING))
  265. );
  266. }
  267. #endif // DBG
  268. //
  269. // Although it's tempting to put pTask as entity1 and pRask->Hdr.szDescption as
  270. // entity2 below, we specify NULL for both so that we can be sure that ONLY one
  271. // primary task can be active at any one time.
  272. //
  273. DBG_ADDASSOC(
  274. &pAdapter->Hdr,
  275. NULL, // Entity1
  276. NULL, // Entity2
  277. EPVC_ASSOC_ACTDEACT_AD_TASK,
  278. " Secondary task\n",
  279. pSR
  280. );
  281. pAdapter->bind.pSecondaryTask = pTask;
  282. SET_AD_ACTIVE_STATE(pAdapter, SecondaryState);
  283. EXIT()
  284. }
  285. VOID
  286. epvcClearSecondaryAdapterTask(
  287. PEPVC_ADAPTER pAdapter, // LOCKIN LOCKOUT
  288. PRM_TASK pTask,
  289. ULONG SecondaryState,
  290. PRM_STACK_RECORD pSR
  291. )
  292. {
  293. ENTER("epvcClearSecondaryAdapterTask", 0x698552bd)
  294. RM_ASSERT_OBJLOCKED(&pAdapter->Hdr, pSR);
  295. if (pAdapter->bind.pSecondaryTask != pTask)
  296. {
  297. ASSERT(FALSE);
  298. return; // EARLY RETURN
  299. }
  300. // Veriy that SecondaryState is a valid primary state.
  301. //
  302. ASSERT(
  303. (SecondaryState == EPVC_AD_AS_ACTIVATED)
  304. || (SecondaryState == EPVC_AD_AS_FAILEDACTIVATE)
  305. || (SecondaryState == EPVC_AD_AS_DEACTIVATED)
  306. );
  307. // Delete the association added when setting the primary IF task
  308. //
  309. DBG_DELASSOC(
  310. &pAdapter->Hdr,
  311. NULL,
  312. NULL,
  313. EPVC_ASSOC_ACTDEACT_AD_TASK,
  314. pSR
  315. );
  316. pAdapter->bind.pSecondaryTask = NULL;
  317. SET_AD_ACTIVE_STATE(pAdapter, SecondaryState);
  318. EXIT()
  319. }
  320. NDIS_STATUS
  321. epvcCopyUnicodeString(
  322. OUT PNDIS_STRING pDest,
  323. IN PNDIS_STRING pSrc,
  324. BOOLEAN fUpCase
  325. )
  326. /*++
  327. Routine Description:
  328. Copy the contents of unicode string pSrc into pDest.
  329. pDest->Buffer is allocated using NdisAllocateMemoryWithTag; Caller is
  330. responsible for freeing it.
  331. EXTRA EXTRA EXTRA:
  332. This make sure the destination is NULL terminated.
  333. IPAddInterface expects the Unicode string passed in to be
  334. NULL terminated.
  335. Return Value:
  336. NDIS_STATUS_SUCCESS on success;
  337. NDIS failure status on failure.
  338. --*/
  339. {
  340. USHORT Length = pSrc->Length;
  341. PWCHAR pwStr;
  342. epvcAllocateMemoryWithTag(&pwStr, Length+sizeof(WCHAR), MTAG_STRING);
  343. EPVC_ZEROSTRUCT(pDest);
  344. if (pwStr == NULL)
  345. {
  346. return NDIS_STATUS_RESOURCES;
  347. }
  348. else
  349. {
  350. pDest->Length = Length;
  351. pDest->MaximumLength = Length+sizeof(WCHAR);
  352. pDest->Buffer = pwStr;
  353. {
  354. NdisMoveMemory(pwStr, pSrc->Buffer, Length);
  355. if (Length & 0x1)
  356. {
  357. ((PUCHAR)pwStr)[Length] = 0;
  358. }
  359. else
  360. {
  361. pwStr[Length/sizeof(*pwStr)] = 0;
  362. }
  363. }
  364. return NDIS_STATUS_SUCCESS;
  365. }
  366. }
  367. VOID
  368. epvcSetFlags(
  369. IN OUT ULONG* pulFlags,
  370. IN ULONG ulMask )
  371. // Set 'ulMask' bits in '*pulFlags' flags as an interlocked operation.
  372. //
  373. {
  374. ULONG ulFlags;
  375. ULONG ulNewFlags;
  376. do
  377. {
  378. ulFlags = *pulFlags;
  379. ulNewFlags = ulFlags | ulMask;
  380. }
  381. while (InterlockedCompareExchange(
  382. pulFlags, ulNewFlags, ulFlags ) != (LONG )ulFlags);
  383. }
  384. VOID
  385. epvcClearFlags(
  386. IN OUT ULONG* pulFlags,
  387. IN ULONG ulMask )
  388. // Set 'ulMask' bits in '*pulFlags' flags as an interlocked operation.
  389. //
  390. {
  391. ULONG ulFlags;
  392. ULONG ulNewFlags;
  393. do
  394. {
  395. ulFlags = *pulFlags;
  396. ulNewFlags = ulFlags & ~(ulMask);
  397. }
  398. while (InterlockedCompareExchange(
  399. pulFlags, ulNewFlags, ulFlags ) != (LONG )ulFlags);
  400. }
  401. ULONG
  402. epvcReadFlags(
  403. IN ULONG* pulFlags )
  404. // Read the value of '*pulFlags' as an interlocked operation.
  405. //
  406. {
  407. return *pulFlags;
  408. }
  409. BOOLEAN
  410. epvcIsThisTaskPrimary (
  411. PRM_TASK pTask,
  412. PRM_TASK* ppLocation
  413. )
  414. {
  415. BOOLEAN fIsThisTaskPrimary = FALSE;
  416. ASSERT (*ppLocation != pTask);
  417. if (*ppLocation == NULL)
  418. {
  419. *ppLocation = pTask;
  420. return TRUE;
  421. }
  422. else
  423. {
  424. return FALSE;
  425. }
  426. }
  427. VOID
  428. epvcClearPrimaryTask (
  429. PRM_TASK* ppLocation
  430. )
  431. {
  432. *ppLocation = NULL;
  433. }
  434. #if DBG
  435. VOID
  436. CheckList(
  437. IN LIST_ENTRY* pList,
  438. IN BOOLEAN fShowLinks )
  439. // Tries to detect corruption in list 'pList', printing verbose linkage
  440. // output if 'fShowLinks' is set.
  441. //
  442. {
  443. LIST_ENTRY* pLink;
  444. ULONG ul;
  445. ul = 0;
  446. for (pLink = pList->Flink;
  447. pLink != pList;
  448. pLink = pLink->Flink)
  449. {
  450. if (fShowLinks)
  451. {
  452. DbgPrint( "EPVC: CheckList($%p) Flink(%d)=$%p\n",
  453. pList, ul, pLink );
  454. }
  455. ++ul;
  456. }
  457. for (pLink = pList->Blink;
  458. pLink != pList;
  459. pLink = pLink->Blink)
  460. {
  461. if (fShowLinks)
  462. {
  463. DbgPrint( "EPVC: CheckList($%p) Blink(%d)=$%p\n",
  464. pList, ul, pLink );
  465. }
  466. --ul;
  467. }
  468. if (ul)
  469. {
  470. DbgBreakPoint();
  471. }
  472. }
  473. #endif
  474. #if DBG
  475. VOID
  476. Dump(
  477. IN CHAR* p,
  478. IN ULONG cb,
  479. IN BOOLEAN fAddress,
  480. IN ULONG ulGroup )
  481. // Hex dump 'cb' bytes starting at 'p' grouping 'ulGroup' bytes together.
  482. // For example, with 'ulGroup' of 1, 2, and 4:
  483. //
  484. // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
  485. // 0000 0000 0000 0000 0000 0000 0000 0000 |................|
  486. // 00000000 00000000 00000000 00000000 |................|
  487. //
  488. // If 'fAddress' is true, the memory address dumped is prepended to each
  489. // line.
  490. //
  491. {
  492. while (cb)
  493. {
  494. INT cbLine;
  495. cbLine = (cb < DUMP_BytesPerLine) ? cb : DUMP_BytesPerLine;
  496. DumpLine( p, cbLine, fAddress, ulGroup );
  497. cb -= cbLine;
  498. p += cbLine;
  499. }
  500. }
  501. #endif
  502. #if DBG
  503. VOID
  504. DumpLine(
  505. IN CHAR* p,
  506. IN ULONG cb,
  507. IN BOOLEAN fAddress,
  508. IN ULONG ulGroup )
  509. {
  510. CHAR* pszDigits = "0123456789ABCDEF";
  511. CHAR szHex[ ((2 + 1) * DUMP_BytesPerLine) + 1 ];
  512. CHAR* pszHex = szHex;
  513. CHAR szAscii[ DUMP_BytesPerLine + 1 ];
  514. CHAR* pszAscii = szAscii;
  515. ULONG ulGrouped = 0;
  516. if (fAddress)
  517. DbgPrint( "EPVC: %p: ", p );
  518. else
  519. DbgPrint( "EPVC: " );
  520. while (cb)
  521. {
  522. *pszHex++ = pszDigits[ ((UCHAR )*p) / 16 ];
  523. *pszHex++ = pszDigits[ ((UCHAR )*p) % 16 ];
  524. if (++ulGrouped >= ulGroup)
  525. {
  526. *pszHex++ = ' ';
  527. ulGrouped = 0;
  528. }
  529. *pszAscii++ = (*p >= 32 && *p < 128) ? *p : '.';
  530. ++p;
  531. --cb;
  532. }
  533. *pszHex = '\0';
  534. *pszAscii = '\0';
  535. DbgPrint(
  536. "%-*s|%-*s|\n",
  537. (2 * DUMP_BytesPerLine) + (DUMP_BytesPerLine / ulGroup), szHex,
  538. DUMP_BytesPerLine, szAscii );
  539. }
  540. #endif
  541. VOID
  542. epvcInitializeLookasideList(
  543. IN OUT PEPVC_NPAGED_LOOKASIDE_LIST pLookasideList,
  544. ULONG Size,
  545. ULONG Tag,
  546. USHORT Depth
  547. )
  548. /*++
  549. Routine Description:
  550. Allocates and initializes a epvc Lookaside list
  551. Arguments:
  552. Return Value:
  553. --*/
  554. {
  555. TRACE( TL_T, TM_Mp, ( "==> epvcInitializeLookasideList pLookaside List %x, size %x, Tag %x, Depth %x, ",
  556. pLookasideList, Size, Tag, Depth) );
  557. NdisInitializeNPagedLookasideList( &pLookasideList->List,
  558. NULL, //Allocate
  559. NULL, // Free
  560. 0, // Flags
  561. Size,
  562. Tag,
  563. Depth ); // Depth
  564. pLookasideList->Size = Size;
  565. pLookasideList->bIsAllocated = TRUE;
  566. TRACE( TL_T, TM_Mp, ( "<== epvcInitializeLookasideList " ) );
  567. }
  568. VOID
  569. epvcDeleteLookasideList (
  570. IN OUT PEPVC_NPAGED_LOOKASIDE_LIST pLookasideList
  571. )
  572. /*++
  573. Routine Description:
  574. Deletes a lookaside list, only if it has been allocated
  575. Arguments:
  576. Return Value:
  577. --*/
  578. {
  579. TRACE( TL_T, TM_Mp, ( "==> epvcDeleteLookasideList pLookaside List %x",pLookasideList ) );
  580. if (pLookasideList && pLookasideList->bIsAllocated == TRUE)
  581. {
  582. while (pLookasideList->OutstandingPackets != 0)
  583. {
  584. NdisMSleep( 10000);
  585. }
  586. NdisDeleteNPagedLookasideList (&pLookasideList->List);
  587. }
  588. TRACE( TL_T, TM_Mp, ( "<== epvcDeleteLookasideList pLookaside List %x", pLookasideList) );
  589. }
  590. PVOID
  591. epvcGetLookasideBuffer(
  592. IN PEPVC_NPAGED_LOOKASIDE_LIST pLookasideList
  593. )
  594. // Function Description:
  595. // Allocate an buffer from the lookaside list.
  596. // will be changed to a macro
  597. //
  598. //
  599. //
  600. // Arguments
  601. // Lookaside list - from which the buffer is allocated
  602. //
  603. //
  604. // Return Value:
  605. // Return buffer can be NULL
  606. //
  607. {
  608. PVOID pLocalBuffer = NULL;
  609. TRACE( TL_T, TM_Send, ( "==>epvcGetLookasideBuffer pList %x",pLookasideList) );
  610. ASSERT (pLookasideList != NULL);
  611. //
  612. // Optimize the lookaside list code path
  613. //
  614. pLocalBuffer = NdisAllocateFromNPagedLookasideList (&pLookasideList->List);
  615. if (pLocalBuffer != NULL)
  616. {
  617. NdisZeroMemory (pLocalBuffer, pLookasideList->Size);
  618. NdisInterlockedIncrement (&pLookasideList->OutstandingPackets);
  619. }
  620. else
  621. {
  622. epvcIncrementMallocFailure();
  623. }
  624. TRACE( TL_T, TM_Send, ( "<==epvcGetLookasideBuffer, %x", pLocalBuffer ) );
  625. return pLocalBuffer ;
  626. }
  627. VOID
  628. epvcFreeToNPagedLookasideList (
  629. IN PEPVC_NPAGED_LOOKASIDE_LIST pLookasideList,
  630. IN PVOID pBuffer
  631. )
  632. // Function Description:
  633. // Return the local buffer to the lookaside list
  634. //
  635. // Atguments
  636. // Lookaside list and its buffer
  637. // Return Value:
  638. // None
  639. {
  640. TRACE( TL_T, TM_Send, ( "==> epvcFreeToNPagedLookasideList , Lookaside list %x, plocalbuffer %x",pLookasideList, pBuffer ) );
  641. NdisFreeToNPagedLookasideList (&pLookasideList->List, pBuffer);
  642. NdisInterlockedDecrement (&pLookasideList->OutstandingPackets);
  643. TRACE( TL_T, TM_Send, ( "<== epvcFreeToNPagedLookasideList ") );
  644. }