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

3879 lines
74 KiB

  1. /*++
  2. Copyright (c) 1997 FORE Systems, Inc.
  3. Copyright (c) 1997 Microsoft Corporation
  4. Module Name:
  5. utils.c
  6. Abstract:
  7. Utility routines.
  8. Author:
  9. Larry Cleeton, FORE Systems (v-lcleet@microsoft.com, lrc@fore.com)
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. VOID
  17. AtmLaneInitGlobals(
  18. VOID
  19. )
  20. /*++
  21. Routine Description:
  22. Initialize the global data structures.
  23. Arguments:
  24. None
  25. Return Value:
  26. None
  27. --*/
  28. {
  29. TRACEIN(InitGlobals);
  30. NdisZeroMemory(pAtmLaneGlobalInfo, sizeof(ATMLANE_GLOBALS));
  31. INIT_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  32. NdisInitializeListHead(&pAtmLaneGlobalInfo->AdapterList);
  33. #if DBG_TRACE
  34. //
  35. // Init trace log
  36. //
  37. pTraceLogSpace = NULL;
  38. InitTraceLog(&TraceLog, NULL, 0);
  39. // allocate space and init trace log if configured
  40. if (DbgLogSize > 0)
  41. {
  42. ALLOC_MEM(&pTraceLogSpace, DbgLogSize);
  43. if (pTraceLogSpace == NULL)
  44. {
  45. DBGP((0, "Failed to allocate %d bytes space for trace log\n",
  46. DbgLogSize));
  47. }
  48. else
  49. {
  50. InitTraceLog(
  51. &TraceLog,
  52. pTraceLogSpace,
  53. DbgLogSize);
  54. }
  55. }
  56. #endif // DBG_TRACE
  57. TRACEOUT(InitGlobals);
  58. return;
  59. }
  60. PATMLANE_ADAPTER
  61. AtmLaneAllocAdapter(
  62. IN PNDIS_STRING pDeviceName,
  63. IN PVOID SystemSpecific1
  64. )
  65. /*++
  66. Routine Description:
  67. Allocates an Adapter data structure.
  68. Arguments:
  69. pDeviceName - Points to name of adapter device
  70. SystemSpecific1 - What we got into our BindAdapter handler.
  71. Return Value:
  72. Pointer to allocated Adapter structure or NULL.
  73. --*/
  74. {
  75. PATMLANE_ADAPTER pAdapter;
  76. NDIS_STATUS Status;
  77. ULONG TotalLength;
  78. PNDIS_STRING pConfigString;
  79. TRACEIN(AllocAdapter);
  80. //
  81. // Initialize
  82. //
  83. pAdapter = NULL_PATMLANE_ADAPTER;
  84. pConfigString = (PNDIS_STRING)SystemSpecific1;
  85. do
  86. {
  87. //
  88. // Allocate everything. Adapter struct size plus two
  89. // UNICODE string buffers with extra WCHAR each for NULL termination.
  90. //
  91. TotalLength = sizeof(ATMLANE_ADAPTER) +
  92. pDeviceName->MaximumLength + sizeof(WCHAR) +
  93. pConfigString->MaximumLength + sizeof(WCHAR);
  94. ALLOC_MEM(&pAdapter, TotalLength);
  95. if (NULL_PATMLANE_ADAPTER == pAdapter)
  96. {
  97. Status = NDIS_STATUS_RESOURCES;
  98. break;
  99. }
  100. //
  101. // Zero it.
  102. //
  103. NdisZeroMemory(pAdapter, TotalLength);
  104. //
  105. // Debugging info.
  106. //
  107. #if DBG
  108. pAdapter->atmlane_adapter_sig = atmlane_adapter_signature;
  109. #endif
  110. //
  111. // Init lock.
  112. //
  113. INIT_ADAPTER_LOCK(pAdapter);
  114. //
  115. // Init blocking objects.
  116. //
  117. INIT_BLOCK_STRUCT(&pAdapter->Block);
  118. INIT_BLOCK_STRUCT(&pAdapter->UnbindBlock);
  119. //
  120. // Init ElanList
  121. //
  122. NdisInitializeListHead(&pAdapter->ElanList);
  123. //
  124. // Copy in the device name
  125. //
  126. pAdapter->DeviceName.MaximumLength = pDeviceName->MaximumLength + sizeof(WCHAR);
  127. pAdapter->DeviceName.Length = pDeviceName->Length;
  128. pAdapter->DeviceName.Buffer = (PWCHAR)((PUCHAR)pAdapter + sizeof(ATMLANE_ADAPTER));
  129. NdisMoveMemory(pAdapter->DeviceName.Buffer,
  130. pDeviceName->Buffer,
  131. pDeviceName->Length);
  132. pAdapter->DeviceName.Buffer[pDeviceName->Length/sizeof(WCHAR)] = ((WCHAR)0);
  133. //
  134. // Copy in the Config string - we will use this to open the
  135. // registry section for this adapter at a later point.
  136. //
  137. pAdapter->ConfigString.MaximumLength = pConfigString->MaximumLength;
  138. pAdapter->ConfigString.Length = pConfigString->Length;
  139. pAdapter->ConfigString.Buffer = (PWCHAR)((PUCHAR)pAdapter +
  140. sizeof(ATMLANE_ADAPTER) +
  141. pAdapter->DeviceName.MaximumLength);
  142. NdisMoveMemory(pAdapter->ConfigString.Buffer,
  143. pConfigString->Buffer,
  144. pConfigString->Length);
  145. pAdapter->ConfigString.Buffer[pConfigString->Length/sizeof(WCHAR)] = ((WCHAR)0);
  146. //
  147. // Link into global Adapter list.
  148. //
  149. ACQUIRE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  150. InsertTailList(&pAtmLaneGlobalInfo->AdapterList, &pAdapter->Link);
  151. RELEASE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  152. } while (FALSE);
  153. TRACEOUT(AllocAdapter);
  154. return pAdapter;
  155. }
  156. VOID
  157. AtmLaneDeallocateAdapter(
  158. IN PATMLANE_ADAPTER pAdapter
  159. )
  160. /*++
  161. Routine Description:
  162. Deallocate an Adapter structure. It is assumed that all
  163. references to this structure have gone, so it is not necessary
  164. to acquire a lock to it.
  165. Also unlink this from the global Adapter list.
  166. Arguments:
  167. pAdapter - Pointer to Adapter structure to be deallocated.
  168. Return Value:
  169. None
  170. --*/
  171. {
  172. PATMLANE_NAME pName;
  173. STRUCT_ASSERT(pAdapter, atmlane_adapter);
  174. TRACEIN(DeallocateAdapter);
  175. ASSERT(pAdapter->RefCount == 0);
  176. //
  177. // Unlink from global Adapter list.
  178. //
  179. ACQUIRE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  180. RemoveEntryList(&pAdapter->Link);
  181. RELEASE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  182. //
  183. // Free the lock.
  184. //
  185. FREE_ADAPTER_LOCK(pAdapter);
  186. #if DBG
  187. pAdapter->atmlane_adapter_sig++;
  188. #endif
  189. //
  190. // Free string buffers that may have been allocated
  191. //
  192. if (NULL != pAdapter->CfgUpperBindings.Buffer)
  193. {
  194. FREE_MEM(pAdapter->CfgUpperBindings.Buffer);
  195. }
  196. if (NULL != pAdapter->CfgElanName.Buffer)
  197. {
  198. FREE_MEM(pAdapter->CfgElanName.Buffer);
  199. }
  200. //
  201. // Free the name lists that may have been allocated.
  202. //
  203. while (pAdapter->UpperBindingsList)
  204. {
  205. DBGP((1, "DeallocateAdapter: pname 0x%x\n"));
  206. pName = pAdapter->UpperBindingsList;
  207. pAdapter->UpperBindingsList = pName->pNext;
  208. FREE_MEM(pName);
  209. }
  210. while (pAdapter->ElanNameList)
  211. {
  212. DBGP((1, "DeallocateAdapter: pname 0x%x\n"));
  213. pName = pAdapter->ElanNameList;
  214. pAdapter->ElanNameList = pName->pNext;
  215. FREE_MEM(pName);
  216. }
  217. //
  218. // Finally free the Adapter structure.
  219. //
  220. FREE_MEM(pAdapter);
  221. TRACEOUT(DeallocateAdapter);
  222. return;
  223. }
  224. BOOLEAN
  225. AtmLaneReferenceAdapter(
  226. IN PATMLANE_ADAPTER pAdapter,
  227. IN PUCHAR String
  228. )
  229. /*++
  230. Routine Description:
  231. Add a references to an Adapter structure.
  232. NOTE: The caller is assumed to possess the Adapter's lock.
  233. Arguments:
  234. pAdapter - Pointer to the Adapter structure.
  235. Return Value:
  236. None.
  237. --*/
  238. {
  239. BOOLEAN bReferenced;
  240. TRACEIN(ReferenceAdapter);
  241. STRUCT_ASSERT(pAdapter, atmlane_adapter);
  242. if ((pAdapter->Flags & ADAPTER_FLAGS_DEALLOCATING) == 0)
  243. {
  244. pAdapter->RefCount++;
  245. bReferenced = TRUE;
  246. }
  247. else
  248. {
  249. bReferenced = FALSE;
  250. }
  251. DBGP((5, "ReferenceAdapter: Adapter %x (%s) new count %d\n",
  252. pAdapter, String, pAdapter->RefCount));
  253. TRACEOUT(ReferenceAdapter);
  254. return bReferenced;
  255. }
  256. ULONG
  257. AtmLaneDereferenceAdapter(
  258. IN PATMLANE_ADAPTER pAdapter,
  259. IN PUCHAR String
  260. )
  261. /*++
  262. Routine Description:
  263. Subtract a reference from an Adapter structure.
  264. If the reference count becomes zero, deallocate it.
  265. NOTE: The caller is assumed to posses the Adapter's lock.
  266. Arguments:
  267. pAdapter - Pointer to an adapter structure.
  268. Return Value:
  269. None.
  270. --*/
  271. {
  272. ULONG rc;
  273. TRACEIN(DereferenceAdapter);
  274. STRUCT_ASSERT(pAdapter, atmlane_adapter);
  275. ASSERT(pAdapter->RefCount > 0);
  276. rc = --(pAdapter->RefCount);
  277. if (rc == 0)
  278. {
  279. pAdapter->Flags |= ADAPTER_FLAGS_DEALLOCATING;
  280. RELEASE_ADAPTER_LOCK(pAdapter);
  281. AtmLaneDeallocateAdapter(pAdapter);
  282. }
  283. DBGP((5, "DereferenceAdapter: Adapter %x (%s) new count %d\n",
  284. pAdapter, String, rc));
  285. TRACEOUT(DereferenceAdapter);
  286. return (rc);
  287. }
  288. NDIS_STATUS
  289. AtmLaneAllocElan(
  290. IN PATMLANE_ADAPTER pAdapter,
  291. IN OUT PATMLANE_ELAN *ppElan
  292. )
  293. /*++
  294. Routine Description:
  295. Allocates an ELAN data structure.
  296. Arguments:
  297. None
  298. Return Value:
  299. NDIS_STATUS_SUCCESS or NDIS_STATUS_RESOURCES.
  300. --*/
  301. {
  302. NDIS_STATUS Status;
  303. PATMLANE_ELAN pElan;
  304. PATMLANE_MAC_ENTRY * pMacTable;
  305. PATMLANE_TIMER_LIST pTimerList;
  306. USHORT NameBufferSize;
  307. UINT i;
  308. ULONG SapSize;
  309. PCO_SAP pLesSapInfo;
  310. PCO_SAP pBusSapInfo;
  311. PCO_SAP pDataSapInfo;
  312. ULONG ElanNumber;
  313. TRACEIN(AllocElan);
  314. //
  315. // Initialize
  316. //
  317. Status = NDIS_STATUS_SUCCESS;
  318. pElan = NULL_PATMLANE_ELAN;
  319. pMacTable = (PATMLANE_MAC_ENTRY *)NULL;
  320. pLesSapInfo = pBusSapInfo = pDataSapInfo = (PCO_SAP)NULL;
  321. SapSize = sizeof(CO_SAP)+sizeof(ATM_SAP)+sizeof(ATM_ADDRESS);
  322. do
  323. {
  324. //
  325. // Allocate everything.
  326. //
  327. ALLOC_MEM(&pElan, sizeof(ATMLANE_ELAN));
  328. ALLOC_MEM((PVOID *)&pMacTable, ATMLANE_MAC_TABLE_SIZE*sizeof(PATMLANE_MAC_ENTRY));
  329. ALLOC_MEM(&pLesSapInfo, SapSize);
  330. ALLOC_MEM(&pBusSapInfo, SapSize);
  331. ALLOC_MEM(&pDataSapInfo, SapSize);
  332. if (NULL_PATMLANE_ELAN != pElan)
  333. {
  334. //
  335. // Zero the Elan structure now so that we clean up properly
  336. // if any errors occur later on.
  337. //
  338. NdisZeroMemory(pElan, sizeof(ATMLANE_ELAN));
  339. }
  340. if ((NULL_PATMLANE_ELAN == pElan) ||
  341. (NULL == pMacTable) ||
  342. (NULL == pLesSapInfo) ||
  343. (NULL == pBusSapInfo) ||
  344. (NULL == pDataSapInfo))
  345. {
  346. Status = NDIS_STATUS_RESOURCES;
  347. break;
  348. }
  349. //
  350. // Allocate timer structures
  351. //
  352. for (i = 0; i < ALT_CLASS_MAX; i++)
  353. {
  354. pTimerList = &(pElan->TimerList[i]);
  355. #if DBG
  356. pTimerList->atmlane_timerlist_sig = atmlane_timerlist_signature;
  357. #endif
  358. ALLOC_MEM(&(pTimerList->pTimers),
  359. sizeof(ATMLANE_TIMER) * AtmLaneTimerListSize[i]);
  360. if (NULL_PATMLANE_TIMER == pTimerList->pTimers)
  361. {
  362. Status = NDIS_STATUS_RESOURCES;
  363. break;
  364. }
  365. }
  366. if (Status != NDIS_STATUS_SUCCESS)
  367. {
  368. break;
  369. }
  370. //
  371. // Continue initializing the ELAN structure
  372. //
  373. #if DBG
  374. //
  375. // Signatures, for debugging.
  376. //
  377. pElan->atmlane_elan_sig = atmlane_elan_signature;
  378. pElan->LesSap.atmlane_sap_sig = atmlane_sap_signature;
  379. pElan->BusSap.atmlane_sap_sig = atmlane_sap_signature;
  380. pElan->DataSap.atmlane_sap_sig = atmlane_sap_signature;
  381. #endif
  382. //
  383. // Initialize state fields.
  384. //
  385. pElan->AdminState = ELAN_STATE_INIT;
  386. pElan->State = ELAN_STATE_ALLOCATED;
  387. NdisInitializeWorkItem(&pElan->EventWorkItem, AtmLaneEventHandler, pElan);
  388. //
  389. // Initialize spinlocks.
  390. //
  391. #if SENDLIST
  392. NdisAllocateSpinLock(&pElan->SendListLock);
  393. #endif // SENDLIST
  394. INIT_ELAN_LOCK(pElan);
  395. INIT_ELAN_MAC_TABLE_LOCK(pElan);
  396. INIT_ELAN_ATM_LIST_LOCK(pElan);
  397. INIT_ELAN_TIMER_LOCK(pElan);
  398. INIT_BLOCK_STRUCT(&pElan->Block);
  399. INIT_BLOCK_STRUCT(&pElan->InitBlock);
  400. INIT_BLOCK_STRUCT(&pElan->AfBlock);
  401. INIT_HEADER_LOCK(pElan);
  402. //
  403. // Init event queue.
  404. //
  405. InitializeListHead(&pElan->EventQueue);
  406. //
  407. // Initialize timer wheels.
  408. //
  409. for (i = 0; i < ALT_CLASS_MAX; i++)
  410. {
  411. pTimerList = &(pElan->TimerList[i]);
  412. NdisZeroMemory(
  413. pTimerList->pTimers,
  414. sizeof(ATMLANE_TIMER) * AtmLaneTimerListSize[i]
  415. );
  416. pTimerList->MaxTimer = AtmLaneMaxTimerValue[i];
  417. pTimerList->TimerPeriod = AtmLaneTimerPeriod[i];
  418. pTimerList->ListContext = (PVOID)pElan;
  419. pTimerList->TimerListSize = AtmLaneTimerListSize[i];
  420. INIT_SYSTEM_TIMER(
  421. &(pTimerList->NdisTimer),
  422. AtmLaneTickHandler,
  423. (PVOID)pTimerList
  424. );
  425. }
  426. //
  427. // Initialize all sub-components.
  428. //
  429. NdisZeroMemory(pMacTable, ATMLANE_MAC_TABLE_SIZE*sizeof(PATMLANE_MAC_ENTRY));
  430. NdisZeroMemory(pLesSapInfo, SapSize);
  431. NdisZeroMemory(pBusSapInfo, SapSize);
  432. NdisZeroMemory(pDataSapInfo, SapSize);
  433. //
  434. // Link sub-components to the Elan structure.
  435. //
  436. pElan->pMacTable = pMacTable;
  437. pElan->LesSap.pInfo = pLesSapInfo;
  438. pElan->BusSap.pInfo = pBusSapInfo;
  439. pElan->DataSap.pInfo = pDataSapInfo;
  440. //
  441. // Link the Elan to the adapter.
  442. //
  443. pElan->pAdapter = pAdapter;
  444. ACQUIRE_ADAPTER_LOCK(pAdapter);
  445. //
  446. // Find a free ELAN number.
  447. //
  448. for (ElanNumber = 0; ElanNumber <= pAdapter->ElanCount; ElanNumber++)
  449. {
  450. PATMLANE_ELAN pThisElan = NULL;
  451. PLIST_ENTRY p;
  452. for (p = pAdapter->ElanList.Flink;
  453. p != &pAdapter->ElanList;
  454. p = p->Flink)
  455. {
  456. pThisElan = CONTAINING_RECORD(p, ATMLANE_ELAN, Link);
  457. if (pThisElan->ElanNumber == ElanNumber)
  458. {
  459. break;
  460. }
  461. }
  462. //
  463. // See if we made it to the end of the list without hitting
  464. // the current ElanNumber. If so, use this ElanNumber.
  465. //
  466. if (p == &pAdapter->ElanList)
  467. {
  468. break;
  469. }
  470. }
  471. DBGP((0, "%d Assign ElanNumber to ELAN %x\n", ElanNumber, pElan));
  472. (VOID)AtmLaneReferenceAdapter(pAdapter, "elan");
  473. InsertTailList(&pAdapter->ElanList, &pElan->Link);
  474. pElan->ElanNumber = ElanNumber;
  475. pAdapter->ElanCount++;
  476. RELEASE_ADAPTER_LOCK(pAdapter);
  477. //
  478. // Cache NdisAdapterHandle.
  479. //
  480. pElan->NdisAdapterHandle = pAdapter->NdisAdapterHandle;
  481. //
  482. // Generate a MAC Address for the elan
  483. //
  484. AtmLaneGenerateMacAddr(pElan);
  485. //
  486. // Set the rest of the LANE Run-time parameters to defaults
  487. //
  488. pElan->ControlTimeout = LANE_C7_DEF;
  489. pElan->MaxUnkFrameCount = LANE_C10_DEF;
  490. pElan->MaxUnkFrameTime = LANE_C11_DEF;
  491. pElan->VccTimeout = LANE_C12_DEF;
  492. pElan->MaxRetryCount = LANE_C13_DEF;
  493. pElan->AgingTime = LANE_C17_DEF;
  494. pElan->ForwardDelayTime = LANE_C18_DEF;
  495. pElan->ArpResponseTime = LANE_C20_DEF;
  496. pElan->FlushTimeout = LANE_C21_DEF;
  497. pElan->PathSwitchingDelay = LANE_C22_DEF;
  498. pElan->ConnComplTimer = LANE_C28_DEF;
  499. //
  500. // Calc the bus rate limiter parameters
  501. //
  502. pElan->LimitTime = pElan->MaxUnkFrameTime * 1000;
  503. pElan->IncrTime = pElan->LimitTime / pElan->MaxUnkFrameCount;
  504. Status = NDIS_STATUS_SUCCESS;
  505. break;
  506. } while (FALSE);
  507. if (NDIS_STATUS_SUCCESS != Status)
  508. {
  509. //
  510. // Failure cleanup.
  511. //
  512. if (NULL_PATMLANE_ELAN != pElan)
  513. {
  514. for (i = 0; i < ALT_CLASS_MAX; i++)
  515. {
  516. pTimerList = &(pElan->TimerList[i]);
  517. if (NULL != pTimerList->pTimers)
  518. {
  519. FREE_MEM(pTimerList->pTimers);
  520. }
  521. }
  522. }
  523. if (NULL != pLesSapInfo)
  524. {
  525. FREE_MEM(pLesSapInfo);
  526. }
  527. if (NULL != pBusSapInfo)
  528. {
  529. FREE_MEM(pBusSapInfo);
  530. }
  531. if (NULL != pDataSapInfo)
  532. {
  533. FREE_MEM(pDataSapInfo);
  534. }
  535. if (NULL != pMacTable)
  536. {
  537. FREE_MEM(pMacTable);
  538. }
  539. if (NULL_PATMLANE_ELAN != pElan)
  540. {
  541. FREE_MEM(pElan);
  542. pElan = NULL_PATMLANE_ELAN;
  543. }
  544. }
  545. //
  546. // Output pElan
  547. //
  548. *ppElan = pElan;
  549. TRACEOUT(AllocElan);
  550. return Status;
  551. }
  552. VOID
  553. AtmLaneDeallocateElan(
  554. IN PATMLANE_ELAN pElan
  555. )
  556. /*++
  557. Routine Description:
  558. Deallocate an Elan structure. It is assumed that all
  559. references to this structure have gone, so it is not necessary
  560. to acquire a lock to it.
  561. Also delink this from the Adapter's Elan list.
  562. Arguments:
  563. pElan - Pointer to Elan structure to be deallocated.
  564. Return Value:
  565. None
  566. --*/
  567. {
  568. PATMLANE_ADAPTER pAdapter;
  569. PATMLANE_ATM_ENTRY pAtmEntry;
  570. PATMLANE_ATM_ENTRY pNext;
  571. UINT i;
  572. TRACEIN(DeallocateElan);
  573. STRUCT_ASSERT(pElan, atmlane_elan);
  574. ASSERT(pElan->RefCount == 0);
  575. DBGP((0, "%d Deleting ELAN %p\n", pElan->ElanNumber, pElan));
  576. //
  577. // Free all subcomponents
  578. //
  579. //
  580. // MAC Table
  581. //
  582. if ((PATMLANE_MAC_ENTRY *)NULL != pElan->pMacTable)
  583. {
  584. FREE_MEM(pElan->pMacTable);
  585. pElan->pMacTable = (PATMLANE_MAC_ENTRY *)NULL;
  586. }
  587. //
  588. // ATM Entry List
  589. //
  590. for (pAtmEntry = pElan->pAtmEntryList;
  591. pAtmEntry != NULL_PATMLANE_ATM_ENTRY;
  592. pAtmEntry = (PATMLANE_ATM_ENTRY)pNext)
  593. {
  594. pNext = (PVOID)pAtmEntry->pNext;
  595. FREE_MEM(pAtmEntry);
  596. }
  597. pElan->pAtmEntryList = NULL_PATMLANE_ATM_ENTRY;
  598. //
  599. // Timers
  600. //
  601. for (i = 0; i < ALT_CLASS_MAX; i++)
  602. {
  603. PATMLANE_TIMER_LIST pTimerList = &(pElan->TimerList[i]);
  604. if (NULL != pTimerList->pTimers)
  605. {
  606. FREE_MEM(pTimerList->pTimers);
  607. }
  608. pTimerList->pTimers = NULL_PATMLANE_TIMER;
  609. }
  610. //
  611. // ProtocolPacketPool
  612. // ProtocolBufferPool
  613. // ProtocolBufList
  614. //
  615. AtmLaneDeallocateProtoBuffers(pElan);
  616. //
  617. // TransmitPacketPool
  618. //
  619. if (pElan->TransmitPacketPool != NULL_NDIS_HANDLE)
  620. {
  621. NdisFreePacketPool(pElan->TransmitPacketPool);
  622. pElan->TransmitPacketPool = NULL_NDIS_HANDLE;
  623. }
  624. //
  625. // ReceivePacketPool
  626. //
  627. if (pElan->ReceivePacketPool != NULL_NDIS_HANDLE)
  628. {
  629. NdisFreePacketPool(pElan->ReceivePacketPool);
  630. pElan->ReceivePacketPool = NULL_NDIS_HANDLE;
  631. }
  632. //
  633. // ReceiveBufferPool
  634. //
  635. if (pElan->ReceiveBufferPool != NULL_NDIS_HANDLE)
  636. {
  637. NdisFreeBufferPool(pElan->ReceiveBufferPool);
  638. pElan->ReceiveBufferPool = NULL_NDIS_HANDLE;
  639. }
  640. //
  641. // HeaderBufList
  642. // pHeaderTrkList
  643. //
  644. AtmLaneDeallocateHeaderBuffers(pElan);
  645. //
  646. // PadBufList
  647. // pPadTrkList
  648. //
  649. AtmLaneDeallocatePadBufs(pElan);
  650. //
  651. // Free the config strings
  652. //
  653. if (NULL != pElan->CfgBindName.Buffer)
  654. {
  655. FREE_MEM(pElan->CfgBindName.Buffer);
  656. }
  657. if (NULL != pElan->CfgDeviceName.Buffer)
  658. {
  659. FREE_MEM(pElan->CfgDeviceName.Buffer);
  660. }
  661. if (NULL != pElan->CfgElanName.Buffer)
  662. {
  663. FREE_MEM(pElan->CfgElanName.Buffer);
  664. }
  665. //
  666. // Free the Sap info
  667. //
  668. if (NULL != pElan->LesSap.pInfo)
  669. {
  670. FREE_MEM(pElan->LesSap.pInfo);
  671. }
  672. if (NULL != pElan->BusSap.pInfo)
  673. {
  674. FREE_MEM(pElan->BusSap.pInfo);
  675. }
  676. if (NULL != pElan->DataSap.pInfo)
  677. {
  678. FREE_MEM(pElan->DataSap.pInfo);
  679. }
  680. //
  681. // Free the locks.
  682. //
  683. #if SENDLIST
  684. NdisFreeSpinLock(&pElan->SendListLock);
  685. #endif // SENDLIST
  686. FREE_ELAN_LOCK(pElan);
  687. FREE_ELAN_MAC_TABLE_LOCK(pElan);
  688. FREE_ELAN_ATM_LIST_LOCK(pElan);
  689. FREE_ELAN_TIMER_LOCK(pElan);
  690. FREE_BLOCK_STRUCT(&pElan->Block);
  691. FREE_HEADER_LOCK(pElan);
  692. AtmLaneUnlinkElanFromAdapter(pElan);
  693. #if DBG
  694. pElan->atmlane_elan_sig++;
  695. #endif
  696. //
  697. // Finally free the Elan structure.
  698. //
  699. FREE_MEM(pElan);
  700. TRACEOUT(DeallocateElan);
  701. return;
  702. }
  703. VOID
  704. AtmLaneReferenceElan(
  705. IN PATMLANE_ELAN pElan,
  706. IN PUCHAR String
  707. )
  708. /*++
  709. Routine Description:
  710. Add a references to an Elan structure.
  711. NOTE: The caller is assumed to possess the Elan's lock.
  712. Arguments:
  713. pElan - Pointer to the Elan structure.
  714. Return Value:
  715. None.
  716. --*/
  717. {
  718. TRACEIN(ReferenceElan);
  719. STRUCT_ASSERT(pElan, atmlane_elan);
  720. pElan->RefCount++;
  721. DBGP((5, "ReferenceElan: Elan %p/%x (%s) new count %d\n",
  722. pElan, pElan->Flags, String, pElan->RefCount));
  723. TRACEOUT(ReferenceElan);
  724. return;
  725. }
  726. ULONG
  727. AtmLaneDereferenceElan(
  728. IN PATMLANE_ELAN pElan,
  729. IN PUCHAR String
  730. )
  731. /*++
  732. Routine Description:
  733. Subtract a reference from an Elan structure.
  734. If the reference count becomes zero, deallocate it.
  735. NOTE: The caller is assumed to posses the Elan's lock.
  736. Arguments:
  737. pElan - Pointer to an Elan structure.
  738. Return Value:
  739. None.
  740. --*/
  741. {
  742. ULONG rc;
  743. #if DBG
  744. ULONG Flags = pElan->Flags;
  745. #endif
  746. TRACEIN(DereferenceElan);
  747. STRUCT_ASSERT(pElan, atmlane_elan);
  748. ASSERT(pElan->RefCount > 0);
  749. rc = --(pElan->RefCount);
  750. if (rc == 0)
  751. {
  752. pElan->Flags |= ELAN_DEALLOCATING;
  753. RELEASE_ELAN_LOCK(pElan);
  754. AtmLaneDeallocateElan(pElan);
  755. }
  756. DBGP((5, "DereferenceElan: Elan %p/%x (%s) new count %d\n",
  757. pElan, Flags, String, rc));
  758. TRACEOUT(DereferenceElan);
  759. return (rc);
  760. }
  761. VOID
  762. AtmLaneUnlinkElanFromAdapter(
  763. IN PATMLANE_ELAN pElan
  764. )
  765. /*++
  766. Routine Description:
  767. Unlinks an ELAN structure from the Adapter structure it is linked to.
  768. Also continues any pending operation on the Adapter.
  769. Arguments:
  770. pElan - Pointer to Elan
  771. Return Value:
  772. None
  773. --*/
  774. {
  775. PATMLANE_ADAPTER pAdapter;
  776. BOOLEAN CompleteUnbind;
  777. DBGP((1, "%d UnlinkElanFromAdapter: pElan %p/%x, Ref %d, pAdapter %p\n",
  778. pElan->ElanNumber, pElan, pElan->Flags, pElan->RefCount, pElan->pAdapter));
  779. pAdapter = pElan->pAdapter;
  780. if (pAdapter != NULL_PATMLANE_ADAPTER)
  781. {
  782. DBGP((1, "UnlinkElanFromAdapter: pAdapter %x, Flags %x, RefCount %d\n",
  783. pAdapter,
  784. pAdapter->Flags, pAdapter->RefCount));
  785. //
  786. // Unlink from adapter list.
  787. //
  788. ACQUIRE_ADAPTER_LOCK(pAdapter);
  789. pElan->pAdapter = NULL_PATMLANE_ADAPTER;
  790. RemoveEntryList(&pElan->Link);
  791. pAdapter->ElanCount--;
  792. AtmLaneDereferenceAdapter(pAdapter, "elan");
  793. if (IsListEmpty(&pAdapter->ElanList) &&
  794. (pAdapter->Flags & ADAPTER_FLAGS_UNBIND_COMPLETE_PENDING))
  795. {
  796. pAdapter->Flags &= ~ADAPTER_FLAGS_UNBIND_COMPLETE_PENDING;
  797. CompleteUnbind = TRUE;
  798. }
  799. else
  800. {
  801. CompleteUnbind = FALSE;
  802. }
  803. RELEASE_ADAPTER_LOCK(pAdapter);
  804. //
  805. // If we just freed the last elan structure on this
  806. // adapter, and an Unbind operation was in progress, complete
  807. // it now.
  808. //
  809. if (CompleteUnbind)
  810. {
  811. AtmLaneCompleteUnbindAdapter(pAdapter);
  812. }
  813. }
  814. }
  815. PATMLANE_ATM_ENTRY
  816. AtmLaneAllocateAtmEntry(
  817. IN PATMLANE_ELAN pElan
  818. )
  819. /*++
  820. Routine Description:
  821. Allocate an ATM Entry structure, initialize it, and return it.
  822. Arguments:
  823. pElan - Pointer to Elan on which the entry is allocated
  824. Return Value:
  825. Pointer to allocated ATM Entry structure if successful, NULL otherwise.
  826. --*/
  827. {
  828. PATMLANE_ATM_ENTRY pAtmEntry;
  829. TRACEIN(AllocateAtmEntry);
  830. STRUCT_ASSERT(pElan, atmlane_elan);
  831. ALLOC_MEM(&pAtmEntry, sizeof(ATMLANE_ATM_ENTRY));
  832. if (pAtmEntry != NULL_PATMLANE_ATM_ENTRY)
  833. {
  834. NdisZeroMemory(pAtmEntry, sizeof(ATMLANE_ATM_ENTRY));
  835. #if DBG
  836. pAtmEntry->atmlane_atm_sig = atmlane_atm_signature;
  837. #endif
  838. pAtmEntry->Flags = ATM_ENTRY_IDLE;
  839. INIT_ATM_ENTRY_LOCK(pAtmEntry);
  840. pAtmEntry->pElan = pElan;
  841. }
  842. DBGP((5, "AllocateAtmEntry:ATM Entry: Elan %x, Entry %x\n",
  843. pElan, pAtmEntry));
  844. TRACEOUT(AllocateAtmEntry);
  845. return (pAtmEntry);
  846. }
  847. VOID
  848. AtmLaneDeallocateAtmEntry(
  849. IN PATMLANE_ATM_ENTRY pAtmEntry
  850. )
  851. /*++
  852. Routine Description:
  853. Free an ATM Entry structure. It is assumed that all references
  854. to the structure have gone. We don't need any locks here.
  855. Arguments:
  856. pAtmEntry - Pointer to ATM Entry to be freed.
  857. Return Value:
  858. None
  859. --*/
  860. {
  861. TRACEIN(DeallocateAtmEntry);
  862. STRUCT_ASSERT(pAtmEntry, atmlane_atm);
  863. ASSERT(pAtmEntry->RefCount == 0);
  864. ASSERT(pAtmEntry->pVcList == NULL_PATMLANE_VC);
  865. #if DBG
  866. pAtmEntry->atmlane_atm_sig++;
  867. #endif
  868. FREE_ATM_ENTRY_LOCK(pAtmEntry);
  869. FREE_MEM(pAtmEntry);
  870. DBGP((5, "DeallocateAtmEntry: ATM Entry: %x\n", pAtmEntry));
  871. TRACEOUT(DeallocateAtmEntry);
  872. }
  873. VOID
  874. AtmLaneReferenceAtmEntry(
  875. IN PATMLANE_ATM_ENTRY pAtmEntry,
  876. IN PUCHAR String
  877. )
  878. /*++
  879. Routine Description:
  880. Add a reference to the specified ATM Entry.
  881. NOTE: The caller is assumed to possess a lock for the Entry.
  882. Arguments:
  883. pAtmEntry - Pointer to the Entry to be referenced
  884. Return Value:
  885. None
  886. --*/
  887. {
  888. TRACEIN(ReferenceAtmEntry);
  889. STRUCT_ASSERT(pAtmEntry, atmlane_atm);
  890. pAtmEntry->RefCount++;
  891. DBGP((5, "ReferenceAtmEntry: Entry %x (%s) new count %d\n",
  892. pAtmEntry, String, pAtmEntry->RefCount));
  893. TRACEOUT(ReferenceAtmEntry);
  894. }
  895. ULONG
  896. AtmLaneDereferenceAtmEntry(
  897. IN PATMLANE_ATM_ENTRY pAtmEntry,
  898. IN PUCHAR String
  899. )
  900. /*++
  901. Routine Description:
  902. Subtract a reference from the specified ATM Entry. If the Entry's
  903. reference count becomes zero, deallocate it.
  904. NOTE: The caller is assumed to possess a lock for the Entry.
  905. SIDE EFFECT: See Return Value below
  906. Arguments:
  907. pAtmEntry - Pointer to the Entry to be dereferenced.
  908. Return Value:
  909. Is the new reference count.
  910. [IMPORTANT] If the Entry's reference count became zero, the Entry will be
  911. deallocated -- the Entry lock is, obviously, released in this case.
  912. --*/
  913. {
  914. ULONG rc;
  915. PATMLANE_ELAN pElan;
  916. TRACEIN(DereferenceAtmEntry);
  917. STRUCT_ASSERT(pAtmEntry, atmlane_atm);
  918. if (pAtmEntry->RefCount == 0)
  919. {
  920. rc = 0;
  921. }
  922. else
  923. {
  924. rc = --(pAtmEntry->RefCount);
  925. }
  926. if (rc == 0)
  927. {
  928. PATMLANE_ATM_ENTRY * ppAtmEntry;
  929. DBGP((5, "DerefAtmEntry %x, RefCount is 0\n", pAtmEntry));
  930. //
  931. // Unlink this entry from the Elan's list of ATM Entries.
  932. //
  933. //
  934. // Acquire locks in the right order. However note that in doing so,
  935. // some other thread might stumble across this ATM entry and reference
  936. // it (and also dereference it!). To handle this, add a temp ref first.
  937. //
  938. pAtmEntry->RefCount++;
  939. pElan = pAtmEntry->pElan;
  940. STRUCT_ASSERT(pElan, atmlane_elan);
  941. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  942. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  943. ACQUIRE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  944. //
  945. // Remove the temp ref above. If the ref count is still at 0,
  946. // nobody is using this ATM entry and it is safe to remove it
  947. // from the list.
  948. //
  949. rc = --(pAtmEntry->RefCount);
  950. if (rc == 0)
  951. {
  952. //
  953. // Safe to delete this ATM entry.
  954. //
  955. #if DBG
  956. if (pAtmEntry->pMacEntryList != NULL)
  957. {
  958. DBGP((0, "ATMLANE: derefed pAtmEntry %x, but MACEntryList isn't NULL!\n",
  959. pAtmEntry));
  960. ASSERT(FALSE);
  961. }
  962. #endif // DBG
  963. ppAtmEntry = &(pElan->pAtmEntryList);
  964. while (*ppAtmEntry != pAtmEntry)
  965. {
  966. ASSERT(*ppAtmEntry != NULL_PATMLANE_ATM_ENTRY);
  967. ppAtmEntry = &((*ppAtmEntry)->pNext);
  968. }
  969. *ppAtmEntry = pAtmEntry->pNext;
  970. pElan->NumAtmEntries--;
  971. //
  972. // If ATM Entry is for a LANE server
  973. // then also invalidate elan's cached pointer to it
  974. //
  975. switch (pAtmEntry->Type)
  976. {
  977. case ATM_ENTRY_TYPE_LECS:
  978. pElan->pLecsAtmEntry = NULL_PATMLANE_ATM_ENTRY;
  979. break;
  980. case ATM_ENTRY_TYPE_LES:
  981. pElan->pLesAtmEntry = NULL_PATMLANE_ATM_ENTRY;
  982. break;
  983. case ATM_ENTRY_TYPE_BUS:
  984. pElan->pBusAtmEntry = NULL_PATMLANE_ATM_ENTRY;
  985. break;
  986. }
  987. }
  988. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  989. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  990. if (rc == 0)
  991. {
  992. AtmLaneDeallocateAtmEntry(pAtmEntry);
  993. }
  994. else
  995. {
  996. //
  997. // As far as this caller is concerned, the ATM entry is gone.
  998. // Return 0.
  999. //
  1000. rc = 0;
  1001. }
  1002. }
  1003. DBGP((5, "DereferenceAtmEntry: Entry %x (%s) new count %d\n",
  1004. pAtmEntry, String, rc));
  1005. TRACEOUT(DereferenceAtmEntry);
  1006. return (rc);
  1007. }
  1008. PATMLANE_VC
  1009. AtmLaneAllocateVc(
  1010. IN PATMLANE_ELAN pElan
  1011. )
  1012. /*++
  1013. Routine Description:
  1014. Allocate an ATMLANE VC structure, initialize it, and return it.
  1015. Arguments:
  1016. pElan - Elan for which this VC is created.
  1017. Return Value:
  1018. Pointer to VC if allocated, NULL otherwise.
  1019. --*/
  1020. {
  1021. PATMLANE_VC pVc;
  1022. TRACEIN(AllocateVc);
  1023. STRUCT_ASSERT(pElan, atmlane_elan);
  1024. ALLOC_MEM(&pVc, sizeof(ATMLANE_VC));
  1025. if (pVc != NULL_PATMLANE_VC)
  1026. {
  1027. NdisZeroMemory(pVc, sizeof(ATMLANE_VC));
  1028. #if DBG
  1029. pVc->atmlane_vc_sig = atmlane_vc_signature;
  1030. #endif // DBG
  1031. pVc->pElan = pElan;
  1032. INIT_VC_LOCK(pVc);
  1033. }
  1034. DBGP((3, "Allocated Vc %x\n", pVc));
  1035. TRACEOUT(AllocateVc);
  1036. return (pVc);
  1037. }
  1038. VOID
  1039. AtmLaneDeallocateVc(
  1040. IN PATMLANE_VC pVc
  1041. )
  1042. /*++
  1043. Routine Description:
  1044. Deallocate an ATMLANE VC structure. It is assumed that all references
  1045. to this VC have gone, so there is no need to acquire a lock to the VC.
  1046. Arguments:
  1047. pVc - Pointer to the VC to be deallocated
  1048. Return Value:
  1049. None
  1050. --*/
  1051. {
  1052. TRACEIN(DeallocateVc);
  1053. STRUCT_ASSERT(pVc, atmlane_vc);
  1054. ASSERT(pVc->RefCount == 0);
  1055. #if DBG
  1056. pVc->atmlane_vc_sig++;
  1057. #endif
  1058. FREE_VC_LOCK(pVc);
  1059. FREE_MEM(pVc);
  1060. DBGP((5, "Deallocated Vc %x\n", pVc));
  1061. TRACEOUT(DeallocateVc);
  1062. return;
  1063. }
  1064. VOID
  1065. AtmLaneReferenceVc(
  1066. IN PATMLANE_VC pVc,
  1067. IN PUCHAR String
  1068. )
  1069. /*++
  1070. Routine Description:
  1071. Add a reference to the specified ATMLANE VC.
  1072. NOTE: The caller is assumed to possess a lock for the VC.
  1073. Arguments:
  1074. pVc - Pointer to the VC to be referenced
  1075. Return Value:
  1076. None
  1077. --*/
  1078. {
  1079. TRACEIN(ReferenceVc);
  1080. STRUCT_ASSERT(pVc, atmlane_vc);
  1081. pVc->RefCount++;
  1082. DBGP((5, "ReferenceVc: Vc %x (%s) new count %d\n",
  1083. pVc, String, pVc->RefCount));
  1084. TRACEOUT(ReferenceVc);
  1085. return;
  1086. }
  1087. ULONG
  1088. AtmLaneDereferenceVc(
  1089. IN PATMLANE_VC pVc,
  1090. IN PUCHAR String
  1091. )
  1092. /*++
  1093. Routine Description:
  1094. Subtract a reference from the specified ATMLANE VC. If the VC's
  1095. reference count becomes zero, deallocate it.
  1096. NOTE: The caller is assumed to possess a lock for the VC.
  1097. SIDE EFFECT: See Return Value below
  1098. Arguments:
  1099. pVc - Pointer to the VC to be dereferenced.
  1100. Return Value:
  1101. Is the new reference count.
  1102. [IMPORTANT] If the VC's reference count became zero, the VC will be
  1103. deallocated -- the VC lock is, obviously, released in this case.
  1104. --*/
  1105. {
  1106. ULONG rv;
  1107. TRACEIN(DereferenceVc);
  1108. STRUCT_ASSERT(pVc, atmlane_vc);
  1109. ASSERT(pVc->RefCount > 0);
  1110. rv = --(pVc->RefCount);
  1111. if (rv == 0)
  1112. {
  1113. RELEASE_VC_LOCK(pVc);
  1114. AtmLaneDeallocateVc(pVc);
  1115. }
  1116. DBGP((5, "DereferenceVc: Vc %x (%s) new count %d\n",
  1117. pVc, String, rv));
  1118. TRACEOUT(DereferenceVc);
  1119. return (rv);
  1120. }
  1121. PATMLANE_MAC_ENTRY
  1122. AtmLaneAllocateMacEntry(
  1123. IN PATMLANE_ELAN pElan
  1124. )
  1125. /*++
  1126. Routine Description:
  1127. Allocate an ATMLANE MAC Entry structure, initialize it, and
  1128. return it.
  1129. Arguments:
  1130. pElan - Pointer to ATMLANE Interface on which this MAC
  1131. Entry is allocated.
  1132. Return Value:
  1133. Pointer to allocated MAC Entry structure if successful,
  1134. NULL otherwise.
  1135. --*/
  1136. {
  1137. PATMLANE_MAC_ENTRY pMacEntry;
  1138. TRACEIN(AllocateMacEntry);
  1139. ALLOC_MEM(&pMacEntry, sizeof(ATMLANE_MAC_ENTRY));
  1140. if (pMacEntry != NULL_PATMLANE_MAC_ENTRY)
  1141. {
  1142. NdisZeroMemory(pMacEntry, sizeof(ATMLANE_MAC_ENTRY));
  1143. #if DBG
  1144. pMacEntry->atmlane_mac_sig = atmlane_mac_signature;
  1145. #endif // DBG
  1146. pMacEntry->pElan = pElan;
  1147. pMacEntry->Flags = MAC_ENTRY_NEW;
  1148. INIT_MAC_ENTRY_LOCK(pMacEntry);
  1149. INIT_SYSTEM_TIMER(
  1150. &pMacEntry->BusTimer,
  1151. AtmLaneBusSendTimer,
  1152. pMacEntry);
  1153. pMacEntry->LimitTime = pElan->LimitTime;
  1154. pMacEntry->IncrTime = pElan->IncrTime;
  1155. }
  1156. DBGP((5, "AllocateMacEntry: Allocated Entry %x\n", pMacEntry));
  1157. TRACEOUT(AllocateMacEntry);
  1158. return (pMacEntry);
  1159. }
  1160. VOID
  1161. AtmLaneDeallocateMacEntry(
  1162. IN PATMLANE_MAC_ENTRY pMacEntry
  1163. )
  1164. /*++
  1165. Routine Description:
  1166. Deallocate an ATMLANE Mac Entry. It is assumed that all references
  1167. to this Mac Entry have gone, so there is no need to acquire its
  1168. lock.
  1169. Arguments:
  1170. pMacEntry - Pointer to the Mac Entry to be deallocated.
  1171. Return Value:
  1172. None
  1173. --*/
  1174. {
  1175. TRACEIN(DeallocateMacEntry);
  1176. STRUCT_ASSERT(pMacEntry, atmlane_mac);
  1177. ASSERT(pMacEntry->RefCount == 0);
  1178. #if DBG
  1179. pMacEntry->atmlane_mac_sig++;
  1180. #endif
  1181. FREE_MAC_ENTRY_LOCK(pMacEntry);
  1182. FREE_MEM(pMacEntry);
  1183. DBGP((5,"DeallocateMacEntry: Deallocated Entry %x\n", pMacEntry));
  1184. TRACEOUT(DeallocateMacEntry);
  1185. return;
  1186. }
  1187. VOID
  1188. AtmLaneReferenceMacEntry(
  1189. IN PATMLANE_MAC_ENTRY pMacEntry,
  1190. IN PUCHAR String
  1191. )
  1192. /*++
  1193. Routine Description:
  1194. Add a reference to an ATMLANE Mac Entry.
  1195. NOTE: The caller is assumed to possess a lock for the Mac Entry.
  1196. Arguments:
  1197. pMacEntry - Pointer to an ATMLANE Mac Entry.
  1198. Return Value:
  1199. None
  1200. --*/
  1201. {
  1202. TRACEIN(ReferenceMacEntry);
  1203. STRUCT_ASSERT(pMacEntry, atmlane_mac);
  1204. pMacEntry->RefCount++;
  1205. DBGP((5, "ReferenceMacEntry: Entry %x (%s) new count %d\n",
  1206. pMacEntry, String, pMacEntry->RefCount));
  1207. TRACEOUT(ReferenceMacEntry);
  1208. return;
  1209. }
  1210. ULONG
  1211. AtmLaneDereferenceMacEntry(
  1212. IN PATMLANE_MAC_ENTRY pMacEntry,
  1213. IN PUCHAR String
  1214. )
  1215. /*++
  1216. Routine Description:
  1217. Subtract a reference from an ATMLANE MAC Entry. If the reference
  1218. count becomes zero, deallocate it.
  1219. NOTE: It is assumed that the caller holds a lock to the MAC Entry.
  1220. See SIDE EFFECT below.
  1221. Arguments:
  1222. pMacEntry - Pointer to ATMLANE MAC Entry
  1223. Return Value:
  1224. The resulting reference count. If this is zero, then there are two
  1225. SIDE EFFECTS: (1) the MAC Entry lock is released (2) the structure
  1226. is freed.
  1227. --*/
  1228. {
  1229. ULONG rc;
  1230. TRACEIN(DereferenceMacEntry);
  1231. STRUCT_ASSERT(pMacEntry, atmlane_mac);
  1232. rc = --(pMacEntry->RefCount);
  1233. if (rc == 0)
  1234. {
  1235. PVOID Caller, CallersCaller;
  1236. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  1237. //
  1238. // Save away the caller's address for debugging purposes...
  1239. //
  1240. RtlGetCallersAddress(&Caller, &CallersCaller);
  1241. pMacEntry->Timer.ContextPtr = Caller;
  1242. AtmLaneDeallocateMacEntry(pMacEntry);
  1243. }
  1244. DBGP((5, "DereferenceMacEntry: Entry %x (%s) new count %d\n",
  1245. pMacEntry, String, rc));
  1246. TRACEOUT(DereferenceMacEntry);
  1247. return (rc);
  1248. }
  1249. PNDIS_PACKET
  1250. AtmLaneAllocProtoPacket(
  1251. IN PATMLANE_ELAN pElan
  1252. )
  1253. /*++
  1254. Routine Description:
  1255. Allocate an NDIS packet for use as a LANE control frame.
  1256. Arguments:
  1257. pElan - Pointer to ATMLANE ELAN structure
  1258. Return Value:
  1259. Pointer to NDIS packet if allocated, NULL otherwise.
  1260. --*/
  1261. {
  1262. NDIS_STATUS Status;
  1263. PNDIS_PACKET pNdisPacket;
  1264. TRACEIN(AllocProtoPacket);
  1265. NdisAllocatePacket(
  1266. &Status,
  1267. &pNdisPacket,
  1268. pElan->ProtocolPacketPool
  1269. );
  1270. if (pNdisPacket != (PNDIS_PACKET)NULL)
  1271. {
  1272. //
  1273. // Init ProtocolReserved and mark packet owned by ATMLANE
  1274. //
  1275. ZERO_SEND_RSVD(pNdisPacket);
  1276. #if PROTECT_PACKETS
  1277. INIT_SENDPACKET_LOCK(pNdisPacket);
  1278. #endif // PROTECT_PACKETS
  1279. SET_FLAG(
  1280. PSEND_RSVD(pNdisPacket)->Flags,
  1281. PACKET_RESERVED_OWNER_MASK,
  1282. PACKET_RESERVED_OWNER_ATMLANE
  1283. );
  1284. #if PKT_HDR_COUNTS
  1285. InterlockedDecrement(&pElan->ProtPktCount);
  1286. if ((pElan->ProtPktCount % 20) == 0)
  1287. {
  1288. DBGP((1, "ProtPktCount %d\n", pElan->ProtPktCount));
  1289. }
  1290. #endif
  1291. }
  1292. TRACEOUT(AllocProtoPacket);
  1293. return (pNdisPacket);
  1294. }
  1295. VOID
  1296. AtmLaneFreeProtoPacket(
  1297. IN PATMLANE_ELAN pElan,
  1298. IN PNDIS_PACKET pNdisPacket
  1299. )
  1300. /*++
  1301. Routine Description:
  1302. Allocate an NDIS packet used as a LANE control frame.
  1303. Arguments:
  1304. pElan - Pointer to ATMLANE ELAN structure
  1305. pNdisPacket - pointer to NDIS_PACKET to free.
  1306. Return Value:
  1307. None
  1308. --*/
  1309. {
  1310. TRACEIN(FreeProtoPacket);
  1311. if (pNdisPacket != (PNDIS_PACKET)NULL)
  1312. {
  1313. #if PROTECT_PACKETS
  1314. FREE_SENDPACKET_LOCK(pNdisPacket);
  1315. #endif // PROTECT_PACKETS
  1316. NdisFreePacket(pNdisPacket);
  1317. #if PKT_HDR_COUNTS
  1318. InterlockedIncrement(&pElan->ProtPktCount);
  1319. if ((pElan->ProtPktCount % 20) == 0 &&
  1320. pElan->ProtPktCount != pElan->MaxProtocolBufs)
  1321. {
  1322. DBGP((1, "ProtPktCount %d\n", pElan->ProtPktCount));
  1323. }
  1324. #endif
  1325. }
  1326. TRACEOUT(FreeProtoPacket);
  1327. return;
  1328. }
  1329. PNDIS_BUFFER
  1330. AtmLaneGrowHeaders(
  1331. IN PATMLANE_ELAN pElan
  1332. )
  1333. /*++
  1334. Routine Description:
  1335. Allocate a bunch of header buffers on the specified ATMLANE Elan.
  1336. Return one of them.
  1337. We allocate a new Buffer tracker structure, a new NDIS Buffer pool, and
  1338. finally a chunk of system memory that we break down into header buffers.
  1339. These header buffers are then attached to NDIS Buffers before they are
  1340. inserted into the list of free header buffers for this Interface.
  1341. Caller is assumed to hold appropriate lock.
  1342. Arguments:
  1343. pElan - Pointer to ATMLANE Elan structure
  1344. Return Value:
  1345. Pointer to allocated NDIS buffer if successful, NULL otherwise.
  1346. --*/
  1347. {
  1348. PATMLANE_BUFFER_TRACKER pTracker; // for new set of buffers
  1349. PUCHAR pSpace;
  1350. PNDIS_BUFFER pNdisBuffer;
  1351. PNDIS_BUFFER pReturnBuffer;
  1352. PNDIS_BUFFER pBufferList; // allocated list
  1353. INT i; // iteration counter
  1354. NDIS_STATUS Status;
  1355. TRACEIN(GrowHeaders);
  1356. //
  1357. // Initialize
  1358. //
  1359. pTracker = NULL_PATMLANE_BUFFER_TRACKER;
  1360. pReturnBuffer = (PNDIS_BUFFER)NULL;
  1361. do
  1362. {
  1363. if (pElan->CurHeaderBufs >= pElan->MaxHeaderBufs)
  1364. {
  1365. DBGP((2, "GrowHeaders: Elan %x, CurHdrBufs %d > MaxHdrBufs %d\n",
  1366. pElan, pElan->CurHeaderBufs, pElan->MaxHeaderBufs));
  1367. break;
  1368. }
  1369. //
  1370. // Allocate and initialize Buffer tracker
  1371. //
  1372. ALLOC_MEM(&pTracker, sizeof(ATMLANE_BUFFER_TRACKER));
  1373. if (pTracker == NULL_PATMLANE_BUFFER_TRACKER)
  1374. {
  1375. DBGP((0, "GrowHeaders: Elan %x, alloc failed for tracker\n",
  1376. pElan));
  1377. break;
  1378. }
  1379. NdisZeroMemory(pTracker, sizeof(ATMLANE_BUFFER_TRACKER));
  1380. //
  1381. // Get the NDIS Buffer pool
  1382. //
  1383. NdisAllocateBufferPool(
  1384. &Status,
  1385. &(pTracker->NdisHandle),
  1386. DEF_HDRBUF_GROW_SIZE
  1387. );
  1388. if (Status != NDIS_STATUS_SUCCESS)
  1389. {
  1390. DBGP((0,
  1391. "GrowHeaders: Elan %x, NdisAllocateBufferPool err status %x\n",
  1392. pElan, Status));
  1393. break;
  1394. }
  1395. //
  1396. // Allocate system space for a bunch of header buffers
  1397. // Note we use RealHeaderBufSize here so that the
  1398. // buffers end up on ULONG boundaries.
  1399. //
  1400. ALLOC_MEM(&(pTracker->pPoolStart),
  1401. pElan->RealHeaderBufSize * DEF_HDRBUF_GROW_SIZE);
  1402. if (pTracker->pPoolStart == (PUCHAR)NULL)
  1403. {
  1404. DBGP((0, "GrowHeaders: Elan %x, could not alloc buf space %d bytes\n",
  1405. pElan, pElan->HeaderBufSize * DEF_HDRBUF_GROW_SIZE));
  1406. break;
  1407. }
  1408. //
  1409. // Make NDIS buffers out of the allocated space, and put them
  1410. // into the free header buffer list. Retain one for returning
  1411. // to caller.
  1412. //
  1413. pBufferList = (PNDIS_BUFFER)NULL;
  1414. pSpace = pTracker->pPoolStart;
  1415. for (i = 0; i < DEF_HDRBUF_GROW_SIZE; i++)
  1416. {
  1417. NdisAllocateBuffer(
  1418. &Status,
  1419. &pNdisBuffer,
  1420. pTracker->NdisHandle,
  1421. pSpace,
  1422. pElan->HeaderBufSize
  1423. );
  1424. if (Status != NDIS_STATUS_SUCCESS)
  1425. {
  1426. DBGP((0,
  1427. "GrowHeaders: NdisAllocateBuffer failed: Elan %x, status %x\n",
  1428. pElan, Status));
  1429. break;
  1430. }
  1431. if (i == 0)
  1432. {
  1433. pReturnBuffer = pNdisBuffer;
  1434. }
  1435. else
  1436. {
  1437. NDIS_BUFFER_LINKAGE(pNdisBuffer) = pBufferList;
  1438. pBufferList = pNdisBuffer;
  1439. }
  1440. pSpace += pElan->RealHeaderBufSize;
  1441. }
  1442. if (i > 0)
  1443. {
  1444. //
  1445. // Successfully allocated at least one more header buffer
  1446. //
  1447. pTracker->pNext = pElan->pHeaderTrkList;
  1448. pElan->pHeaderTrkList = pTracker;
  1449. pElan->CurHeaderBufs += i;
  1450. pNdisBuffer = pBufferList;
  1451. while (pNdisBuffer != (PNDIS_BUFFER)NULL)
  1452. {
  1453. pBufferList = NDIS_BUFFER_LINKAGE(pNdisBuffer);
  1454. NDIS_BUFFER_LINKAGE(pNdisBuffer) = NULL;
  1455. AtmLaneFreeHeader(pElan, pNdisBuffer, TRUE);
  1456. pNdisBuffer = pBufferList;
  1457. }
  1458. }
  1459. } while (FALSE);
  1460. if (pReturnBuffer == (PNDIS_BUFFER)NULL)
  1461. {
  1462. //
  1463. // Failed to allocate. Undo all.
  1464. //
  1465. if (pTracker != NULL_PATMLANE_BUFFER_TRACKER)
  1466. {
  1467. if (pTracker->pPoolStart != (PUCHAR)NULL)
  1468. {
  1469. FREE_MEM(pTracker->pPoolStart);
  1470. }
  1471. if (pTracker->NdisHandle != (NDIS_HANDLE)NULL)
  1472. {
  1473. NdisFreeBufferPool(pTracker->NdisHandle);
  1474. }
  1475. FREE_MEM(pTracker);
  1476. }
  1477. }
  1478. DBGP((2, "GrowHeaders: Elan %x, RetBuf %x, New Tracker %x\n",
  1479. pElan, pReturnBuffer, pTracker));
  1480. TRACEOUT(GrowHeaders);
  1481. return (pReturnBuffer);
  1482. }
  1483. PNDIS_BUFFER
  1484. AtmLaneAllocateHeader(
  1485. IN PATMLANE_ELAN pElan,
  1486. OUT PUCHAR * pBufferAddress
  1487. )
  1488. /*++
  1489. Routine Description:
  1490. Allocate an NDIS Buffer to be used for LECID a MAC packet.
  1491. We pick up the buffer at the top of the pre-allocated
  1492. buffer list, if one exists. Otherwise, we try to grow this list and
  1493. allocate.
  1494. Arguments:
  1495. pElan - Pointer to ATMLANE Elan
  1496. pBufferAddress - Place to return virtual address of allocated buffer
  1497. Return Value:
  1498. Pointer to NDIS buffer if successful, NULL otherwise.
  1499. --*/
  1500. {
  1501. PNDIS_BUFFER pNdisBuffer;
  1502. NDIS_STATUS Status;
  1503. ULONG Length;
  1504. TRACEIN(AllocateHeader);
  1505. ACQUIRE_HEADER_LOCK(pElan);
  1506. pNdisBuffer = pElan->HeaderBufList;
  1507. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  1508. {
  1509. pElan->HeaderBufList = NDIS_BUFFER_LINKAGE(pNdisBuffer);
  1510. NDIS_BUFFER_LINKAGE(pNdisBuffer) = NULL;
  1511. NdisQueryBuffer(pNdisBuffer, (PVOID)pBufferAddress, &Length);
  1512. }
  1513. else
  1514. {
  1515. pNdisBuffer = AtmLaneGrowHeaders(pElan);
  1516. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  1517. {
  1518. NDIS_BUFFER_LINKAGE(pNdisBuffer) = NULL;
  1519. NdisQueryBuffer(pNdisBuffer, (PVOID)pBufferAddress, &Length);
  1520. }
  1521. }
  1522. DBGP((5, "AllocateHeader: Buffer %x, Elan %x\n",
  1523. pNdisBuffer, pElan));
  1524. RELEASE_HEADER_LOCK(pElan);
  1525. TRACEOUT(AllocateHeader);
  1526. return (pNdisBuffer);
  1527. }
  1528. VOID
  1529. AtmLaneFreeHeader(
  1530. IN PATMLANE_ELAN pElan,
  1531. IN PNDIS_BUFFER pNdisBuffer,
  1532. IN BOOLEAN LockHeld
  1533. )
  1534. /*++
  1535. Routine Description:
  1536. Deallocate a header buffer.
  1537. Arguments:
  1538. pElan - Pointer to ATMLANE Elan from which the buffer came
  1539. pNdisBuffer - Pointer to NDIS buffer being freed
  1540. LockHeld - TRUE if appropriate lock already held
  1541. Return Value:
  1542. None
  1543. --*/
  1544. {
  1545. TRACEIN(FreeHeader);
  1546. if (!LockHeld)
  1547. {
  1548. ACQUIRE_HEADER_LOCK(pElan);
  1549. }
  1550. NDIS_BUFFER_LINKAGE(pNdisBuffer) = pElan->HeaderBufList;
  1551. pElan->HeaderBufList = pNdisBuffer;
  1552. DBGP((5, "FreeHeader: Buffer %x, Elan %x\n",
  1553. pNdisBuffer, pElan));
  1554. if (!LockHeld)
  1555. {
  1556. RELEASE_HEADER_LOCK(pElan);
  1557. }
  1558. TRACEOUT(FreeHeader);
  1559. }
  1560. VOID
  1561. AtmLaneDeallocateHeaderBuffers(
  1562. IN PATMLANE_ELAN pElan
  1563. )
  1564. /*++
  1565. Routine Description:
  1566. Deallocate everything pertaining to header buffers on an Elan.
  1567. Arguments:
  1568. pElan - Pointer to ATMLANE Elan.
  1569. Return Value:
  1570. None
  1571. --*/
  1572. {
  1573. PNDIS_BUFFER pNdisBuffer;
  1574. NDIS_STATUS Status;
  1575. PATMLANE_BUFFER_TRACKER pTracker;
  1576. PATMLANE_BUFFER_TRACKER pNextTracker;
  1577. TRACEIN(DeallocateHeaderBuffers);
  1578. //
  1579. // Free all NDIS buffers in the header buffer list.
  1580. //
  1581. ACQUIRE_HEADER_LOCK(pElan);
  1582. do
  1583. {
  1584. pNdisBuffer = pElan->HeaderBufList;
  1585. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  1586. {
  1587. pElan->HeaderBufList = NDIS_BUFFER_LINKAGE(pNdisBuffer);
  1588. NDIS_BUFFER_LINKAGE(pNdisBuffer) = NULL;
  1589. NdisFreeBuffer(pNdisBuffer);
  1590. }
  1591. else
  1592. {
  1593. //
  1594. // No more NDIS buffers.
  1595. //
  1596. break;
  1597. }
  1598. }
  1599. while (TRUE);
  1600. //
  1601. // Now free all the buffer trackers.
  1602. //
  1603. pTracker = pElan->pHeaderTrkList;
  1604. while (pTracker != NULL_PATMLANE_BUFFER_TRACKER)
  1605. {
  1606. pNextTracker = pTracker->pNext;
  1607. if (pTracker->pPoolStart != (PUCHAR)NULL)
  1608. {
  1609. FREE_MEM(pTracker->pPoolStart);
  1610. pTracker->pPoolStart = (PUCHAR)NULL;
  1611. }
  1612. if (pTracker->NdisHandle != (NDIS_HANDLE)NULL)
  1613. {
  1614. NdisFreeBufferPool(pTracker->NdisHandle);
  1615. pTracker->NdisHandle = (NDIS_HANDLE)NULL;
  1616. }
  1617. FREE_MEM(pTracker);
  1618. pTracker = pNextTracker;
  1619. }
  1620. RELEASE_HEADER_LOCK(pElan);
  1621. TRACEOUT(DeallocateHeaderBuffers);
  1622. }
  1623. PNDIS_BUFFER
  1624. AtmLaneGrowPadBufs(
  1625. IN PATMLANE_ELAN pElan
  1626. )
  1627. /*++
  1628. Routine Description:
  1629. Allocate a bunch of packet pad buffers on the specified ATMLANE Elan.
  1630. Return one of them.
  1631. We allocate a new Buffer tracker structure, a new NDIS Buffer pool, and
  1632. finally a chunk of system memory (if not allocated already, only need one).
  1633. This buffer is then attached to the NDIS Buffers before they are
  1634. inserted into the list of free pad buffers for this Interface.
  1635. Caller is assumed to hold appropriate lock.
  1636. Arguments:
  1637. pElan - Pointer to ATMLANE Elan structure
  1638. Return Value:
  1639. Pointer to allocated NDIS buffer if successful, NULL otherwise.
  1640. --*/
  1641. {
  1642. PATMLANE_BUFFER_TRACKER pTracker; // for new set of buffers
  1643. PUCHAR pSpace;
  1644. PNDIS_BUFFER pNdisBuffer;
  1645. PNDIS_BUFFER pReturnBuffer;
  1646. PNDIS_BUFFER pBufferList; // allocated list
  1647. INT i; // iteration counter
  1648. NDIS_STATUS Status;
  1649. TRACEIN(GrowPadBufs);
  1650. //
  1651. // Initialize
  1652. //
  1653. pTracker = NULL_PATMLANE_BUFFER_TRACKER;
  1654. pReturnBuffer = (PNDIS_BUFFER)NULL;
  1655. do
  1656. {
  1657. if (pElan->CurPadBufs >= pElan->MaxPadBufs)
  1658. {
  1659. DBGP((0, "GrowPadBufs: Max Reached! Elan %x, CurPadBufs %d > MaxPadBufs %d\n",
  1660. pElan, pElan->CurPadBufs, pElan->MaxPadBufs));
  1661. break;
  1662. }
  1663. //
  1664. // Allocate and initialize Buffer tracker
  1665. //
  1666. ALLOC_MEM(&pTracker, sizeof(ATMLANE_BUFFER_TRACKER));
  1667. if (pTracker == NULL_PATMLANE_BUFFER_TRACKER)
  1668. {
  1669. DBGP((0, "GrowPadBufs: Elan %x, alloc failed for tracker\n",
  1670. pElan));
  1671. break;
  1672. }
  1673. NdisZeroMemory(pTracker, sizeof(ATMLANE_BUFFER_TRACKER));
  1674. //
  1675. // Get the NDIS Buffer pool
  1676. //
  1677. NdisAllocateBufferPool(
  1678. &Status,
  1679. &(pTracker->NdisHandle),
  1680. DEF_HDRBUF_GROW_SIZE
  1681. );
  1682. if (Status != NDIS_STATUS_SUCCESS)
  1683. {
  1684. DBGP((0,
  1685. "GrowPadBufs: Elan %x, NdisAllocateBufferPool err status %x\n",
  1686. pElan, Status));
  1687. break;
  1688. }
  1689. //
  1690. // Allocate system space for a single pad buffer.
  1691. //
  1692. ALLOC_MEM(&(pTracker->pPoolStart), pElan->PadBufSize);
  1693. if (pTracker->pPoolStart == (PUCHAR)NULL)
  1694. {
  1695. DBGP((0, "GrowPadBufs: Elan %x, could not alloc buf space %d bytes\n",
  1696. pElan, pElan->PadBufSize * DEF_HDRBUF_GROW_SIZE));
  1697. break;
  1698. }
  1699. //
  1700. // Make NDIS buffers out of the allocated space, and put them
  1701. // into the free pad buffer list. Retain one for returning
  1702. // to caller. NOTE we put same pad buffer in each ndis buffer header
  1703. // since contents is irrelevent.
  1704. //
  1705. pBufferList = (PNDIS_BUFFER)NULL;
  1706. pSpace = pTracker->pPoolStart;
  1707. for (i = 0; i < DEF_HDRBUF_GROW_SIZE; i++)
  1708. {
  1709. NdisAllocateBuffer(
  1710. &Status,
  1711. &pNdisBuffer,
  1712. pTracker->NdisHandle,
  1713. pSpace,
  1714. pElan->PadBufSize
  1715. );
  1716. if (Status != NDIS_STATUS_SUCCESS)
  1717. {
  1718. DBGP((0,
  1719. "GrowPadBufs: NdisAllocateBuffer failed: Elan %x, status %x\n",
  1720. pElan, Status));
  1721. break;
  1722. }
  1723. if (i == 0)
  1724. {
  1725. pReturnBuffer = pNdisBuffer;
  1726. }
  1727. else
  1728. {
  1729. NDIS_BUFFER_LINKAGE(pNdisBuffer) = pBufferList;
  1730. pBufferList = pNdisBuffer;
  1731. }
  1732. }
  1733. if (i > 0)
  1734. {
  1735. //
  1736. // Successfully allocated at least one more pad buffer
  1737. //
  1738. pTracker->pNext = pElan->pPadTrkList;
  1739. pElan->pPadTrkList = pTracker;
  1740. pElan->CurPadBufs += i;
  1741. pNdisBuffer = pBufferList;
  1742. while (pNdisBuffer != (PNDIS_BUFFER)NULL)
  1743. {
  1744. pBufferList = NDIS_BUFFER_LINKAGE(pNdisBuffer);
  1745. NDIS_BUFFER_LINKAGE(pNdisBuffer) = NULL;
  1746. AtmLaneFreePadBuf(pElan, pNdisBuffer, TRUE);
  1747. pNdisBuffer = pBufferList;
  1748. }
  1749. }
  1750. } while (FALSE);
  1751. if (pReturnBuffer == (PNDIS_BUFFER)NULL)
  1752. {
  1753. //
  1754. // Failed to allocate. Undo all.
  1755. //
  1756. if (pTracker != NULL_PATMLANE_BUFFER_TRACKER)
  1757. {
  1758. if (pTracker->pPoolStart != (PUCHAR)NULL)
  1759. {
  1760. FREE_MEM(pTracker->pPoolStart);
  1761. }
  1762. if (pTracker->NdisHandle != (NDIS_HANDLE)NULL)
  1763. {
  1764. NdisFreeBufferPool(pTracker->NdisHandle);
  1765. }
  1766. FREE_MEM(pTracker);
  1767. }
  1768. }
  1769. DBGP((2, "GrowPadBufs: Elan %x, RetBuf %x, New Tracker %x\n",
  1770. pElan, pReturnBuffer, pTracker));
  1771. TRACEOUT(GrowPadBufs);
  1772. return (pReturnBuffer);
  1773. }
  1774. PNDIS_BUFFER
  1775. AtmLaneAllocatePadBuf(
  1776. IN PATMLANE_ELAN pElan,
  1777. OUT PUCHAR * pBufferAddress
  1778. )
  1779. /*++
  1780. Routine Description:
  1781. Allocate an NDIS Buffer to be used to pad a MAC packet to min length.
  1782. We pick up the buffer at the top of the pre-allocated
  1783. buffer list, if one exists. Otherwise, we try to grow this list and
  1784. allocate.
  1785. Arguments:
  1786. pElan - Pointer to ATMLANE Elan
  1787. pBufferAddress - Place to return virtual address of allocated buffer
  1788. Return Value:
  1789. Pointer to NDIS buffer if successful, NULL otherwise.
  1790. --*/
  1791. {
  1792. PNDIS_BUFFER pNdisBuffer;
  1793. NDIS_STATUS Status;
  1794. ULONG Length;
  1795. TRACEIN(AtmLaneAllocatePadBuf);
  1796. ACQUIRE_HEADER_LOCK(pElan);
  1797. pNdisBuffer = pElan->PadBufList;
  1798. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  1799. {
  1800. pElan->PadBufList = NDIS_BUFFER_LINKAGE(pNdisBuffer);
  1801. NDIS_BUFFER_LINKAGE(pNdisBuffer) = NULL;
  1802. NdisQueryBuffer(pNdisBuffer, (PVOID)pBufferAddress, &Length);
  1803. }
  1804. else
  1805. {
  1806. pNdisBuffer = AtmLaneGrowPadBufs(pElan);
  1807. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  1808. {
  1809. NDIS_BUFFER_LINKAGE(pNdisBuffer) = NULL;
  1810. NdisQueryBuffer(pNdisBuffer, (PVOID)pBufferAddress, &Length);
  1811. }
  1812. }
  1813. DBGP((5, "AllocatePadBuf: Buffer %x, Elan %x\n",
  1814. pNdisBuffer, pElan));
  1815. RELEASE_HEADER_LOCK(pElan);
  1816. TRACEOUT(AllocatePadBuf);
  1817. return (pNdisBuffer);
  1818. }
  1819. VOID
  1820. AtmLaneFreePadBuf(
  1821. IN PATMLANE_ELAN pElan,
  1822. IN PNDIS_BUFFER pNdisBuffer,
  1823. IN BOOLEAN LockHeld
  1824. )
  1825. /*++
  1826. Routine Description:
  1827. Deallocate a Pad buffer.
  1828. Arguments:
  1829. pElan - Pointer to ATMLANE Elan from which the buffer came
  1830. pNdisBuffer - Pointer to NDIS buffer being freed
  1831. LockHeld - TRUE if appropriate lock already held
  1832. Return Value:
  1833. None
  1834. --*/
  1835. {
  1836. TRACEIN(FreePadBuf);
  1837. if (!LockHeld)
  1838. {
  1839. ACQUIRE_HEADER_LOCK(pElan);
  1840. }
  1841. NDIS_BUFFER_LINKAGE(pNdisBuffer) = pElan->PadBufList;
  1842. pElan->PadBufList = pNdisBuffer;
  1843. DBGP((5, "FreePadBuf: Buffer %x, Elan %x\n",
  1844. pNdisBuffer, pElan));
  1845. if (!LockHeld)
  1846. {
  1847. RELEASE_HEADER_LOCK(pElan);
  1848. }
  1849. TRACEOUT(FreePadBuf);
  1850. }
  1851. VOID
  1852. AtmLaneDeallocatePadBufs(
  1853. IN PATMLANE_ELAN pElan
  1854. )
  1855. /*++
  1856. Routine Description:
  1857. Deallocate everything pertaining to Pad buffers on an Elan.
  1858. Arguments:
  1859. pElan - Pointer to ATMLANE Elan.
  1860. Return Value:
  1861. None
  1862. --*/
  1863. {
  1864. PNDIS_BUFFER pNdisBuffer;
  1865. NDIS_STATUS Status;
  1866. PATMLANE_BUFFER_TRACKER pTracker;
  1867. PATMLANE_BUFFER_TRACKER pNextTracker;
  1868. TRACEIN(DeallocatePadBufs);
  1869. //
  1870. // Free all NDIS buffers in the Pad buffer list.
  1871. //
  1872. ACQUIRE_HEADER_LOCK(pElan);
  1873. do
  1874. {
  1875. pNdisBuffer = pElan->PadBufList;
  1876. if (pNdisBuffer != (PNDIS_BUFFER)NULL)
  1877. {
  1878. pElan->PadBufList = NDIS_BUFFER_LINKAGE(pNdisBuffer);
  1879. NDIS_BUFFER_LINKAGE(pNdisBuffer) = NULL;
  1880. NdisFreeBuffer(pNdisBuffer);
  1881. }
  1882. else
  1883. {
  1884. //
  1885. // No more NDIS buffers.
  1886. //
  1887. break;
  1888. }
  1889. }
  1890. while (TRUE);
  1891. //
  1892. // Now free all the buffer trackers.
  1893. //
  1894. pTracker = pElan->pPadTrkList;
  1895. while (pTracker != NULL_PATMLANE_BUFFER_TRACKER)
  1896. {
  1897. pNextTracker = pTracker->pNext;
  1898. if (pTracker->pPoolStart != (PUCHAR)NULL)
  1899. {
  1900. FREE_MEM(pTracker->pPoolStart);
  1901. pTracker->pPoolStart = (PUCHAR)NULL;
  1902. }
  1903. if (pTracker->NdisHandle != (NDIS_HANDLE)NULL)
  1904. {
  1905. NdisFreeBufferPool(pTracker->NdisHandle);
  1906. pTracker->NdisHandle = (NDIS_HANDLE)NULL;
  1907. }
  1908. FREE_MEM(pTracker);
  1909. pTracker = pNextTracker;
  1910. }
  1911. RELEASE_HEADER_LOCK(pElan);
  1912. TRACEOUT(DeallocatePadBufs);
  1913. }
  1914. PNDIS_BUFFER
  1915. AtmLaneAllocateProtoBuffer(
  1916. IN PATMLANE_ELAN pElan,
  1917. IN ULONG Length,
  1918. OUT PUCHAR * pBufferAddress
  1919. )
  1920. /*++
  1921. Routine Description:
  1922. Allocate a buffer to be used for a LANE protocol message. Attach
  1923. it to an NDIS_BUFFER structure and return a pointer to this.
  1924. Arguments:
  1925. pElan - Pointer to ATMLANE Elan
  1926. Length - Length, in bytes, of the buffer.
  1927. pBufferAddress - Place to return virtual address of allocated buffer.
  1928. Return Value:
  1929. Pointer to NDIS Buffer if successful, NULL otherwise.
  1930. --*/
  1931. {
  1932. PNDIS_BUFFER pNdisBuffer;
  1933. NDIS_STATUS Status;
  1934. TRACEIN(AllocateProtobuffer);
  1935. //
  1936. // Initialize
  1937. //
  1938. pNdisBuffer = NULL;
  1939. ACQUIRE_ELAN_LOCK(pElan);
  1940. ASSERT(Length <= pElan->ProtocolBufSize);
  1941. *pBufferAddress = pElan->ProtocolBufList;
  1942. if (*pBufferAddress != (PUCHAR)NULL)
  1943. {
  1944. NdisAllocateBuffer(
  1945. &Status,
  1946. &pNdisBuffer,
  1947. pElan->ProtocolBufferPool,
  1948. *pBufferAddress,
  1949. Length
  1950. );
  1951. if (Status == NDIS_STATUS_SUCCESS)
  1952. {
  1953. pElan->ProtocolBufList = *((PUCHAR *)*pBufferAddress);
  1954. }
  1955. }
  1956. RELEASE_ELAN_LOCK(pElan);
  1957. DBGP((5,
  1958. "AllocateProtoBuffer: ELan %x, pNdisBuffer %x, Length %d, Loc %x\n",
  1959. pElan, pNdisBuffer, Length, *pBufferAddress));
  1960. TRACEOUT(AllocateProtoBuffer);
  1961. return (pNdisBuffer);
  1962. }
  1963. VOID
  1964. AtmLaneFreeProtoBuffer(
  1965. IN PATMLANE_ELAN pElan,
  1966. IN PNDIS_BUFFER pNdisBuffer
  1967. )
  1968. /*++
  1969. Routine Description:
  1970. Free an NDIS buffer (and associated memory) used for a protocol
  1971. packet. We return the associated memory to the ProtocolBufList
  1972. in the Elan structure, and the NDIS buffer to NDIS.
  1973. Arguments:
  1974. pElan - Pointer to ATMLANE Elan structure
  1975. pNdisBuffer - Pointer to NDIS buffer to be freed
  1976. Return Value:
  1977. None
  1978. --*/
  1979. {
  1980. PUCHAR * pBufferLinkage;
  1981. ULONG Length;
  1982. TRACEIN(FreeProtoBuffer);
  1983. #if 0
  1984. pBufferLinkage = (PUCHAR *)NdisBufferVirtualAddress(pNdisBuffer);
  1985. #else
  1986. NdisQueryBuffer(pNdisBuffer, (PVOID)&pBufferLinkage, &Length);
  1987. #endif
  1988. ACQUIRE_ELAN_LOCK(pElan);
  1989. *pBufferLinkage = pElan->ProtocolBufList;
  1990. pElan->ProtocolBufList = (PUCHAR)pBufferLinkage;
  1991. RELEASE_ELAN_LOCK(pElan);
  1992. NdisFreeBuffer(pNdisBuffer);
  1993. DBGP((5, "FreeProtoBuffer: Elan %x, pNdisBuffer %x, Loc %x\n",
  1994. pElan, pNdisBuffer, (ULONG_PTR)pBufferLinkage));
  1995. TRACEOUT(FreeProtoBuffer);
  1996. return;
  1997. }
  1998. NDIS_STATUS
  1999. AtmLaneInitProtoBuffers(
  2000. IN PATMLANE_ELAN pElan
  2001. )
  2002. /*++
  2003. Routine Description:
  2004. Initialize the protocol buffer pool for an elan.
  2005. Allocate a chunk of memory to be used for ATMLANE protocol messages.
  2006. We prepare a linked list of protocol buffers, and attach it to the
  2007. Interface structure.
  2008. Arguments:
  2009. pElan - Pointer to Interface on which we need to allocate
  2010. protocol buffers.
  2011. Return Value:
  2012. NDIS_STATUS_SUCCESS if successful, NDIS_STATUS_RESOURCES if we run
  2013. into a resource failure.
  2014. --*/
  2015. {
  2016. NDIS_STATUS Status;
  2017. PUCHAR pSpace;
  2018. ULONG i;
  2019. TRACEIN(InitProtoBuffers);
  2020. do
  2021. {
  2022. NdisAllocatePacketPool(
  2023. &Status,
  2024. &(pElan->ProtocolPacketPool),
  2025. pElan->MaxProtocolBufs,
  2026. sizeof(SEND_PACKET_RESERVED)
  2027. );
  2028. #if PKT_HDR_COUNTS
  2029. pElan->ProtPktCount = pElan->MaxProtocolBufs;
  2030. DBGP((1, "ProtPktCount %d\n", pElan->ProtPktCount));
  2031. #endif
  2032. if (Status != NDIS_STATUS_SUCCESS)
  2033. {
  2034. break;
  2035. }
  2036. NdisAllocateBufferPool(
  2037. &Status,
  2038. &(pElan->ProtocolBufferPool),
  2039. pElan->MaxProtocolBufs
  2040. );
  2041. if (Status != NDIS_STATUS_SUCCESS)
  2042. {
  2043. break;
  2044. }
  2045. //
  2046. // Allocate a big chunk of system memory that we can divide up into
  2047. // protocol buffers.
  2048. //
  2049. ALLOC_MEM(
  2050. &(pElan->ProtocolBufTracker),
  2051. (pElan->ProtocolBufSize * pElan->MaxProtocolBufs)
  2052. );
  2053. if (pElan->ProtocolBufTracker == (PUCHAR)NULL)
  2054. {
  2055. Status = NDIS_STATUS_RESOURCES;
  2056. break;
  2057. }
  2058. Status = NDIS_STATUS_SUCCESS;
  2059. //
  2060. // Make all protocol buffers free.
  2061. //
  2062. pSpace = pElan->ProtocolBufTracker;
  2063. {
  2064. PUCHAR LinkPtr;
  2065. LinkPtr = (PUCHAR)NULL;
  2066. for (i = 0; i < pElan->MaxProtocolBufs; i++)
  2067. {
  2068. *((PUCHAR *)pSpace) = LinkPtr;
  2069. LinkPtr = pSpace;
  2070. pSpace += pElan->ProtocolBufSize;
  2071. }
  2072. pSpace -= pElan->ProtocolBufSize;
  2073. pElan->ProtocolBufList = pSpace;
  2074. }
  2075. }
  2076. while (FALSE);
  2077. if (Status != NDIS_STATUS_SUCCESS)
  2078. {
  2079. //
  2080. // Undo everything.
  2081. //
  2082. AtmLaneDeallocateProtoBuffers(pElan);
  2083. }
  2084. TRACEOUT(InitProtoBuffers);
  2085. return (Status);
  2086. }
  2087. VOID
  2088. AtmLaneDeallocateProtoBuffers(
  2089. IN PATMLANE_ELAN pElan
  2090. )
  2091. /*++
  2092. Routine Description:
  2093. Free the protocol buffer pool for an interface.
  2094. Arguments:
  2095. pElan - Pointer to ATMLANE elan structure
  2096. Return Value:
  2097. None
  2098. --*/
  2099. {
  2100. if (pElan->ProtocolPacketPool != (NDIS_HANDLE)NULL)
  2101. {
  2102. NdisFreePacketPool(pElan->ProtocolPacketPool);
  2103. pElan->ProtocolPacketPool = NULL;
  2104. }
  2105. if (pElan->ProtocolBufferPool != (NDIS_HANDLE)NULL)
  2106. {
  2107. NdisFreeBufferPool(pElan->ProtocolBufferPool);
  2108. pElan->ProtocolBufferPool = NULL;
  2109. }
  2110. if (pElan->ProtocolBufTracker != (PUCHAR)NULL)
  2111. {
  2112. FREE_MEM(pElan->ProtocolBufTracker);
  2113. pElan->ProtocolBufTracker = (PUCHAR)NULL;
  2114. }
  2115. }
  2116. VOID
  2117. AtmLaneLinkVcToAtmEntry(
  2118. IN PATMLANE_VC pVc,
  2119. IN PATMLANE_ATM_ENTRY pAtmEntry,
  2120. IN BOOLEAN ServerIncoming
  2121. )
  2122. /*++
  2123. Routine Description:
  2124. Link an ATMLANE VC to an ATM Entry. The caller is assumed to
  2125. hold locks to both structures.
  2126. Arguments:
  2127. pVc - Pointer to ATMLANE VC structure
  2128. pAtmEntry - Pointer to ATMLANE ATM Entry structure
  2129. ServerIncoming - Incoming call from server
  2130. Return Value:
  2131. None
  2132. --*/
  2133. {
  2134. PATMLANE_VC * ppNext;
  2135. PATMLANE_VC pVcEntry;
  2136. BOOLEAN WasRunning;
  2137. TRACEIN(LinkVcToAtmEntry);
  2138. DBGP((2, "LinkVcToAtmEntry: pVc %x to pAtmEntry %x ServerIncoming %s\n",
  2139. pVc, pAtmEntry, ServerIncoming?"TRUE":"FALSE"));
  2140. //
  2141. // Back pointer from VC to ATM Entry.
  2142. //
  2143. pVc->pAtmEntry = pAtmEntry;
  2144. //
  2145. // If server incoming connection cache the VC
  2146. // special location in the AtmEntry.
  2147. //
  2148. if (ServerIncoming)
  2149. {
  2150. pAtmEntry->pVcIncoming = pVc;
  2151. pVc->pNextVc = NULL_PATMLANE_VC;
  2152. }
  2153. else
  2154. {
  2155. //
  2156. // Otherwise...
  2157. //
  2158. // Add VC to the list in ascending calling party ATM address order
  2159. //
  2160. ppNext = &pAtmEntry->pVcList;
  2161. while (*ppNext != NULL_PATMLANE_VC)
  2162. {
  2163. if (memcmp(
  2164. &pVc->CallingAtmAddress.Address,
  2165. (*ppNext)->CallingAtmAddress.Address,
  2166. ATM_ADDRESS_LENGTH) < 0)
  2167. {
  2168. //
  2169. // Calling address is less than existing VC.
  2170. //
  2171. break;
  2172. }
  2173. else
  2174. {
  2175. //
  2176. // Calling address is equal or greater than existing VC.
  2177. // Move on to next.
  2178. //
  2179. ppNext = &((*ppNext)->pNextVc);
  2180. }
  2181. }
  2182. //
  2183. // Found the place we were looking for. Insert the VC here.
  2184. //
  2185. pVc->pNextVc = *ppNext;
  2186. *ppNext = pVc;
  2187. }
  2188. //
  2189. // Add the VC reference to the ATM entry.
  2190. //
  2191. AtmLaneReferenceAtmEntry(pAtmEntry, "vc"); // VC reference
  2192. //
  2193. // Add the ATM Entry reference to the VC.
  2194. //
  2195. AtmLaneReferenceVc(pVc, "atm");
  2196. //
  2197. // If this VC is not the first in the list, i.e., not the lowest
  2198. // calling party number, then set the timeout to the fast VC
  2199. // timeout value. This will get rid of redundant DataDirect VCs quickly
  2200. // ONLY if they don't get used within the fast timeout period.
  2201. // Otherwise the timeout handler to keep the VC and set
  2202. // the timeout to the normal C12-VccTimeout value.
  2203. //
  2204. if (pVc != pAtmEntry->pVcList)
  2205. {
  2206. pVc->AgingTime = FAST_VC_TIMEOUT;
  2207. }
  2208. TRACEOUT(LinkVcToAtmEntry);
  2209. }
  2210. BOOLEAN
  2211. AtmLaneUnlinkVcFromAtmEntry(
  2212. IN PATMLANE_VC pVc
  2213. )
  2214. /*++
  2215. Routine Description:
  2216. Unlink an ATMLANE VC from the ATM Entry it is linked to.
  2217. The caller is assumed to hold a lock for the VC structure.
  2218. Arguments:
  2219. pVc - Pointer to ATMLANE VC structure
  2220. Return Value:
  2221. TRUE if we found the VC linked to the list on the ATM entry, and unlinked it.
  2222. --*/
  2223. {
  2224. PATMLANE_ATM_ENTRY pAtmEntry;
  2225. PATMLANE_MAC_ENTRY pMacEntry, pNextMacEntry;
  2226. ULONG rc;
  2227. PATMLANE_VC * ppVc;
  2228. BOOLEAN Found;
  2229. DBGP((3, "UnlinkVcFromAtmEntry: pVc %x from pAtmEntry %x\n",
  2230. pVc, pVc->pAtmEntry));
  2231. pAtmEntry = pVc->pAtmEntry;
  2232. ASSERT(NULL_PATMLANE_ATM_ENTRY != pAtmEntry);
  2233. pVc->pAtmEntry = NULL_PATMLANE_ATM_ENTRY;
  2234. //
  2235. // Reacquire locks in the right order.
  2236. //
  2237. AtmLaneReferenceVc(pVc, "temp");
  2238. RELEASE_VC_LOCK(pVc);
  2239. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  2240. ACQUIRE_VC_LOCK(pVc);
  2241. //
  2242. // VC is either a server incoming uni-directional connection,
  2243. // where it is linked to the AtmEntry via pVcIncoming, or a
  2244. // bi-directional connection that is in the pVcList.
  2245. //
  2246. if (pAtmEntry->pVcIncoming == pVc)
  2247. {
  2248. //
  2249. // If server incoming VC just remove single entry
  2250. //
  2251. pAtmEntry->pVcIncoming = NULL_PATMLANE_VC;
  2252. Found = TRUE;
  2253. }
  2254. else
  2255. {
  2256. //
  2257. // Otherwise, find this VC in the ATM Entry's VC list
  2258. //
  2259. ppVc = &(pAtmEntry->pVcList);
  2260. while (*ppVc != NULL_PATMLANE_VC && *ppVc != pVc)
  2261. {
  2262. ppVc = &((*ppVc)->pNextVc);
  2263. }
  2264. //
  2265. // Remove this VC by making it's predecessor in the list
  2266. // point to the next VC in the list.
  2267. //
  2268. if (*ppVc == pVc)
  2269. {
  2270. *ppVc = pVc->pNextVc;
  2271. Found = TRUE;
  2272. }
  2273. else
  2274. {
  2275. Found = FALSE;
  2276. }
  2277. }
  2278. rc = AtmLaneDereferenceVc(pVc, "temp");
  2279. if (rc > 0)
  2280. {
  2281. RELEASE_VC_LOCK(pVc);
  2282. }
  2283. //
  2284. // If no more VC's in list mark AtmEntry as NOT connected
  2285. //
  2286. if (pAtmEntry->pVcList == NULL_PATMLANE_VC)
  2287. {
  2288. SET_FLAG(
  2289. pAtmEntry->Flags,
  2290. ATM_ENTRY_STATE_MASK,
  2291. ATM_ENTRY_VALID);
  2292. DBGP((2, "UnlinkVcFromAtmEntry: Aborting MAC Entries\n"));
  2293. pMacEntry = pAtmEntry->pMacEntryList;
  2294. //
  2295. // Take the MAC entry list out so that we can reference
  2296. // entries in this list in peace later on below.
  2297. //
  2298. pAtmEntry->pMacEntryList = NULL_PATMLANE_MAC_ENTRY;
  2299. //
  2300. // Let go of the ATM entry lock while we abort all
  2301. // the MAC entries in the list above. The ATM entry
  2302. // won't go away because of the VC reference still on it.
  2303. // The MAC entries in the list won't go away since they
  2304. // have the ATM entry reference on them (see UnlinkMacEntry..).
  2305. //
  2306. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2307. while (pMacEntry != NULL)
  2308. {
  2309. pNextMacEntry = pMacEntry->pNextToAtm;
  2310. //
  2311. // Now abort the MAC Entry. Put this MAC entry back
  2312. // on the ATM entry's list so that it gets handled
  2313. // appropriately by AbortMacEntry.
  2314. //
  2315. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2316. ACQUIRE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  2317. pMacEntry->pNextToAtm = pAtmEntry->pMacEntryList;
  2318. pAtmEntry->pMacEntryList = pMacEntry;
  2319. ASSERT(pMacEntry->pAtmEntry == pAtmEntry);
  2320. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  2321. AtmLaneAbortMacEntry(pMacEntry);
  2322. // MacEntry lock released in above
  2323. pMacEntry = pNextMacEntry;
  2324. }
  2325. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  2326. }
  2327. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "vc"); // VC reference
  2328. if (rc > 0)
  2329. {
  2330. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2331. }
  2332. //
  2333. // else the ATM Entry is gone!
  2334. //
  2335. //
  2336. // Acquire the VC lock again for the caller's sake
  2337. //
  2338. ACQUIRE_VC_LOCK(pVc);
  2339. return (Found);
  2340. }
  2341. BOOLEAN
  2342. AtmLaneUnlinkMacEntryFromAtmEntry(
  2343. IN PATMLANE_MAC_ENTRY pMacEntry
  2344. )
  2345. /*++
  2346. Routine Description:
  2347. Unlink a Mac Entry from the ATM Entry it is linked to.
  2348. Allow for the MAC entry to be absent in the ATM Entry's list.
  2349. The caller is assumed to hold a lock for the Mac Entry.
  2350. Arguments:
  2351. pMacEntry - Pointer to Mac Entry to be unlinked.
  2352. Return Value:
  2353. TRUE iff the MAC entry was found and unlinked.
  2354. --*/
  2355. {
  2356. PATMLANE_ATM_ENTRY pAtmEntry;
  2357. PATMLANE_MAC_ENTRY * ppNextMacEntry;
  2358. ULONG rc; // Ref Count on ATM Entry
  2359. BOOLEAN bFound = FALSE;
  2360. pAtmEntry = pMacEntry->pAtmEntry;
  2361. ASSERT(pAtmEntry != NULL_PATMLANE_ATM_ENTRY);
  2362. DBGP((2, "%d UnlinkMacEntryFromAtmEntry: MacEntry %x AtmEntry %x\n",
  2363. pAtmEntry->pElan->ElanNumber,
  2364. pMacEntry, pMacEntry->pAtmEntry));
  2365. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  2366. //
  2367. // Locate the position of this MAC Entry in the ATM Entry's list.
  2368. //
  2369. ppNextMacEntry = &(pAtmEntry->pMacEntryList);
  2370. while (*ppNextMacEntry != NULL_PATMLANE_MAC_ENTRY)
  2371. {
  2372. if (*ppNextMacEntry == pMacEntry)
  2373. {
  2374. //
  2375. // Found it.
  2376. //
  2377. bFound = TRUE;
  2378. break;
  2379. }
  2380. else
  2381. {
  2382. ppNextMacEntry = &((*ppNextMacEntry)->pNextToAtm);
  2383. }
  2384. }
  2385. if (bFound)
  2386. {
  2387. //
  2388. // Make the predecessor point to the next entry.
  2389. //
  2390. *ppNextMacEntry = pMacEntry->pNextToAtm;
  2391. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "mac"); // MAC entry reference
  2392. if (rc != 0)
  2393. {
  2394. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2395. }
  2396. //
  2397. // else the ATM Entry is gone.
  2398. //
  2399. }
  2400. else
  2401. {
  2402. //
  2403. // The entry wasn't found.
  2404. //
  2405. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2406. }
  2407. return bFound;
  2408. }
  2409. VOID
  2410. AtmLaneStartTimer(
  2411. IN PATMLANE_ELAN pElan,
  2412. IN PATMLANE_TIMER pTimer,
  2413. IN ATMLANE_TIMEOUT_HANDLER TimeoutHandler,
  2414. IN ULONG SecondsToGo,
  2415. IN PVOID ContextPtr
  2416. )
  2417. /*++
  2418. Routine Description:
  2419. Start an ATMLANE timer. Based on the length (SecondsToGo) of the
  2420. timer, we decide on whether to insert it in the short duration
  2421. timer list or in the long duration timer list in the Elan
  2422. structure.
  2423. NOTE: the caller is assumed to either hold a lock to the structure
  2424. that contains the timer, or ensure that it is safe to access the
  2425. timer structure.
  2426. Arguments:
  2427. pElan - Pointer to the ATMLANE Elan
  2428. pTimer - Pointer to ATMLANE Timer structure
  2429. TimeoutHandler - Handler function to be called if this timer expires
  2430. SecondsToGo - When does this timer go off?
  2431. ContextPtr - To be passed to timeout handler if this timer expires
  2432. ContextValue - To be passed to timeout handler if this timer expires
  2433. Return Value:
  2434. None
  2435. --*/
  2436. {
  2437. PATMLANE_TIMER_LIST pTimerList; // List to which this timer goes
  2438. PATMLANE_TIMER pTimerListHead; // Head of above list
  2439. ULONG Index; // Into timer wheel
  2440. ULONG TicksToGo;
  2441. INT i;
  2442. TRACEIN(StartTimer);
  2443. STRUCT_ASSERT(pElan, atmlane_elan);
  2444. DBGP((5,
  2445. "StartTimer: pElan %x, Secs %d, Handler %x, Ctxtp %x, pTimer %x\n",
  2446. pElan, SecondsToGo, TimeoutHandler, ContextPtr, pTimer));
  2447. if (IS_TIMER_ACTIVE(pTimer))
  2448. {
  2449. DBGP((5,
  2450. "Start timer: pTimer %x: is active (list %x, hndlr %x), stopping it\n",
  2451. pTimer, pTimer->pTimerList, pTimer->TimeoutHandler));
  2452. AtmLaneStopTimer(pTimer, pElan);
  2453. }
  2454. ACQUIRE_ELAN_TIMER_LOCK(pElan);
  2455. ASSERT(!IS_TIMER_ACTIVE(pTimer));
  2456. //
  2457. // Find the list to which this timer should go, and the
  2458. // offset (TicksToGo)
  2459. //
  2460. Try_Again:
  2461. for (i = 0; i < ALT_CLASS_MAX; i++)
  2462. {
  2463. pTimerList = &(pElan->TimerList[i]);
  2464. if (SecondsToGo <= pTimerList->MaxTimer)
  2465. {
  2466. //
  2467. // Found it.
  2468. //
  2469. TicksToGo = SecondsToGo / (pTimerList->TimerPeriod);
  2470. if (TicksToGo >= 1)
  2471. TicksToGo--;
  2472. break;
  2473. }
  2474. }
  2475. if (i == ALT_CLASS_MAX)
  2476. {
  2477. //
  2478. // Force this timer down!
  2479. //
  2480. SecondsToGo = pTimerList->MaxTimer;
  2481. goto Try_Again;
  2482. }
  2483. //
  2484. // Find the position in the list for this timer
  2485. //
  2486. Index = pTimerList->CurrentTick + TicksToGo;
  2487. if (Index >= pTimerList->TimerListSize)
  2488. {
  2489. Index -= pTimerList->TimerListSize;
  2490. }
  2491. ASSERT(Index < pTimerList->TimerListSize);
  2492. pTimerListHead = &(pTimerList->pTimers[Index]);
  2493. //
  2494. // Fill in the timer
  2495. //
  2496. pTimer->pTimerList = pTimerList;
  2497. pTimer->LastRefreshTime = pTimerList->CurrentTick;
  2498. pTimer->Duration = TicksToGo;
  2499. pTimer->TimeoutHandler = TimeoutHandler;
  2500. pTimer->ContextPtr = ContextPtr;
  2501. //
  2502. // Insert this timer in the "ticking" list
  2503. //
  2504. pTimer->pPrevTimer = pTimerListHead;
  2505. pTimer->pNextTimer = pTimerListHead->pNextTimer;
  2506. if (pTimer->pNextTimer != NULL_PATMLANE_TIMER)
  2507. {
  2508. pTimer->pNextTimer->pPrevTimer = pTimer;
  2509. }
  2510. pTimerListHead->pNextTimer = pTimer;
  2511. //
  2512. // Start off the system tick timer if necessary.
  2513. //
  2514. pTimerList->TimerCount++;
  2515. if (pTimerList->TimerCount == 1)
  2516. {
  2517. DBGP((5,
  2518. "StartTimer: Starting system timer %x, class %d on Elan %x\n",
  2519. &(pTimerList->NdisTimer), i, pElan));
  2520. START_SYSTEM_TIMER(&(pTimerList->NdisTimer), pTimerList->TimerPeriod);
  2521. }
  2522. RELEASE_ELAN_TIMER_LOCK(pElan);
  2523. //
  2524. // We're done
  2525. //
  2526. DBGP((5,
  2527. "Started timer %x, Elan %x, Secs %d, Index %d, Head %x\n",
  2528. pTimer,
  2529. pElan,
  2530. SecondsToGo,
  2531. Index,
  2532. pTimerListHead));
  2533. TRACEOUT(StartTimer);
  2534. return;
  2535. }
  2536. BOOLEAN
  2537. AtmLaneStopTimer(
  2538. IN PATMLANE_TIMER pTimer,
  2539. IN PATMLANE_ELAN pElan
  2540. )
  2541. /*++
  2542. Routine Description:
  2543. Stop an ATMLANE timer, if it is running. We remove this timer from
  2544. the active timer list and mark it so that we know it's not running.
  2545. NOTE: the caller is assumed to either hold a lock to the structure
  2546. that contains the timer, or ensure that it is safe to access the
  2547. timer structure.
  2548. SIDE EFFECT: If we happen to stop the last timer (of this "duration") on
  2549. the Interface, we also stop the appropriate Tick function.
  2550. Arguments:
  2551. pTimer - Pointer to ATMLANE Timer structure
  2552. pElan - Pointer to interface to which the timer belongs
  2553. Return Value:
  2554. TRUE if the timer was running, FALSE otherwise.
  2555. --*/
  2556. {
  2557. PATMLANE_TIMER_LIST pTimerList; // Timer List to which this timer belongs
  2558. BOOLEAN WasRunning;
  2559. TRACEIN(StopTimer);
  2560. DBGP((5,
  2561. "Stopping Timer %x, Elan %x, List %x, Prev %x, Next %x\n",
  2562. pTimer,
  2563. pElan,
  2564. pTimer->pTimerList,
  2565. pTimer->pPrevTimer,
  2566. pTimer->pNextTimer));
  2567. ACQUIRE_ELAN_TIMER_LOCK(pElan);
  2568. if (IS_TIMER_ACTIVE(pTimer))
  2569. {
  2570. WasRunning = TRUE;
  2571. //
  2572. // Unlink timer from the list
  2573. //
  2574. ASSERT(pTimer->pPrevTimer); // the list head always exists
  2575. pTimer->pPrevTimer->pNextTimer = pTimer->pNextTimer;
  2576. if (pTimer->pNextTimer)
  2577. {
  2578. pTimer->pNextTimer->pPrevTimer = pTimer->pPrevTimer;
  2579. }
  2580. pTimer->pNextTimer = pTimer->pPrevTimer = NULL_PATMLANE_TIMER;
  2581. //
  2582. // Update timer count on Interface, for this class of timers
  2583. //
  2584. pTimerList = pTimer->pTimerList;
  2585. pTimerList->TimerCount--;
  2586. //
  2587. // If all timers of this class are gone, stop the system tick timer
  2588. // for this class
  2589. //
  2590. if (pTimerList->TimerCount == 0)
  2591. {
  2592. DBGP((5,
  2593. "Stopping system timer %x, List %x, Elan %x\n",
  2594. &(pTimerList->NdisTimer),
  2595. pTimerList,
  2596. pElan));
  2597. pTimerList->CurrentTick = 0;
  2598. STOP_SYSTEM_TIMER(&(pTimerList->NdisTimer));
  2599. }
  2600. //
  2601. // Mark stopped timer as not active
  2602. //
  2603. pTimer->pTimerList = (PATMLANE_TIMER_LIST)NULL;
  2604. }
  2605. else
  2606. {
  2607. WasRunning = FALSE;
  2608. }
  2609. RELEASE_ELAN_TIMER_LOCK(pElan);
  2610. TRACEOUT(StopTimer);
  2611. return (WasRunning);
  2612. }
  2613. VOID
  2614. AtmLaneRefreshTimer(
  2615. IN PATMLANE_TIMER pTimer
  2616. )
  2617. /*++
  2618. Routine Description:
  2619. Refresh a timer that is already running.
  2620. NOTE: The caller is assumed to possess a lock protecting the
  2621. timer structure (i.e. to the structure containing the timer).
  2622. NOTE: We don't acquire the IF Timer Lock here, to optimize
  2623. the refresh operation. So, _within_ the confines of this routine,
  2624. the tick handler may fire, and expire this timer. The only care
  2625. that we take here is to make sure that we don't crash if the
  2626. timer expires while we access the Timer list.
  2627. Arguments:
  2628. pTimer - Pointer to ATMLANE_TIMER structure
  2629. Return Value:
  2630. None
  2631. --*/
  2632. {
  2633. PATMLANE_TIMER_LIST pTimerList;
  2634. TRACEIN(RefreshTimer);
  2635. if ((pTimerList = pTimer->pTimerList) != (PATMLANE_TIMER_LIST)NULL)
  2636. {
  2637. pTimer->LastRefreshTime = pTimerList->CurrentTick;
  2638. }
  2639. else
  2640. {
  2641. DBGP((5,
  2642. "RefreshTimer: pTimer %x not active: Hnd %x, Ctxtp %x\n",
  2643. pTimer,
  2644. pTimer->TimeoutHandler,
  2645. pTimer->ContextPtr
  2646. ));
  2647. }
  2648. DBGP((5,
  2649. "Refreshed timer %x, List %x, hnd %x, Ctxtp %x, LastRefresh %d\n",
  2650. pTimer,
  2651. pTimer->pTimerList,
  2652. pTimer->TimeoutHandler,
  2653. pTimer->ContextPtr,
  2654. pTimer->LastRefreshTime));
  2655. TRACEOUT(RefreshTimer);
  2656. return;
  2657. }
  2658. VOID
  2659. AtmLaneTickHandler(
  2660. IN PVOID SystemSpecific1,
  2661. IN PVOID Context,
  2662. IN PVOID SystemSpecific2,
  2663. IN PVOID SystemSpecific3
  2664. )
  2665. /*++
  2666. Routine Description:
  2667. This is the handler we register with the system for processing each
  2668. Timer List. This is called every "tick" seconds, where "tick" is
  2669. determined by the granularity of the timer type.
  2670. Arguments:
  2671. Context - Actually a pointer to a Timer List structure
  2672. SystemSpecific[1-3] - Not used
  2673. Return Value:
  2674. None
  2675. --*/
  2676. {
  2677. PATMLANE_ELAN pElan;
  2678. PATMLANE_TIMER_LIST pTimerList;
  2679. PATMLANE_TIMER pExpiredTimer; // Start of list of expired timers
  2680. PATMLANE_TIMER pNextTimer; // for walking above list
  2681. PATMLANE_TIMER pTimer; // temp, for walking timer list
  2682. PATMLANE_TIMER pPrevExpiredTimer; // for creating expired timer list
  2683. ULONG Index; // into the timer wheel
  2684. ULONG NewIndex; // for refreshed timers
  2685. TRACEIN(TickHandler);
  2686. pTimerList = (PATMLANE_TIMER_LIST)Context;
  2687. STRUCT_ASSERT(pTimerList, atmlane_timerlist);
  2688. pElan = (PATMLANE_ELAN)pTimerList->ListContext;
  2689. STRUCT_ASSERT(pElan, atmlane_elan);
  2690. DBGP((5,
  2691. "Tick: pElan %x, List %x, Count %d\n",
  2692. pElan, pTimerList, pTimerList->TimerCount));
  2693. pExpiredTimer = NULL_PATMLANE_TIMER;
  2694. ACQUIRE_ELAN_TIMER_LOCK(pElan);
  2695. if (ELAN_STATE_OPERATIONAL == pElan->AdminState)
  2696. {
  2697. //
  2698. // Pick up the list of timers scheduled to have expired at the
  2699. // current tick. Some of these might have been refreshed.
  2700. //
  2701. Index = pTimerList->CurrentTick;
  2702. pExpiredTimer = (pTimerList->pTimers[Index]).pNextTimer;
  2703. (pTimerList->pTimers[Index]).pNextTimer = NULL_PATMLANE_TIMER;
  2704. //
  2705. // Go through the list of timers scheduled to expire at this tick.
  2706. // Prepare a list of expired timers, using the pNextExpiredTimer
  2707. // link to chain them together.
  2708. //
  2709. // Some timers may have been refreshed, in which case we reinsert
  2710. // them in the active timer list.
  2711. //
  2712. pPrevExpiredTimer = NULL_PATMLANE_TIMER;
  2713. for (pTimer = pExpiredTimer;
  2714. pTimer != NULL_PATMLANE_TIMER;
  2715. pTimer = pNextTimer)
  2716. {
  2717. //
  2718. // Save a pointer to the next timer, for the next iteration.
  2719. //
  2720. pNextTimer = pTimer->pNextTimer;
  2721. DBGP((5,
  2722. "Tick Handler: pElan %x, looking at timer %x, next %x\n",
  2723. pElan, pTimer, pNextTimer));
  2724. //
  2725. // Find out when this timer should actually expire.
  2726. //
  2727. NewIndex = pTimer->LastRefreshTime + pTimer->Duration;
  2728. if (NewIndex >= pTimerList->TimerListSize)
  2729. {
  2730. NewIndex -= pTimerList->TimerListSize;
  2731. }
  2732. //
  2733. // Check if we are currently at the point of expiry.
  2734. //
  2735. if (NewIndex != Index)
  2736. {
  2737. //
  2738. // This timer still has some way to go, so put it back.
  2739. //
  2740. DBGP((5,
  2741. "Tick: Reinserting Timer %x: Hnd %x, Durn %d, Ind %d, NewInd %d\n",
  2742. pTimer, pTimer->TimeoutHandler, pTimer->Duration, Index, NewIndex));
  2743. //
  2744. // Remove it from the expired timer list. Note that we only
  2745. // need to update the forward (pNextExpiredTimer) links.
  2746. //
  2747. if (pPrevExpiredTimer == NULL_PATMLANE_TIMER)
  2748. {
  2749. pExpiredTimer = pNextTimer;
  2750. }
  2751. else
  2752. {
  2753. pPrevExpiredTimer->pNextExpiredTimer = pNextTimer;
  2754. }
  2755. //
  2756. // And insert it back into the running timer list.
  2757. //
  2758. pTimer->pNextTimer = (pTimerList->pTimers[NewIndex]).pNextTimer;
  2759. if (pTimer->pNextTimer != NULL_PATMLANE_TIMER)
  2760. {
  2761. pTimer->pNextTimer->pPrevTimer = pTimer;
  2762. }
  2763. pTimer->pPrevTimer = &(pTimerList->pTimers[NewIndex]);
  2764. (pTimerList->pTimers[NewIndex]).pNextTimer = pTimer;
  2765. }
  2766. else
  2767. {
  2768. //
  2769. // This one has expired. Keep it in the expired timer list.
  2770. //
  2771. pTimer->pNextExpiredTimer = pNextTimer;
  2772. if (pPrevExpiredTimer == NULL_PATMLANE_TIMER)
  2773. {
  2774. pExpiredTimer = pTimer;
  2775. }
  2776. pPrevExpiredTimer = pTimer;
  2777. //
  2778. // Mark it as inactive.
  2779. //
  2780. ASSERT(pTimer->pTimerList == pTimerList);
  2781. pTimer->pTimerList = (PATMLANE_TIMER_LIST)NULL;
  2782. //
  2783. // Update the active timer count.
  2784. //
  2785. pTimerList->TimerCount--;
  2786. }
  2787. }
  2788. //
  2789. // Update current tick index in readiness for the next tick.
  2790. //
  2791. if (++Index == pTimerList->TimerListSize)
  2792. {
  2793. pTimerList->CurrentTick = 0;
  2794. }
  2795. else
  2796. {
  2797. pTimerList->CurrentTick = Index;
  2798. }
  2799. if (pTimerList->TimerCount > 0)
  2800. {
  2801. //
  2802. // Re-arm the tick handler
  2803. //
  2804. DBGP((5,
  2805. "Tick[%d]: Starting system timer %x, on Elan %x\n",
  2806. pTimerList->CurrentTick, &(pTimerList->NdisTimer), pElan));
  2807. START_SYSTEM_TIMER(&(pTimerList->NdisTimer), pTimerList->TimerPeriod);
  2808. }
  2809. else
  2810. {
  2811. pTimerList->CurrentTick = 0;
  2812. }
  2813. }
  2814. RELEASE_ELAN_TIMER_LOCK(pElan);
  2815. //
  2816. // Now pExpiredTimer is a list of expired timers.
  2817. // Walk through the list and call the timeout handlers
  2818. // for each timer.
  2819. //
  2820. while (pExpiredTimer != NULL_PATMLANE_TIMER)
  2821. {
  2822. pNextTimer = pExpiredTimer->pNextExpiredTimer;
  2823. DBGP((5,
  2824. "Expired timer %x: handler %x, next %x\n",
  2825. pExpiredTimer, pExpiredTimer->TimeoutHandler, pNextTimer));
  2826. (*(pExpiredTimer->TimeoutHandler))(
  2827. pExpiredTimer,
  2828. pExpiredTimer->ContextPtr
  2829. );
  2830. pExpiredTimer = pNextTimer;
  2831. }
  2832. TRACEOUT(TickHandler);
  2833. return;
  2834. }
  2835. ULONG
  2836. AtmLaneSystemTimeMs(void)
  2837. /*++
  2838. Routine Description:
  2839. This routine get the current system clock tick value and
  2840. returns this value converted to milliseconds.
  2841. Arguments:
  2842. None
  2843. Return Value:
  2844. The system clock value in milliseconds.
  2845. --*/
  2846. {
  2847. #if BINARY_COMPATIBLE
  2848. LARGE_INTEGER SystemTime;
  2849. NdisGetCurrentSystemTime(&SystemTime);
  2850. // comes back in 100 nanosecond units, we want milliseconds
  2851. SystemTime.QuadPart /= 10000;
  2852. return SystemTime.LowPart;
  2853. #else
  2854. static LARGE_INTEGER Frequency = {0L,0L};
  2855. LARGE_INTEGER SystemTime;
  2856. SystemTime = KeQueryPerformanceCounter(Frequency.LowPart == 0?&Frequency:NULL);
  2857. SystemTime.QuadPart = SystemTime.QuadPart * 1000000 / Frequency.QuadPart;
  2858. return SystemTime.LowPart;
  2859. #endif
  2860. }
  2861. VOID
  2862. AtmLaneBitSwapMacAddr(
  2863. IN OUT PUCHAR ap
  2864. )
  2865. /*++
  2866. Routine Description:
  2867. This routine swaps (reverses) the bits in each individual
  2868. byte of a MAC Address. Use for Token Ring MAC addresses.
  2869. Arguments:
  2870. ap - Pointer to array of bytes to bitswap in-place.
  2871. Return Value:
  2872. None
  2873. --*/
  2874. {
  2875. int i;
  2876. unsigned int x;
  2877. for (i = 0; i != 6; i++)
  2878. {
  2879. x = ap[i];
  2880. x = ((x & 0xaau) >> 1) | ((x & 0x55u) << 1);
  2881. x = ((x & 0xccu) >> 2) | ((x & 0x33u) << 2);
  2882. x = ((x & 0xf0u) >> 4) | ((x & 0x0fu) << 4);
  2883. ap[i] = (UCHAR)x;
  2884. }
  2885. }
  2886. BOOLEAN
  2887. AtmLaneCopyUnicodeString(
  2888. IN OUT PUNICODE_STRING pDestString,
  2889. IN OUT PUNICODE_STRING pSrcString,
  2890. IN BOOLEAN AllocDest,
  2891. IN BOOLEAN ConvertToUpper
  2892. )
  2893. {
  2894. /*++
  2895. Routine Description:
  2896. This routine optionally allocates space in the destination string
  2897. for the source string plus a terminating null. It
  2898. copies the source string to the destination string and
  2899. terminates the destination string with a null.
  2900. -*/
  2901. BOOLEAN Result = TRUE;
  2902. TRACEIN(CopyUnicodeString);
  2903. do
  2904. {
  2905. // Alloc space for the destination string if requested
  2906. if (AllocDest)
  2907. {
  2908. ALLOC_MEM(&(pDestString->Buffer), pSrcString->Length + sizeof(WCHAR));
  2909. if (NULL == pDestString->Buffer)
  2910. {
  2911. Result = FALSE;
  2912. break;
  2913. }
  2914. // Init lengths in dest string
  2915. pDestString->Length = 0;
  2916. pDestString->MaximumLength = pSrcString->Length + sizeof(WCHAR);
  2917. }
  2918. // Copy the string
  2919. if (ConvertToUpper)
  2920. {
  2921. #ifndef LANE_WIN98
  2922. (VOID)NdisUpcaseUnicodeString(pDestString, pSrcString);
  2923. #else
  2924. memcpy(pDestString->Buffer, pSrcString->Buffer, pSrcString->Length);
  2925. #endif // LANE_WIN98
  2926. }
  2927. else
  2928. {
  2929. RtlCopyUnicodeString(pDestString, pSrcString);
  2930. }
  2931. // Null terminate the dest string
  2932. if (pDestString->Length < pDestString->MaximumLength)
  2933. {
  2934. pDestString->Buffer[pDestString->Length/sizeof(WCHAR)] = ((WCHAR)0);
  2935. }
  2936. else
  2937. {
  2938. pDestString->Buffer[(pDestString->MaximumLength - sizeof(WCHAR))/sizeof(WCHAR)] =
  2939. ((WCHAR)0);
  2940. }
  2941. } while (FALSE);
  2942. TRACEOUT(CopyUnicodeString);
  2943. return Result;
  2944. }
  2945. PWSTR
  2946. AtmLaneStrTok(
  2947. IN PWSTR StrToken,
  2948. IN WCHAR ChrDelim,
  2949. OUT PUSHORT pStrLength
  2950. )
  2951. {
  2952. static PWSTR StrSave = NULL;
  2953. USHORT StrLength = 0;
  2954. PWSTR StrOut = NULL;
  2955. TRACEIN(StrTok);
  2956. do
  2957. {
  2958. // check for bad input
  2959. if ((StrToken == NULL && StrSave == NULL) ||
  2960. ChrDelim == ((WCHAR)0))
  2961. {
  2962. break;
  2963. }
  2964. // if starting with new string, reset StrSave
  2965. if (StrToken != NULL)
  2966. {
  2967. StrSave = StrToken;
  2968. }
  2969. // token starts at start of current string
  2970. StrOut = StrSave;
  2971. // walk string until delimiter or NULL
  2972. while (*StrSave != ChrDelim && *StrSave != ((WCHAR)0))
  2973. {
  2974. StrSave++;
  2975. StrLength++;
  2976. }
  2977. // If we found a delimiter then NULL it out and
  2978. // move saved ptr to next token to setup for next
  2979. // call on same string.
  2980. if (*StrSave == ChrDelim)
  2981. {
  2982. *StrSave = ((WCHAR)0);
  2983. StrSave++;
  2984. }
  2985. // If pointing at empty string then return null ptr
  2986. if (*StrOut == ((WCHAR)0))
  2987. {
  2988. StrOut = NULL;
  2989. }
  2990. } while (FALSE);
  2991. TRACEOUT(StrTok);
  2992. *pStrLength = StrLength * sizeof(WCHAR);
  2993. return StrOut;
  2994. }