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.

3420 lines
72 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. utils.c - Utility functions.
  5. Abstract:
  6. Internal utility functions for ATMARP:
  7. - Allocation and deallocation of various structures
  8. - Timer management
  9. - Buffer/Packet management
  10. - Linking/unlinking ATMARP structures
  11. - Copy support functions
  12. Revision History:
  13. Who When What
  14. -------- -------- ----------------------------------------------
  15. arvindm 07-15-96 Created
  16. Notes:
  17. --*/
  18. #include <precomp.h>
  19. #define _FILENUMBER 'LITU'
  20. //
  21. // AtmArpValidateTimerList and AtmArpValidateTimer are used in the checked
  22. // build to validate the state of a timerlist and timer, respectively.
  23. // They are not defined and used in the free build.
  24. //
  25. #if DBG
  26. void
  27. AtmArpValidateTimerList(
  28. PATMARP_TIMER_LIST pTimerList
  29. );
  30. void
  31. AtmArpValidateTimer(
  32. PATMARP_TIMER_LIST pTimerList,
  33. PATMARP_TIMER pTimer
  34. );
  35. //
  36. // AtmArpValidateTimerList is overkill for general use (even default
  37. // free build) -- because it goes through the entire timer list --
  38. // so disable it by default
  39. //
  40. #if 0
  41. #define AA_VALIDATE_TIMER_LIST(_ptl) AtmArpValidateTimerList(_ptl)
  42. #else
  43. #define AA_VALIDATE_TIMER_LIST(_ptl) ((void) 0)
  44. #endif
  45. #define AA_VALIDATE_TIMER(_ptl,_pt) AtmArpValidateTimer(_ptl,_pt)
  46. #else // !DBG
  47. #define AA_VALIDATE_TIMER_LIST(_ptl) ((void) 0)
  48. #define AA_VALIDATE_TIMER(_ptl,_pt) ((void) 0)
  49. #endif // !DBG
  50. VOID
  51. AtmArpSetMemory(
  52. IN PUCHAR pStart,
  53. IN UCHAR Value,
  54. IN ULONG NumberOfBytes
  55. )
  56. /*++
  57. Routine Description:
  58. Set "NumberOfBytes" bytes starting from "pStart" to "Value".
  59. Arguments:
  60. pStart - where to start filling.
  61. Value - the value to put everywhere
  62. NumberOfBytes - how many bytes to fill in
  63. Return Value:
  64. None
  65. --*/
  66. {
  67. while (NumberOfBytes--)
  68. {
  69. *pStart++ = Value;
  70. }
  71. }
  72. ULONG
  73. AtmArpMemCmp(
  74. IN PUCHAR pString1,
  75. IN PUCHAR pString2,
  76. IN ULONG Length
  77. )
  78. /*++
  79. Routine Description:
  80. Compare two byte strings.
  81. Arguments:
  82. pString1 - Start of first string
  83. pString2 - Start of second string
  84. Length - Length to compare
  85. Return Value:
  86. 0 if both are equal, -1 if string 1 is "smaller", +1 if string 1 is "larger".
  87. --*/
  88. {
  89. while (Length--)
  90. {
  91. if (*pString1 != *pString2)
  92. {
  93. return ((*pString1 > *pString2)? (ULONG)1 : (ULONG)-1);
  94. }
  95. pString1++;
  96. pString2++;
  97. }
  98. return (0);
  99. }
  100. LONG
  101. AtmArpRandomNumber(
  102. VOID
  103. )
  104. /*++
  105. Routine Description:
  106. Generate a positive pseudo-random number; simple linear congruential
  107. algorithm. ANSI C "rand()" function. Courtesy JameelH.
  108. Arguments:
  109. None
  110. Return Value:
  111. a random number.
  112. --*/
  113. {
  114. LARGE_INTEGER Li;
  115. static LONG seed = 0;
  116. if (seed == 0)
  117. {
  118. NdisGetCurrentSystemTime(&Li);
  119. seed = Li.LowPart;
  120. }
  121. seed *= (0x41C64E6D + 0x3039);
  122. return (seed & 0x7FFFFFFF);
  123. }
  124. VOID
  125. AtmArpCheckIfTimerIsInActiveList(
  126. IN PATMARP_TIMER pTimerToCheck,
  127. IN PATMARP_INTERFACE pInterface,
  128. IN PVOID pStruct,
  129. IN PCHAR pStructName
  130. )
  131. /*
  132. Instrumentation to catch a bug that causes the timer list to
  133. contain a pointer to an element that's been freed.
  134. */
  135. {
  136. PATMARP_TIMER_LIST pTimerList;
  137. PATMARP_TIMER pTimer;
  138. ULONG i, j;
  139. do
  140. {
  141. if (pInterface == NULL)
  142. {
  143. break;
  144. }
  145. if (pTimerToCheck->State == ATMARP_TIMER_STATE_RUNNING ||
  146. pTimerToCheck->State == ATMARP_TIMER_STATE_EXPIRING)
  147. {
  148. DbgPrint("ATMARPC: %s at %x contains timer %x still active on IF %x\n",
  149. pStructName,
  150. pStruct,
  151. pTimerToCheck,
  152. pInterface);
  153. DbgBreakPoint();
  154. }
  155. AA_STRUCT_ASSERT(pInterface, aai);
  156. AA_ACQUIRE_IF_TIMER_LOCK(pInterface);
  157. for (i = 0; i < AAT_CLASS_MAX; i++)
  158. {
  159. pTimerList = &pInterface->TimerList[i];
  160. for (j = 0; j < pTimerList->TimerListSize; j++)
  161. {
  162. for (pTimer = pTimerList->pTimers[j].pNextTimer;
  163. pTimer != NULL_PATMARP_TIMER;
  164. pTimer = pTimer->pNextTimer)
  165. {
  166. if (pTimer == pTimerToCheck)
  167. {
  168. DbgPrint("ATMARPC: %s at %x contains timer %x still active on IF %x, Head of list %x\n",
  169. pStructName,
  170. pStruct,
  171. pTimerToCheck,
  172. pInterface,
  173. &pTimerList->pTimers[j]);
  174. DbgBreakPoint();
  175. }
  176. }
  177. }
  178. }
  179. AA_RELEASE_IF_TIMER_LOCK(pInterface);
  180. break;
  181. }
  182. while (FALSE);
  183. }
  184. PATMARP_VC
  185. AtmArpAllocateVc(
  186. IN PATMARP_INTERFACE pInterface
  187. )
  188. /*++
  189. Routine Description:
  190. Allocate an ATMARP VC structure, initialize it, and return it.
  191. Arguments:
  192. pInterface - Interface for which this VC is created.
  193. Return Value:
  194. Pointer to VC if allocated, NULL otherwise.
  195. --*/
  196. {
  197. PATMARP_VC pVc;
  198. AA_STRUCT_ASSERT(pInterface, aai);
  199. AA_ALLOC_MEM(pVc, ATMARP_VC, sizeof(ATMARP_VC));
  200. if (pVc != NULL_PATMARP_VC)
  201. {
  202. AA_SET_MEM(pVc, 0, sizeof(ATMARP_VC));
  203. #if DBG
  204. pVc->avc_sig = avc_signature;
  205. #endif // DBG
  206. pVc->pInterface = pInterface;
  207. AA_INIT_VC_LOCK(pVc);
  208. }
  209. AADEBUGP(AAD_LOUD, ("Allocated Vc 0x%x\n", pVc));
  210. return (pVc);
  211. }
  212. VOID
  213. AtmArpDeallocateVc(
  214. IN PATMARP_VC pVc
  215. )
  216. /*++
  217. Routine Description:
  218. Deallocate an ATMARP VC structure. It is assumed that all references
  219. to this VC have gone, so there is no need to acquire a lock to the VC.
  220. Arguments:
  221. pVc - Pointer to the VC to be deallocated
  222. Return Value:
  223. None
  224. --*/
  225. {
  226. AA_STRUCT_ASSERT(pVc, avc);
  227. AA_ASSERT(pVc->RefCount == 0);
  228. AA_ASSERT(!AA_IS_TIMER_ACTIVE(&pVc->Timer));
  229. AA_CHECK_TIMER_IN_ACTIVE_LIST(&pVc->Timer, pVc->pInterface, pVc, "VC");
  230. #if DBG
  231. pVc->avc_sig++;
  232. #endif
  233. AA_FREE_VC_LOCK(pVc);
  234. AA_FREE_MEM(pVc);
  235. AADEBUGP(AAD_LOUD, ("Deallocated Vc 0x%x\n", pVc));
  236. }
  237. VOID
  238. AtmArpReferenceVc(
  239. IN PATMARP_VC pVc
  240. )
  241. /*++
  242. Routine Description:
  243. Add a reference to the specified ATMARP VC.
  244. NOTE: The caller is assumed to possess a lock for the VC.
  245. Arguments:
  246. pVc - Pointer to the VC to be referenced
  247. Return Value:
  248. None
  249. --*/
  250. {
  251. AA_STRUCT_ASSERT(pVc, avc);
  252. pVc->RefCount++;
  253. AADEBUGP(AAD_VERY_LOUD, ("Referencing Vc 0x%x, new count %d\n",
  254. pVc, pVc->RefCount));
  255. }
  256. ULONG
  257. AtmArpDereferenceVc(
  258. IN PATMARP_VC pVc
  259. )
  260. /*++
  261. Routine Description:
  262. Subtract a reference from the specified ATMARP VC. If the VC's
  263. reference count becomes zero, deallocate it.
  264. NOTE: The caller is assumed to possess a lock for the VC.
  265. SIDE EFFECT: See Return Value below
  266. Arguments:
  267. pVc - Pointer to the VC to be dereferenced.
  268. Return Value:
  269. Is the new reference count.
  270. [IMPORTANT] If the VC's reference count became zero, the VC will be
  271. deallocated -- the VC lock is, obviously, released in this case.
  272. --*/
  273. {
  274. ULONG rv;
  275. NDIS_HANDLE NdisVcHandle;
  276. BOOLEAN bVcOwnerIsAtmArp;
  277. NDIS_STATUS Status;
  278. AA_STRUCT_ASSERT(pVc, avc);
  279. AA_ASSERT(pVc->RefCount > 0);
  280. rv = --(pVc->RefCount);
  281. if (rv == 0)
  282. {
  283. #ifdef VC_REFS_ON_SENDS
  284. NdisVcHandle = pVc->NdisVcHandle;
  285. bVcOwnerIsAtmArp = AA_IS_FLAG_SET(pVc->Flags,
  286. AA_VC_OWNER_MASK,
  287. AA_VC_OWNER_IS_ATMARP);
  288. #endif // VC_REFS_ON_SENDS
  289. AA_RELEASE_VC_LOCK(pVc);
  290. AtmArpDeallocateVc(pVc);
  291. #ifdef VC_REFS_ON_SENDS
  292. if ((NdisVcHandle != NULL) &&
  293. (bVcOwnerIsAtmArp))
  294. {
  295. Status = NdisCoDeleteVc(NdisVcHandle);
  296. AA_ASSERT(Status == NDIS_STATUS_SUCCESS);
  297. AADEBUGP(AAD_LOUD, ("DereferenceVc 0x%x, deleted NdisVcHandle 0x%x\n",
  298. pVc, NdisVcHandle));
  299. }
  300. #endif // VC_REFS_ON_SENDS
  301. }
  302. AADEBUGP(AAD_VERY_LOUD, ("Dereference Vc 0x%x, New RefCount %d\n", pVc, rv));
  303. return (rv);
  304. }
  305. PATMARP_ATM_ENTRY
  306. AtmArpAllocateAtmEntry(
  307. IN PATMARP_INTERFACE pInterface,
  308. IN BOOLEAN IsMulticast
  309. )
  310. /*++
  311. Routine Description:
  312. Allocate an ATM Entry structure, initialize it, and return it.
  313. Arguments:
  314. pInterface - Pointer to ATMARP interface on which the entry is allocated
  315. IsMulticast - Is this a Multicast entry?
  316. Return Value:
  317. Pointer to allocated ATM Entry structure if successful, NULL otherwise.
  318. --*/
  319. {
  320. PATMARP_ATM_ENTRY pAtmEntry;
  321. ULONG Size;
  322. AA_STRUCT_ASSERT(pInterface, aai);
  323. Size = sizeof(ATMARP_ATM_ENTRY)
  324. #ifdef IPMCAST
  325. + (IsMulticast? sizeof(ATMARP_IPMC_ATM_INFO): 0);
  326. #else
  327. ;
  328. #endif
  329. AA_ALLOC_MEM(pAtmEntry, ATMARP_ATM_ENTRY, Size);
  330. if (pAtmEntry != NULL_PATMARP_ATM_ENTRY)
  331. {
  332. AA_SET_MEM(pAtmEntry, 0, Size);
  333. #if DBG
  334. pAtmEntry->aae_sig = aae_signature;
  335. #endif
  336. pAtmEntry->Flags = AA_ATM_ENTRY_IDLE;
  337. #ifdef IPMCAST
  338. if (IsMulticast)
  339. {
  340. pAtmEntry->Flags |= AA_ATM_ENTRY_TYPE_NUCAST;
  341. pAtmEntry->pMcAtmInfo = (PATMARP_IPMC_ATM_INFO)
  342. ((PUCHAR)pAtmEntry + sizeof(ATMARP_ATM_ENTRY));
  343. }
  344. #endif // IPMCAST
  345. AA_INIT_AE_LOCK(pAtmEntry);
  346. pAtmEntry->pInterface = pInterface;
  347. }
  348. AADEBUGP(AAD_INFO, ("Allocated ATM Entry: IF 0x%x, Entry 0x%x\n",
  349. pInterface, pAtmEntry));
  350. return (pAtmEntry);
  351. }
  352. VOID
  353. AtmArpDeallocateAtmEntry(
  354. IN PATMARP_ATM_ENTRY pAtmEntry
  355. )
  356. /*++
  357. Routine Description:
  358. Free an ATMARP ATM Entry structure. It is assumed that all references
  359. to the structure have gone. We don't need any locks here.
  360. Arguments:
  361. pAtmEntry - Pointer to ATMARP ATM Entry to be freed.
  362. Return Value:
  363. None
  364. --*/
  365. {
  366. AA_STRUCT_ASSERT(pAtmEntry, aae);
  367. AA_ASSERT(pAtmEntry->RefCount == 0);
  368. AA_ASSERT(pAtmEntry->pVcList == NULL_PATMARP_VC);
  369. AA_ASSERT(!AA_AE_IS_ALIVE(pAtmEntry));
  370. #if DBG
  371. pAtmEntry->aae_sig++;
  372. #endif
  373. AA_FREE_AE_LOCK(pAtmEntry);
  374. AA_FREE_MEM(pAtmEntry);
  375. AADEBUGP(AAD_INFO, ("Deallocated ATM Entry: 0x%x\n", pAtmEntry));
  376. }
  377. VOID
  378. AtmArpReferenceAtmEntry(
  379. IN PATMARP_ATM_ENTRY pAtmEntry
  380. )
  381. /*++
  382. Routine Description:
  383. Add a reference to the specified ATMARP Entry.
  384. NOTE: The caller is assumed to possess a lock for the Entry.
  385. Arguments:
  386. pAtmEntry - Pointer to the Entry to be referenced
  387. Return Value:
  388. None
  389. --*/
  390. {
  391. AA_STRUCT_ASSERT(pAtmEntry, aae);
  392. pAtmEntry->RefCount++;
  393. AADEBUGP(AAD_VERY_LOUD, ("Referencing AtmEntry 0x%x, new count %d\n",
  394. pAtmEntry, pAtmEntry->RefCount));
  395. }
  396. ULONG
  397. AtmArpDereferenceAtmEntry(
  398. IN PATMARP_ATM_ENTRY pAtmEntry
  399. )
  400. /*++
  401. Routine Description:
  402. Subtract a reference from the specified ATM Entry. If the Entry's
  403. reference count becomes zero, deallocate it.
  404. NOTE: The caller is assumed to possess a lock for the Entry.
  405. SIDE EFFECT: See Return Value below
  406. Arguments:
  407. pAtmEntry - Pointer to the Entry to be dereferenced.
  408. Return Value:
  409. Is the new reference count.
  410. [IMPORTANT] If the Entry's reference count became zero, the Entry will be
  411. deallocated -- the Entry lock is, obviously, released in this case.
  412. --*/
  413. {
  414. ULONG rc;
  415. PATMARP_INTERFACE pInterface;
  416. AA_STRUCT_ASSERT(pAtmEntry, aae);
  417. AA_ASSERT(pAtmEntry->RefCount > 0);
  418. rc = --(pAtmEntry->RefCount);
  419. if (rc == 0)
  420. {
  421. PATMARP_ATM_ENTRY * ppAtmEntry;
  422. //
  423. // We are most likely going to delete this entry...
  424. //
  425. // We must observe the protocol of 1st locking the list lock then
  426. // the pAtmEntry's lock, so this requires us to do the
  427. // release/lock/lock sequence below.
  428. //
  429. // Temporarly addref it again, to make sure that when we
  430. // release the lock below someone else doesn't get confused.
  431. //
  432. pAtmEntry->RefCount++;
  433. pInterface = pAtmEntry->pInterface;
  434. AA_STRUCT_ASSERT(pInterface, aai);
  435. AA_RELEASE_AE_LOCK(pAtmEntry);
  436. //
  437. // No locks held at this time!
  438. //
  439. //
  440. // Acquire locks in the correct order...
  441. //
  442. AA_ACQUIRE_IF_ATM_LIST_LOCK(pInterface);
  443. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  444. AA_ASSERT(pAtmEntry->RefCount > 0);
  445. rc = --(pAtmEntry->RefCount);
  446. //
  447. // We can't assume that the ref count is still zero -- in principle
  448. // someone may have addrefd this pAtmEntry while both locks
  449. // were released above...
  450. //
  451. if (rc == 0)
  452. {
  453. //
  454. // Unlink this entry from the Interface's list of ATM Entries.
  455. //
  456. ppAtmEntry = &(pInterface->pAtmEntryList);
  457. while (*ppAtmEntry != pAtmEntry)
  458. {
  459. AA_ASSERT(*ppAtmEntry != NULL_PATMARP_ATM_ENTRY);
  460. ppAtmEntry = &((*ppAtmEntry)->pNext);
  461. }
  462. *ppAtmEntry = pAtmEntry->pNext;
  463. //
  464. // Set state back to idle -- AtmArpDeallocate checks this...
  465. //
  466. AA_SET_FLAG(
  467. pAtmEntry->Flags,
  468. AA_ATM_ENTRY_STATE_MASK,
  469. AA_ATM_ENTRY_IDLE
  470. );
  471. }
  472. AA_RELEASE_AE_LOCK(pAtmEntry);
  473. AA_RELEASE_IF_ATM_LIST_LOCK(pInterface);
  474. if (rc == 0)
  475. {
  476. AtmArpDeallocateAtmEntry(pAtmEntry);
  477. }
  478. else
  479. {
  480. //
  481. // Caller expects to still hold the lock on pAtmEntry!
  482. // if we return nonzero rc ...
  483. // We can't simply re-acquire the lock because the caller expects
  484. // the that lock was never released.
  485. // So, since the ref count had gone to zero, as far as the caller
  486. // is concerned this structure has gone away and so we lie
  487. // and return 0 here...
  488. //
  489. rc = 0;
  490. }
  491. }
  492. AADEBUGP(AAD_VERY_LOUD,
  493. ("Dereference AtmEntry 0x%x, New RefCount %d\n", pAtmEntry, rc));
  494. return (rc);
  495. }
  496. PATMARP_IP_ENTRY
  497. AtmArpAllocateIPEntry(
  498. IN PATMARP_INTERFACE pInterface
  499. )
  500. /*++
  501. Routine Description:
  502. Allocate an ATMARP IP Entry structure, initialize it, and
  503. return it.
  504. Arguments:
  505. pInterface - Pointer to ATMARP Interface on which this IP
  506. Entry is allocated.
  507. Return Value:
  508. Pointer to allocated IP Entry structure if successful,
  509. NULL otherwise.
  510. --*/
  511. {
  512. PATMARP_IP_ENTRY pIpEntry;
  513. AA_ALLOC_MEM(pIpEntry, ATMARP_IP_ENTRY, sizeof(ATMARP_IP_ENTRY));
  514. if (pIpEntry != NULL_PATMARP_IP_ENTRY)
  515. {
  516. AA_SET_MEM(pIpEntry, 0, sizeof(ATMARP_IP_ENTRY));
  517. #if DBG
  518. pIpEntry->aip_sig = aip_signature;
  519. #endif // DBG
  520. pIpEntry->pInterface = pInterface;
  521. pIpEntry->Flags = AA_IP_ENTRY_IDLE;
  522. #ifdef IPMCAST
  523. pIpEntry->NextMultiSeq = AA_MARS_INITIAL_Y; // Init on allocation
  524. #endif
  525. AA_INIT_IE_LOCK(pIpEntry);
  526. }
  527. AADEBUGP(AAD_VERY_LOUD, ("Allocated IP Entry 0x%x\n", pIpEntry));
  528. return (pIpEntry);
  529. }
  530. VOID
  531. AtmArpDeallocateIPEntry(
  532. IN PATMARP_IP_ENTRY pIpEntry
  533. )
  534. /*++
  535. Routine Description:
  536. Deallocate an ATMARP IP Entry. It is assumed that all references
  537. to this IP Entry have gone, so there is no need to acquire its
  538. lock.
  539. Arguments:
  540. pIpEntry - Pointer to the IP Entry to be deallocated.
  541. Return Value:
  542. None
  543. --*/
  544. {
  545. AA_STRUCT_ASSERT(pIpEntry, aip);
  546. AA_ASSERT(pIpEntry->RefCount == 0);
  547. AA_ASSERT(!AA_IE_IS_ALIVE(pIpEntry));
  548. AA_ASSERT(!AA_IS_TIMER_ACTIVE(&pIpEntry->Timer));
  549. AA_CHECK_TIMER_IN_ACTIVE_LIST(&pIpEntry->Timer, pIpEntry->pInterface, pIpEntry, "IP Entry");
  550. #if DBG
  551. pIpEntry->aip_sig = ~(pIpEntry->aip_sig);
  552. #endif // DBG
  553. AA_FREE_IE_LOCK(pIpEntry);
  554. AA_FREE_MEM(pIpEntry);
  555. AADEBUGP(AAD_LOUD, ("Deallocated IP Entry 0x%x\n", pIpEntry));
  556. }
  557. VOID
  558. AtmArpReferenceIPEntry(
  559. IN PATMARP_IP_ENTRY pIpEntry
  560. )
  561. /*++
  562. Routine Description:
  563. Add a reference to an ATMARP IP Entry.
  564. NOTE: The caller is assumed to possess a lock for the IP Entry.
  565. Arguments:
  566. pIpEntry - Pointer to an ATMARP IP Entry.
  567. Return Value:
  568. None
  569. --*/
  570. {
  571. AA_STRUCT_ASSERT(pIpEntry, aip);
  572. pIpEntry->RefCount++;
  573. AADEBUGP(AAD_VERY_LOUD, ("Referenced IP Entry 0x%x, new count %d\n",
  574. pIpEntry, pIpEntry->RefCount));
  575. }
  576. ULONG
  577. AtmArpDereferenceIPEntry(
  578. IN PATMARP_IP_ENTRY pIpEntry
  579. )
  580. /*++
  581. Routine Description:
  582. Subtract a reference from an ATMARP IP Entry. If the reference
  583. count becomes zero, deallocate it.
  584. NOTE: It is assumed that the caller holds a lock to the IP Entry.
  585. See SIDE EFFECT below.
  586. Arguments:
  587. pIpEntry - Pointer to ATMARP IP Entry
  588. Return Value:
  589. The resulting reference count. If this is zero, then there are two
  590. SIDE EFFECTS: (1) the IP Entry lock is released (2) the structure
  591. is freed.
  592. --*/
  593. {
  594. ULONG rc;
  595. AA_STRUCT_ASSERT(pIpEntry, aip);
  596. rc = --(pIpEntry->RefCount);
  597. if (rc == 0)
  598. {
  599. AA_RELEASE_IE_LOCK(pIpEntry);
  600. AtmArpDeallocateIPEntry(pIpEntry);
  601. }
  602. AADEBUGP(AAD_VERY_LOUD, ("Dereference IP Entry 0x%x: new count %d\n",
  603. pIpEntry, rc));
  604. return (rc);
  605. }
  606. PATMARP_INTERFACE
  607. AtmArpAllocateInterface(
  608. IN PATMARP_ADAPTER pAdapter
  609. )
  610. /*++
  611. Routine Description:
  612. Allocate an ATMARP interface structure, initialize it, link it to
  613. the given adapter structure, and return it.
  614. Arguments:
  615. None.
  616. Return Value:
  617. Pointer to ATMARP interface structure, if successful, else NULL.
  618. --*/
  619. {
  620. PATMARP_INTERFACE pInterface;
  621. PATMARP_IP_ENTRY * pArpTable;
  622. PATMARP_TIMER_LIST pTimerList;
  623. NDIS_STATUS Status;
  624. PCO_SAP pIfSap;
  625. ULONG SapSize;
  626. PWSTR pIPConfigBuffer;
  627. USHORT ConfigBufferSize;
  628. INT i;
  629. //
  630. // Initialize
  631. //
  632. Status = NDIS_STATUS_SUCCESS;
  633. pInterface = NULL_PATMARP_INTERFACE;
  634. pArpTable = (PATMARP_IP_ENTRY *)NULL;
  635. pIfSap = (PCO_SAP)NULL;
  636. pIPConfigBuffer = (PWSTR)NULL;
  637. SapSize = sizeof(CO_SAP)+sizeof(ATM_SAP)+sizeof(ATM_ADDRESS);
  638. ConfigBufferSize = MAX_IP_CONFIG_STRING_LEN * sizeof(WCHAR);
  639. do
  640. {
  641. //
  642. // Allocate everything.
  643. //
  644. AA_ALLOC_MEM(pInterface, ATMARP_INTERFACE, sizeof(ATMARP_INTERFACE));
  645. AA_ALLOC_MEM(pArpTable, PATMARP_IP_ENTRY, ATMARP_TABLE_SIZE*sizeof(PATMARP_IP_ENTRY));
  646. AA_ALLOC_MEM(pIfSap, CO_SAP, SapSize);
  647. if ((pInterface == NULL_PATMARP_INTERFACE) ||
  648. (pArpTable == (PATMARP_IP_ENTRY *)NULL) ||
  649. (pIfSap == (PCO_SAP)NULL))
  650. {
  651. Status = NDIS_STATUS_RESOURCES;
  652. break;
  653. }
  654. //
  655. // Got (almost) everything allocated. Initialize the main IF structure
  656. // first. IMPORTANT: Keep this SET_MEM right here! Otherwise, we will
  657. // trash the timer list allocation coming right up.
  658. //
  659. AA_SET_MEM(pInterface, 0, sizeof(ATMARP_INTERFACE));
  660. //
  661. // Set up the Buffer pool quadword-aligned slist pointers.
  662. //
  663. {
  664. for (i=0;i<AA_HEADER_TYPE_MAX;i++)
  665. {
  666. //
  667. // Verify that HeaderBufList is 8-byte aligned...
  668. // (we fully expect it to be because HeaderBufList is of type
  669. // SLIST_HEADER which has longlong alignment) -- so that
  670. // if the INTERFACE structure in which it is embedded in is
  671. // 8-byte aligned, so will HeaderBufList...).
  672. //
  673. ASSERT((((ULONG_PTR)&(pInterface->HeaderPool[i].HeaderBufList))
  674. & 0x7) == 0);
  675. //
  676. // Spec says you gotta init it...
  677. //
  678. AA_INIT_SLIST(&(pInterface->HeaderPool[i].HeaderBufList));
  679. }
  680. }
  681. //
  682. // Allocate timer structures
  683. //
  684. for (i = 0; i < AAT_CLASS_MAX; i++)
  685. {
  686. pTimerList = &(pInterface->TimerList[i]);
  687. #if DBG
  688. pTimerList->atl_sig = atl_signature;
  689. #endif // DBG
  690. AA_ALLOC_MEM(
  691. pTimerList->pTimers,
  692. ATMARP_TIMER,
  693. sizeof(ATMARP_TIMER) * AtmArpTimerListSize[i]
  694. );
  695. if (pTimerList->pTimers == NULL_PATMARP_TIMER)
  696. {
  697. Status = NDIS_STATUS_RESOURCES;
  698. break;
  699. }
  700. }
  701. if (Status != NDIS_STATUS_SUCCESS)
  702. {
  703. break;
  704. }
  705. //
  706. // Continue initializing the IF structure.
  707. //
  708. #if DBG
  709. //
  710. // Signatures, for debugging.
  711. //
  712. pInterface->aai_sig = aai_signature;
  713. pInterface->aaim_sig = aaim_signature;
  714. pInterface->aaia_sig = aaia_signature;
  715. pInterface->aait_sig = aait_signature;
  716. pInterface->aaio_sig = aaio_signature;
  717. pInterface->aaic_sig = aaic_signature;
  718. pInterface->SapList.aas_sig = aas_signature;
  719. #if ATMARP_WMI
  720. pInterface->aaiw_sig = aaiw_signature;
  721. #endif
  722. #endif // DBG
  723. //
  724. // Initialize state fields.
  725. //
  726. pInterface->AdminState = IF_STATUS_DOWN;
  727. pInterface->State = IF_STATUS_DOWN;
  728. pInterface->LastChangeTime = GetTimeTicks();
  729. pInterface->ReconfigState = RECONFIG_NOT_IN_PROGRESS;
  730. //
  731. // Initialize IP interface fields.
  732. //
  733. pInterface->BroadcastMask = 0;
  734. pInterface->BroadcastAddress = IP_LOCAL_BCST;
  735. #ifndef OLD_ENTITY_LIST
  736. pInterface->ATInstance = INVALID_ENTITY_INSTANCE;
  737. pInterface->IFInstance = INVALID_ENTITY_INSTANCE;
  738. #endif // OLD_ENTITY_LIST
  739. //
  740. // Initialize spinlocks.
  741. //
  742. AA_INIT_IF_LOCK(pInterface);
  743. AA_INIT_IF_TABLE_LOCK(pInterface);
  744. AA_INIT_IF_ATM_LIST_LOCK(pInterface);
  745. AA_INIT_IF_TIMER_LOCK(pInterface);
  746. AA_INIT_BLOCK_STRUCT(&(pInterface->Block));
  747. NdisAllocateSpinLock(&(pInterface->BufferLock));
  748. //
  749. // Initialize list and table status
  750. //
  751. pInterface->AtmEntryListUp = TRUE;
  752. pInterface->ArpTableUp = TRUE;
  753. //
  754. // Initialize timer wheels.
  755. //
  756. for (i = 0; i < AAT_CLASS_MAX; i++)
  757. {
  758. pTimerList = &(pInterface->TimerList[i]);
  759. AA_SET_MEM(
  760. pTimerList->pTimers,
  761. 0,
  762. sizeof(ATMARP_TIMER) * AtmArpTimerListSize[i]
  763. );
  764. pTimerList->MaxTimer = AtmArpMaxTimerValue[i];
  765. pTimerList->TimerPeriod = AtmArpTimerPeriod[i];
  766. pTimerList->ListContext = (PVOID)pInterface;
  767. pTimerList->TimerListSize = AtmArpTimerListSize[i];
  768. AA_INIT_SYSTEM_TIMER(
  769. &(pTimerList->NdisTimer),
  770. AtmArpTickHandler,
  771. (PVOID)pTimerList
  772. );
  773. }
  774. //
  775. // Initialize all sub-components.
  776. //
  777. AA_SET_MEM(pArpTable, 0, ATMARP_TABLE_SIZE*sizeof(PATMARP_IP_ENTRY));
  778. AA_SET_MEM(pIfSap, 0, SapSize);
  779. //
  780. // Link all sub-components to the Interface structure.
  781. //
  782. pInterface->pArpTable = pArpTable;
  783. pInterface->SapList.pInfo = pIfSap;
  784. //
  785. // Link the Interface to the Adapter.
  786. //
  787. pInterface->pAdapter = pAdapter;
  788. pInterface->pNextInterface = pAdapter->pInterfaceList;
  789. pAdapter->pInterfaceList = pInterface;
  790. //
  791. // Cache the adapter handle.
  792. //
  793. pInterface->NdisAdapterHandle = pAdapter->NdisAdapterHandle;
  794. Status = NDIS_STATUS_SUCCESS;
  795. break;
  796. }
  797. while (FALSE);
  798. if (Status != NDIS_STATUS_SUCCESS)
  799. {
  800. //
  801. // Failed to allocate atleast one component. Free the other(s).
  802. //
  803. if (pInterface != NULL_PATMARP_INTERFACE)
  804. {
  805. for (i = 0; i < AAT_CLASS_MAX; i++)
  806. {
  807. pTimerList = &(pInterface->TimerList[i]);
  808. if (pTimerList->pTimers != NULL_PATMARP_TIMER)
  809. {
  810. AA_FREE_MEM(pTimerList->pTimers);
  811. pTimerList->pTimers = NULL_PATMARP_TIMER;
  812. }
  813. }
  814. AA_FREE_MEM(pInterface);
  815. pInterface = NULL_PATMARP_INTERFACE; // return value
  816. }
  817. if (pArpTable != (PATMARP_IP_ENTRY *)NULL)
  818. {
  819. AA_FREE_MEM(pArpTable);
  820. }
  821. if (pIfSap != (PCO_SAP)NULL)
  822. {
  823. AA_FREE_MEM(pIfSap);
  824. }
  825. }
  826. AADEBUGP(AAD_VERY_LOUD, ("Allocated ATMARP Interface 0x%x\n", pInterface));
  827. return (pInterface);
  828. }
  829. VOID
  830. AtmArpDeallocateInterface(
  831. IN PATMARP_INTERFACE pInterface
  832. )
  833. /*++
  834. Routine Description:
  835. Deallocate an ATMARP Interface structure. It is assumed that all
  836. references to this structure have gone, so it is not necessary
  837. to acquire a lock to it.
  838. Also delink this from the adapter structure it's linked to.
  839. Arguments:
  840. pInterface - Pointer to Interface structure to be deallocated.
  841. Return Value:
  842. None
  843. --*/
  844. {
  845. PATMARP_INTERFACE * ppInterface;
  846. PATMARP_ADAPTER pAdapter;
  847. PATMARP_SAP pAtmArpSap;
  848. PIP_ADDRESS_ENTRY pIpEntry;
  849. PATMARP_SERVER_ENTRY pServerEntry;
  850. PPROXY_ARP_ENTRY pProxyEntry;
  851. PATMARP_ATM_ENTRY pAtmEntry;
  852. PATMARP_VC pVc;
  853. INT i;
  854. PVOID pNext; // Catch-all for all list traversals
  855. AA_STRUCT_ASSERT(pInterface, aai);
  856. AA_ASSERT(pInterface->RefCount == 0);
  857. AADEBUGP(AAD_INFO, ("Deallocate Interface 0x%x\n", pInterface));
  858. #if DBG
  859. pInterface->aai_sig = ~(pInterface->aai_sig);
  860. #endif // DBG
  861. //
  862. // Unlink from Adapter structure
  863. //
  864. AA_ACQUIRE_GLOBAL_LOCK(pAtmArpGlobalInfo);
  865. pAdapter = pInterface->pAdapter;
  866. if (pAdapter != NULL_PATMARP_ADAPTER)
  867. {
  868. ppInterface = &(pAdapter->pInterfaceList);
  869. while (*ppInterface != NULL_PATMARP_INTERFACE)
  870. {
  871. if (*ppInterface == pInterface)
  872. {
  873. *ppInterface = pInterface->pNextInterface;
  874. break;
  875. }
  876. else
  877. {
  878. ppInterface = &((*ppInterface)->pNextInterface);
  879. }
  880. }
  881. }
  882. AA_RELEASE_GLOBAL_LOCK(pAtmArpGlobalInfo);
  883. //
  884. // Free all subcomponents
  885. //
  886. //
  887. // ARP Table
  888. //
  889. if (pInterface->pArpTable != (PATMARP_IP_ENTRY *)NULL)
  890. {
  891. AA_FREE_MEM(pInterface->pArpTable);
  892. pInterface->pArpTable = (PATMARP_IP_ENTRY *)NULL;
  893. }
  894. //
  895. // Local SAP list
  896. //
  897. for (pAtmArpSap = pInterface->SapList.pNextSap;
  898. pAtmArpSap != NULL_PATMARP_SAP;
  899. pAtmArpSap = (PATMARP_SAP)pNext)
  900. {
  901. pNext = (PVOID)(pAtmArpSap->pNextSap);
  902. if (pAtmArpSap->pInfo != (PCO_SAP)NULL)
  903. {
  904. AA_FREE_MEM(pAtmArpSap->pInfo);
  905. }
  906. AA_FREE_MEM(pAtmArpSap);
  907. }
  908. if (pInterface->SapList.pInfo != (PCO_SAP)NULL)
  909. {
  910. AA_FREE_MEM(pInterface->SapList.pInfo);
  911. }
  912. pInterface->SapList.pNextSap = NULL_PATMARP_SAP;
  913. //
  914. // List of local IP addresses
  915. //
  916. for (pIpEntry = pInterface->LocalIPAddress.pNext;
  917. pIpEntry != (PIP_ADDRESS_ENTRY)NULL;
  918. pIpEntry = (PIP_ADDRESS_ENTRY)pNext)
  919. {
  920. pNext = (PVOID)pIpEntry->pNext;
  921. AA_FREE_MEM(pIpEntry);
  922. }
  923. //
  924. // List of proxy ARP addresses
  925. //
  926. for (pProxyEntry = pInterface->pProxyList;
  927. pProxyEntry != (PPROXY_ARP_ENTRY)NULL;
  928. pProxyEntry = (PPROXY_ARP_ENTRY)pNext)
  929. {
  930. pNext = (PVOID)pProxyEntry->pNext;
  931. AA_FREE_MEM(pProxyEntry);
  932. }
  933. pInterface->pProxyList = (PPROXY_ARP_ENTRY)NULL;
  934. //
  935. // List of ARP Server addresses
  936. //
  937. for (pServerEntry = pInterface->ArpServerList.pList;
  938. pServerEntry != NULL_PATMARP_SERVER_ENTRY;
  939. pServerEntry = (PATMARP_SERVER_ENTRY)pNext)
  940. {
  941. pNext = (PVOID)pServerEntry->pNext;
  942. AA_FREE_MEM(pServerEntry);
  943. }
  944. pInterface->ArpServerList.pList = NULL_PATMARP_SERVER_ENTRY;
  945. #ifdef IPMCAST
  946. //
  947. // List of MARS Server addresses
  948. //
  949. for (pServerEntry = pInterface->MARSList.pList;
  950. pServerEntry != NULL_PATMARP_SERVER_ENTRY;
  951. pServerEntry = (PATMARP_SERVER_ENTRY)pNext)
  952. {
  953. pNext = (PVOID)pServerEntry->pNext;
  954. AA_FREE_MEM(pServerEntry);
  955. }
  956. pInterface->MARSList.pList = NULL_PATMARP_SERVER_ENTRY;
  957. #endif // IPMCAST
  958. //
  959. // ARP Table
  960. //
  961. if (pInterface->pArpTable != (PATMARP_IP_ENTRY *)NULL)
  962. {
  963. AA_FREE_MEM(pInterface->pArpTable);
  964. pInterface->pArpTable = (PATMARP_IP_ENTRY *)NULL;
  965. }
  966. //
  967. // ATM Entry List
  968. //
  969. for (pAtmEntry = pInterface->pAtmEntryList;
  970. pAtmEntry != NULL_PATMARP_ATM_ENTRY;
  971. pAtmEntry = (PATMARP_ATM_ENTRY)pNext)
  972. {
  973. pNext = (PVOID)pAtmEntry->pNext;
  974. AA_FREE_MEM(pAtmEntry);
  975. }
  976. pInterface->pAtmEntryList = NULL_PATMARP_ATM_ENTRY;
  977. //
  978. // Unresolved VC list
  979. //
  980. for (pVc = pInterface->pUnresolvedVcs;
  981. pVc != NULL_PATMARP_VC;
  982. pVc = (PATMARP_VC)pNext)
  983. {
  984. pNext = (PVOID)pVc->pNextVc;
  985. AA_FREE_MEM(pVc);
  986. }
  987. pInterface->pUnresolvedVcs = (PATMARP_VC)NULL;
  988. //
  989. // Timers
  990. //
  991. for (i = 0; i < AAT_CLASS_MAX; i++)
  992. {
  993. PATMARP_TIMER_LIST pTimerList = &(pInterface->TimerList[i]);
  994. if (pTimerList->pTimers != NULL_PATMARP_TIMER)
  995. {
  996. AA_FREE_MEM(pTimerList->pTimers);
  997. pTimerList->pTimers = NULL_PATMARP_TIMER;
  998. }
  999. }
  1000. //
  1001. // ProtocolPacketPool
  1002. // ProtocolBufferPool
  1003. // ProtocolBufList
  1004. //
  1005. AtmArpDeallocateProtoBuffers(pInterface);
  1006. //
  1007. // HeaderBufList
  1008. // pHeaderTrkList
  1009. //
  1010. AtmArpDeallocateHeaderBuffers(pInterface);
  1011. //
  1012. // Free all Interface locks.
  1013. //
  1014. AA_FREE_IF_LOCK(pInterface);
  1015. AA_FREE_IF_TABLE_LOCK(pInterface);
  1016. AA_FREE_IF_ATM_LIST_LOCK(pInterface);
  1017. AA_FREE_IF_TIMER_LOCK(pInterface);
  1018. AA_FREE_BLOCK_STRUCT(&(pInterface->Block));
  1019. NdisFreeSpinLock(&(pInterface->BufferLock));
  1020. //
  1021. // Free the Interface structure now
  1022. //
  1023. AA_FREE_MEM(pInterface);
  1024. //
  1025. // If we just freed the last Interface structure on this
  1026. // adapter, and an Unbind operation was in progress, complete
  1027. // it now.
  1028. //
  1029. if ((pAdapter->pInterfaceList == NULL_PATMARP_INTERFACE) &&
  1030. (pAdapter->Flags & AA_ADAPTER_FLAGS_UNBINDING))
  1031. {
  1032. AtmArpCompleteUnbindAdapter(pAdapter);
  1033. }
  1034. }
  1035. VOID
  1036. AtmArpReferenceInterface(
  1037. IN PATMARP_INTERFACE pInterface
  1038. )
  1039. /*++
  1040. Routine Description:
  1041. Add a reference to an Interface structure.
  1042. NOTE: The caller is assumed to possess a lock for the interface
  1043. structure.
  1044. Arguments:
  1045. pInterface - Pointer to the ATMARP interface
  1046. Return Value:
  1047. None
  1048. --*/
  1049. {
  1050. AA_STRUCT_ASSERT(pInterface, aai);
  1051. pInterface->RefCount++;
  1052. AADEBUGP(AAD_VERY_LOUD, ("Reference Interface 0x%x, new count %d\n",
  1053. pInterface, pInterface->RefCount));
  1054. }
  1055. ULONG
  1056. AtmArpDereferenceInterface(
  1057. IN PATMARP_INTERFACE pInterface
  1058. )
  1059. /*++
  1060. Routine Description:
  1061. Subtract a reference from an ATMARP Interface. If the reference
  1062. count becomes zero, deallocate it.
  1063. NOTE: It is assumed that the caller holds a lock to the Interface
  1064. structure. See SIDE EFFECT below.
  1065. Arguments:
  1066. pInterface - Pointer to the ATMARP interface
  1067. Return Value:
  1068. The resulting reference count. If this is zero, then there are two
  1069. SIDE EFFECTS: (1) the Interface lock is released (2) the structure
  1070. is freed.
  1071. --*/
  1072. {
  1073. ULONG rc;
  1074. AA_STRUCT_ASSERT(pInterface, aai);
  1075. AA_ASSERT(pInterface->RefCount > 0);
  1076. rc = --(pInterface->RefCount);
  1077. AADEBUGP(AAD_VERY_LOUD, ("Dereference Interface 0x%x, new count %d\n",
  1078. pInterface, rc));
  1079. if (rc == 0)
  1080. {
  1081. AA_RELEASE_IF_LOCK(pInterface);
  1082. AtmArpDeallocateInterface(pInterface);
  1083. }
  1084. return (rc);
  1085. }
  1086. VOID
  1087. AtmArpReferenceJoinEntry(
  1088. IN PATMARP_IPMC_JOIN_ENTRY pJoinEntry
  1089. )
  1090. /*++
  1091. Routine Description:
  1092. Add a reference to a Join Entry.
  1093. Arguments:
  1094. pJoinEntry - Pointer to Join Entry
  1095. Return Value:
  1096. None
  1097. --*/
  1098. {
  1099. NdisInterlockedIncrement(&pJoinEntry->RefCount);
  1100. }
  1101. ULONG
  1102. AtmArpDereferenceJoinEntry(
  1103. IN PATMARP_IPMC_JOIN_ENTRY pJoinEntry
  1104. )
  1105. /*++
  1106. Routine Description:
  1107. Decrements the ref count on a Join Entry. If it goes down to zero,
  1108. deallocates it.
  1109. Arguments:
  1110. pJoinEntry - Pointer to the Join Entry
  1111. Return Value:
  1112. The final ref count
  1113. --*/
  1114. {
  1115. ULONG rc;
  1116. rc = NdisInterlockedDecrement(&pJoinEntry->RefCount);
  1117. if (rc == 0)
  1118. {
  1119. AA_CHECK_TIMER_IN_ACTIVE_LIST(&pJoinEntry->Timer, pJoinEntry->pInterface, pJoinEntry, "Join Entry");
  1120. AA_FREE_MEM(pJoinEntry);
  1121. }
  1122. return (rc);
  1123. }
  1124. VOID
  1125. AtmArpStartTimer(
  1126. IN PATMARP_INTERFACE pInterface,
  1127. IN PATMARP_TIMER pTimer,
  1128. IN ATMARP_TIMEOUT_HANDLER TimeoutHandler,
  1129. IN ULONG SecondsToGo,
  1130. IN PVOID Context
  1131. )
  1132. /*++
  1133. Routine Description:
  1134. Start an ATMARP timer. Based on the length (SecondsToGo) of the
  1135. timer, we decide on whether to insert it in the short duration
  1136. timer list or in the long duration timer list in the Interface
  1137. structure.
  1138. NOTE: the caller is assumed to either hold a lock to the structure
  1139. that contains the timer, or ensure that it is safe to access the
  1140. timer structure.
  1141. Arguments:
  1142. pInterface - Pointer to the ATMARP Interface
  1143. pTimer - Pointer to ATMARP Timer structure
  1144. TimeoutHandler - Handler function to be called if this timer expires
  1145. SecondsToGo - When does this timer go off?
  1146. Context - To be passed to timeout handler if this timer expires
  1147. Return Value:
  1148. None
  1149. --*/
  1150. {
  1151. PATMARP_TIMER_LIST pTimerList; // List to which this timer goes
  1152. PATMARP_TIMER pTimerListHead; // Head of above list
  1153. ULONG Index; // Into timer wheel
  1154. ULONG TicksToGo;
  1155. INT i;
  1156. AA_STRUCT_ASSERT(pInterface, aai);
  1157. AADEBUGP(AAD_EXTRA_LOUD,
  1158. ("StartTimer: pIf 0x%x, Secs %d, Handler 0x%x, Ctxt 0x%x, pTimer 0x%x\n",
  1159. pInterface, SecondsToGo, TimeoutHandler, Context, pTimer));
  1160. if (AA_IS_TIMER_ACTIVE(pTimer))
  1161. {
  1162. AADEBUGP(AAD_ERROR,
  1163. ("Start timer: pTimer 0x%x: is active (list 0x%x, hnd 0x%x), stopping it\n",
  1164. pTimer, pTimer->pTimerList, pTimer->TimeoutHandler));
  1165. AtmArpStopTimer(pTimer, pInterface);
  1166. }
  1167. AA_ACQUIRE_IF_TIMER_LOCK(pInterface);
  1168. AA_ASSERT(!AA_IS_TIMER_ACTIVE(pTimer));
  1169. //
  1170. // Find the list to which this timer should go, and the
  1171. // offset (TicksToGo)
  1172. //
  1173. for (i = 0; i < AAT_CLASS_MAX; i++)
  1174. {
  1175. pTimerList = &(pInterface->TimerList[i]);
  1176. if (SecondsToGo < pTimerList->MaxTimer)
  1177. {
  1178. //
  1179. // Found it.
  1180. //
  1181. TicksToGo = SecondsToGo / (pTimerList->TimerPeriod);
  1182. break;
  1183. }
  1184. }
  1185. AA_ASSERT(i < AAT_CLASS_MAX);
  1186. AA_VALIDATE_TIMER_LIST(pTimerList);
  1187. //
  1188. // Find the position in the list for this timer
  1189. //
  1190. Index = pTimerList->CurrentTick + TicksToGo;
  1191. if (Index >= pTimerList->TimerListSize)
  1192. {
  1193. Index -= pTimerList->TimerListSize;
  1194. }
  1195. AA_ASSERT(Index < pTimerList->TimerListSize);
  1196. pTimerListHead = &(pTimerList->pTimers[Index]);
  1197. //
  1198. // Fill in the timer
  1199. //
  1200. pTimer->pTimerList = pTimerList;
  1201. pTimer->LastRefreshTime = pTimerList->CurrentTick;
  1202. pTimer->Duration = TicksToGo;
  1203. pTimer->TimeoutHandler = TimeoutHandler;
  1204. pTimer->Context = Context;
  1205. pTimer->State = ATMARP_TIMER_STATE_RUNNING;
  1206. //
  1207. // Insert this timer in the "ticking" list
  1208. //
  1209. pTimer->pPrevTimer = pTimerListHead;
  1210. pTimer->pNextTimer = pTimerListHead->pNextTimer;
  1211. if (pTimer->pNextTimer != NULL_PATMARP_TIMER)
  1212. {
  1213. pTimer->pNextTimer->pPrevTimer = pTimer;
  1214. }
  1215. pTimerListHead->pNextTimer = pTimer;
  1216. //
  1217. // Start off the system tick timer if necessary.
  1218. //
  1219. pTimerList->TimerCount++;
  1220. if (pTimerList->TimerCount == 1)
  1221. {
  1222. AADEBUGP(AAD_LOUD,
  1223. ("StartTimer: Starting system timer 0x%x, class %d on IF 0x%x\n",
  1224. &(pTimerList->NdisTimer), i, pInterface));
  1225. AA_START_SYSTEM_TIMER(&(pTimerList->NdisTimer), pTimerList->TimerPeriod);
  1226. }
  1227. AA_VALIDATE_TIMER_LIST(pTimerList);
  1228. AA_VALIDATE_TIMER(pTimerList, pTimer);
  1229. AA_RELEASE_IF_TIMER_LOCK(pInterface);
  1230. //
  1231. // We're done
  1232. //
  1233. AADEBUGP(AAD_LOUD,
  1234. ("Started timer 0x%x, IF 0x%x, Secs %d, Index %d, Head 0x%x\n",
  1235. pTimer,
  1236. pInterface,
  1237. SecondsToGo,
  1238. Index,
  1239. pTimerListHead));
  1240. return;
  1241. }
  1242. BOOLEAN
  1243. AtmArpStopTimer(
  1244. IN PATMARP_TIMER pTimer,
  1245. IN PATMARP_INTERFACE pInterface
  1246. )
  1247. /*++
  1248. Routine Description:
  1249. Stop an ATMARP timer, if it is running. We remove this timer from
  1250. the active timer list and mark it so that we know it's not running.
  1251. NOTE: the caller is assumed to either hold a lock to the structure
  1252. that contains the timer, or ensure that it is safe to access the
  1253. timer structure.
  1254. SIDE EFFECT: If we happen to stop the last timer (of this "duration") on
  1255. the Interface, we also stop the appropriate Tick function.
  1256. Arguments:
  1257. pTimer - Pointer to ATMARP Timer structure
  1258. pInterface - Pointer to interface to which the timer belongs
  1259. Return Value:
  1260. TRUE if the timer was running, FALSE otherwise.
  1261. --*/
  1262. {
  1263. PATMARP_TIMER_LIST pTimerList; // Timer List to which this timer belongs
  1264. BOOLEAN WasRunning;
  1265. AADEBUGP(AAD_LOUD,
  1266. ("Stopping Timer 0x%x, IF 0x%x, List 0x%x, Prev 0x%x, Next 0x%x\n",
  1267. pTimer,
  1268. pInterface,
  1269. pTimer->pTimerList,
  1270. pTimer->pPrevTimer,
  1271. pTimer->pNextTimer));
  1272. AA_ACQUIRE_IF_TIMER_LOCK(pInterface);
  1273. if (AA_IS_TIMER_ACTIVE(pTimer))
  1274. {
  1275. WasRunning = TRUE;
  1276. AA_VALIDATE_TIMER_LIST(pTimer->pTimerList);
  1277. AA_VALIDATE_TIMER(NULL, pTimer);
  1278. //
  1279. // Unlink timer from the list
  1280. //
  1281. AA_ASSERT(pTimer->pPrevTimer); // the list head always exists
  1282. pTimer->pPrevTimer->pNextTimer = pTimer->pNextTimer;
  1283. if (pTimer->pNextTimer)
  1284. {
  1285. pTimer->pNextTimer->pPrevTimer = pTimer->pPrevTimer;
  1286. }
  1287. pTimer->pNextTimer = pTimer->pPrevTimer = NULL_PATMARP_TIMER;
  1288. //
  1289. // Update timer count on Interface, for this class of timers
  1290. //
  1291. pTimerList = pTimer->pTimerList;
  1292. pTimerList->TimerCount--;
  1293. //
  1294. // If all timers of this class are gone, stop the system tick timer
  1295. // for this class
  1296. //
  1297. if (pTimerList->TimerCount == 0)
  1298. {
  1299. AADEBUGP(AAD_LOUD, ("Stopping system timer 0x%x, List 0x%x, IF 0x%x\n",
  1300. &(pTimerList->NdisTimer),
  1301. pTimerList,
  1302. pInterface));
  1303. pTimerList->CurrentTick = 0;
  1304. AA_STOP_SYSTEM_TIMER(&(pTimerList->NdisTimer));
  1305. }
  1306. //
  1307. // Mark stopped timer as not active
  1308. //
  1309. pTimer->pTimerList = (PATMARP_TIMER_LIST)NULL;
  1310. pTimer->State = ATMARP_TIMER_STATE_IDLE;
  1311. AA_VALIDATE_TIMER_LIST(pTimerList);
  1312. }
  1313. else
  1314. {
  1315. WasRunning = FALSE;
  1316. }
  1317. AA_RELEASE_IF_TIMER_LOCK(pInterface);
  1318. return (WasRunning);
  1319. }
  1320. #ifdef NO_TIMER_MACRO
  1321. VOID
  1322. AtmArpRefreshTimer(
  1323. IN PATMARP_TIMER pTimer
  1324. )
  1325. /*++
  1326. Routine Description:
  1327. Refresh a timer that is already running.
  1328. NOTE: The caller is assumed to possess a lock protecting the
  1329. timer structure (i.e. to the structure containing the timer).
  1330. NOTE: We don't acquire the IF Timer Lock here, to optimize
  1331. the refresh operation. So, _within_ the confines of this routine,
  1332. the tick handler may fire, and expire this timer. The only care
  1333. that we take here is to make sure that we don't crash if the
  1334. timer expires while we access the Timer list.
  1335. Arguments:
  1336. pTimer - Pointer to ATMARP_TIMER structure
  1337. Return Value:
  1338. None
  1339. --*/
  1340. {
  1341. PATMARP_TIMER_LIST pTimerList;
  1342. if ((pTimerList = pTimer->pTimerList) != (PATMARP_TIMER_LIST)NULL)
  1343. {
  1344. pTimer->LastRefreshTime = pTimerList->CurrentTick;
  1345. }
  1346. else
  1347. {
  1348. AADEBUGP(AAD_VERY_LOUD,
  1349. ("RefreshTimer: pTimer 0x%x not active: Hnd 0x%x, Cntxt 0x%x\n",
  1350. pTimer,
  1351. pTimer->TimeoutHandler,
  1352. pTimer->Context
  1353. ));
  1354. }
  1355. AADEBUGP(AAD_LOUD,
  1356. ("Refreshed timer 0x%x, List 0x%x, hnd 0x%x, Cntxt 0x%x, LastRefresh %d\n",
  1357. pTimer,
  1358. pTimer->pTimerList,
  1359. pTimer->TimeoutHandler,
  1360. pTimer->Context,
  1361. pTimer->LastRefreshTime));
  1362. }
  1363. #endif // NO_TIMER_MACRO
  1364. VOID
  1365. AtmArpTickHandler(
  1366. IN PVOID SystemSpecific1,
  1367. IN PVOID Context,
  1368. IN PVOID SystemSpecific2,
  1369. IN PVOID SystemSpecific3
  1370. )
  1371. /*++
  1372. Routine Description:
  1373. This is the handler we register with the system for processing each
  1374. Timer List. This is called every "tick" seconds, where "tick" is
  1375. determined by the granularity of the timer type.
  1376. Arguments:
  1377. Context - Actually a pointer to a Timer List structure
  1378. SystemSpecific[1-3] - Not used
  1379. Return Value:
  1380. None
  1381. --*/
  1382. {
  1383. PATMARP_INTERFACE pInterface;
  1384. PATMARP_TIMER_LIST pTimerList;
  1385. PATMARP_TIMER pExpiredTimer; // Start of list of expired timers
  1386. PATMARP_TIMER pNextTimer; // for walking above list
  1387. PATMARP_TIMER pTimer; // temp, for walking timer list
  1388. PATMARP_TIMER pPrevExpiredTimer; // for creating expired timer list
  1389. ULONG Index; // into the timer wheel
  1390. ULONG NewIndex; // for refreshed timers
  1391. pTimerList = (PATMARP_TIMER_LIST)Context;
  1392. AA_STRUCT_ASSERT(pTimerList, atl);
  1393. pInterface = (PATMARP_INTERFACE)pTimerList->ListContext;
  1394. AA_STRUCT_ASSERT(pInterface, aai);
  1395. AADEBUGP(AAD_VERY_LOUD, ("Tick: pIf 0x%x, List 0x%x, Count %d\n",
  1396. pInterface, pTimerList, pTimerList->TimerCount));
  1397. pExpiredTimer = NULL_PATMARP_TIMER;
  1398. AA_ACQUIRE_IF_TIMER_LOCK(pInterface);
  1399. AA_VALIDATE_TIMER_LIST(pTimerList);
  1400. if (pInterface->AdminState == IF_STATUS_UP)
  1401. {
  1402. //
  1403. // Pick up the list of timers scheduled to have expired at the
  1404. // current tick. Some of these might have been refreshed.
  1405. //
  1406. Index = pTimerList->CurrentTick;
  1407. pExpiredTimer = (pTimerList->pTimers[Index]).pNextTimer;
  1408. (pTimerList->pTimers[Index]).pNextTimer = NULL_PATMARP_TIMER;
  1409. //
  1410. // Go through the list of timers scheduled to expire at this tick.
  1411. // Prepare a list of expired timers, using the pNextExpiredTimer
  1412. // link to chain them together.
  1413. //
  1414. // Some timers may have been refreshed, in which case we reinsert
  1415. // them in the active timer list.
  1416. //
  1417. pPrevExpiredTimer = NULL_PATMARP_TIMER;
  1418. for (pTimer = pExpiredTimer;
  1419. pTimer != NULL_PATMARP_TIMER;
  1420. pTimer = pNextTimer)
  1421. {
  1422. //
  1423. // Save a pointer to the next timer, for the next iteration.
  1424. //
  1425. pNextTimer = pTimer->pNextTimer;
  1426. AADEBUGP(AAD_EXTRA_LOUD,
  1427. ("Tick Handler: pIf 0x%x, looking at timer 0x%x, next 0x%x\n",
  1428. pInterface, pTimer, pNextTimer));
  1429. //
  1430. // Find out when this timer should actually expire.
  1431. //
  1432. NewIndex = pTimer->LastRefreshTime + pTimer->Duration;
  1433. if (NewIndex >= pTimerList->TimerListSize)
  1434. {
  1435. NewIndex -= pTimerList->TimerListSize;
  1436. }
  1437. //
  1438. // Check if we are currently at the point of expiry.
  1439. //
  1440. if (NewIndex != Index)
  1441. {
  1442. //
  1443. // This timer still has some way to go, so put it back.
  1444. //
  1445. AADEBUGP(AAD_LOUD,
  1446. ("Tick: Reinserting Timer 0x%x: Hnd 0x%x, Durn %d, Ind %d, NewInd %d\n",
  1447. pTimer, pTimer->TimeoutHandler, pTimer->Duration, Index, NewIndex));
  1448. //
  1449. // Remove it from the expired timer list. Note that we only
  1450. // need to update the forward (pNextExpiredTimer) links.
  1451. //
  1452. if (pPrevExpiredTimer == NULL_PATMARP_TIMER)
  1453. {
  1454. pExpiredTimer = pNextTimer;
  1455. }
  1456. else
  1457. {
  1458. pPrevExpiredTimer->pNextExpiredTimer = pNextTimer;
  1459. }
  1460. //
  1461. // And insert it back into the running timer list.
  1462. //
  1463. pTimer->pNextTimer = (pTimerList->pTimers[NewIndex]).pNextTimer;
  1464. if (pTimer->pNextTimer != NULL_PATMARP_TIMER)
  1465. {
  1466. pTimer->pNextTimer->pPrevTimer = pTimer;
  1467. }
  1468. pTimer->pPrevTimer = &(pTimerList->pTimers[NewIndex]);
  1469. (pTimerList->pTimers[NewIndex]).pNextTimer = pTimer;
  1470. }
  1471. else
  1472. {
  1473. //
  1474. // This one has expired. Keep it in the expired timer list.
  1475. //
  1476. pTimer->pNextExpiredTimer = pNextTimer;
  1477. if (pPrevExpiredTimer == NULL_PATMARP_TIMER)
  1478. {
  1479. pExpiredTimer = pTimer;
  1480. }
  1481. pPrevExpiredTimer = pTimer;
  1482. //
  1483. // Mark it as inactive.
  1484. //
  1485. AA_ASSERT(pTimer->pTimerList == pTimerList);
  1486. pTimer->pTimerList = (PATMARP_TIMER_LIST)NULL;
  1487. pTimer->State = ATMARP_TIMER_STATE_EXPIRING;
  1488. //
  1489. // Update the active timer count.
  1490. //
  1491. pTimerList->TimerCount--;
  1492. }
  1493. }
  1494. //
  1495. // Update current tick index in readiness for the next tick.
  1496. //
  1497. if (++Index == pTimerList->TimerListSize)
  1498. {
  1499. pTimerList->CurrentTick = 0;
  1500. }
  1501. else
  1502. {
  1503. pTimerList->CurrentTick = Index;
  1504. }
  1505. if (pTimerList->TimerCount > 0)
  1506. {
  1507. //
  1508. // Re-arm the tick handler
  1509. //
  1510. AADEBUGP(AAD_LOUD, ("Tick[%d]: Starting system timer 0x%x, on IF 0x%x\n",
  1511. pTimerList->CurrentTick, &(pTimerList->NdisTimer), pInterface));
  1512. AA_START_SYSTEM_TIMER(&(pTimerList->NdisTimer), pTimerList->TimerPeriod);
  1513. }
  1514. else
  1515. {
  1516. pTimerList->CurrentTick = 0;
  1517. }
  1518. }
  1519. AA_RELEASE_IF_TIMER_LOCK(pInterface);
  1520. //
  1521. // Now pExpiredTimer is a list of expired timers.
  1522. // Walk through the list and call the timeout handlers
  1523. // for each timer.
  1524. //
  1525. while (pExpiredTimer != NULL_PATMARP_TIMER)
  1526. {
  1527. pNextTimer = pExpiredTimer->pNextExpiredTimer;
  1528. AADEBUGP(AAD_LOUD, ("Expired timer 0x%x: handler 0x%x, next 0x%x\n",
  1529. pExpiredTimer, pExpiredTimer->TimeoutHandler, pNextTimer));
  1530. pExpiredTimer->State = ATMARP_TIMER_STATE_EXPIRED;
  1531. (*(pExpiredTimer->TimeoutHandler))(
  1532. pExpiredTimer,
  1533. pExpiredTimer->Context
  1534. );
  1535. pExpiredTimer = pNextTimer;
  1536. }
  1537. }
  1538. PNDIS_PACKET
  1539. AtmArpAllocatePacket(
  1540. IN PATMARP_INTERFACE pInterface
  1541. )
  1542. /*++
  1543. Routine Description:
  1544. Allocate an NDIS packet for the specified Interface.
  1545. Currently just a wrapper for the corresponding NDIS function.
  1546. Arguments:
  1547. pInterface - Pointer to ATMARP Interface structure
  1548. Return Value:
  1549. Pointer to NDIS packet if allocated, NULL otherwise.
  1550. --*/
  1551. {
  1552. NDIS_STATUS Status;
  1553. PNDIS_PACKET pNdisPacket;
  1554. struct PacketContext *PC;
  1555. NdisAllocatePacket(
  1556. &Status,
  1557. &pNdisPacket,
  1558. pInterface->ProtocolPacketPool
  1559. );
  1560. if (pNdisPacket != (PNDIS_PACKET)NULL)
  1561. {
  1562. PC = (struct PacketContext *)pNdisPacket->ProtocolReserved;
  1563. PC->pc_common.pc_owner = PACKET_OWNER_LINK;
  1564. }
  1565. AADEBUGP(AAD_EXTRA_LOUD, ("Allocate Packet: IF 0x%x, Status 0x%x, Packet 0x%x\n",
  1566. pInterface,
  1567. Status,
  1568. pNdisPacket));
  1569. return (pNdisPacket);
  1570. }
  1571. VOID
  1572. AtmArpFreePacket(
  1573. IN PATMARP_INTERFACE pInterface,
  1574. IN PNDIS_PACKET pPacket
  1575. )
  1576. /*++
  1577. Routine Description:
  1578. Deallocate an NDIS packet on the specified Interface.
  1579. Currently just a wrapper around the corresponding NDIS function.
  1580. Arguments:
  1581. pInterface - Pointer to ATMARP Interface structure
  1582. pPacket - Pointer to packet being freed.
  1583. Return Value:
  1584. None
  1585. --*/
  1586. {
  1587. NdisFreePacket(pPacket);
  1588. AADEBUGP(AAD_EXTRA_LOUD, ("Free Packet: IF 0x%x, Packet 0x%x\n",
  1589. pInterface,
  1590. pPacket));
  1591. }
  1592. PNDIS_BUFFER
  1593. AtmArpGrowHeaders(
  1594. IN PATMARP_INTERFACE pInterface,
  1595. IN AA_HEADER_TYPE HdrType
  1596. )
  1597. /*++
  1598. Routine Description:
  1599. Allocate a bunch of header buffers on the specified ATMARP interface.
  1600. Return one of them.
  1601. We allocate a new Buffer tracker structure, a new NDIS Buffer pool, and
  1602. finally a chunk of system memory that we break down into header buffers.
  1603. These header buffers are then attached to NDIS Buffers before they are
  1604. inserted into the list of free header buffers for this Interface.
  1605. Arguments:
  1606. pInterface - Pointer to ATMARP Interface structure
  1607. HdrType - Unicast or Nonunicast
  1608. Return Value:
  1609. Pointer to allocated NDIS buffer if successful, NULL otherwise.
  1610. --*/
  1611. {
  1612. PATMARP_BUFFER_TRACKER pTracker; // for new set of buffers
  1613. PUCHAR pSpace;
  1614. PNDIS_BUFFER pNdisBuffer;
  1615. PNDIS_BUFFER pReturnBuffer;
  1616. PNDIS_BUFFER pBufferList; // allocated list
  1617. INT i; // iteration counter
  1618. NDIS_STATUS Status;
  1619. AA_ASSERT(HdrType < AA_HEADER_TYPE_MAX);
  1620. //
  1621. // Initialize
  1622. //
  1623. pTracker = NULL_PATMARP_BUFFER_TRACKER;
  1624. pReturnBuffer = (PNDIS_BUFFER)NULL;
  1625. NdisAcquireSpinLock(&pInterface->BufferLock);
  1626. do
  1627. {
  1628. if (pInterface->HeaderPool[HdrType].CurHeaderBufs >=
  1629. pInterface->HeaderPool[HdrType].MaxHeaderBufs)
  1630. {
  1631. AADEBUGP(AAD_WARNING,
  1632. ("Grow Hdrs: IF 0x%x, Type %d, CurHdrBufs %d > MaxHdrBufs %d\n",
  1633. pInterface,
  1634. HdrType,
  1635. pInterface->HeaderPool[HdrType].CurHeaderBufs,
  1636. pInterface->HeaderPool[HdrType].MaxHeaderBufs));
  1637. break;
  1638. }
  1639. //
  1640. // Allocate and initialize Buffer tracker
  1641. //
  1642. AA_ALLOC_MEM(pTracker, ATMARP_BUFFER_TRACKER, sizeof(ATMARP_BUFFER_TRACKER));
  1643. if (pTracker == NULL_PATMARP_BUFFER_TRACKER)
  1644. {
  1645. AADEBUGP(AAD_WARNING, ("Grow Hdrs: IF 0x%x, alloc failed for tracker\n",
  1646. pInterface));
  1647. break;
  1648. }
  1649. AA_SET_MEM(pTracker, 0, sizeof(ATMARP_BUFFER_TRACKER));
  1650. //
  1651. // Get the NDIS Buffer pool
  1652. //
  1653. NdisAllocateBufferPool(
  1654. &Status,
  1655. &(pTracker->NdisHandle),
  1656. AA_DEF_HDRBUF_GROW_SIZE
  1657. );
  1658. if (Status != NDIS_STATUS_SUCCESS)
  1659. {
  1660. AADEBUGP(AAD_WARNING,
  1661. ("Grow Hdrs: IF 0x%x, NdisAllocateBufferPool err status 0x%x\n",
  1662. pInterface, Status));
  1663. break;
  1664. }
  1665. //
  1666. // Allocate system space for a bunch of header buffers
  1667. //
  1668. AA_ALLOC_MEM(pTracker->pPoolStart,
  1669. UCHAR,
  1670. pInterface->HeaderPool[HdrType].HeaderBufSize *
  1671. AA_DEF_HDRBUF_GROW_SIZE);
  1672. if (pTracker->pPoolStart == (PUCHAR)NULL)
  1673. {
  1674. AADEBUGP(AAD_WARNING,
  1675. ("Grow Hdrs: IF 0x%x, could not alloc buf space %d bytes\n",
  1676. pInterface,
  1677. pInterface->HeaderPool[HdrType].HeaderBufSize *
  1678. AA_DEF_HDRBUF_GROW_SIZE));
  1679. break;
  1680. }
  1681. //
  1682. // Make NDIS buffers out of the allocated space, and put them
  1683. // into the free header buffer list. Retain one for returning
  1684. // to caller.
  1685. //
  1686. // We also fill in the contents of the buffers right away, so
  1687. // that we don't have to prepare them afresh for each transmit.
  1688. //
  1689. pBufferList = (PNDIS_BUFFER)NULL;
  1690. pSpace = pTracker->pPoolStart;
  1691. for (i = 0; i < AA_DEF_HDRBUF_GROW_SIZE; i++)
  1692. {
  1693. if (HdrType == AA_HEADER_TYPE_UNICAST)
  1694. {
  1695. //
  1696. // Fill in the (Unicast) LLC/SNAP header
  1697. //
  1698. AA_COPY_MEM(pSpace,
  1699. &AtmArpLlcSnapHeader,
  1700. pInterface->HeaderPool[HdrType].HeaderBufSize);
  1701. }
  1702. else
  1703. {
  1704. AA_ASSERT(HdrType == AA_HEADER_TYPE_NUNICAST);
  1705. //
  1706. // Fill in the (Multicast) Type 1 short form header
  1707. //
  1708. #ifdef IPMCAST
  1709. AA_COPY_MEM(pSpace,
  1710. &AtmArpMcType1ShortHeader,
  1711. pInterface->HeaderPool[HdrType].HeaderBufSize);
  1712. #else
  1713. AA_ASSERT(FALSE);
  1714. #endif // IPMCAST
  1715. }
  1716. NdisAllocateBuffer(
  1717. &Status,
  1718. &pNdisBuffer,
  1719. pTracker->NdisHandle,
  1720. pSpace,
  1721. pInterface->HeaderPool[HdrType].HeaderBufSize
  1722. );
  1723. if (Status != NDIS_STATUS_SUCCESS)
  1724. {
  1725. AADEBUGP(AAD_WARNING,
  1726. ("Grow Hdrs: NdisAllocateBuffer failed: IF 0x%x, status 0x%x\n",
  1727. pInterface, Status));
  1728. break;
  1729. }
  1730. if (i == 0)
  1731. {
  1732. pReturnBuffer = pNdisBuffer;
  1733. }
  1734. else
  1735. {
  1736. NDIS_BUFFER_LINKAGE(pNdisBuffer) = pBufferList;
  1737. pBufferList = pNdisBuffer;
  1738. }
  1739. pSpace += pInterface->HeaderPool[HdrType].HeaderBufSize;
  1740. }
  1741. if (i > 0)
  1742. {
  1743. //
  1744. // Successfully allocated atleast one more header buffer
  1745. //
  1746. pTracker->pNext = pInterface->HeaderPool[HdrType].pHeaderTrkList;
  1747. pInterface->HeaderPool[HdrType].pHeaderTrkList = pTracker;
  1748. pInterface->HeaderPool[HdrType].CurHeaderBufs += i;
  1749. NdisReleaseSpinLock(&pInterface->BufferLock);
  1750. pNdisBuffer = pBufferList;
  1751. while (pNdisBuffer != (PNDIS_BUFFER)NULL)
  1752. {
  1753. pBufferList = NDIS_BUFFER_LINKAGE(pNdisBuffer);
  1754. NDIS_BUFFER_LINKAGE(pNdisBuffer) = NULL;
  1755. AtmArpFreeHeader(pInterface, pNdisBuffer, HdrType);
  1756. pNdisBuffer = pBufferList;
  1757. }
  1758. }
  1759. } while (FALSE);
  1760. if (pReturnBuffer == (PNDIS_BUFFER)NULL)
  1761. {
  1762. //
  1763. // Failed to allocate. Undo all.
  1764. //
  1765. NdisReleaseSpinLock(&pInterface->BufferLock);
  1766. if (pTracker != NULL_PATMARP_BUFFER_TRACKER)
  1767. {
  1768. if (pTracker->pPoolStart != (PUCHAR)NULL)
  1769. {
  1770. AA_FREE_MEM(pTracker->pPoolStart);
  1771. }
  1772. if (pTracker->NdisHandle != (NDIS_HANDLE)NULL)
  1773. {
  1774. NdisFreeBufferPool(pTracker->NdisHandle);
  1775. }
  1776. AA_FREE_MEM(pTracker);
  1777. }
  1778. }
  1779. AADEBUGP(AAD_INFO, ("Grow ARP Headers: IF 0x%x, RetBuf 0x%x, New Tracker 0x%x\n",
  1780. pInterface, pReturnBuffer, pTracker));
  1781. return (pReturnBuffer);
  1782. }
  1783. PNDIS_BUFFER
  1784. AtmArpAllocateHeader(
  1785. IN PATMARP_INTERFACE pInterface,
  1786. IN AA_HEADER_TYPE HdrType,
  1787. OUT PUCHAR * pBufferAddress
  1788. )
  1789. /*++
  1790. Routine Description:
  1791. Allocate an NDIS Buffer to be used as an LLC/SNAP header prepended
  1792. to an IP packet. We pick up the buffer at the top of the pre-allocated
  1793. buffer list, if one exists. Otherwise, we try to grow this list and
  1794. allocate.
  1795. Arguments:
  1796. pInterface - Pointer to ATMARP Interface
  1797. HdrType - Unicast or Nonunicast
  1798. pBufferAddress - Place to return virtual address of allocated buffer
  1799. Return Value:
  1800. Pointer to NDIS buffer if successful, NULL otherwise.
  1801. --*/
  1802. {
  1803. PNDIS_BUFFER pNdisBuffer;
  1804. NDIS_STATUS Status;
  1805. ULONG Length;
  1806. PAA_SINGLE_LIST_ENTRY pListEntry;
  1807. pListEntry = AA_POP_FROM_SLIST(
  1808. &(pInterface->HeaderPool[HdrType].HeaderBufList),
  1809. &(pInterface->BufferLock.SpinLock)
  1810. );
  1811. if (pListEntry != NULL_PAA_SINGLE_LIST_ENTRY)
  1812. {
  1813. pNdisBuffer = STRUCT_OF(NDIS_BUFFER, pListEntry, Next);
  1814. NDIS_BUFFER_LINKAGE(pNdisBuffer) = NULL;
  1815. *pBufferAddress = NdisBufferVirtualAddress(pNdisBuffer);
  1816. }
  1817. else
  1818. {
  1819. pNdisBuffer = AtmArpGrowHeaders(pInterface, HdrType);
  1820. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  1821. {
  1822. NDIS_BUFFER_LINKAGE(pNdisBuffer) = NULL;
  1823. NdisQueryBuffer(pNdisBuffer, (PVOID)pBufferAddress, &Length);
  1824. AADEBUGP(AAD_INFO,
  1825. ("After growing hdrs: Type %d, returning pNdisBuf 0x%x, Start 0x%x, Len %d\n",
  1826. HdrType, pNdisBuffer, *pBufferAddress, Length));
  1827. }
  1828. }
  1829. AADEBUGP(AAD_VERY_LOUD, ("Allocated Header Buffer: 0x%x, IF: 0x%x\n",
  1830. pNdisBuffer, pInterface));
  1831. return (pNdisBuffer);
  1832. }
  1833. VOID
  1834. AtmArpFreeHeader(
  1835. IN PATMARP_INTERFACE pInterface,
  1836. IN PNDIS_BUFFER pNdisBuffer,
  1837. IN AA_HEADER_TYPE HdrType
  1838. )
  1839. /*++
  1840. Routine Description:
  1841. Deallocate a header buffer.
  1842. Arguments:
  1843. pInterface - Pointer to ATMARP interface from which the buffer came
  1844. pNdisBuffer - Pointer to NDIS buffer being freed
  1845. HdrType - Unicast or Nonunicast
  1846. Return Value:
  1847. None
  1848. --*/
  1849. {
  1850. AA_PUSH_TO_SLIST(
  1851. &(pInterface->HeaderPool[HdrType].HeaderBufList),
  1852. STRUCT_OF(AA_SINGLE_LIST_ENTRY, &(pNdisBuffer->Next), Next),
  1853. &(pInterface->BufferLock.SpinLock)
  1854. );
  1855. AADEBUGP(AAD_VERY_LOUD, ("Freed Header Buffer: 0x%x, IF: 0x%x, HdrType %d\n",
  1856. pNdisBuffer, pInterface, HdrType));
  1857. }
  1858. VOID
  1859. AtmArpDeallocateHeaderBuffers(
  1860. IN PATMARP_INTERFACE pInterface
  1861. )
  1862. /*++
  1863. Routine Description:
  1864. Deallocate everything pertaining to header buffers on an Interface.
  1865. Arguments:
  1866. pInterface - Pointer to ATMARP Interface
  1867. Return Value:
  1868. None
  1869. --*/
  1870. {
  1871. PNDIS_BUFFER pNdisBuffer;
  1872. NDIS_STATUS Status;
  1873. PAA_SINGLE_LIST_ENTRY pListEntry;
  1874. PATMARP_BUFFER_TRACKER pTracker;
  1875. PATMARP_BUFFER_TRACKER pNextTracker;
  1876. AA_HEADER_TYPE HdrType;
  1877. for (HdrType = 0; HdrType < AA_HEADER_TYPE_MAX; HdrType++)
  1878. {
  1879. //
  1880. // Free all NDIS buffers in the header buffer list.
  1881. //
  1882. do
  1883. {
  1884. pListEntry = AA_POP_FROM_SLIST(
  1885. &(pInterface->HeaderPool[HdrType].HeaderBufList),
  1886. &(pInterface->BufferLock.SpinLock)
  1887. );
  1888. if (pListEntry != NULL_PAA_SINGLE_LIST_ENTRY)
  1889. {
  1890. pNdisBuffer = STRUCT_OF(NDIS_BUFFER, pListEntry, Next);
  1891. NDIS_BUFFER_LINKAGE(pNdisBuffer) = NULL;
  1892. NdisFreeBuffer(pNdisBuffer);
  1893. }
  1894. else
  1895. {
  1896. //
  1897. // No more NDIS buffers.
  1898. //
  1899. break;
  1900. }
  1901. }
  1902. while (TRUE);
  1903. //
  1904. // Now free all the buffer trackers.
  1905. //
  1906. pTracker = pInterface->HeaderPool[HdrType].pHeaderTrkList;
  1907. while (pTracker != NULL_PATMARP_BUFFER_TRACKER)
  1908. {
  1909. pNextTracker = pTracker->pNext;
  1910. if (pTracker->pPoolStart != (PUCHAR)NULL)
  1911. {
  1912. AA_FREE_MEM(pTracker->pPoolStart);
  1913. pTracker->pPoolStart = (PUCHAR)NULL;
  1914. }
  1915. if (pTracker->NdisHandle != (NDIS_HANDLE)NULL)
  1916. {
  1917. NdisFreeBufferPool(pTracker->NdisHandle);
  1918. pTracker->NdisHandle = (NDIS_HANDLE)NULL;
  1919. }
  1920. AA_FREE_MEM(pTracker);
  1921. pTracker = pNextTracker;
  1922. }
  1923. } // for
  1924. }
  1925. PNDIS_BUFFER
  1926. AtmArpAllocateProtoBuffer(
  1927. IN PATMARP_INTERFACE pInterface,
  1928. IN ULONG Length,
  1929. OUT PUCHAR * pBufferAddress
  1930. )
  1931. /*++
  1932. Routine Description:
  1933. Allocate a buffer to be used for an ATM ARP protocol message. Attach
  1934. it to an NDIS_BUFFER structure and return a pointer to this.
  1935. Arguments:
  1936. pInterface - Pointer to ATMARP Interface
  1937. Length - Length, in bytes, of the buffer.
  1938. pBufferAddress - Place to return virtual address of allocated buffer.
  1939. Return Value:
  1940. Pointer to NDIS Buffer if successful, NULL otherwise.
  1941. --*/
  1942. {
  1943. PNDIS_BUFFER pNdisBuffer;
  1944. NDIS_STATUS Status;
  1945. //
  1946. // Initialize
  1947. //
  1948. pNdisBuffer = NULL;
  1949. AA_ASSERT(Length <= pInterface->ProtocolBufSize);
  1950. NdisAcquireSpinLock(&pInterface->BufferLock);
  1951. *pBufferAddress = pInterface->ProtocolBufList;
  1952. if (*pBufferAddress != (PUCHAR)NULL)
  1953. {
  1954. NdisAllocateBuffer(
  1955. &Status,
  1956. &pNdisBuffer,
  1957. pInterface->ProtocolBufferPool,
  1958. *pBufferAddress,
  1959. Length
  1960. );
  1961. if (Status == NDIS_STATUS_SUCCESS)
  1962. {
  1963. pInterface->ProtocolBufList = *((PUCHAR *)*pBufferAddress);
  1964. }
  1965. }
  1966. NdisReleaseSpinLock(&pInterface->BufferLock);
  1967. AADEBUGP(AAD_LOUD,
  1968. ("Allocated protocol buffer: IF 0x%x, pNdisBuffer 0x%x, Length %d, Loc 0x%x\n",
  1969. pInterface, pNdisBuffer, Length, *pBufferAddress));
  1970. return (pNdisBuffer);
  1971. }
  1972. VOID
  1973. AtmArpFreeProtoBuffer(
  1974. IN PATMARP_INTERFACE pInterface,
  1975. IN PNDIS_BUFFER pNdisBuffer
  1976. )
  1977. /*++
  1978. Routine Description:
  1979. Free an NDIS buffer (and associated memory) used for a protocol
  1980. packet. We return the associated memory to the ProtocolBufList
  1981. in the interface structure, and the NDIS buffer to NDIS.
  1982. Arguments:
  1983. pInterface - Pointer to ATMARP interface structure
  1984. pNdisBuffer - Pointer to NDIS buffer to be freed
  1985. Return Value:
  1986. None
  1987. --*/
  1988. {
  1989. PUCHAR * pBufferLinkage;
  1990. ULONG Length;
  1991. NdisQueryBuffer(pNdisBuffer, (PVOID)&pBufferLinkage, &Length);
  1992. NdisAcquireSpinLock(&pInterface->BufferLock);
  1993. *pBufferLinkage = pInterface->ProtocolBufList;
  1994. pInterface->ProtocolBufList = (PUCHAR)pBufferLinkage;
  1995. NdisReleaseSpinLock(&pInterface->BufferLock);
  1996. NdisFreeBuffer(pNdisBuffer);
  1997. AADEBUGP(AAD_LOUD, ("Freed Protocol Buf: IF 0x%x, pNdisBuffer 0x%x, Loc 0x%x\n",
  1998. pInterface, pNdisBuffer, pBufferLinkage));
  1999. }
  2000. NDIS_STATUS
  2001. AtmArpInitProtoBuffers(
  2002. IN PATMARP_INTERFACE pInterface
  2003. )
  2004. /*++
  2005. Routine Description:
  2006. Initialize the protocol buffer pool for an interface.
  2007. Allocate a chunk of memory to be used for ATMARP protocol messages.
  2008. We prepare a linked list of protocol buffers, and attach it to the
  2009. Interface structure.
  2010. Arguments:
  2011. pInterface - Pointer to Interface on which we need to allocate
  2012. protocol buffers.
  2013. Return Value:
  2014. NDIS_STATUS_SUCCESS if successful, NDIS_STATUS_RESOURCES if we run
  2015. into a resource failure.
  2016. --*/
  2017. {
  2018. NDIS_STATUS Status;
  2019. PUCHAR pSpace;
  2020. ULONG i;
  2021. do
  2022. {
  2023. NdisAllocatePacketPool(
  2024. &Status,
  2025. &(pInterface->ProtocolPacketPool),
  2026. pInterface->MaxProtocolBufs,
  2027. sizeof(struct PCCommon)
  2028. );
  2029. if (Status != NDIS_STATUS_SUCCESS)
  2030. {
  2031. break;
  2032. }
  2033. NdisAllocateBufferPool(
  2034. &Status,
  2035. &(pInterface->ProtocolBufferPool),
  2036. pInterface->MaxProtocolBufs
  2037. );
  2038. if (Status != NDIS_STATUS_SUCCESS)
  2039. {
  2040. break;
  2041. }
  2042. //
  2043. // Allocate a big chunk of system memory that we can divide up into
  2044. // protocol buffers.
  2045. //
  2046. AA_ALLOC_MEM(
  2047. pInterface->ProtocolBufTracker,
  2048. UCHAR,
  2049. (pInterface->ProtocolBufSize * pInterface->MaxProtocolBufs)
  2050. );
  2051. if (pInterface->ProtocolBufTracker == (PUCHAR)NULL)
  2052. {
  2053. Status = NDIS_STATUS_RESOURCES;
  2054. break;
  2055. }
  2056. Status = NDIS_STATUS_SUCCESS;
  2057. //
  2058. // Make all protocol buffers free.
  2059. //
  2060. pSpace = pInterface->ProtocolBufTracker;
  2061. {
  2062. PUCHAR LinkPtr;
  2063. LinkPtr = (PUCHAR)NULL;
  2064. for (i = 0; i < pInterface->MaxProtocolBufs; i++)
  2065. {
  2066. *((PUCHAR *)pSpace) = LinkPtr;
  2067. LinkPtr = pSpace;
  2068. pSpace += pInterface->ProtocolBufSize;
  2069. }
  2070. pSpace -= pInterface->ProtocolBufSize;
  2071. pInterface->ProtocolBufList = pSpace;
  2072. }
  2073. }
  2074. while (FALSE);
  2075. if (Status != NDIS_STATUS_SUCCESS)
  2076. {
  2077. //
  2078. // Undo everything.
  2079. //
  2080. AtmArpDeallocateProtoBuffers(pInterface);
  2081. }
  2082. return (Status);
  2083. }
  2084. VOID
  2085. AtmArpDeallocateProtoBuffers(
  2086. IN PATMARP_INTERFACE pInterface
  2087. )
  2088. /*++
  2089. Routine Description:
  2090. Free the protocol buffer pool for an interface.
  2091. Arguments:
  2092. pInterface - Pointer to ATMARP interface structure
  2093. Return Value:
  2094. None
  2095. --*/
  2096. {
  2097. if (pInterface->ProtocolPacketPool != (NDIS_HANDLE)NULL)
  2098. {
  2099. NdisFreePacketPool(pInterface->ProtocolPacketPool);
  2100. pInterface->ProtocolPacketPool = NULL;
  2101. }
  2102. if (pInterface->ProtocolBufferPool != (NDIS_HANDLE)NULL)
  2103. {
  2104. NdisFreeBufferPool(pInterface->ProtocolBufferPool);
  2105. pInterface->ProtocolBufferPool = NULL;
  2106. }
  2107. if (pInterface->ProtocolBufTracker != (PUCHAR)NULL)
  2108. {
  2109. AA_FREE_MEM(pInterface->ProtocolBufTracker);
  2110. pInterface->ProtocolBufTracker = (PUCHAR)NULL;
  2111. }
  2112. }
  2113. VOID
  2114. AtmArpLinkVcToAtmEntry(
  2115. IN PATMARP_VC pVc,
  2116. IN PATMARP_ATM_ENTRY pAtmEntry
  2117. )
  2118. /*++
  2119. Routine Description:
  2120. Link an ATMARP VC to an ATM Entry. The caller is assumed to
  2121. hold locks to both structures.
  2122. If this VC is a "best effort" VC, and there is no "best effort"
  2123. VC linked to the ATM Entry, we make this as the "best effort VC"
  2124. on this ATM Entry.
  2125. Arguments:
  2126. pVc - Pointer to ATMARP VC structure
  2127. pAtmEntry - Pointer to ATMARP ATM Entry structure
  2128. Return Value:
  2129. None
  2130. --*/
  2131. {
  2132. PATMARP_VC *ppNext;
  2133. ULONG SendBandwidth;
  2134. AADEBUGP(AAD_EXTRA_LOUD, ("Link VC: 0x%x to AtmEntry 0x%x\n",
  2135. pVc, pAtmEntry));
  2136. //
  2137. // Back pointer from VC to ATM Entry.
  2138. //
  2139. pVc->pAtmEntry = pAtmEntry;
  2140. //
  2141. // Find the position in which this VC should appear in the ATM Entry's
  2142. // VC list. We maintain this list in descending order of send bandwidth,
  2143. // so that the largest bandwidth VC to a destination appears first.
  2144. //
  2145. SendBandwidth = pVc->FlowSpec.SendPeakBandwidth;
  2146. ppNext = &(pAtmEntry->pVcList);
  2147. while (*ppNext != NULL_PATMARP_VC)
  2148. {
  2149. if (SendBandwidth >= (*ppNext)->FlowSpec.SendPeakBandwidth)
  2150. {
  2151. break;
  2152. }
  2153. else
  2154. {
  2155. ppNext = &((*ppNext)->pNextVc);
  2156. }
  2157. }
  2158. //
  2159. // Found the place we were looking for. Insert the VC here.
  2160. //
  2161. pVc->pNextVc = *ppNext;
  2162. *ppNext = pVc;
  2163. if ((pAtmEntry->pBestEffortVc == NULL_PATMARP_VC) &&
  2164. AA_IS_BEST_EFFORT_FLOW(&(pVc->FlowSpec)))
  2165. {
  2166. pAtmEntry->pBestEffortVc = pVc;
  2167. }
  2168. AA_REF_AE(pAtmEntry, AE_REFTYPE_VC); // VC reference
  2169. }
  2170. VOID
  2171. AtmArpUnlinkVcFromAtmEntry(
  2172. IN PATMARP_VC pVc,
  2173. IN BOOLEAN bDerefAtmEntry
  2174. )
  2175. /*++
  2176. Routine Description:
  2177. Unlink an ATMARP VC from the ATM Entry it is linked to.
  2178. The caller is assumed to hold a lock for the VC structure.
  2179. Arguments:
  2180. pVc - Pointer to ATMARP VC structure
  2181. bDerefAtmEntry - Should we deref the ATM entry or not.
  2182. Return Value:
  2183. None
  2184. --*/
  2185. {
  2186. PATMARP_ATM_ENTRY pAtmEntry;
  2187. PATMARP_VC * ppVc;
  2188. AADEBUGP(AAD_EXTRA_LOUD, ("Unlink VC: 0x%x from AtmEntry 0x%x\n",
  2189. pVc, pVc->pAtmEntry));
  2190. pAtmEntry = pVc->pAtmEntry;
  2191. AA_ASSERT(pAtmEntry != NULL_PATMARP_ATM_ENTRY);
  2192. pVc->pAtmEntry = NULL_PATMARP_ATM_ENTRY;
  2193. //
  2194. // Reacquire locks in the right order.
  2195. //
  2196. AA_RELEASE_VC_LOCK(pVc);
  2197. AA_ACQUIRE_AE_LOCK(pAtmEntry);
  2198. AA_ACQUIRE_VC_LOCK_DPC(pVc);
  2199. //
  2200. // Search for the position of this VC in the ATM Entry's VC list
  2201. //
  2202. ppVc = &(pAtmEntry->pVcList);
  2203. while (*ppVc != pVc)
  2204. {
  2205. AA_ASSERT(*ppVc != NULL_PATMARP_VC);
  2206. ppVc = &((*ppVc)->pNextVc);
  2207. }
  2208. //
  2209. // Make the predecessor point to the next VC in the list.
  2210. //
  2211. *ppVc = pVc->pNextVc;
  2212. AA_RELEASE_VC_LOCK_DPC(pVc);
  2213. //
  2214. // If this was the Best Effort VC for this ATM Entry, try
  2215. // to find a replacement
  2216. //
  2217. if (pAtmEntry->pBestEffortVc == pVc)
  2218. {
  2219. //
  2220. // Yes, it was. Walk through the list of remaining VCs,
  2221. // if we find another Best Effort VC, make that the
  2222. // BestEffortVc for this ATM Entry
  2223. //
  2224. pAtmEntry->pBestEffortVc = NULL_PATMARP_VC;
  2225. ppVc = &(pAtmEntry->pVcList);
  2226. while (*ppVc != NULL_PATMARP_VC)
  2227. {
  2228. if (AA_IS_BEST_EFFORT_FLOW(&((*ppVc)->FlowSpec)))
  2229. {
  2230. pAtmEntry->pBestEffortVc = *ppVc;
  2231. break;
  2232. }
  2233. else
  2234. {
  2235. ppVc = &((*ppVc)->pNextVc);
  2236. }
  2237. }
  2238. AADEBUGP(AAD_LOUD, ("Atm Entry 0x%x, new Best Effort VC: 0x%x\n",
  2239. pAtmEntry, pAtmEntry->pBestEffortVc));
  2240. }
  2241. if (bDerefAtmEntry)
  2242. {
  2243. if (AA_DEREF_AE(pAtmEntry, AE_REFTYPE_VC) != 0)
  2244. {
  2245. AA_RELEASE_AE_LOCK(pAtmEntry);
  2246. }
  2247. }
  2248. else
  2249. {
  2250. AA_RELEASE_AE_LOCK(pAtmEntry);
  2251. }
  2252. //
  2253. // Acquire the VC lock again for the caller's sake
  2254. //
  2255. AA_ACQUIRE_VC_LOCK(pVc);
  2256. }
  2257. PNDIS_BUFFER
  2258. AtmArpCopyToNdisBuffer(
  2259. IN PNDIS_BUFFER pDestBuffer,
  2260. IN PUCHAR pDataSrc,
  2261. IN UINT LenToCopy,
  2262. IN OUT PUINT pOffsetInBuffer
  2263. )
  2264. /*++
  2265. Routine Description:
  2266. Copy data into an NDIS buffer chain. Use up as much of the given
  2267. NDIS chain as needed for "LenToCopy" bytes. After copying is over,
  2268. return a pointer to the first NDIS buffer that has space for writing
  2269. into (for the next Copy operation), and the offset within this from
  2270. which to start writing.
  2271. Arguments:
  2272. pDestBuffer - First NDIS buffer in a chain of buffers
  2273. pDataSrc - Where to copy data from
  2274. LenToCopy - How much data to copy
  2275. pOffsetInBuffer - Offset in pDestBuffer where we can start copying into.
  2276. Return Value:
  2277. The NDIS buffer in the chain where the next Copy can be done. We also
  2278. set *pOffsetInBuffer to the write offset in the returned NDIS buffer.
  2279. Note: if we are low on memory and run into a failure, we return NULL.
  2280. --*/
  2281. {
  2282. //
  2283. // Size and destination for individual (contiguous) copy operations
  2284. //
  2285. UINT CopySize;
  2286. PUCHAR pDataDst;
  2287. //
  2288. // Start Virtual address for each NDIS buffer in chain.
  2289. //
  2290. PUCHAR VirtualAddress;
  2291. //
  2292. // Offset within pDestBuffer
  2293. //
  2294. UINT OffsetInBuffer = *pOffsetInBuffer;
  2295. //
  2296. // Bytes remaining in current buffer
  2297. //
  2298. UINT DestSize;
  2299. //
  2300. // Total Buffer Length
  2301. //
  2302. UINT BufferLength;
  2303. AA_ASSERT(pDestBuffer != (PNDIS_BUFFER)NULL);
  2304. AA_ASSERT(pDataSrc != NULL);
  2305. #ifdef ATMARP_WIN98
  2306. NdisQueryBuffer(
  2307. pDestBuffer,
  2308. &VirtualAddress,
  2309. &BufferLength
  2310. );
  2311. #else
  2312. NdisQueryBufferSafe(
  2313. pDestBuffer,
  2314. &VirtualAddress,
  2315. &BufferLength,
  2316. NormalPagePriority
  2317. );
  2318. if (VirtualAddress == NULL)
  2319. {
  2320. return (NULL);
  2321. }
  2322. #endif // ATMARP_WIN98
  2323. AA_ASSERT(BufferLength >= OffsetInBuffer);
  2324. pDataDst = VirtualAddress + OffsetInBuffer;
  2325. DestSize = BufferLength - OffsetInBuffer;
  2326. for (;;)
  2327. {
  2328. CopySize = MIN(LenToCopy, DestSize);
  2329. AA_COPY_MEM(pDataDst, pDataSrc, CopySize);
  2330. pDataDst += CopySize;
  2331. pDataSrc += CopySize;
  2332. LenToCopy -= CopySize;
  2333. if (LenToCopy == 0)
  2334. {
  2335. break;
  2336. }
  2337. DestSize -= CopySize;
  2338. if (DestSize == 0)
  2339. {
  2340. //
  2341. // Out of space in the current buffer. Move to the next.
  2342. //
  2343. pDestBuffer = NDIS_BUFFER_LINKAGE(pDestBuffer);
  2344. AA_ASSERT(pDestBuffer != (PNDIS_BUFFER)NULL);
  2345. #ifdef ATMARP_WIN98
  2346. NdisQueryBuffer(
  2347. pDestBuffer,
  2348. &VirtualAddress,
  2349. &BufferLength
  2350. );
  2351. #else
  2352. NdisQueryBufferSafe(
  2353. pDestBuffer,
  2354. &VirtualAddress,
  2355. &BufferLength,
  2356. NormalPagePriority
  2357. );
  2358. if (VirtualAddress == NULL)
  2359. {
  2360. return (NULL);
  2361. }
  2362. #endif // ATMARP_WIN98
  2363. pDataDst = VirtualAddress;
  2364. DestSize = BufferLength;
  2365. }
  2366. }
  2367. *pOffsetInBuffer = (UINT) (pDataDst - VirtualAddress);
  2368. return (pDestBuffer);
  2369. }
  2370. PATMARP_INTERFACE
  2371. AtmArpAddInterfaceToAdapter (
  2372. IN PATMARP_ADAPTER pAdapter,
  2373. IN NDIS_HANDLE LISConfigHandle, // Handle to per-LIS config
  2374. IN NDIS_STRING *pIPConfigString
  2375. )
  2376. {
  2377. NDIS_STATUS Status;
  2378. struct LLIPBindInfo BindInfo;
  2379. PATMARP_INTERFACE pInterface;
  2380. #ifdef ATMARP_WIN98
  2381. ANSI_STRING AnsiConfigString;
  2382. #endif
  2383. do
  2384. {
  2385. //
  2386. // Create an ATMARP Interface structure to represent this LIS.
  2387. //
  2388. pInterface = AtmArpAllocateInterface(pAdapter);
  2389. if (pInterface == NULL_PATMARP_INTERFACE)
  2390. {
  2391. AADEBUGP(AAD_WARNING, ("NotifyRegAfHandler: could not allocate Interface\n"));
  2392. Status = NDIS_STATUS_RESOURCES;
  2393. break;
  2394. }
  2395. //
  2396. // Adapter Binding Reference:
  2397. //
  2398. AtmArpReferenceInterface(pInterface);
  2399. //
  2400. // Get all configuration information for this LIS.
  2401. //
  2402. Status = AtmArpCfgReadLISConfiguration(
  2403. LISConfigHandle,
  2404. pInterface
  2405. );
  2406. if (Status != NDIS_STATUS_SUCCESS)
  2407. {
  2408. AADEBUGP(AAD_WARNING, ("AddInterfaceToAdapter: bad status (0x%x) reading LIS cfg\n",
  2409. Status));
  2410. break;
  2411. }
  2412. #ifndef ATMARP_WIN98
  2413. pInterface->IPConfigString = *pIPConfigString; // struct copy.
  2414. #else
  2415. //
  2416. // Win98: Convert IPConfig string from Unicode to ANSI.
  2417. //
  2418. AnsiConfigString.MaximumLength = pIPConfigString->MaximumLength / sizeof(WCHAR) + sizeof(CHAR);
  2419. AA_ALLOC_MEM(AnsiConfigString.Buffer, CHAR, AnsiConfigString.MaximumLength);
  2420. if (AnsiConfigString.Buffer == NULL)
  2421. {
  2422. AADEBUGP(AAD_WARNING, ("NotifyRegAfHandler: couldn't alloc Ansi string (%d)\n",
  2423. AnsiConfigString.MaximumLength));
  2424. Status = NDIS_STATUS_RESOURCES;
  2425. break;
  2426. }
  2427. AnsiConfigString.Length = 0;
  2428. NdisUnicodeStringToAnsiString(&AnsiConfigString, pIPConfigString);
  2429. AnsiConfigString.Buffer[AnsiConfigString.Length] = '\0';
  2430. #endif // !ATMARP_WIN98
  2431. //
  2432. // Allocate protocol buffers for this LIS.
  2433. //
  2434. Status = AtmArpInitProtoBuffers(pInterface);
  2435. if (Status != NDIS_STATUS_SUCCESS)
  2436. {
  2437. AADEBUGP(AAD_WARNING, ("AddInterfaceToAdapter: bad status (0x%x) from InitBufs\n",
  2438. Status));
  2439. break;
  2440. }
  2441. //
  2442. // Initialize IP/ATM data structures for this LIS.
  2443. //
  2444. Status = AtmArpInitIpOverAtm(pInterface);
  2445. if (Status != NDIS_STATUS_SUCCESS)
  2446. {
  2447. AADEBUGP(AAD_WARNING, ("AddInterfaceToAdapter: bad status (0x%x) from InitIP/ATM\n",
  2448. Status));
  2449. break;
  2450. }
  2451. //
  2452. // Initialize the Call Manager interface for this LIS.
  2453. //
  2454. Status = AtmArpOpenCallMgr(pInterface);
  2455. if (Status != NDIS_STATUS_SUCCESS)
  2456. {
  2457. AADEBUGP(AAD_WARNING, ("AddInterfaceToAdapter: bad status (0x%x) from OpenCallMgr\n",
  2458. Status));
  2459. break;
  2460. }
  2461. //
  2462. // Announce this new interface to IP, along with our BindInfo
  2463. // structure.
  2464. //
  2465. AA_SET_MEM(&BindInfo, 0, sizeof(BindInfo));
  2466. #if ATMOFFLOAD
  2467. //
  2468. // Query and set NIC offload capabilities.
  2469. //
  2470. BindInfo.lip_OffloadFlags = pAdapter->Offload.Flags;
  2471. BindInfo.lip_MaxOffLoadSize = pAdapter->Offload.MaxOffLoadSize;
  2472. BindInfo.lip_MaxSegments = pAdapter->Offload.MinSegmentCount;
  2473. #endif // ATMOFFLOAD
  2474. BindInfo.lip_context = (PVOID)pInterface;
  2475. #ifdef ATMARP_WIN98
  2476. BindInfo.lip_transmit = AtmArpIfTransmit;
  2477. #else
  2478. BindInfo.lip_transmit = AtmArpIfMultiTransmit;
  2479. #endif
  2480. BindInfo.lip_transfer = AtmArpIfTransfer;
  2481. BindInfo.lip_close = AtmArpIfClose;
  2482. BindInfo.lip_addaddr = AtmArpIfAddAddress;
  2483. BindInfo.lip_deladdr = AtmArpIfDelAddress;
  2484. BindInfo.lip_invalidate = AtmArpIfInvalidate;
  2485. BindInfo.lip_open = AtmArpIfOpen;
  2486. BindInfo.lip_qinfo = AtmArpIfQueryInfo;
  2487. BindInfo.lip_setinfo = AtmArpIfSetInfo;
  2488. BindInfo.lip_getelist = AtmArpIfGetEList;
  2489. BindInfo.lip_mss = pInterface->MTU;
  2490. BindInfo.lip_speed = pInterface->Speed;
  2491. //
  2492. // Set LIP_COPY_FLAG to avoid having TransferData
  2493. // called all the time.
  2494. //
  2495. BindInfo.lip_flags = LIP_COPY_FLAG;
  2496. BindInfo.lip_addrlen = AA_ATM_PHYSADDR_LEN;
  2497. BindInfo.lip_addr = &(pInterface->LocalAtmAddress.Address[AA_ATM_ESI_OFFSET]);
  2498. #ifdef _PNP_POWER_
  2499. BindInfo.lip_pnpcomplete = AtmArpIfPnPComplete;
  2500. #endif // _PNP_POWER_
  2501. #ifdef PROMIS
  2502. BindInfo.lip_setndisrequest = AtmArpIfSetNdisRequest;
  2503. #endif // PROMIS
  2504. #ifdef ATMARP_WIN98
  2505. #if DBG
  2506. AADEBUGP(AAD_FATAL, ("Will call AddIF: DeviceName [%ws]\n",
  2507. &(pInterface->pAdapter->DeviceName.Buffer)));
  2508. AADEBUGP(AAD_FATAL, ("And ConfigString: [%s]\n", AnsiConfigString.Buffer));
  2509. #endif
  2510. #endif // ATMARP_WIN98
  2511. Status = (*(pAtmArpGlobalInfo->pIPAddInterfaceRtn))(
  2512. &(pInterface->pAdapter->DeviceName),
  2513. #ifndef ATMARP_WIN98
  2514. #if IFCHANGE1
  2515. NULL, // IfName (unused) -- See 10/14/1998 entry
  2516. // in notes.txt
  2517. #endif // IFCHANGE1
  2518. pIPConfigString,
  2519. #else
  2520. (PNDIS_STRING)&AnsiConfigString,
  2521. #endif
  2522. pAdapter->SystemSpecific2,
  2523. (PVOID)pInterface,
  2524. AtmArpIfDynRegister,
  2525. &BindInfo
  2526. #if IFCHANGE1
  2527. #ifndef ATMARP_WIN98
  2528. ,0, // RequestedIndex (unused) -- See 10/14/1998 entry
  2529. // in notes.txt
  2530. IF_TYPE_IPOVER_ATM,
  2531. IF_ACCESS_BROADCAST,
  2532. IF_CONNECTION_DEDICATED
  2533. #endif
  2534. #endif // IFCHANGE1
  2535. );
  2536. if (Status == IP_SUCCESS)
  2537. {
  2538. Status = NDIS_STATUS_SUCCESS;
  2539. }
  2540. else
  2541. {
  2542. AADEBUGP(AAD_ERROR, ("AddInterface: IPAddInterface ret 0x%x\n",
  2543. Status));
  2544. Status = NDIS_STATUS_FAILURE;
  2545. }
  2546. break;
  2547. }
  2548. while (FALSE);
  2549. if (Status != NDIS_STATUS_SUCCESS)
  2550. {
  2551. //
  2552. // There was a failure in processing this LIS.
  2553. //
  2554. if (pInterface != NULL_PATMARP_INTERFACE)
  2555. {
  2556. if (pInterface->NdisAfHandle != NULL)
  2557. {
  2558. (VOID)AtmArpCloseCallMgr(pInterface);
  2559. }
  2560. pInterface->RefCount = 0;
  2561. AtmArpDeallocateInterface(pInterface);
  2562. pInterface = NULL_PATMARP_INTERFACE;
  2563. }
  2564. }
  2565. return pInterface;
  2566. }
  2567. #if DBG
  2568. void
  2569. AtmArpValidateTimerList(
  2570. PATMARP_TIMER_LIST pTimerList
  2571. )
  2572. /*++
  2573. Routine Description:
  2574. Arguments:
  2575. pTimerList - Timer list
  2576. Return Value:
  2577. None -- will assert if timer is not valid.
  2578. --*/
  2579. {
  2580. PATMARP_TIMER pTimer;
  2581. UINT u;
  2582. UINT cTimers=0;
  2583. AA_ASSERT(pTimerList->atl_sig == atl_signature);
  2584. AA_ASSERT(pTimerList->CurrentTick < pTimerList->TimerListSize);
  2585. for (u=0;u<pTimerList->TimerListSize;u++)
  2586. {
  2587. for ( pTimer = pTimerList->pTimers[u].pNextTimer;
  2588. pTimer;
  2589. pTimer = pTimer->pNextTimer)
  2590. {
  2591. AtmArpValidateTimer(pTimerList, pTimer);
  2592. cTimers++;
  2593. }
  2594. }
  2595. AA_ASSERT(pTimerList->TimerCount == cTimers);
  2596. }
  2597. void
  2598. AtmArpValidateTimer(
  2599. PATMARP_TIMER_LIST pTimerList, // OPTIONAL
  2600. PATMARP_TIMER pTimer
  2601. )
  2602. /*++
  2603. Routine Description:
  2604. Arguments:
  2605. pTimer - Timer
  2606. Return Value:
  2607. None -- will assert if timer is not valid.
  2608. --*/
  2609. {
  2610. if (pTimerList)
  2611. {
  2612. AA_ASSERT(pTimerList == pTimer->pTimerList);
  2613. }
  2614. if (pTimer->pPrevTimer)
  2615. {
  2616. AA_ASSERT(pTimer->pPrevTimer->pNextTimer == pTimer);
  2617. }
  2618. if (pTimer->pNextTimer)
  2619. {
  2620. AA_ASSERT(pTimer->pNextTimer->pPrevTimer == pTimer);
  2621. }
  2622. }
  2623. #endif // DBG