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.

5627 lines
113 KiB

  1. /*++
  2. Copyright (c) 1997 FORE Systems, Inc.
  3. Copyright (c) 1997 Microsoft Corporation
  4. Module Name:
  5. elanproc.c
  6. Abstract:
  7. Revision History:
  8. Notes:
  9. --*/
  10. #include <precomp.h>
  11. #pragma hdrstop
  12. VOID
  13. AtmLaneEventHandler(
  14. IN PNDIS_WORK_ITEM pWorkItem,
  15. IN PVOID pContext
  16. )
  17. /*++
  18. Routine Description:
  19. Elan state machine event handler.
  20. Arguments:
  21. pContext - should be pointer to ATMLANE Elan
  22. Return Value:
  23. None
  24. --*/
  25. {
  26. PATMLANE_ELAN pElan;
  27. PATMLANE_MAC_ENTRY pMacEntry;
  28. PATMLANE_EVENT pEvent;
  29. ULONG Event;
  30. NDIS_STATUS EventStatus;
  31. NDIS_STATUS Status;
  32. NDIS_HANDLE AdapterHandle;
  33. ULONG rc;
  34. BOOLEAN WasCancelled;
  35. PLIST_ENTRY p;
  36. #if DEBUG_IRQL
  37. KIRQL EntryIrql;
  38. #endif
  39. #if DEBUG_IRQL
  40. GET_ENTRY_IRQL(EntryIrql);
  41. ASSERT(EntryIrql == PASSIVE_LEVEL);
  42. #endif
  43. TRACEIN(EventHandler);
  44. // Get the pointer to the Elan
  45. pElan = (PATMLANE_ELAN)pContext;
  46. STRUCT_ASSERT(pElan, atmlane_elan);
  47. // Lock the Elan
  48. ACQUIRE_ELAN_LOCK(pElan);
  49. // Release the timer reference
  50. rc = AtmLaneDereferenceElan(pElan, "eventtimer");
  51. ASSERT(rc > 0);
  52. pElan->Flags &= ~ ELAN_EVENT_WORK_ITEM_SET;
  53. // Remove the event at the head of the queue
  54. pEvent = AtmLaneDequeueElanEvent(pElan);
  55. if (pEvent == NULL)
  56. {
  57. RELEASE_ELAN_LOCK(pElan);
  58. CHECK_EXIT_IRQL(EntryIrql);
  59. return;
  60. }
  61. // Save locally the important stuff
  62. Event = pEvent->Event;
  63. EventStatus = pEvent->EventStatus;
  64. // Free the event struct
  65. FREE_MEM(pEvent);
  66. // Check if the ELAN is gone.
  67. if (rc == 1)
  68. {
  69. DBGP((0, "EventHandler: ELAN %x is gone!\n", pElan));
  70. CHECK_EXIT_IRQL(EntryIrql);
  71. return;
  72. }
  73. // If queue isn't empty schedule next event handler
  74. if (!IsListEmpty(&pElan->EventQueue))
  75. {
  76. NDIS_STATUS NdisStatus;
  77. AtmLaneReferenceElan(pElan, "workitemevent");
  78. pElan->Flags |= ELAN_EVENT_WORK_ITEM_SET;
  79. p = pElan->EventQueue.Flink;
  80. pEvent = CONTAINING_RECORD(p, ATMLANE_EVENT, Link);
  81. NdisInitializeWorkItem(&pElan->EventWorkItem, AtmLaneEventHandler, pElan);
  82. DBGP((0, " %d EventHandler: Multiple events queued, pElan %x, State %d, Flags %x, Ref %d, processing %d, queued event %d!\n",
  83. pElan->ElanNumber, pElan, pElan->State, pElan->Flags, pElan->RefCount, Event, pEvent->Event));
  84. NdisStatus = NdisScheduleWorkItem(&pElan->EventWorkItem);
  85. ASSERT(NdisStatus == NDIS_STATUS_SUCCESS);
  86. }
  87. switch (pElan->State)
  88. {
  89. //
  90. // INIT STATE ---------------------------------------------------
  91. //
  92. case ELAN_STATE_INIT:
  93. switch (Event)
  94. {
  95. case ELAN_EVENT_START:
  96. DBGP((1, "%d INIT - START\n", pElan->ElanNumber));
  97. //
  98. // Open Call Manager and get ATM address
  99. //
  100. //
  101. // Make sure that ShutdownElan does not
  102. // pre-empt us here.
  103. //
  104. pElan->Flags |= ELAN_OPENING_AF;
  105. AtmLaneReferenceElan(pElan, "openaf");
  106. INIT_BLOCK_STRUCT(&pElan->AfBlock);
  107. RELEASE_ELAN_LOCK(pElan);
  108. Status = AtmLaneOpenCallMgr(pElan);
  109. if (NDIS_STATUS_SUCCESS == Status)
  110. {
  111. AtmLaneGetAtmAddress(pElan);
  112. }
  113. ACQUIRE_ELAN_LOCK(pElan);
  114. rc = AtmLaneDereferenceElan(pElan, "openaf");
  115. if (rc != 0)
  116. {
  117. pElan->Flags &= ~ELAN_OPENING_AF;
  118. SIGNAL_BLOCK_STRUCT(&pElan->AfBlock, NDIS_STATUS_SUCCESS);
  119. RELEASE_ELAN_LOCK(pElan);
  120. }
  121. break;
  122. case ELAN_EVENT_NEW_ATM_ADDRESS:
  123. DBGP((1, "%d INIT - NEW ATM ADDRESS\n", pElan->ElanNumber));
  124. if (!pElan->CfgUseLecs)
  125. {
  126. //
  127. // If configured to NOT use an LECS then
  128. // set ELAN vars from registry config vars
  129. // (normally established in ConfigResponseHandler)
  130. // and advance to the LES CONNECT Phase.
  131. pElan->LanType = (UCHAR)pElan->CfgLanType;
  132. if (pElan->LanType == LANE_LANTYPE_UNSPEC)
  133. {
  134. pElan->LanType = LANE_LANTYPE_ETH;
  135. }
  136. pElan->MaxFrameSizeCode = (UCHAR)pElan->CfgMaxFrameSizeCode;
  137. if (pElan->MaxFrameSizeCode == LANE_MAXFRAMESIZE_CODE_UNSPEC)
  138. {
  139. pElan->MaxFrameSizeCode = LANE_MAXFRAMESIZE_CODE_1516;
  140. }
  141. switch (pElan->MaxFrameSizeCode)
  142. {
  143. case LANE_MAXFRAMESIZE_CODE_18190:
  144. pElan->MaxFrameSize = 18190;
  145. break;
  146. case LANE_MAXFRAMESIZE_CODE_9234:
  147. pElan->MaxFrameSize = 9234;
  148. break;
  149. case LANE_MAXFRAMESIZE_CODE_4544:
  150. pElan->MaxFrameSize = 4544;
  151. break;
  152. case LANE_MAXFRAMESIZE_CODE_1516:
  153. case LANE_MAXFRAMESIZE_CODE_UNSPEC:
  154. default:
  155. pElan->MaxFrameSize = 1516;
  156. break;
  157. }
  158. if (pElan->LanType == LANE_LANTYPE_ETH)
  159. {
  160. pElan->MinFrameSize = LANE_MIN_ETHPACKET;
  161. }
  162. else
  163. {
  164. pElan->MinFrameSize = LANE_MIN_TRPACKET;
  165. }
  166. NdisMoveMemory(
  167. &pElan->LesAddress,
  168. &pElan->CfgLesAddress,
  169. sizeof(ATM_ADDRESS));
  170. pElan->State = ELAN_STATE_LES_CONNECT;
  171. pElan->RetriesLeft = 4;
  172. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_START, 0);
  173. RELEASE_ELAN_LOCK(pElan);
  174. }
  175. else
  176. {
  177. //
  178. // If configured to NOT discover the LECS then
  179. // advance to the LECS CONNECT CFG state.
  180. //
  181. if (!pElan->CfgDiscoverLecs)
  182. {
  183. pElan->State = ELAN_STATE_LECS_CONNECT_CFG;
  184. pElan->RetriesLeft = 4;
  185. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_START, 0);
  186. RELEASE_ELAN_LOCK(pElan);
  187. }
  188. else
  189. {
  190. //
  191. // Otherwise, advance to LECS CONNECT ILMI state
  192. //
  193. pElan->State = ELAN_STATE_LECS_CONNECT_ILMI;
  194. pElan->RetriesLeft = 4;
  195. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_START, 0);
  196. RELEASE_ELAN_LOCK(pElan);
  197. }
  198. }
  199. break;
  200. case ELAN_EVENT_RESTART:
  201. DBGP((1, "%d INIT - RESTART\n", pElan->ElanNumber));
  202. AtmLaneShutdownElan(pElan, TRUE);
  203. break;
  204. case ELAN_EVENT_STOP:
  205. DBGP((1, "%d INIT - STOP\n", pElan->ElanNumber));
  206. AtmLaneShutdownElan(pElan, FALSE);
  207. break;
  208. default:
  209. DBGP((0, "%d INIT - UNEXPECTED EVENT %d\n",
  210. pElan->ElanNumber, Event));
  211. RELEASE_ELAN_LOCK(pElan);
  212. break;
  213. }
  214. break;
  215. //
  216. // LECS CONNECT ILMI STATE -------------------------------------------
  217. //
  218. case ELAN_STATE_LECS_CONNECT_ILMI:
  219. switch (Event)
  220. {
  221. case ELAN_EVENT_START:
  222. DBGP((1, "%d LECS CONNECT ILMI - START\n", pElan->ElanNumber));
  223. SET_FLAG(
  224. pElan->Flags,
  225. ELAN_LECS_MASK,
  226. ELAN_LECS_ILMI
  227. );
  228. RELEASE_ELAN_LOCK(pElan);
  229. AtmLaneGetLecsIlmi(pElan);
  230. break;
  231. case ELAN_EVENT_GOT_ILMI_LECS_ADDR:
  232. DBGP((1, "%d LECS CONNECT ILMI - GOT ILMI LECS ADDR (%x)\n",
  233. pElan->ElanNumber, EventStatus));
  234. if (EventStatus == NDIS_STATUS_SUCCESS)
  235. {
  236. RELEASE_ELAN_LOCK(pElan);
  237. //
  238. // Attempt to connect to the LECS
  239. //
  240. AtmLaneConnectToServer(pElan, ATM_ENTRY_TYPE_LECS, FALSE);
  241. }
  242. else
  243. {
  244. if (EventStatus == NDIS_STATUS_INTERFACE_DOWN)
  245. {
  246. //
  247. // Wait for a while for the interface to come up.
  248. //
  249. DBGP((0, "%d LECS CONNECT ILMI - Interface down\n",
  250. pElan->ElanNumber));
  251. AtmLaneQueueElanEventAfterDelay(pElan, ELAN_EVENT_START, NDIS_STATUS_SUCCESS, 2*1000);
  252. }
  253. else
  254. {
  255. //
  256. // Otherwise advance to LECS CONNECT WKA state
  257. //
  258. pElan->State = ELAN_STATE_LECS_CONNECT_WKA;
  259. pElan->RetriesLeft = 4;
  260. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_START, 0);
  261. }
  262. RELEASE_ELAN_LOCK(pElan);
  263. }
  264. break;
  265. case ELAN_EVENT_SVR_CALL_COMPLETE:
  266. DBGP((1, "%d LECS CONNECT ILMI - LECS CALL COMPLETE (%x)\n",
  267. pElan->ElanNumber, EventStatus));
  268. switch (EventStatus)
  269. {
  270. case NDIS_STATUS_SUCCESS:
  271. //
  272. // advance to the CONFIGURE Phase
  273. //
  274. pElan->State = ELAN_STATE_CONFIGURE;
  275. pElan->RetriesLeft = 4;
  276. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_START, 0);
  277. RELEASE_ELAN_LOCK(pElan);
  278. break;
  279. case NDIS_STATUS_INTERFACE_DOWN:
  280. if (pElan->RetriesLeft--)
  281. {
  282. //
  283. // retry in a little while
  284. //
  285. AtmLaneQueueElanEventAfterDelay(
  286. pElan,
  287. ELAN_EVENT_GOT_ILMI_LECS_ADDR,
  288. NDIS_STATUS_SUCCESS,
  289. 2*1000);
  290. RELEASE_ELAN_LOCK(pElan);
  291. }
  292. else
  293. {
  294. //
  295. // Restart the Elan
  296. //
  297. AtmLaneShutdownElan(pElan, TRUE);
  298. //
  299. // lock released in above
  300. //
  301. }
  302. break;
  303. default:
  304. //
  305. // Call failed, advance to LECS CONNECT WKA state
  306. //
  307. pElan->State = ELAN_STATE_LECS_CONNECT_WKA;
  308. pElan->RetriesLeft = 4;
  309. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_START, 0);
  310. RELEASE_ELAN_LOCK(pElan);
  311. break;
  312. }
  313. break;
  314. case ELAN_EVENT_RESTART:
  315. DBGP((1, "%d LECS CONNECT ILMI - RESTART\n", pElan->ElanNumber));
  316. AtmLaneShutdownElan(pElan, TRUE);
  317. break;
  318. case ELAN_EVENT_STOP:
  319. DBGP((1, "%d LECS CONNECT ILMI - STOP\n", pElan->ElanNumber));
  320. AtmLaneShutdownElan(pElan, FALSE);
  321. break;
  322. default:
  323. DBGP((0, "%d LECS CONNECT ILMI - UNEXPECTED EVENT %d\n",
  324. pElan->ElanNumber, Event));
  325. RELEASE_ELAN_LOCK(pElan);
  326. break;
  327. }
  328. break;
  329. //
  330. // LECS CONNECT WKA STATE -------------------------------------------
  331. //
  332. case ELAN_STATE_LECS_CONNECT_WKA:
  333. switch (Event)
  334. {
  335. case ELAN_EVENT_START:
  336. DBGP((1, "%d LECS CONNECT WKA - START\n", pElan->ElanNumber));
  337. //
  338. // Attempt to connect to the LECS with Well-Known Address
  339. //
  340. SET_FLAG(
  341. pElan->Flags,
  342. ELAN_LECS_MASK,
  343. ELAN_LECS_WKA);
  344. NdisMoveMemory(
  345. &pElan->LecsAddress,
  346. &gWellKnownLecsAddress,
  347. sizeof(ATM_ADDRESS));
  348. RELEASE_ELAN_LOCK(pElan);
  349. AtmLaneConnectToServer(pElan, ATM_ENTRY_TYPE_LECS, FALSE);
  350. break;
  351. case ELAN_EVENT_SVR_CALL_COMPLETE:
  352. DBGP((1, "%d LECS CONNECT WKA - LECS CALL COMPLETE (%x)\n",
  353. pElan->ElanNumber, EventStatus));
  354. switch (EventStatus)
  355. {
  356. case NDIS_STATUS_SUCCESS:
  357. //
  358. // advance to the CONFIGURE Phase
  359. //
  360. pElan->State = ELAN_STATE_CONFIGURE;
  361. pElan->RetriesLeft = 4;
  362. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_START, 0);
  363. RELEASE_ELAN_LOCK(pElan);
  364. break;
  365. case NDIS_STATUS_INTERFACE_DOWN:
  366. if (pElan->RetriesLeft--)
  367. {
  368. //
  369. // retry in a little while
  370. //
  371. AtmLaneQueueElanEventAfterDelay(
  372. pElan,
  373. ELAN_EVENT_START,
  374. NDIS_STATUS_SUCCESS,
  375. 2*1000);
  376. RELEASE_ELAN_LOCK(pElan);
  377. }
  378. else
  379. {
  380. //
  381. // Return to the Init State in a little while
  382. //
  383. AtmLaneShutdownElan(pElan, TRUE);
  384. //
  385. // lock released in above
  386. //
  387. }
  388. break;
  389. default:
  390. //
  391. // Call failed, advance to LECS CONNECT PVC state
  392. //
  393. pElan->State = ELAN_STATE_LECS_CONNECT_PVC;
  394. pElan->RetriesLeft = 2;
  395. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_START, 0);
  396. RELEASE_ELAN_LOCK(pElan);
  397. break;
  398. }
  399. break;
  400. case ELAN_EVENT_RESTART:
  401. DBGP((1, "%d LECS CONNECT WKA - RESTART\n", pElan->ElanNumber));
  402. AtmLaneShutdownElan(pElan, TRUE);
  403. break;
  404. case ELAN_EVENT_STOP:
  405. DBGP((1, "%d LECS CONNECT WKA - STOP\n", pElan->ElanNumber));
  406. AtmLaneShutdownElan(pElan, FALSE);
  407. break;
  408. default:
  409. DBGP((0, "%d LECS CONNECT WKA - UNEXPECTED EVENT %d\n",
  410. pElan->ElanNumber, Event));
  411. RELEASE_ELAN_LOCK(pElan);
  412. break;
  413. }
  414. break;
  415. //
  416. // LECS CONNECT PVC STATE -------------------------------------------
  417. //
  418. case ELAN_STATE_LECS_CONNECT_PVC:
  419. switch (Event)
  420. {
  421. case ELAN_EVENT_START:
  422. DBGP((1, "%d LECS CONNECT PVC - START\n", pElan->ElanNumber));
  423. //
  424. // Attempt to connect to the LECS using PVC (0,17)
  425. //
  426. SET_FLAG(
  427. pElan->Flags,
  428. ELAN_LECS_MASK,
  429. ELAN_LECS_PVC);
  430. NdisZeroMemory(
  431. &pElan->LecsAddress,
  432. sizeof(ATM_ADDRESS));
  433. RELEASE_ELAN_LOCK(pElan);
  434. AtmLaneConnectToServer(pElan, ATM_ENTRY_TYPE_LECS, TRUE);
  435. break;
  436. case ELAN_EVENT_SVR_CALL_COMPLETE:
  437. DBGP((1, "%d LECS CONNECT PVC - LECS CALL COMPLETE (%x)\n",
  438. pElan->ElanNumber, EventStatus));
  439. switch (EventStatus)
  440. {
  441. case NDIS_STATUS_SUCCESS:
  442. //
  443. // advance to the CONFIGURE Phase
  444. //
  445. pElan->State = ELAN_STATE_CONFIGURE;
  446. pElan->RetriesLeft = 2;
  447. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_START, 0);
  448. RELEASE_ELAN_LOCK(pElan);
  449. break;
  450. case NDIS_STATUS_INTERFACE_DOWN:
  451. if (pElan->RetriesLeft--)
  452. {
  453. //
  454. // retry in a little while
  455. //
  456. AtmLaneQueueElanEventAfterDelay(
  457. pElan,
  458. ELAN_EVENT_START,
  459. NDIS_STATUS_SUCCESS,
  460. 2*1000);
  461. RELEASE_ELAN_LOCK(pElan);
  462. }
  463. else
  464. {
  465. //
  466. // Return to the Init State in a little while
  467. //
  468. AtmLaneShutdownElan(pElan, TRUE);
  469. //
  470. // lock released in above
  471. //
  472. }
  473. break;
  474. default:
  475. //
  476. // Call failed, Return to the Init State in a little while
  477. //
  478. AtmLaneShutdownElan(pElan, TRUE);
  479. //
  480. // lock released in above
  481. //
  482. break;
  483. }
  484. break;
  485. case ELAN_EVENT_RESTART:
  486. DBGP((1, "%d LECS CONNECT PVC - RESTART\n", pElan->ElanNumber));
  487. AtmLaneShutdownElan(pElan, TRUE);
  488. break;
  489. case ELAN_EVENT_STOP:
  490. DBGP((1, "%d LECS CONNECT PVC - STOP\n", pElan->ElanNumber));
  491. AtmLaneShutdownElan(pElan, FALSE);
  492. break;
  493. default:
  494. DBGP((0, "%d LECS CONNECT PVC - UNEXPECTED %d\n",
  495. pElan->ElanNumber, Event));
  496. RELEASE_ELAN_LOCK(pElan);
  497. break;
  498. }
  499. break;
  500. //
  501. // LECS CONNECT CFG STATE -------------------------------------------
  502. //
  503. case ELAN_STATE_LECS_CONNECT_CFG:
  504. switch (Event)
  505. {
  506. case ELAN_EVENT_START:
  507. DBGP((1, "%d LECS CONNECT CFG - START\n", pElan->ElanNumber));
  508. //
  509. // Attempt to connect to the LECS with configured Address
  510. //
  511. SET_FLAG(
  512. pElan->Flags,
  513. ELAN_LECS_MASK,
  514. ELAN_LECS_CFG);
  515. NdisMoveMemory(
  516. &pElan->LecsAddress,
  517. &pElan->CfgLecsAddress,
  518. sizeof(ATM_ADDRESS));
  519. RELEASE_ELAN_LOCK(pElan);
  520. AtmLaneConnectToServer(pElan, ATM_ENTRY_TYPE_LECS, FALSE);
  521. break;
  522. case ELAN_EVENT_SVR_CALL_COMPLETE:
  523. DBGP((1, "%d LECS CONNECT CFG - LECS CALL COMPLETE (%x)\n",
  524. pElan->ElanNumber, EventStatus));
  525. switch (EventStatus)
  526. {
  527. case NDIS_STATUS_SUCCESS:
  528. //
  529. // advance to the CONFIGURE Phase
  530. //
  531. pElan->State = ELAN_STATE_CONFIGURE;
  532. pElan->RetriesLeft = 4;
  533. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_START, 0);
  534. RELEASE_ELAN_LOCK(pElan);
  535. break;
  536. case NDIS_STATUS_INTERFACE_DOWN:
  537. if (pElan->RetriesLeft--)
  538. {
  539. //
  540. // retry in a little while
  541. //
  542. AtmLaneQueueElanEventAfterDelay(
  543. pElan,
  544. ELAN_EVENT_START,
  545. NDIS_STATUS_SUCCESS,
  546. 2*1000);
  547. RELEASE_ELAN_LOCK(pElan);
  548. }
  549. else
  550. {
  551. //
  552. // Return to the Init State in a little while
  553. //
  554. AtmLaneShutdownElan(pElan, TRUE);
  555. //
  556. // lock released in above
  557. //
  558. }
  559. break;
  560. default:
  561. //
  562. // Call failed, XXX What to do ?? Shutdown ?? Log ??
  563. //
  564. RELEASE_ELAN_LOCK(pElan);
  565. break;
  566. }
  567. break;
  568. case ELAN_EVENT_RESTART:
  569. DBGP((1, "%d LECS CONNECT CFG - RESTART\n", pElan->ElanNumber));
  570. AtmLaneShutdownElan(pElan, TRUE);
  571. break;
  572. case ELAN_EVENT_STOP:
  573. DBGP((1, "%d LECS CONNECT CFG - STOP\n", pElan->ElanNumber));
  574. AtmLaneShutdownElan(pElan, FALSE);
  575. break;
  576. default:
  577. DBGP((0, "%d LECS CONNECT CFG - UNEXPECTED EVENT %d\n",
  578. pElan->ElanNumber, Event));
  579. RELEASE_ELAN_LOCK(pElan);
  580. break;
  581. }
  582. break;
  583. //
  584. // CONFIGURE STATE -------------------------------------------
  585. //
  586. case ELAN_STATE_CONFIGURE:
  587. switch (Event)
  588. {
  589. case ELAN_EVENT_START:
  590. DBGP((1, "%d CONFIGURE - START\n", pElan->ElanNumber));
  591. //
  592. // Start configure request timer
  593. //
  594. AtmLaneReferenceElan(pElan, "timer"); // timer reference
  595. AtmLaneStartTimer(
  596. pElan,
  597. &pElan->Timer,
  598. AtmLaneConfigureResponseTimeout,
  599. pElan->ControlTimeout,
  600. pElan);
  601. RELEASE_ELAN_LOCK(pElan);
  602. //
  603. // Send a configure request
  604. //
  605. AtmLaneSendConfigureRequest(pElan);
  606. break;
  607. case ELAN_EVENT_CONFIGURE_RESPONSE:
  608. DBGP((1, "%d CONFIGURE - CONFIGURE RESPONSE (%x)\n",
  609. pElan->ElanNumber, EventStatus));
  610. switch (EventStatus)
  611. {
  612. case NDIS_STATUS_SUCCESS:
  613. //
  614. // Stop configure request timer
  615. //
  616. if (AtmLaneStopTimer(&pElan->Timer, pElan))
  617. {
  618. rc = AtmLaneDereferenceElan(pElan, "timer");
  619. ASSERT(rc > 0);
  620. }
  621. //
  622. // Close the LECS Connection
  623. //
  624. RELEASE_ELAN_LOCK(pElan);
  625. ACQUIRE_ATM_ENTRY_LOCK(pElan->pLecsAtmEntry);
  626. AtmLaneInvalidateAtmEntry(pElan->pLecsAtmEntry);
  627. //
  628. // Advance to LES CONNECT phase.
  629. //
  630. ACQUIRE_ELAN_LOCK(pElan);
  631. pElan->State = ELAN_STATE_LES_CONNECT;
  632. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_START, 0);
  633. RELEASE_ELAN_LOCK(pElan);
  634. break;
  635. case NDIS_STATUS_TIMEOUT:
  636. //
  637. // Return to the Init State in a little while
  638. //
  639. AtmLaneShutdownElan(pElan, TRUE);
  640. //
  641. // lock released in above
  642. //
  643. break;
  644. case NDIS_STATUS_FAILURE:
  645. //
  646. // Return to the Init State in a little while
  647. //
  648. AtmLaneShutdownElan(pElan, TRUE);
  649. //
  650. // lock released in above
  651. //
  652. break;
  653. } // switch (EventStatus)
  654. break;
  655. case ELAN_EVENT_RESTART:
  656. DBGP((1, "%d CONFIGURE - RESTART\n", pElan->ElanNumber));
  657. AtmLaneShutdownElan(pElan, TRUE);
  658. break;
  659. case ELAN_EVENT_STOP:
  660. DBGP((1, "%d CONFIGURE - STOP\n", pElan->ElanNumber));
  661. AtmLaneShutdownElan(pElan, FALSE);
  662. break;
  663. default:
  664. DBGP((1, "%d CONFIGURE - UNEXPECTED EVENT %d\n",
  665. pElan->ElanNumber, Event));
  666. RELEASE_ELAN_LOCK(pElan);
  667. break;
  668. }
  669. break;
  670. //
  671. // LES CONNECT STATE --------------------------------------------
  672. //
  673. case ELAN_STATE_LES_CONNECT:
  674. switch (Event)
  675. {
  676. case ELAN_EVENT_START:
  677. DBGP((1, "%d LES CONNECT - START\n", pElan->ElanNumber));
  678. //
  679. // Register our SAPs
  680. //
  681. AtmLaneRegisterSaps(pElan);
  682. //
  683. // Elan lock is released in above.
  684. //
  685. break;
  686. case ELAN_EVENT_SAPS_REGISTERED:
  687. DBGP((1, "%d LES CONNECT - SAPS REGISTERED (%x)\n",
  688. pElan->ElanNumber, EventStatus));
  689. if (NDIS_STATUS_SUCCESS == EventStatus)
  690. {
  691. pElan->RetriesLeft = 4;
  692. RELEASE_ELAN_LOCK(pElan);
  693. //
  694. // Connect to the LES
  695. //
  696. AtmLaneConnectToServer(pElan, ATM_ENTRY_TYPE_LES, FALSE);
  697. //
  698. // Elan lock is released in above.
  699. //
  700. }
  701. else
  702. {
  703. // XXX - What to do?
  704. RELEASE_ELAN_LOCK(pElan);
  705. }
  706. break;
  707. case ELAN_EVENT_SVR_CALL_COMPLETE:
  708. DBGP((1, "%d LES CONNECT - LES CALL COMPLETE (%x)\n",
  709. pElan->ElanNumber, EventStatus));
  710. switch (EventStatus)
  711. {
  712. case NDIS_STATUS_SUCCESS:
  713. //
  714. // Advance to Join state
  715. //
  716. pElan->State = ELAN_STATE_JOIN;
  717. pElan->RetriesLeft = 4;
  718. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_START, 0);
  719. RELEASE_ELAN_LOCK(pElan);
  720. break;
  721. case NDIS_STATUS_INTERFACE_DOWN:
  722. if (pElan->RetriesLeft--)
  723. {
  724. //
  725. // retry in a little while
  726. //
  727. AtmLaneQueueElanEventAfterDelay(
  728. pElan,
  729. ELAN_EVENT_SAPS_REGISTERED,
  730. NDIS_STATUS_SUCCESS,
  731. 2*1000);
  732. RELEASE_ELAN_LOCK(pElan);
  733. }
  734. else
  735. {
  736. //
  737. // Return to the Init State in a little while
  738. //
  739. AtmLaneShutdownElan(pElan, TRUE);
  740. //
  741. // lock released in above
  742. //
  743. }
  744. break;
  745. default:
  746. //
  747. // Call failed, return to the Init State in a little while
  748. //
  749. AtmLaneShutdownElan(pElan, TRUE);
  750. //
  751. // lock released in above
  752. //
  753. break;
  754. }
  755. break;
  756. case ELAN_EVENT_RESTART:
  757. DBGP((1, "%d LES CONNECT - RESTART\n", pElan->ElanNumber));
  758. AtmLaneShutdownElan(pElan, TRUE);
  759. break;
  760. case ELAN_EVENT_STOP:
  761. DBGP((1, "%d LES CONNECT - STOP\n", pElan->ElanNumber));
  762. AtmLaneShutdownElan(pElan, FALSE);
  763. break;
  764. default:
  765. DBGP((0, "%d LES CONNECT - UNEXPECTED EVENT %d\n",
  766. pElan->ElanNumber, Event));
  767. RELEASE_ELAN_LOCK(pElan);
  768. break;
  769. }
  770. break;
  771. //
  772. // JOIN STATE ---------------------------------------------------
  773. //
  774. case ELAN_STATE_JOIN:
  775. switch (Event)
  776. {
  777. case ELAN_EVENT_START:
  778. DBGP((1, "%d JOIN - START\n", pElan->ElanNumber));
  779. //
  780. // Start join request timer
  781. //
  782. AtmLaneReferenceElan(pElan, "timer"); // timer reference
  783. AtmLaneStartTimer(
  784. pElan,
  785. &pElan->Timer,
  786. AtmLaneJoinResponseTimeout,
  787. pElan->ControlTimeout,
  788. pElan);
  789. RELEASE_ELAN_LOCK(pElan);
  790. //
  791. // Send a Join request
  792. //
  793. AtmLaneSendJoinRequest(pElan);
  794. break;
  795. case ELAN_EVENT_JOIN_RESPONSE:
  796. DBGP((1, "%d JOIN - JOIN RESPONSE (%x)\n",
  797. pElan->ElanNumber, EventStatus));
  798. switch (EventStatus)
  799. {
  800. case NDIS_STATUS_SUCCESS:
  801. //
  802. // Stop join request timer
  803. //
  804. if (AtmLaneStopTimer(&pElan->Timer, pElan))
  805. {
  806. rc = AtmLaneDereferenceElan(pElan, "timer");
  807. ASSERT(rc > 0);
  808. }
  809. //
  810. // Advance to BUS CONNECT phase.
  811. //
  812. pElan->State = ELAN_STATE_BUS_CONNECT;
  813. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_START, 0);
  814. RELEASE_ELAN_LOCK(pElan);
  815. break;
  816. case NDIS_STATUS_TIMEOUT:
  817. //
  818. // restart the Elan
  819. //
  820. AtmLaneShutdownElan(pElan, TRUE);
  821. //
  822. // lock released in above
  823. //
  824. break;
  825. case NDIS_STATUS_FAILURE:
  826. //
  827. // restart the Elan
  828. //
  829. AtmLaneShutdownElan(pElan, TRUE);
  830. //
  831. // lock released in above
  832. //
  833. break;
  834. }
  835. break;
  836. case ELAN_EVENT_LES_CALL_CLOSED:
  837. DBGP((1, "%d JOIN - LES CALL CLOSED\n", pElan->ElanNumber));
  838. //
  839. // restart the Elan
  840. //
  841. AtmLaneShutdownElan(pElan, TRUE);
  842. //
  843. // lock released in above
  844. //
  845. break;
  846. case ELAN_EVENT_RESTART:
  847. DBGP((1, "%d JOIN - RESTART\n", pElan->ElanNumber));
  848. AtmLaneShutdownElan(pElan, TRUE);
  849. break;
  850. case ELAN_EVENT_STOP:
  851. DBGP((1, "%d JOIN - STOP\n", pElan->ElanNumber));
  852. AtmLaneShutdownElan(pElan, FALSE);
  853. break;
  854. default:
  855. DBGP((0, "%d JOIN - UNEXPECTED %d\n",
  856. pElan->ElanNumber, Event));
  857. RELEASE_ELAN_LOCK(pElan);
  858. break;
  859. }
  860. break;
  861. //
  862. // BUS CONNECT STATE ---------------------------------------------------
  863. //
  864. case ELAN_STATE_BUS_CONNECT:
  865. switch (Event)
  866. {
  867. case ELAN_EVENT_START:
  868. DBGP((1, "%d BUS CONNECT - START\n", pElan->ElanNumber));
  869. RELEASE_ELAN_LOCK(pElan);
  870. //
  871. // Find or create a MAC entry for the Broadcast MAC Addr
  872. //
  873. ACQUIRE_ELAN_MAC_TABLE_LOCK(pElan);
  874. pMacEntry = AtmLaneSearchForMacAddress(
  875. pElan,
  876. LANE_MACADDRTYPE_MACADDR,
  877. &gMacBroadcastAddress,
  878. TRUE);
  879. RELEASE_ELAN_MAC_TABLE_LOCK(pElan);
  880. if (pMacEntry == NULL_PATMLANE_MAC_ENTRY)
  881. {
  882. break;
  883. }
  884. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  885. SET_FLAG(
  886. pMacEntry->Flags,
  887. MAC_ENTRY_STATE_MASK,
  888. MAC_ENTRY_ARPING);
  889. pMacEntry->Flags |= MAC_ENTRY_BROADCAST;
  890. //
  891. // Send ARP Request
  892. //
  893. AtmLaneStartTimer(
  894. pElan,
  895. &pMacEntry->Timer,
  896. AtmLaneArpTimeout,
  897. pElan->ArpResponseTime,
  898. (PVOID)pMacEntry
  899. );
  900. pMacEntry->RetriesLeft = pElan->MaxRetryCount;
  901. AtmLaneReferenceMacEntry(pMacEntry, "timer");
  902. pMacEntry->Flags |= MAC_ENTRY_ARPING;
  903. AtmLaneSendArpRequest(pElan, pMacEntry);
  904. //
  905. // MAC Entry lock released in above
  906. //
  907. break;
  908. case ELAN_EVENT_ARP_RESPONSE:
  909. DBGP((1, "%d BUS CONNECT - ARP RESPONSE (%x)\n",
  910. pElan->ElanNumber, EventStatus));
  911. if (NDIS_STATUS_SUCCESS == EventStatus)
  912. {
  913. pElan->RetriesLeft = 4;
  914. RELEASE_ELAN_LOCK(pElan);
  915. //
  916. // Connect to the BUS
  917. //
  918. AtmLaneConnectToServer(pElan, ATM_ENTRY_TYPE_BUS, FALSE);
  919. }
  920. else
  921. {
  922. DBGP((2, "ELAN %d: NO ARP RESPONSE for BUS, restarting\n"));
  923. //
  924. // restart the Elan
  925. //
  926. AtmLaneShutdownElan(pElan, TRUE);
  927. //
  928. // lock released in above
  929. //
  930. }
  931. break;
  932. case ELAN_EVENT_SVR_CALL_COMPLETE:
  933. DBGP((1, "%d BUS CONNECT - BUS CALL COMPLETE (%x)\n",
  934. pElan->ElanNumber, EventStatus));
  935. switch (EventStatus)
  936. {
  937. case NDIS_STATUS_SUCCESS:
  938. //
  939. // Now connected to BUS, start the Operational phase
  940. //
  941. pElan->State = ELAN_STATE_OPERATIONAL;
  942. pElan->RetriesLeft = 4;
  943. AdapterHandle = pElan->MiniportAdapterHandle;
  944. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_START, 0);
  945. RELEASE_ELAN_LOCK(pElan);
  946. //
  947. // Indicate media connect status if our miniport is up:
  948. //
  949. if (AdapterHandle != NULL)
  950. {
  951. NdisMIndicateStatus(
  952. AdapterHandle,
  953. NDIS_STATUS_MEDIA_CONNECT,
  954. (PVOID)NULL,
  955. 0);
  956. NdisMIndicateStatusComplete(AdapterHandle);
  957. }
  958. break;
  959. case NDIS_STATUS_INTERFACE_DOWN:
  960. if (pElan->RetriesLeft--)
  961. {
  962. //
  963. // retry in a little while
  964. //
  965. AtmLaneQueueElanEventAfterDelay(
  966. pElan,
  967. ELAN_EVENT_ARP_RESPONSE,
  968. NDIS_STATUS_SUCCESS,
  969. 2*1000);
  970. RELEASE_ELAN_LOCK(pElan);
  971. }
  972. else
  973. {
  974. //
  975. // return to the Init State in a little while
  976. //
  977. AtmLaneShutdownElan(pElan, TRUE);
  978. //
  979. // lock released in above
  980. //
  981. }
  982. break;
  983. default:
  984. //
  985. // Call failed,
  986. // Close the LES connection and
  987. // return to the Init State in a little while.
  988. //
  989. AtmLaneShutdownElan(pElan, TRUE);
  990. //
  991. // lock released in above
  992. //
  993. break;
  994. }
  995. break;
  996. case ELAN_EVENT_LES_CALL_CLOSED:
  997. DBGP((1, "%d BUS CONNECT - LES CALL CLOSED\n", pElan->ElanNumber));
  998. //
  999. // restart the Elan
  1000. //
  1001. AtmLaneShutdownElan(pElan, TRUE);
  1002. //
  1003. // lock released in above
  1004. //
  1005. break;
  1006. case ELAN_EVENT_RESTART:
  1007. DBGP((1, "%d BUS CONNECT - RESTART\n", pElan->ElanNumber));
  1008. AtmLaneShutdownElan(pElan, TRUE);
  1009. break;
  1010. case ELAN_EVENT_STOP:
  1011. DBGP((1, "%d BUS CONNECT - STOP\n", pElan->ElanNumber));
  1012. AtmLaneShutdownElan(pElan, FALSE);
  1013. break;
  1014. default:
  1015. DBGP((0, "%d BUS CONNECT - UNEXPECTED EVENT %d\n",
  1016. pElan->ElanNumber, Event));
  1017. RELEASE_ELAN_LOCK(pElan);
  1018. break;
  1019. }
  1020. break;
  1021. //
  1022. // OPERATIONAL STATE ---------------------------------------------------
  1023. //
  1024. case ELAN_STATE_OPERATIONAL:
  1025. switch (Event)
  1026. {
  1027. case ELAN_EVENT_START:
  1028. DBGP((1, "%d OPERATIONAL - START\n", pElan->ElanNumber));
  1029. // Initialize the miniport if not already
  1030. if ((pElan->Flags & ELAN_MINIPORT_INITIALIZED) == 0)
  1031. {
  1032. // Only if we have a device name
  1033. if (pElan->CfgDeviceName.Length > 0)
  1034. {
  1035. pElan->Flags |= ELAN_MINIPORT_INITIALIZED;
  1036. //
  1037. // Schedule a PASSIVE_LEVEL thread to call
  1038. // NdisIMInitializeDeviceInstance
  1039. //
  1040. NdisInitializeWorkItem(
  1041. &pElan->NdisWorkItem,
  1042. AtmLaneInitializeMiniportDevice,
  1043. pElan);
  1044. AtmLaneReferenceElan(pElan, "workitem");
  1045. NdisScheduleWorkItem(&pElan->NdisWorkItem);
  1046. }
  1047. else
  1048. {
  1049. DBGP((0, "EventHandler: No miniport device name configured\n"));
  1050. }
  1051. }
  1052. //
  1053. // Clear last event log code
  1054. //
  1055. pElan->LastEventCode = 0;
  1056. RELEASE_ELAN_LOCK(pElan);
  1057. break;
  1058. case ELAN_EVENT_LES_CALL_CLOSED:
  1059. DBGP((1, "%d OPERATIONAL - LES CALL CLOSED\n", pElan->ElanNumber));
  1060. //
  1061. // Tear everything down and restart
  1062. //
  1063. AtmLaneShutdownElan(pElan, TRUE);
  1064. //
  1065. // lock released in above
  1066. //
  1067. break;
  1068. case ELAN_EVENT_BUS_CALL_CLOSED:
  1069. DBGP((1, "%d OPERATIONAL - BUS CALL CLOSED\n", pElan->ElanNumber));
  1070. //
  1071. // Tear everything down and restart
  1072. //
  1073. AtmLaneShutdownElan(pElan, TRUE);
  1074. //
  1075. // lock released in above
  1076. //
  1077. break;
  1078. break;
  1079. case ELAN_EVENT_RESTART:
  1080. DBGP((1, "%d OPERATIONAL - RESTART\n", pElan->ElanNumber));
  1081. AtmLaneShutdownElan(pElan, TRUE);
  1082. break;
  1083. case ELAN_EVENT_STOP:
  1084. DBGP((1, "%d OPERATIONAL - STOP\n", pElan->ElanNumber));
  1085. AtmLaneShutdownElan(pElan, FALSE);
  1086. break;
  1087. default:
  1088. DBGP((0, "%d OPERATIONAL - UNEXPECTED EVENT%d\n",
  1089. pElan->ElanNumber, Event));
  1090. RELEASE_ELAN_LOCK(pElan);
  1091. break;
  1092. }
  1093. break;
  1094. default:
  1095. DBGP((0, "%d UNKOWN STATE %d EVENT %d\n",
  1096. pElan->ElanNumber, pElan->State, Event));
  1097. RELEASE_ELAN_LOCK(pElan);
  1098. break;
  1099. } // switch (pElan->State)
  1100. TRACEOUT(EventHandler);
  1101. CHECK_EXIT_IRQL(EntryIrql);
  1102. return;
  1103. }
  1104. VOID
  1105. AtmLaneBootStrapElans(
  1106. IN PATMLANE_ADAPTER pAdapter
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. Start up the ELANs configured for an adapter.
  1111. Done upon receipt of AF notify from call manager.
  1112. Arguments:
  1113. pAdapter - Pointer to ATMLANE Adapter structure
  1114. Return Value:
  1115. None
  1116. --*/
  1117. {
  1118. NDIS_STATUS Status;
  1119. NDIS_HANDLE AdapterConfigHandle;
  1120. NDIS_STRING ElanListKeyName;
  1121. NDIS_HANDLE ElanListConfigHandle;
  1122. NDIS_HANDLE ElanConfigHandle;
  1123. NDIS_STRING ElanKeyName;
  1124. UINT Index;
  1125. PLIST_ENTRY p;
  1126. PATMLANE_ELAN pElan;
  1127. PATMLANE_NAME pName;
  1128. BOOLEAN bBootStrapping;
  1129. TRACEIN(BootStrapElans);
  1130. //
  1131. // Initialize.
  1132. //
  1133. Status = NDIS_STATUS_SUCCESS;
  1134. AdapterConfigHandle = NULL_NDIS_HANDLE;
  1135. ElanListConfigHandle = NULL_NDIS_HANDLE;
  1136. ElanConfigHandle = NULL_NDIS_HANDLE;
  1137. bBootStrapping = TRUE;
  1138. do
  1139. {
  1140. DBGP((1, "BootStrapElans: Starting ELANs on adapter %p\n", pAdapter));
  1141. ACQUIRE_ADAPTER_LOCK(pAdapter);
  1142. if (pAdapter->Flags & (ADAPTER_FLAGS_BOOTSTRAP_IN_PROGRESS|
  1143. ADAPTER_FLAGS_UNBINDING))
  1144. {
  1145. DBGP((0, "Skipping bootstrap on adapter %x/%x\n", pAdapter, pAdapter->Flags));
  1146. RELEASE_ADAPTER_LOCK(pAdapter);
  1147. bBootStrapping = FALSE;
  1148. break;
  1149. }
  1150. pAdapter->Flags |= ADAPTER_FLAGS_BOOTSTRAP_IN_PROGRESS;
  1151. INIT_BLOCK_STRUCT(&pAdapter->UnbindBlock);
  1152. RELEASE_ADAPTER_LOCK(pAdapter);
  1153. //
  1154. // Open the AtmLane protocol configuration section for this adapter.
  1155. //
  1156. NdisOpenProtocolConfiguration(
  1157. &Status,
  1158. &AdapterConfigHandle,
  1159. &pAdapter->ConfigString
  1160. );
  1161. if (NDIS_STATUS_SUCCESS != Status)
  1162. {
  1163. AdapterConfigHandle = NULL_NDIS_HANDLE;
  1164. DBGP((0, "BootStrapElans: OpenProtocolConfiguration failed\n"));
  1165. Status = NDIS_STATUS_OPEN_FAILED;
  1166. break;
  1167. }
  1168. //
  1169. // Get the protocol specific configuration
  1170. //
  1171. AtmLaneGetProtocolConfiguration(AdapterConfigHandle, pAdapter);
  1172. //
  1173. // We bootstrap the ELANs differently on NT5 and Memphis(Win98)
  1174. //
  1175. if (!pAdapter->RunningOnMemphis)
  1176. {
  1177. //
  1178. // This is the NT5 ELAN bootstrap case
  1179. //
  1180. do
  1181. {
  1182. //
  1183. // Open the Elan List configuration key.
  1184. //
  1185. NdisInitUnicodeString(&ElanListKeyName, ATMLANE_ELANLIST_STRING);
  1186. NdisOpenConfigurationKeyByName(
  1187. &Status,
  1188. AdapterConfigHandle,
  1189. &ElanListKeyName,
  1190. &ElanListConfigHandle);
  1191. if (NDIS_STATUS_SUCCESS != Status)
  1192. {
  1193. ElanListConfigHandle = NULL_NDIS_HANDLE;
  1194. DBGP((0, "BootStrapElans: Failed open of ElanList key\n"));
  1195. Status = NDIS_STATUS_FAILURE;
  1196. break;
  1197. }
  1198. //
  1199. // Iterate thru the configured Elans
  1200. //
  1201. for (Index = 0;
  1202. ; // Stop only on error or no more Elans
  1203. Index++)
  1204. {
  1205. //
  1206. // Open the "next" Elan key
  1207. //
  1208. NdisOpenConfigurationKeyByIndex(
  1209. &Status,
  1210. ElanListConfigHandle,
  1211. Index,
  1212. &ElanKeyName,
  1213. &ElanConfigHandle
  1214. );
  1215. if (NDIS_STATUS_SUCCESS != Status)
  1216. {
  1217. ElanConfigHandle = NULL_NDIS_HANDLE;
  1218. }
  1219. //
  1220. // If NULL handle, assume no more ELANs.
  1221. //
  1222. if (NULL_NDIS_HANDLE == ElanConfigHandle)
  1223. {
  1224. break;
  1225. }
  1226. //
  1227. // Create this Elan
  1228. //
  1229. DBGP((2, "Bootstrap ELANs: Adapter %x, KeyName: len %d, max %d, name: [%ws]\n",
  1230. pAdapter,
  1231. ElanKeyName.Length,
  1232. ElanKeyName.MaximumLength,
  1233. ElanKeyName.Buffer));
  1234. (VOID)AtmLaneCreateElan(pAdapter, &ElanKeyName, &pElan);
  1235. }
  1236. } while (FALSE);
  1237. Status = NDIS_STATUS_SUCCESS;
  1238. }
  1239. else
  1240. {
  1241. //
  1242. // This is the Memphis/Win98 ELAN bootstrap case
  1243. //
  1244. // Create Elans for each entry in the UpperBindings List
  1245. //
  1246. pName = pAdapter->UpperBindingsList;
  1247. while (pName != NULL)
  1248. {
  1249. (VOID)AtmLaneCreateElan(pAdapter, NULL, &pElan);
  1250. pName = pName->pNext;
  1251. }
  1252. }
  1253. } while (FALSE);
  1254. //
  1255. // Close config handles
  1256. //
  1257. if (NULL_NDIS_HANDLE != ElanConfigHandle)
  1258. {
  1259. NdisCloseConfiguration(ElanConfigHandle);
  1260. ElanConfigHandle = NULL_NDIS_HANDLE;
  1261. }
  1262. if (NULL_NDIS_HANDLE != ElanListConfigHandle)
  1263. {
  1264. NdisCloseConfiguration(ElanListConfigHandle);
  1265. ElanListConfigHandle = NULL_NDIS_HANDLE;
  1266. }
  1267. if (NULL_NDIS_HANDLE != AdapterConfigHandle)
  1268. {
  1269. NdisCloseConfiguration(AdapterConfigHandle);
  1270. AdapterConfigHandle = NULL_NDIS_HANDLE;
  1271. }
  1272. //
  1273. // Loop thru the ELANs and kickstart them - only the newly
  1274. // allocated ones.
  1275. //
  1276. if (!IsListEmpty(&pAdapter->ElanList))
  1277. {
  1278. p = pAdapter->ElanList.Flink;
  1279. while (p != &pAdapter->ElanList)
  1280. {
  1281. pElan = CONTAINING_RECORD(p, ATMLANE_ELAN, Link);
  1282. STRUCT_ASSERT(pElan, atmlane_elan);
  1283. ACQUIRE_ELAN_LOCK(pElan);
  1284. if (ELAN_STATE_ALLOCATED == pElan->State)
  1285. {
  1286. pElan->AdminState = ELAN_STATE_OPERATIONAL;
  1287. pElan->State = ELAN_STATE_INIT;
  1288. AtmLaneQueueElanEventAfterDelay(pElan, ELAN_EVENT_START, Status, 1*1000);
  1289. }
  1290. RELEASE_ELAN_LOCK(pElan);
  1291. p = p->Flink;
  1292. }
  1293. }
  1294. if (bBootStrapping)
  1295. {
  1296. ACQUIRE_ADAPTER_LOCK(pAdapter);
  1297. pAdapter->Flags &= ~ADAPTER_FLAGS_BOOTSTRAP_IN_PROGRESS;
  1298. RELEASE_ADAPTER_LOCK(pAdapter);
  1299. SIGNAL_BLOCK_STRUCT(&pAdapter->UnbindBlock, NDIS_STATUS_SUCCESS);
  1300. }
  1301. TRACEOUT(BootStrapElans);
  1302. return;
  1303. }
  1304. NDIS_STATUS
  1305. AtmLaneCreateElan(
  1306. IN PATMLANE_ADAPTER pAdapter,
  1307. IN PNDIS_STRING pElanKey,
  1308. OUT PATMLANE_ELAN * ppElan
  1309. )
  1310. /*++
  1311. Routine Description:
  1312. Create and start an ELAN.
  1313. Arguments:
  1314. pAdapter - Pointer to ATMLANE Adapter structure
  1315. pElanKey - Points to a Unicode string naming the elan to create.
  1316. ppElan - Pointer to pointer to ATMLANE_ELAN (output)
  1317. Return Value:
  1318. None
  1319. --*/
  1320. {
  1321. NDIS_STATUS Status;
  1322. PATMLANE_ELAN pElan;
  1323. TRACEIN(CreateElan);
  1324. Status = NDIS_STATUS_SUCCESS;
  1325. pElan = NULL_PATMLANE_ELAN;
  1326. DBGP((1, "CreateElan: Adapter %p, ElanKey %ws\n", pAdapter, pElanKey->Buffer));
  1327. do
  1328. {
  1329. //
  1330. // Weed out duplicates.
  1331. //
  1332. if (pElanKey != NULL)
  1333. {
  1334. pElan = AtmLaneFindElan(pAdapter, pElanKey);
  1335. if (NULL_PATMLANE_ELAN != pElan)
  1336. {
  1337. // Duplicate
  1338. DBGP((0, "CreateElan: found duplicate pElan %p\n", pElan));
  1339. Status = NDIS_STATUS_FAILURE;
  1340. pElan = NULL_PATMLANE_ELAN;
  1341. break;
  1342. }
  1343. }
  1344. //
  1345. // Allocate an ELAN data structure.
  1346. //
  1347. Status = AtmLaneAllocElan(pAdapter, &pElan);
  1348. if (NDIS_STATUS_SUCCESS != Status)
  1349. {
  1350. DBGP((0, "CreateElan: Failed allocate of elan data\n"));
  1351. break;
  1352. }
  1353. //
  1354. // Put initial reference on the Elan struct.
  1355. //
  1356. AtmLaneReferenceElan(pElan, "adapter");
  1357. //
  1358. // Store in bind name (NT only, not supplied on Win98)
  1359. //
  1360. if (pElanKey != NULL)
  1361. {
  1362. if (!AtmLaneCopyUnicodeString(&pElan->CfgBindName, pElanKey, TRUE, TRUE))
  1363. {
  1364. DBGP((0, "CreateElan: Failed allocate of bind name string\n"));
  1365. Status = NDIS_STATUS_RESOURCES;
  1366. break;
  1367. }
  1368. }
  1369. //
  1370. // Get the ELAN's configuration.
  1371. //
  1372. AtmLaneGetElanConfiguration(pElanKey, pElan);
  1373. //
  1374. // Allocate protocol buffers for this Elan.
  1375. //
  1376. Status = AtmLaneInitProtoBuffers(pElan);
  1377. if (Status != NDIS_STATUS_SUCCESS)
  1378. {
  1379. DBGP((0,
  1380. "CreateElan: bad status (%x) from InitBufs\n",
  1381. Status));
  1382. break;
  1383. }
  1384. //
  1385. // Allocate transmit packet descriptors for this Elan.
  1386. //
  1387. NdisAllocatePacketPool(
  1388. &Status,
  1389. &pElan->TransmitPacketPool,
  1390. pElan->MaxHeaderBufs,
  1391. sizeof(SEND_PACKET_RESERVED)
  1392. );
  1393. #if PKT_HDR_COUNTS
  1394. pElan->XmitPktCount = pElan->MaxHeaderBufs;
  1395. DBGP((1, "XmitPktCount %d\n", pElan->XmitPktCount));
  1396. #endif
  1397. if (Status != NDIS_STATUS_SUCCESS)
  1398. {
  1399. DBGP((0,
  1400. "CreateElan: bad status (%x)"
  1401. " from NdisAllocatePacketPool (xmit)\n",
  1402. Status));
  1403. break;
  1404. }
  1405. //
  1406. // Allocate receive packet descriptors for this Elan.
  1407. //
  1408. NdisAllocatePacketPool(
  1409. &Status,
  1410. &pElan->ReceivePacketPool,
  1411. pElan->MaxHeaderBufs,
  1412. sizeof(RECV_PACKET_RESERVED)
  1413. );
  1414. #if PKT_HDR_COUNTS
  1415. pElan->RecvPktCount = pElan->MaxHeaderBufs;
  1416. DBGP((1, "RecvPktCount %d\n", pElan->RecvPktCount));
  1417. #endif
  1418. if (Status != NDIS_STATUS_SUCCESS)
  1419. {
  1420. DBGP((0,
  1421. "CreateElan: bad status (%x)"
  1422. " from NdisAllocatePacketPool (xmit)\n",
  1423. Status));
  1424. break;
  1425. }
  1426. //
  1427. // Allocate receive buffer descriptors for this Elan.
  1428. //
  1429. NdisAllocateBufferPool(&Status,
  1430. &pElan->ReceiveBufferPool,
  1431. pElan->MaxHeaderBufs
  1432. );
  1433. if (Status != NDIS_STATUS_SUCCESS)
  1434. {
  1435. DBGP((0,
  1436. "AfRegisterNotifyHandler: bad status (%x)"
  1437. " from NdisAllocateBufferPool\n",
  1438. Status));
  1439. break;
  1440. }
  1441. }
  1442. while (FALSE);
  1443. if (Status != NDIS_STATUS_SUCCESS)
  1444. {
  1445. //
  1446. // There was a failure in processing this Elan.
  1447. //
  1448. if (NULL_PATMLANE_ELAN != pElan)
  1449. {
  1450. ACQUIRE_ELAN_LOCK(pElan);
  1451. AtmLaneDereferenceElan(pElan, "adapter");
  1452. }
  1453. *ppElan = NULL_PATMLANE_ELAN;
  1454. }
  1455. else
  1456. {
  1457. // Output created Elan
  1458. *ppElan = pElan;
  1459. }
  1460. TRACEOUT(CreateElan);
  1461. return Status;
  1462. }
  1463. NDIS_STATUS
  1464. AtmLaneReconfigureHandler(
  1465. IN PATMLANE_ADAPTER pAdapter,
  1466. IN PNET_PNP_EVENT pNetPnPEvent
  1467. )
  1468. /*++
  1469. Routine Description:
  1470. Handler for PnP Reconfigure events.
  1471. Arguments:
  1472. pAdapter - Pointer to our adapter struct.
  1473. pNetPnPEvent - Pointer to PnP Event structure describing the event.
  1474. Return Value:
  1475. Status of handling the reconfigure event.
  1476. --*/
  1477. {
  1478. NDIS_STATUS Status;
  1479. PATMLANE_PNP_RECONFIG_REQUEST pReconfig;
  1480. NDIS_STRING ElanKey;
  1481. PATMLANE_ELAN pElan;
  1482. TRACEIN(ReconfigureHandler);
  1483. do
  1484. {
  1485. DBGP((1, "Reconfigurehandler: Buffer 0x%x BufferLength %d\n",
  1486. pNetPnPEvent->Buffer, pNetPnPEvent->BufferLength));
  1487. Status = NDIS_STATUS_SUCCESS;
  1488. if (pAdapter == NULL_PATMLANE_ADAPTER)
  1489. {
  1490. //
  1491. // Either a global reconfig notification or this is
  1492. // NDIS itself asking us to re-evaluate our ELANs.
  1493. // We go through the list of configured ELANs on all
  1494. // adapters and start any that haven't been started.
  1495. //
  1496. {
  1497. PLIST_ENTRY pEnt, pNextEnt;
  1498. ACQUIRE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  1499. for (pEnt = pAtmLaneGlobalInfo->AdapterList.Flink;
  1500. pEnt != &pAtmLaneGlobalInfo->AdapterList;
  1501. pEnt = pNextEnt)
  1502. {
  1503. pNextEnt = pEnt->Flink;
  1504. RELEASE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  1505. pAdapter = CONTAINING_RECORD(pEnt, ATMLANE_ADAPTER, Link);
  1506. if (pAdapter->Flags & ADAPTER_FLAGS_AF_NOTIFIED)
  1507. {
  1508. DBGP((1, "Reconfig: Will bootstrap ELANs on Adapter %x\n",
  1509. pAdapter));
  1510. AtmLaneBootStrapElans(pAdapter);
  1511. }
  1512. ACQUIRE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  1513. }
  1514. RELEASE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  1515. }
  1516. break;
  1517. }
  1518. // Get pointer to LANE reconfig struct inside the generic PnP struct
  1519. pReconfig = (PATMLANE_PNP_RECONFIG_REQUEST)(pNetPnPEvent->Buffer);
  1520. // Check for null pointer
  1521. if (pReconfig == NULL)
  1522. {
  1523. DBGP((0, "ReconfigureHandler: NULL pointer to event buffer!\n"));
  1524. Status = NDIS_STATUS_INVALID_DATA;
  1525. break;
  1526. }
  1527. // Validate the version
  1528. if (pReconfig->Version != 1)
  1529. {
  1530. DBGP((0, "ReconfigureHandler: Version not 1\n"));
  1531. Status = NDIS_STATUS_BAD_VERSION;
  1532. break;
  1533. }
  1534. // Build a UNICODE string containing the ELAN's key
  1535. NdisInitUnicodeString(&ElanKey, pReconfig->ElanKey);
  1536. // First find the Elan
  1537. pElan = AtmLaneFindElan(pAdapter, &ElanKey);
  1538. DBGP((0, "ReconfigHandler: Adapter %x, ELAN %x, OpType %d\n",
  1539. pAdapter, pElan, pReconfig->OpType));
  1540. // Sanity check: don't add an existing ELAN
  1541. if (ATMLANE_RECONFIG_OP_ADD_ELAN == pReconfig->OpType &&
  1542. NULL_PATMLANE_ELAN != pElan)
  1543. {
  1544. DBGP((0, "ReconfigureHandler: Ignoring ADD existing Elan %x\n", pElan));
  1545. Status = NDIS_STATUS_SUCCESS;
  1546. break;
  1547. }
  1548. // If MOD or DEL first shutdown the existing ELAN
  1549. if (ATMLANE_RECONFIG_OP_MOD_ELAN == pReconfig->OpType ||
  1550. ATMLANE_RECONFIG_OP_DEL_ELAN == pReconfig->OpType)
  1551. {
  1552. if (NULL_PATMLANE_ELAN == pElan)
  1553. {
  1554. DBGP((0, "ReconfigureHandler: No existing Elan found for Modify/Delete\n"));
  1555. Status = NDIS_STATUS_FAILURE;
  1556. break;
  1557. }
  1558. // Shut down the existing Elan
  1559. ACQUIRE_ELAN_LOCK(pElan);
  1560. AtmLaneShutdownElan(pElan, FALSE);
  1561. }
  1562. // If ADD or MOD startup the new ELAN
  1563. if (ATMLANE_RECONFIG_OP_ADD_ELAN == pReconfig->OpType ||
  1564. ATMLANE_RECONFIG_OP_MOD_ELAN == pReconfig->OpType)
  1565. {
  1566. Status = AtmLaneCreateElan(pAdapter, &ElanKey, &pElan);
  1567. if (NDIS_STATUS_SUCCESS == Status)
  1568. {
  1569. pElan->AdminState = ELAN_STATE_OPERATIONAL;
  1570. pElan->State = ELAN_STATE_INIT;
  1571. AtmLaneQueueElanEventAfterDelay(pElan, ELAN_EVENT_START, Status, 1*1000);
  1572. }
  1573. }
  1574. } while (FALSE);
  1575. TRACEOUT(ReconfigureHandler);
  1576. DBGP((0, "Reconfigure: pAdapter %x, returning %x\n", pAdapter, Status));
  1577. return Status;
  1578. }
  1579. PATMLANE_ELAN
  1580. AtmLaneFindElan(
  1581. IN PATMLANE_ADAPTER pAdapter,
  1582. IN PNDIS_STRING pElanKey
  1583. )
  1584. /*++
  1585. Routine Description:
  1586. Find an ELAN by bind name/key
  1587. Arguments:
  1588. pAdapter - Pointer to an adapter struct.
  1589. pElanKey - Pointer to NDIS_STRING containing Elan's bind name.
  1590. Return Value:
  1591. Pointer to matching Elan or NULL if not found.
  1592. --*/
  1593. {
  1594. PLIST_ENTRY p;
  1595. PATMLANE_ELAN pElan;
  1596. BOOLEAN Found;
  1597. NDIS_STRING ElanKeyName;
  1598. TRACEIN(FindElan);
  1599. DBGP((1, "FindElan: Adapter %p, ElanKey %ws\n", pAdapter, pElanKey->Buffer));
  1600. Found = FALSE;
  1601. ElanKeyName.Buffer = NULL;
  1602. pElan = NULL_PATMLANE_ELAN;
  1603. do
  1604. {
  1605. //
  1606. // Make an up-cased copy of the given string.
  1607. //
  1608. ALLOC_MEM(&ElanKeyName.Buffer, pElanKey->MaximumLength);
  1609. if (ElanKeyName.Buffer == NULL)
  1610. {
  1611. break;
  1612. }
  1613. ElanKeyName.Length = pElanKey->Length;
  1614. ElanKeyName.MaximumLength = pElanKey->MaximumLength;
  1615. #ifndef LANE_WIN98
  1616. (VOID)NdisUpcaseUnicodeString(&ElanKeyName, pElanKey);
  1617. #else
  1618. memcpy(ElanKeyName.Buffer, pElanKey->Buffer, ElanKeyName.Length);
  1619. #endif // LANE_WIN98
  1620. ACQUIRE_ADAPTER_LOCK(pAdapter);
  1621. p = pAdapter->ElanList.Flink;
  1622. while (p != &pAdapter->ElanList)
  1623. {
  1624. pElan = CONTAINING_RECORD(p, ATMLANE_ELAN, Link);
  1625. STRUCT_ASSERT(pElan, atmlane_elan);
  1626. // compare the key
  1627. if ((ElanKeyName.Length == pElan->CfgBindName.Length) &&
  1628. (memcmp(ElanKeyName.Buffer, pElan->CfgBindName.Buffer, ElanKeyName.Length) == 0))
  1629. {
  1630. //
  1631. // Skip ELANs that are shutting down and not restarting
  1632. //
  1633. if ((pElan->AdminState != ELAN_STATE_SHUTDOWN) ||
  1634. ((pElan->Flags & ELAN_NEEDS_RESTART) != 0))
  1635. {
  1636. Found = TRUE;
  1637. break;
  1638. }
  1639. }
  1640. // get next link
  1641. p = p->Flink;
  1642. }
  1643. RELEASE_ADAPTER_LOCK(pAdapter);
  1644. }
  1645. while (FALSE);
  1646. if (!Found)
  1647. {
  1648. DBGP((2, "FindElan: No match found!\n"));
  1649. pElan = NULL_PATMLANE_ELAN;
  1650. }
  1651. if (ElanKeyName.Buffer)
  1652. {
  1653. FREE_MEM(ElanKeyName.Buffer);
  1654. }
  1655. TRACEOUT(FindElan);
  1656. return pElan;
  1657. }
  1658. VOID
  1659. AtmLaneConnectToServer(
  1660. IN PATMLANE_ELAN pElan,
  1661. IN ULONG ServerType,
  1662. IN BOOLEAN UsePvc
  1663. )
  1664. /*++
  1665. Routine Description:
  1666. Setup and make call to a LANE Server.
  1667. Arguments:
  1668. pElan - Pointer to ATMLANE Elan structure
  1669. ServerType - LECS, LES, or BUS
  1670. Return Value:
  1671. None
  1672. --*/
  1673. {
  1674. NDIS_STATUS Status;
  1675. ULONG rc;
  1676. PATMLANE_ATM_ENTRY pAtmEntry;
  1677. TRACEIN(ConnectToServer);
  1678. do
  1679. {
  1680. switch (ServerType)
  1681. {
  1682. case ATM_ENTRY_TYPE_LECS:
  1683. //
  1684. // Create the ATM Entry
  1685. //
  1686. pAtmEntry = AtmLaneAllocateAtmEntry(pElan);
  1687. if (NULL_PATMLANE_ATM_ENTRY != pAtmEntry)
  1688. {
  1689. //
  1690. // Init ATM Entry
  1691. //
  1692. pAtmEntry->Type = ServerType;
  1693. NdisMoveMemory(
  1694. &pAtmEntry->AtmAddress,
  1695. &pElan->LecsAddress,
  1696. sizeof(ATM_ADDRESS));
  1697. //
  1698. // Add it to the Elan's list
  1699. //
  1700. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  1701. pElan->pLecsAtmEntry = pAtmEntry;
  1702. pAtmEntry->pNext = pElan->pAtmEntryList;
  1703. pElan->pAtmEntryList = pAtmEntry;
  1704. pElan->NumAtmEntries++;
  1705. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  1706. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  1707. }
  1708. break;
  1709. case ATM_ENTRY_TYPE_LES:
  1710. //
  1711. // Create the ATM Entry
  1712. //
  1713. pAtmEntry = AtmLaneAllocateAtmEntry(pElan);
  1714. if (NULL_PATMLANE_ATM_ENTRY != pAtmEntry)
  1715. {
  1716. //
  1717. // Init ATM Entry
  1718. //
  1719. pAtmEntry->Type = ServerType;
  1720. NdisMoveMemory(
  1721. &pAtmEntry->AtmAddress,
  1722. &pElan->LesAddress,
  1723. sizeof(ATM_ADDRESS));
  1724. //
  1725. // Add it to the Elan's list
  1726. //
  1727. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  1728. pElan->pLesAtmEntry = pAtmEntry;
  1729. pAtmEntry->pNext = pElan->pAtmEntryList;
  1730. pElan->pAtmEntryList = pAtmEntry;
  1731. pElan->NumAtmEntries++;
  1732. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  1733. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  1734. }
  1735. break;
  1736. case ATM_ENTRY_TYPE_BUS:
  1737. ASSERT(NULL_PATMLANE_ATM_ENTRY != pElan->pBusAtmEntry);
  1738. NdisMoveMemory(
  1739. &pElan->BusAddress,
  1740. &pElan->pBusAtmEntry->AtmAddress,
  1741. sizeof(ATM_ADDRESS));
  1742. pAtmEntry = pElan->pBusAtmEntry;
  1743. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  1744. break;
  1745. }
  1746. if (NULL_PATMLANE_ATM_ENTRY == pAtmEntry)
  1747. {
  1748. break;
  1749. }
  1750. //
  1751. // Call the Server
  1752. //
  1753. DBGP((1, "%d: ConnectToServer: pElan %x/ref %d, Type %d, pAtmEnt %x, Ref %d\n",
  1754. pElan->ElanNumber,
  1755. pElan,
  1756. pElan->RefCount,
  1757. ServerType,
  1758. pAtmEntry,
  1759. pAtmEntry->RefCount));
  1760. Status = AtmLaneMakeCall(pElan, pAtmEntry, UsePvc);
  1761. if (NDIS_STATUS_SUCCESS == Status)
  1762. {
  1763. //
  1764. // Call completed synchronously.
  1765. //
  1766. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_SVR_CALL_COMPLETE, Status);
  1767. break;
  1768. }
  1769. if (NDIS_STATUS_PENDING != Status)
  1770. {
  1771. //
  1772. // Call failed.
  1773. // Dereference Atm Entry (should delete it).
  1774. // Signal the elan state machine.
  1775. //
  1776. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  1777. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "elan"); // Elan list reference
  1778. ASSERT(0 == rc);
  1779. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_SVR_CALL_COMPLETE, Status);
  1780. break;
  1781. }
  1782. }
  1783. while (FALSE);
  1784. TRACEOUT(ConnectToServer);
  1785. return;
  1786. }
  1787. VOID
  1788. AtmLaneInvalidateAtmEntry(
  1789. IN PATMLANE_ATM_ENTRY pAtmEntry LOCKIN NOLOCKOUT
  1790. )
  1791. /*++
  1792. Routine Description:
  1793. Invalidate an ATM Entry by unlinking it from MAC entries and
  1794. closing VC's on it.
  1795. Arguments:
  1796. pAtmEntry - The ATM Entry needing invalidating.
  1797. Return Value:
  1798. None
  1799. --*/
  1800. {
  1801. PATMLANE_MAC_ENTRY pMacEntry;
  1802. PATMLANE_MAC_ENTRY pNextMacEntry;
  1803. ULONG rc; // Ref Count of ATM Entry
  1804. INT MacEntriesUnlinked;
  1805. TRACEIN(InvalidateAtmEntry);
  1806. DBGP((1, "%d Del ATM %x: %s\n",
  1807. pAtmEntry->pElan->ElanNumber,
  1808. pAtmEntry,
  1809. AtmAddrToString(pAtmEntry->AtmAddress.Address)));
  1810. DBGP((3,
  1811. "InvalidateAtmEntry: pAtmEntry %x, pMacEntryList %x\n",
  1812. pAtmEntry,
  1813. pAtmEntry->pMacEntryList));
  1814. //
  1815. // Initialize.
  1816. //
  1817. MacEntriesUnlinked = 0;
  1818. //
  1819. // Take the MAC Entry list out of the ATM Entry.
  1820. //
  1821. pMacEntry = pAtmEntry->pMacEntryList;
  1822. pAtmEntry->pMacEntryList = NULL_PATMLANE_MAC_ENTRY;
  1823. //
  1824. // We let go of the ATM Entry lock here because we'll need
  1825. // to lock each MAC Entry in the above list, and we need to make
  1826. // sure that we don't deadlock.
  1827. //
  1828. // However, we make sure that the ATM Entry doesn't go away
  1829. // by adding a reference to it.
  1830. //
  1831. AtmLaneReferenceAtmEntry(pAtmEntry, "temp"); // Temp ref
  1832. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  1833. //
  1834. // Now unlink all MAC entries.
  1835. //
  1836. while (pMacEntry != NULL_PATMLANE_MAC_ENTRY)
  1837. {
  1838. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  1839. pNextMacEntry = pMacEntry->pNextToAtm;
  1840. //
  1841. // Remove the mapping.
  1842. //
  1843. pMacEntry->Flags = MAC_ENTRY_NEW;
  1844. pMacEntry->pAtmEntry = NULL_PATMLANE_ATM_ENTRY;
  1845. pMacEntry->pNextToAtm = NULL_PATMLANE_MAC_ENTRY;
  1846. //
  1847. // Remove the ATM Entry linkage reference.
  1848. //
  1849. if (AtmLaneDereferenceMacEntry(pMacEntry, "atm") != 0)
  1850. {
  1851. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  1852. }
  1853. //
  1854. // else the MAC Entry is gone
  1855. //
  1856. MacEntriesUnlinked++;
  1857. pMacEntry = pNextMacEntry;
  1858. }
  1859. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  1860. //
  1861. // Now dereference the ATM Entry as many times as we unliked
  1862. // MAC Entries from it.
  1863. //
  1864. while (MacEntriesUnlinked-- > 0)
  1865. {
  1866. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "mac"); // MAC Entry reference
  1867. ASSERT(rc != 0);
  1868. }
  1869. //
  1870. // Take out the reference we added at the beginning of
  1871. // this routine.
  1872. //
  1873. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "temp"); // Temp ref
  1874. //
  1875. // Close the SVCs attached to the ATM Entry.
  1876. // But do all this only if the ATM Entry
  1877. // hasn't been dereferenced away already.
  1878. //
  1879. if (rc != 0)
  1880. {
  1881. //
  1882. // The ATM Entry still exists.
  1883. // Close the VCs.
  1884. //
  1885. AtmLaneCloseVCsOnAtmEntry(pAtmEntry);
  1886. //
  1887. // The ATM Entry lock is released within the above.
  1888. //
  1889. }
  1890. //
  1891. // else the ATM Entry is gone
  1892. //
  1893. TRACEOUT(InvalidateAtmEntry);
  1894. return;
  1895. }
  1896. VOID
  1897. AtmLaneCloseVCsOnAtmEntry(
  1898. IN PATMLANE_ATM_ENTRY pAtmEntry LOCKIN NOLOCKOUT
  1899. )
  1900. /*++
  1901. Routine Description:
  1902. Close the (potentially two) VCs attached to an ATM Entry.
  1903. Arguments:
  1904. pAtmEntry - Pointer to ATM Entry on which we want to close SVCs.
  1905. Return Value:
  1906. None
  1907. --*/
  1908. {
  1909. PATMLANE_VC pVcList; // List of "Main" VCs on the ATM Entry
  1910. PATMLANE_VC pVc; // Main VC on the ATM Entry
  1911. PATMLANE_VC pVcIncomingList; // List of Optional incoming VCs on ATM Entry
  1912. PATMLANE_VC pVcIncoming; // Optional incoming VC on ATM Entry
  1913. PATMLANE_VC pNextVc; // Temp, for traversing VC lists.
  1914. ULONG rc; // Ref count on ATM Entry
  1915. TRACEIN(CloseVCsOnAtmEntry);
  1916. //
  1917. // Initialize.
  1918. //
  1919. rc = pAtmEntry->RefCount;
  1920. //
  1921. // Take out the Main VC list from the ATM Entry.
  1922. //
  1923. pVcList = pAtmEntry->pVcList;
  1924. pAtmEntry->pVcList = NULL_PATMLANE_VC;
  1925. //
  1926. // Deref the ATM Entry for each of the Main VCs.
  1927. //
  1928. for (pVc = pVcList;
  1929. NULL_PATMLANE_VC != pVc;
  1930. pVc = pNextVc)
  1931. {
  1932. ASSERT(rc != 0);
  1933. ACQUIRE_VC_LOCK(pVc);
  1934. pNextVc = pVc->pNextVc;
  1935. //
  1936. // Unlink this VC from the ATM Entry.
  1937. //
  1938. pVc->pAtmEntry = NULL_PATMLANE_ATM_ENTRY;
  1939. //
  1940. // Leave AtmEntry Reference on VC so it doesn't go away
  1941. //
  1942. RELEASE_VC_LOCK(pVc);
  1943. DBGP((1, "%d unlink VC %x/%x, Ref %d from ATM Entry %x\n",
  1944. pAtmEntry->pElan->ElanNumber,
  1945. pVc, pVc->Flags, pVc->RefCount,
  1946. pAtmEntry));
  1947. //
  1948. // Dereference the ATM Entry.
  1949. //
  1950. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "vc"); // VC reference
  1951. }
  1952. if (rc != 0)
  1953. {
  1954. //
  1955. // Take out the Incoming VC list from the ATM Entry.
  1956. //
  1957. pVcIncomingList = pAtmEntry->pVcIncoming;
  1958. pAtmEntry->pVcIncoming = NULL_PATMLANE_VC;
  1959. //
  1960. // Deref the ATM Entry for each of the Incoming VCs.
  1961. //
  1962. for (pVcIncoming = pVcIncomingList;
  1963. NULL_PATMLANE_VC != pVcIncoming;
  1964. pVcIncoming = pNextVc)
  1965. {
  1966. ASSERT(rc != 0);
  1967. ACQUIRE_VC_LOCK(pVcIncoming);
  1968. pNextVc = pVcIncoming->pNextVc;
  1969. //
  1970. // Unlink this VC from the ATM Entry.
  1971. //
  1972. pVcIncoming->pAtmEntry = NULL_PATMLANE_ATM_ENTRY;
  1973. //
  1974. // Leave AtmEntry Reference on VC so it doesn't go away
  1975. //
  1976. RELEASE_VC_LOCK(pVcIncoming);
  1977. DBGP((1, "%d unlink Incoming VC %x from ATM Entry %x\n",
  1978. pAtmEntry->pElan->ElanNumber,
  1979. pVcIncoming,
  1980. pAtmEntry));
  1981. //
  1982. // Dereference the ATM Entry.
  1983. //
  1984. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "vc"); // VC reference
  1985. }
  1986. }
  1987. else
  1988. {
  1989. pVcIncomingList = NULL_PATMLANE_VC;
  1990. }
  1991. if (rc != 0)
  1992. {
  1993. //
  1994. // The ATM Entry lives on. We don't need a lock to it anymore.
  1995. //
  1996. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  1997. }
  1998. //
  1999. // Now close the VC(s).
  2000. //
  2001. for (pVc = pVcList;
  2002. NULL_PATMLANE_VC != pVc;
  2003. pVc = pNextVc)
  2004. {
  2005. ACQUIRE_VC_LOCK(pVc);
  2006. pNextVc = pVc->pNextVc;
  2007. rc = AtmLaneDereferenceVc(pVc, "atm"); // ATM Entry reference
  2008. if (rc != 0)
  2009. {
  2010. AtmLaneCloseCall(pVc);
  2011. //
  2012. // The VC lock is released within the above.
  2013. //
  2014. }
  2015. //
  2016. // else the VC is gone.
  2017. //
  2018. }
  2019. for (pVcIncoming = pVcIncomingList;
  2020. NULL_PATMLANE_VC != pVcIncoming;
  2021. pVcIncoming = pNextVc)
  2022. {
  2023. ACQUIRE_VC_LOCK(pVcIncoming);
  2024. pNextVc = pVcIncoming->pNextVc;
  2025. rc = AtmLaneDereferenceVc(pVcIncoming, "atm"); // ATM Entry reference
  2026. if (rc != 0)
  2027. {
  2028. AtmLaneCloseCall(pVcIncoming);
  2029. //
  2030. // The VC lock is released within the above.
  2031. //
  2032. }
  2033. //
  2034. // else the VC is gone.
  2035. //
  2036. }
  2037. TRACEOUT(CloseVCsOnAtmEntry);
  2038. return;
  2039. }
  2040. VOID
  2041. AtmLaneGenerateMacAddr(
  2042. PATMLANE_ELAN pElan
  2043. )
  2044. /*++
  2045. Routine Description:
  2046. Generates a "virtual" MAC address for Elans after the first
  2047. Elan on an ATM interface.
  2048. Arguments:
  2049. pElan - Pointer to ATMLANE elan structure
  2050. Return Value:
  2051. None
  2052. --*/
  2053. {
  2054. TRACEIN(GenerateMacAddress);
  2055. //
  2056. // Start by using the real ATM card's MAC address
  2057. //
  2058. NdisMoveMemory(
  2059. &pElan->MacAddressEth,
  2060. &pElan->pAdapter->MacAddress,
  2061. sizeof(MAC_ADDRESS)
  2062. );
  2063. if (pElan->ElanNumber != 0)
  2064. {
  2065. //
  2066. // Not Elan number zero so generate a locally
  2067. // administered address by manipulating the first two bytes.
  2068. //
  2069. pElan->MacAddressEth.Byte[0] =
  2070. 0x02 | (((UCHAR)pElan->ElanNumber & 0x3f) << 2);
  2071. pElan->MacAddressEth.Byte[1] =
  2072. (pElan->pAdapter->MacAddress.Byte[1] & 0x3f) |
  2073. ((UCHAR)pElan->ElanNumber & 0x3f);
  2074. }
  2075. //
  2076. // Create the Token Ring version of the MAC Address
  2077. //
  2078. NdisMoveMemory(
  2079. &pElan->MacAddressTr,
  2080. &pElan->MacAddressEth,
  2081. sizeof(MAC_ADDRESS)
  2082. );
  2083. AtmLaneBitSwapMacAddr((PUCHAR)&pElan->MacAddressTr);
  2084. DBGP((1, "%d MacAddrEth %s\n",
  2085. pElan->ElanNumber, MacAddrToString(&pElan->MacAddressEth)));
  2086. DBGP((1, "%d MacAddrTr %s\n",
  2087. pElan->ElanNumber, MacAddrToString(&pElan->MacAddressTr)));
  2088. TRACEOUT(GenerateMacAddress);
  2089. return;
  2090. }
  2091. PATMLANE_MAC_ENTRY
  2092. AtmLaneSearchForMacAddress(
  2093. PATMLANE_ELAN pElan,
  2094. ULONG MacAddrType,
  2095. PMAC_ADDRESS pMacAddress,
  2096. BOOLEAN CreateNew
  2097. )
  2098. /*++
  2099. Routine Description:
  2100. Search for an MAC Address in the MAC Table. Optionally, create one
  2101. if a match is not found.
  2102. The caller is assumed to hold a lock to the MAC Table.
  2103. Arguments:
  2104. pElan - Pointer to ATMLANE Elan
  2105. MacAddrType - Type of MAC Addr (MAC vs RD)
  2106. pMacAddress - what we are looking for
  2107. CreateNew - Should a new entry be created if no match?
  2108. Return Value:
  2109. Pointer to a matching Mac Entry if found (or created anew).
  2110. --*/
  2111. {
  2112. ULONG HashIndex;
  2113. PATMLANE_MAC_ENTRY pMacEntry;
  2114. BOOLEAN Found;
  2115. TRACEIN(SearchForMacAddress);
  2116. HashIndex = ATMLANE_HASH(pMacAddress);
  2117. Found = FALSE;
  2118. pMacEntry = pElan->pMacTable[HashIndex];
  2119. //
  2120. // Go through the addresses in this hash list.
  2121. //
  2122. while (pMacEntry != NULL_PATMLANE_MAC_ENTRY)
  2123. {
  2124. if (!IS_FLAG_SET(
  2125. pMacEntry->Flags,
  2126. MAC_ENTRY_STATE_MASK,
  2127. MAC_ENTRY_ABORTING) &&
  2128. (MAC_ADDR_EQUAL(&pMacEntry->MacAddress, pMacAddress)) &&
  2129. (pMacEntry->MacAddrType == MacAddrType))
  2130. {
  2131. Found = TRUE;
  2132. break;
  2133. }
  2134. pMacEntry = pMacEntry->pNextEntry;
  2135. }
  2136. if (!Found && CreateNew && (pElan->AdminState != ELAN_STATE_SHUTDOWN))
  2137. {
  2138. pMacEntry = AtmLaneAllocateMacEntry(pElan);
  2139. if (pMacEntry != NULL_PATMLANE_MAC_ENTRY)
  2140. {
  2141. //
  2142. // Fill in this new entry.
  2143. //
  2144. NdisMoveMemory(&pMacEntry->MacAddress, pMacAddress, sizeof(MAC_ADDRESS));
  2145. pMacEntry->MacAddrType = MacAddrType;
  2146. AtmLaneReferenceMacEntry(pMacEntry, "table"); // Mac Table linkage
  2147. //
  2148. // Link it to the hash table.
  2149. //
  2150. pMacEntry->pNextEntry = pElan->pMacTable[HashIndex];
  2151. pElan->pMacTable[HashIndex] = pMacEntry;
  2152. pElan->NumMacEntries++;
  2153. DBGP((1, "%d New MAC %x: %s\n",
  2154. pElan->ElanNumber,
  2155. pMacEntry,
  2156. MacAddrToString(pMacAddress)));
  2157. }
  2158. else
  2159. {
  2160. DBGP((0, "SearchForMacAddress: alloc of new mac entry failed\n"));
  2161. }
  2162. }
  2163. TRACEOUT(SearchForMacAddress);
  2164. return (pMacEntry);
  2165. }
  2166. PATMLANE_ATM_ENTRY
  2167. AtmLaneSearchForAtmAddress(
  2168. IN PATMLANE_ELAN pElan,
  2169. IN PUCHAR pAtmAddress,
  2170. IN ULONG Type,
  2171. IN BOOLEAN CreateNew
  2172. )
  2173. /*++
  2174. Routine Description:
  2175. Search for an ATM Entry that matches the given ATM address and type.
  2176. Optionally, create one if there is no match.
  2177. NOTE: this routine references the ATM entry it returns. The caller
  2178. should deref it.
  2179. Arguments:
  2180. pElan - Pointer to ATMLANE Elan
  2181. pAtmAddress - ATM Address
  2182. Type - ATM Entry Type (Peer, LECS, LES, BUS)
  2183. CreateNew - Do we create a new entry if we don't find one?
  2184. Return Value:
  2185. Pointer to a matching ATM Entry if found (or created anew).
  2186. --*/
  2187. {
  2188. PATMLANE_ATM_ENTRY pAtmEntry;
  2189. BOOLEAN Found;
  2190. TRACEIN(SearchForAtmAddress);
  2191. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  2192. //
  2193. // Go through the list of ATM Entries on this interface.
  2194. //
  2195. Found = FALSE;
  2196. for (pAtmEntry = pElan->pAtmEntryList;
  2197. pAtmEntry != NULL_PATMLANE_ATM_ENTRY;
  2198. pAtmEntry = pAtmEntry->pNext)
  2199. {
  2200. //
  2201. // Compare the ATM Address and Type
  2202. //
  2203. if ((ATM_ADDR_EQUAL(pAtmAddress, pAtmEntry->AtmAddress.Address)) &&
  2204. (pAtmEntry->Type == Type) &&
  2205. ((pAtmEntry->Flags & ATM_ENTRY_WILL_ABORT) == 0))
  2206. {
  2207. Found = TRUE;
  2208. break;
  2209. }
  2210. }
  2211. if (!Found && CreateNew && (pElan->State != ELAN_STATE_SHUTDOWN))
  2212. {
  2213. pAtmEntry = AtmLaneAllocateAtmEntry(pElan);
  2214. if (pAtmEntry != NULL_PATMLANE_ATM_ENTRY)
  2215. {
  2216. //
  2217. // Fill in this new entry.
  2218. //
  2219. pAtmEntry->Flags = ATM_ENTRY_VALID;
  2220. //
  2221. // The ATM Address.
  2222. //
  2223. pAtmEntry->AtmAddress.AddressType = ATM_NSAP;
  2224. pAtmEntry->AtmAddress.NumberOfDigits = ATM_ADDRESS_LENGTH;
  2225. NdisMoveMemory(
  2226. pAtmEntry->AtmAddress.Address,
  2227. pAtmAddress,
  2228. ATM_ADDRESS_LENGTH);
  2229. //
  2230. // The Type.
  2231. //
  2232. pAtmEntry->Type = Type;
  2233. //
  2234. // Link in this entry to the Elan
  2235. //
  2236. pAtmEntry->pNext = pElan->pAtmEntryList;
  2237. pElan->pAtmEntryList = pAtmEntry;
  2238. pElan->NumAtmEntries++;
  2239. DBGP((1, "%d New ATM %x: %s\n",
  2240. pElan->ElanNumber,
  2241. pAtmEntry,
  2242. AtmAddrToString(pAtmAddress)));
  2243. }
  2244. }
  2245. //
  2246. // Reference this ATM entry so that it won't be derefed away
  2247. // before the caller gets to use this.
  2248. //
  2249. if (NULL_PATMLANE_ATM_ENTRY != pAtmEntry)
  2250. {
  2251. ACQUIRE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  2252. AtmLaneReferenceAtmEntry(pAtmEntry, "search");
  2253. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  2254. }
  2255. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  2256. TRACEOUT(SearchForAtmAddress);
  2257. return (pAtmEntry);
  2258. }
  2259. ULONG
  2260. AtmLaneMacAddrEqual(
  2261. PMAC_ADDRESS pMacAddr1,
  2262. PMAC_ADDRESS pMacAddr2
  2263. )
  2264. /*++
  2265. Routine Description:
  2266. Compares two 48bit(6 Byte) MAC Addresses.
  2267. Arguments:
  2268. pMacAddr1 - First MAC Address.
  2269. pMacAddr2 - Second MAC Address.
  2270. Return Value:
  2271. 1 if equal, 0 if not equal.
  2272. --*/
  2273. {
  2274. ULONG Result;
  2275. TRACEIN(MacAddrEqual);
  2276. //
  2277. // Assume not equal
  2278. //
  2279. Result = 0;
  2280. do
  2281. {
  2282. //
  2283. // Studies have shown the fifth byte to be
  2284. // the most unique on a network.
  2285. //
  2286. if (pMacAddr1->Byte[4] != pMacAddr2->Byte[4])
  2287. break;
  2288. if (pMacAddr1->Byte[5] != pMacAddr2->Byte[5])
  2289. break;
  2290. if (pMacAddr1->Byte[3] != pMacAddr2->Byte[3])
  2291. break;
  2292. if (pMacAddr1->Byte[2] != pMacAddr2->Byte[2])
  2293. break;
  2294. if (pMacAddr1->Byte[1] != pMacAddr2->Byte[1])
  2295. break;
  2296. if (pMacAddr1->Byte[0] != pMacAddr2->Byte[0])
  2297. break;
  2298. Result = 1;
  2299. break;
  2300. }
  2301. while (FALSE);
  2302. TRACEOUT(MacAddrEqual);
  2303. return Result;
  2304. }
  2305. VOID
  2306. AtmLaneAbortMacEntry(
  2307. IN PATMLANE_MAC_ENTRY pMacEntry
  2308. )
  2309. /*++
  2310. Routine Description:
  2311. Clean up and delete an Mac entry.
  2312. The caller is assumed to hold a lock to the Mac Entry,
  2313. which will be released here.
  2314. Arguments:
  2315. pMacEntry - Pointer to Mac Entry to be deleted.
  2316. Return Value:
  2317. None
  2318. --*/
  2319. {
  2320. PATMLANE_ELAN pElan;
  2321. PATMLANE_MAC_ENTRY * ppNextMacEntry;
  2322. ULONG rc;
  2323. BOOLEAN Found;
  2324. BOOLEAN TimerWasRunning;
  2325. ULONG HashIndex;
  2326. PNDIS_PACKET pNdisPacket;
  2327. TRACEIN(AbortMacEntry);
  2328. DBGP((1, "%d Del MAC %x: %s\n",
  2329. pMacEntry->pElan->ElanNumber,
  2330. pMacEntry,
  2331. MacAddrToString(&pMacEntry->MacAddress)));
  2332. //
  2333. // Initialize.
  2334. //
  2335. rc = pMacEntry->RefCount;
  2336. pElan = pMacEntry->pElan;
  2337. do
  2338. {
  2339. if (IS_FLAG_SET(
  2340. pMacEntry->Flags,
  2341. MAC_ENTRY_STATE_MASK,
  2342. MAC_ENTRY_ABORTING))
  2343. {
  2344. DBGP((1, "%d MAC %x already aborting\n",
  2345. pMacEntry->pElan->ElanNumber,
  2346. pMacEntry));
  2347. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2348. break;
  2349. }
  2350. //
  2351. // Set State to ABORTING
  2352. //
  2353. SET_FLAG(
  2354. pMacEntry->Flags,
  2355. MAC_ENTRY_STATE_MASK,
  2356. MAC_ENTRY_ABORTING);
  2357. //
  2358. // Put temp reference on mac entry
  2359. //
  2360. AtmLaneReferenceMacEntry(pMacEntry, "temp");
  2361. //
  2362. // Reacquire the desired locks in the right order.
  2363. //
  2364. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2365. ACQUIRE_ELAN_MAC_TABLE_LOCK(pElan);
  2366. ACQUIRE_MAC_ENTRY_LOCK_DPC(pMacEntry);
  2367. //
  2368. // Unlink this MAC Entry from the MAC Table
  2369. //
  2370. Found = FALSE;
  2371. HashIndex = ATMLANE_HASH(&pMacEntry->MacAddress);
  2372. ppNextMacEntry = &(pElan->pMacTable[HashIndex]);
  2373. while (*ppNextMacEntry != NULL_PATMLANE_MAC_ENTRY)
  2374. {
  2375. if (*ppNextMacEntry == pMacEntry)
  2376. {
  2377. //
  2378. // Make the predecessor point to the next
  2379. // in the list.
  2380. //
  2381. *ppNextMacEntry = pMacEntry->pNextEntry;
  2382. Found = TRUE;
  2383. pElan->NumMacEntries--;
  2384. break;
  2385. }
  2386. else
  2387. {
  2388. ppNextMacEntry = &((*ppNextMacEntry)->pNextEntry);
  2389. }
  2390. }
  2391. if (Found)
  2392. {
  2393. AtmLaneDereferenceMacEntry(pMacEntry, "table");
  2394. }
  2395. RELEASE_MAC_ENTRY_LOCK_DPC(pMacEntry);
  2396. RELEASE_ELAN_MAC_TABLE_LOCK(pElan);
  2397. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2398. //
  2399. // Unlink MAC Entry from the Atm Entry
  2400. //
  2401. if (pMacEntry->pAtmEntry != NULL_PATMLANE_ATM_ENTRY)
  2402. {
  2403. SET_FLAG(
  2404. pMacEntry->Flags,
  2405. MAC_ENTRY_STATE_MASK,
  2406. MAC_ENTRY_NEW);
  2407. Found = AtmLaneUnlinkMacEntryFromAtmEntry(pMacEntry);
  2408. pMacEntry->pAtmEntry = NULL_PATMLANE_ATM_ENTRY;
  2409. if (Found)
  2410. {
  2411. AtmLaneDereferenceMacEntry(pMacEntry, "atm");
  2412. }
  2413. }
  2414. //
  2415. // Stop Arp or Aging timer running on the MAC Entry.
  2416. //
  2417. TimerWasRunning = AtmLaneStopTimer(&(pMacEntry->Timer), pElan);
  2418. if (TimerWasRunning)
  2419. {
  2420. AtmLaneDereferenceMacEntry(pMacEntry, "timer");
  2421. }
  2422. //
  2423. // Stop Bus Timer
  2424. //
  2425. NdisCancelTimer(&pMacEntry->BusTimer, &TimerWasRunning);
  2426. if (TimerWasRunning)
  2427. {
  2428. AtmLaneDereferenceMacEntry(pMacEntry, "bus timer");
  2429. }
  2430. //
  2431. // Stop Flush Timer
  2432. //
  2433. TimerWasRunning = AtmLaneStopTimer(&pMacEntry->FlushTimer, pElan);
  2434. if (TimerWasRunning)
  2435. {
  2436. AtmLaneDereferenceMacEntry(pMacEntry, "flush timer");
  2437. }
  2438. //
  2439. // Now complete all packets hanging on the MacEntry
  2440. //
  2441. DBGP((1, "%d: Aborting MAC %x, Before: PktList %x, PktListCount %d\n",
  2442. pElan->ElanNumber, pMacEntry, pMacEntry->PacketList, pMacEntry->PacketListCount));
  2443. AtmLaneFreePacketQueue(pMacEntry, NDIS_STATUS_SUCCESS);
  2444. DBGP((1, "%d: Aborting MAC %x, After: PktList %x, PktListCount %d\n",
  2445. pElan->ElanNumber, pMacEntry, pMacEntry->PacketList, pMacEntry->PacketListCount));
  2446. //
  2447. // Remove temp reference and unlock if still around
  2448. //
  2449. rc = AtmLaneDereferenceMacEntry(pMacEntry, "temp");
  2450. if (rc > 0)
  2451. {
  2452. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2453. }
  2454. }
  2455. while (FALSE);
  2456. TRACEOUT(AbortMacEntry);
  2457. return;
  2458. }
  2459. VOID
  2460. AtmLaneMacEntryAgingTimeout(
  2461. IN PATMLANE_TIMER pTimer,
  2462. IN PVOID Context
  2463. )
  2464. /*++
  2465. Routine Description:
  2466. This routine is called if some time has passed since an
  2467. MAC entry was last validated.
  2468. If there is no VC associated with this MAC entry, delete it.
  2469. If there has been no sends on the entry since last validated, delete it.
  2470. Otherwise revalidate the entry by starting the ARP protocol.
  2471. Arguments:
  2472. pTimer - Pointer to timer that went off
  2473. Context - Actually a pointer to our ATMLANE Mac Entry structure
  2474. Return Value:
  2475. None
  2476. --*/
  2477. {
  2478. PATMLANE_MAC_ENTRY pMacEntry; // Mac Entry that has aged out
  2479. ULONG rc; // Ref count on Mac Entry
  2480. PATMLANE_VC pVc; // VC going to this Mac Entry
  2481. ULONG Flags; // Flags on above VC
  2482. PATMLANE_ELAN pElan;
  2483. PATMLANE_ATM_ENTRY pAtmEntry;
  2484. TRACEOUT(MacEntryAgingTimeout);
  2485. pMacEntry = (PATMLANE_MAC_ENTRY)Context;
  2486. STRUCT_ASSERT(pMacEntry, atmlane_mac);
  2487. do
  2488. {
  2489. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2490. DBGP((2, "MacEntryAgingTimeout: pMacEntry %x MacAddr %s\n",
  2491. pMacEntry, MacAddrToString(&pMacEntry->MacAddress)));
  2492. rc = AtmLaneDereferenceMacEntry(pMacEntry, "aging timer");
  2493. if (rc == 0)
  2494. {
  2495. break; // It's gone!
  2496. }
  2497. //
  2498. // Continue only if the Elan is not going down
  2499. //
  2500. pElan = pMacEntry->pElan;
  2501. if (ELAN_STATE_OPERATIONAL != pElan->AdminState)
  2502. {
  2503. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2504. break;
  2505. }
  2506. pVc = NULL_PATMLANE_VC;
  2507. pAtmEntry = pMacEntry->pAtmEntry;
  2508. if (pAtmEntry != NULL_PATMLANE_ATM_ENTRY)
  2509. {
  2510. pVc = pAtmEntry->pVcList;
  2511. }
  2512. if (pVc != NULL_PATMLANE_VC &&
  2513. (pMacEntry->Flags & MAC_ENTRY_USED_FOR_SEND) != 0)
  2514. {
  2515. //
  2516. // There is a VC for this Mac Address and it's been
  2517. // used for a send in the last aging period.
  2518. // So we try to revalidate this Mac entry.
  2519. //
  2520. //
  2521. // Set state to AGED
  2522. //
  2523. SET_FLAG(
  2524. pMacEntry->Flags,
  2525. MAC_ENTRY_STATE_MASK,
  2526. MAC_ENTRY_AGED);
  2527. pMacEntry->Flags &= ~ MAC_ENTRY_USED_FOR_SEND;
  2528. //
  2529. // Send ARP Request
  2530. //
  2531. pMacEntry->RetriesLeft = pElan->MaxRetryCount;
  2532. AtmLaneReferenceMacEntry(pMacEntry, "timer");
  2533. AtmLaneStartTimer(
  2534. pElan,
  2535. &pMacEntry->Timer,
  2536. AtmLaneArpTimeout,
  2537. pElan->ArpResponseTime,
  2538. (PVOID)pMacEntry
  2539. );
  2540. AtmLaneSendArpRequest(pElan, pMacEntry);
  2541. //
  2542. // MAC Entry lock released in above
  2543. //
  2544. }
  2545. else
  2546. {
  2547. //
  2548. // No VC associated with this Mac Entry or
  2549. // it hasn't been used in last aging period.
  2550. // Delete it.
  2551. //
  2552. AtmLaneAbortMacEntry(pMacEntry);
  2553. //
  2554. // The Mac Entry lock is released in the above routine.
  2555. //
  2556. }
  2557. }
  2558. while (FALSE);
  2559. TRACEOUT(MacEntryAgingTimeout);
  2560. return;
  2561. }
  2562. VOID
  2563. AtmLaneArpTimeout(
  2564. IN PATMLANE_TIMER pTimer,
  2565. IN PVOID Context
  2566. )
  2567. /*++
  2568. Routine Description:
  2569. This is called when we time out waiting for a response to an ARP Request
  2570. we had sent ages ago in order to resolve/refresh an MAC entry.
  2571. Check if we have tried enough times. If we have retries left, send another
  2572. ARP Request.
  2573. If we have run out of retries, delete the MAC entry, and any VCs going to it.
  2574. Arguments:
  2575. pTimer - Pointer to timer that went off
  2576. Context - Actually a pointer to our ATMLANE MAC Entry structure
  2577. ContextValue - ignored
  2578. Return Value:
  2579. None
  2580. --*/
  2581. {
  2582. PATMLANE_MAC_ENTRY pMacEntry; // MAC Entry being ARP'ed for.
  2583. PATMLANE_VC pVc; // VC to this MAC destination
  2584. PATMLANE_ELAN pElan;
  2585. ULONG rc; // Ref Count on MAC Entry
  2586. ULONG IsBroadcast;
  2587. TRACEIN(ArpTimeout);
  2588. do
  2589. {
  2590. pMacEntry = (PATMLANE_MAC_ENTRY)Context;
  2591. STRUCT_ASSERT(pMacEntry, atmlane_mac);
  2592. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2593. pElan = pMacEntry->pElan;
  2594. DBGP((2, "ArpTimeout: Mac Entry %x\n", pMacEntry));
  2595. rc = AtmLaneDereferenceMacEntry(pMacEntry, "timer"); // Timer reference
  2596. if (rc == 0)
  2597. {
  2598. break; // It's gone!
  2599. }
  2600. //
  2601. // Retry if any retries left
  2602. //
  2603. if (pMacEntry->RetriesLeft != 0)
  2604. {
  2605. pMacEntry->RetriesLeft--;
  2606. AtmLaneReferenceMacEntry(pMacEntry, "timer");
  2607. AtmLaneStartTimer(
  2608. pElan,
  2609. &pMacEntry->Timer,
  2610. AtmLaneArpTimeout,
  2611. pElan->ArpResponseTime,
  2612. (PVOID)pMacEntry
  2613. );
  2614. AtmLaneSendArpRequest(pElan, pMacEntry);
  2615. //
  2616. // MAC Entry lock released in above
  2617. //
  2618. break;
  2619. }
  2620. //
  2621. // Is this the broadcast/BUS entry?
  2622. //
  2623. IsBroadcast = (pMacEntry->Flags & MAC_ENTRY_BROADCAST);
  2624. //
  2625. // We are out of retries. Abort the Mac Entry
  2626. //
  2627. AtmLaneAbortMacEntry(pMacEntry);
  2628. //
  2629. // lock is released in the above routine
  2630. //
  2631. if (IsBroadcast)
  2632. {
  2633. //
  2634. // Signal the event to the state machine
  2635. //
  2636. ACQUIRE_ELAN_LOCK(pElan);
  2637. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_ARP_RESPONSE, NDIS_STATUS_TIMEOUT);
  2638. RELEASE_ELAN_LOCK(pElan);
  2639. }
  2640. }
  2641. while (FALSE);
  2642. TRACEOUT(ArpTimeout);
  2643. return;
  2644. }
  2645. VOID
  2646. AtmLaneConfigureResponseTimeout(
  2647. IN PATMLANE_TIMER pTimer,
  2648. IN PVOID Context
  2649. )
  2650. /*++
  2651. Routine Description:
  2652. This is called when we time out waiting for a response
  2653. to an LE_CONFIGURE_REQUEST we sent to the LECS.
  2654. Arguments:
  2655. pTimer - Pointer to timer that went off
  2656. Context - Actually a pointer to our ATMLANE Elan structure
  2657. Return Value:
  2658. None
  2659. --*/
  2660. {
  2661. PATMLANE_ELAN pElan;
  2662. ULONG rc;
  2663. TRACEIN(ConfigureResponseTimeout);
  2664. pElan = (PATMLANE_ELAN)Context;
  2665. STRUCT_ASSERT(pElan, atmlane_elan);
  2666. do
  2667. {
  2668. ACQUIRE_ELAN_LOCK_DPC(pElan);
  2669. rc = AtmLaneDereferenceElan(pElan, "timer"); // Timer deref
  2670. if (rc == 0)
  2671. {
  2672. //
  2673. // The ELAN is gone.
  2674. //
  2675. break;
  2676. }
  2677. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_CONFIGURE_RESPONSE, NDIS_STATUS_TIMEOUT);
  2678. RELEASE_ELAN_LOCK_DPC(pElan);
  2679. }
  2680. while (FALSE);
  2681. TRACEOUT(ConfigureResponseTimeout);
  2682. return;
  2683. }
  2684. VOID
  2685. AtmLaneJoinResponseTimeout(
  2686. IN PATMLANE_TIMER pTimer,
  2687. IN PVOID Context
  2688. )
  2689. /*++
  2690. Routine Description:
  2691. This is called when we time out waiting for a response
  2692. to an LE_JOIN_REQUEST we sent to the LES.
  2693. Arguments:
  2694. pTimer - Pointer to timer that went off
  2695. Context - Actually a pointer to our ATMLANE Elan structure
  2696. Return Value:
  2697. None
  2698. --*/
  2699. {
  2700. PATMLANE_ELAN pElan;
  2701. ULONG rc;
  2702. TRACEIN(JoinResponseTimeout);
  2703. pElan = (PATMLANE_ELAN)Context;
  2704. STRUCT_ASSERT(pElan, atmlane_elan);
  2705. do
  2706. {
  2707. ACQUIRE_ELAN_LOCK_DPC(pElan);
  2708. rc = AtmLaneDereferenceElan(pElan, "timer"); // Timer deref
  2709. if (rc == 0)
  2710. {
  2711. //
  2712. // The ELAN is gone.
  2713. //
  2714. break;
  2715. }
  2716. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_JOIN_RESPONSE, NDIS_STATUS_TIMEOUT);
  2717. RELEASE_ELAN_LOCK_DPC(pElan);
  2718. }
  2719. while (FALSE);
  2720. TRACEOUT(JoinResponseTimeout);
  2721. return;
  2722. }
  2723. VOID
  2724. AtmLaneInitializeMiniportDevice(
  2725. IN PNDIS_WORK_ITEM NdisWorkItem,
  2726. IN PVOID Context
  2727. )
  2728. {
  2729. PATMLANE_ELAN pElan;
  2730. ULONG rc;
  2731. BOOLEAN bDontBotherToInit;
  2732. NDIS_STATUS Status;
  2733. TRACEIN(InitializeMiniportDevice);
  2734. pElan = (PATMLANE_ELAN)Context;
  2735. STRUCT_ASSERT(pElan, atmlane_elan);
  2736. //
  2737. // If we are shutting down this ELAN (e.g. because we are
  2738. // unbinding from the ATM adapter), then don't bother to
  2739. // initiate MiniportInit.
  2740. //
  2741. ACQUIRE_ELAN_LOCK(pElan);
  2742. if (pElan->AdminState == ELAN_STATE_SHUTDOWN)
  2743. {
  2744. bDontBotherToInit = TRUE;
  2745. }
  2746. else
  2747. {
  2748. bDontBotherToInit = FALSE;
  2749. pElan->Flags |= ELAN_MINIPORT_INIT_PENDING;
  2750. INIT_BLOCK_STRUCT(&pElan->InitBlock);
  2751. }
  2752. RELEASE_ELAN_LOCK(pElan);
  2753. if (!bDontBotherToInit)
  2754. {
  2755. DBGP((1, "%d Miniport INITIALIZING Device %s\n",
  2756. pElan->ElanNumber,
  2757. UnicodeToString(&pElan->CfgDeviceName)));
  2758. Status = NdisIMInitializeDeviceInstanceEx(
  2759. pAtmLaneGlobalInfo->MiniportDriverHandle,
  2760. &pElan->CfgDeviceName,
  2761. (NDIS_HANDLE)pElan);
  2762. if (Status != NDIS_STATUS_SUCCESS)
  2763. {
  2764. DBGP((0, "%d IMInitializeDeviceInstanceEx failed on ELAN %p (%x)\n",
  2765. pElan->ElanNumber, pElan, Status));
  2766. ACQUIRE_ELAN_LOCK(pElan);
  2767. pElan->Flags &= ~ELAN_MINIPORT_INIT_PENDING;
  2768. SIGNAL_BLOCK_STRUCT(&pElan->InitBlock, NDIS_STATUS_SUCCESS);
  2769. RELEASE_ELAN_LOCK(pElan);
  2770. }
  2771. }
  2772. ACQUIRE_ELAN_LOCK(pElan);
  2773. rc = AtmLaneDereferenceElan(pElan, "workitem");
  2774. if (rc > 0)
  2775. {
  2776. RELEASE_ELAN_LOCK(pElan);
  2777. }
  2778. TRACEOUT(InitializeMiniportDevice);
  2779. return;
  2780. }
  2781. VOID
  2782. AtmLaneDeinitializeMiniportDevice(
  2783. IN PNDIS_WORK_ITEM NdisWorkItem,
  2784. IN PVOID Context
  2785. )
  2786. {
  2787. PATMLANE_ELAN pElan;
  2788. NDIS_STATUS Status;
  2789. ULONG rc;
  2790. NDIS_HANDLE AdapterHandle;
  2791. TRACEIN(DeinitializeMiniportDevice);
  2792. pElan = (PATMLANE_ELAN)Context;
  2793. STRUCT_ASSERT(pElan, atmlane_elan);
  2794. DBGP((1, "%d Miniport DEINITIALIZING, AdapterHandle %x, RefCount %d\n",
  2795. pElan->ElanNumber, pElan->MiniportAdapterHandle, pElan->RefCount));
  2796. ACQUIRE_ELAN_LOCK(pElan);
  2797. AdapterHandle = pElan->MiniportAdapterHandle;
  2798. RELEASE_ELAN_LOCK(pElan);
  2799. if (NULL != AdapterHandle)
  2800. {
  2801. DBGP((1, "Will call NdisIMDeInit %x\n", AdapterHandle));
  2802. Status = NdisIMDeInitializeDeviceInstance(AdapterHandle);
  2803. ASSERT(Status == NDIS_STATUS_SUCCESS);
  2804. //
  2805. // Our MHalt routine will be called at some point.
  2806. //
  2807. }
  2808. //
  2809. // else our MHalt routine was called already.
  2810. //
  2811. DBGP((0, "DeInit completing, pElan %x, RefCount %d, State %d\n",
  2812. pElan, pElan->RefCount, pElan->State));
  2813. ACQUIRE_ELAN_LOCK(pElan);
  2814. rc = AtmLaneDereferenceElan(pElan, "workitem");
  2815. if (rc > 0)
  2816. {
  2817. RELEASE_ELAN_LOCK(pElan);
  2818. }
  2819. TRACEOUT(DeinitializeMiniportDevice);
  2820. return;
  2821. }
  2822. VOID
  2823. AtmLaneReadyTimeout(
  2824. IN PATMLANE_TIMER pTimer,
  2825. IN PVOID Context
  2826. )
  2827. /*++
  2828. Routine Description:
  2829. This is called when we time out waiting for a ready indication
  2830. on a incoming data direct VC.
  2831. Arguments:
  2832. pTimer - Pointer to timer that went off
  2833. Context - Actually a pointer to an ATMLANE Vc structure
  2834. Return Value:
  2835. None
  2836. --*/
  2837. {
  2838. PATMLANE_VC pVc;
  2839. PATMLANE_ELAN pElan;
  2840. ULONG rc;
  2841. TRACEIN(AtmLaneReadyTimeout);
  2842. pVc = (PATMLANE_VC)Context;
  2843. STRUCT_ASSERT(pVc, atmlane_vc);
  2844. pElan = pVc->pElan;
  2845. STRUCT_ASSERT(pElan, atmlane_elan);
  2846. do
  2847. {
  2848. ACQUIRE_VC_LOCK(pVc);
  2849. //
  2850. // Remove ready timer reference
  2851. //
  2852. rc = AtmLaneDereferenceVc(pVc, "ready timer");
  2853. if (rc == 0)
  2854. {
  2855. break;
  2856. }
  2857. //
  2858. // Vc is still around, check state
  2859. //
  2860. if (!IS_FLAG_SET(
  2861. pVc->Flags,
  2862. VC_CALL_STATE_MASK,
  2863. VC_CALL_STATE_ACTIVE
  2864. ))
  2865. {
  2866. RELEASE_VC_LOCK(pVc);
  2867. break;
  2868. }
  2869. //
  2870. // Check if any retries left
  2871. //
  2872. if (pVc->RetriesLeft--)
  2873. {
  2874. //
  2875. // Start timer again
  2876. //
  2877. SET_FLAG(
  2878. pVc->Flags,
  2879. VC_READY_STATE_MASK,
  2880. VC_READY_WAIT
  2881. );
  2882. AtmLaneReferenceVc(pVc, "ready timer");
  2883. AtmLaneStartTimer(
  2884. pElan,
  2885. &pVc->ReadyTimer,
  2886. AtmLaneReadyTimeout,
  2887. pElan->ConnComplTimer,
  2888. pVc);
  2889. //
  2890. // Send Ready Query
  2891. //
  2892. AtmLaneSendReadyQuery(pElan, pVc);
  2893. //
  2894. // VC lock is released in above.
  2895. //
  2896. }
  2897. else
  2898. {
  2899. //
  2900. // Give up and mark as having received indication anyway
  2901. //
  2902. SET_FLAG(
  2903. pVc->Flags,
  2904. VC_READY_STATE_MASK,
  2905. VC_READY_INDICATED
  2906. );
  2907. RELEASE_VC_LOCK(pVc);
  2908. }
  2909. }
  2910. while (FALSE);
  2911. TRACEOUT(AtmLaneReadyTimeout);
  2912. return;
  2913. }
  2914. VOID
  2915. AtmLaneFlushTimeout(
  2916. IN PATMLANE_TIMER pTimer,
  2917. IN PVOID Context
  2918. )
  2919. /*++
  2920. Routine Description:
  2921. This is called when we time out waiting for a response to a FLUSH Request.
  2922. Arguments:
  2923. pTimer - Pointer to timer that went off
  2924. Context - Actually a pointer to a ATMLANE MAC Entry structure
  2925. Return Value:
  2926. None
  2927. --*/
  2928. {
  2929. PATMLANE_MAC_ENTRY pMacEntry;
  2930. PATMLANE_ATM_ENTRY pAtmEntry;
  2931. PATMLANE_VC pVc;
  2932. PNDIS_PACKET pNdisPacket;
  2933. ULONG rc;
  2934. TRACEIN(FlushTimeout);
  2935. pMacEntry = (PATMLANE_MAC_ENTRY)Context;
  2936. STRUCT_ASSERT(pMacEntry, atmlane_mac);
  2937. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2938. do
  2939. {
  2940. if (!IS_FLAG_SET(
  2941. pMacEntry->Flags,
  2942. MAC_ENTRY_STATE_MASK,
  2943. MAC_ENTRY_FLUSHING))
  2944. {
  2945. DBGP((0, "%d FlushTimeout: MacEntry %p, bad state, Flags %x\n",
  2946. pMacEntry->pElan->ElanNumber,
  2947. pMacEntry,
  2948. pMacEntry->Flags));
  2949. break;
  2950. }
  2951. if (pMacEntry->pAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  2952. {
  2953. DBGP((0, "%d FlushTimeout: Mac Entry %p, Flags %x, NULL AtmEntry\n",
  2954. pMacEntry->pElan->ElanNumber,
  2955. pMacEntry,
  2956. pMacEntry->Flags));
  2957. SET_FLAG(
  2958. pMacEntry->Flags,
  2959. MAC_ENTRY_STATE_MASK,
  2960. MAC_ENTRY_NEW);
  2961. break;
  2962. }
  2963. //
  2964. // Mark MAC Entry active
  2965. //
  2966. SET_FLAG(
  2967. pMacEntry->Flags,
  2968. MAC_ENTRY_STATE_MASK,
  2969. MAC_ENTRY_ACTIVE);
  2970. //
  2971. // Send any queued packets
  2972. //
  2973. if (pMacEntry->PacketList == (PNDIS_PACKET)NULL)
  2974. {
  2975. break;
  2976. }
  2977. pVc = pMacEntry->pAtmEntry->pVcList;
  2978. if (pVc == NULL_PATMLANE_VC)
  2979. {
  2980. break;
  2981. }
  2982. ACQUIRE_VC_LOCK(pVc);
  2983. //
  2984. // Make sure this VC doesn't go away.
  2985. //
  2986. AtmLaneReferenceVc(pVc, "flushtemp");
  2987. RELEASE_VC_LOCK(pVc);
  2988. while ((pNdisPacket = AtmLaneDequeuePacketFromHead(pMacEntry)) !=
  2989. (PNDIS_PACKET)NULL)
  2990. {
  2991. //
  2992. // Send it
  2993. //
  2994. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2995. ACQUIRE_VC_LOCK(pVc);
  2996. AtmLaneSendPacketOnVc(pVc, pNdisPacket, TRUE);
  2997. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2998. }
  2999. ACQUIRE_VC_LOCK(pVc);
  3000. rc = AtmLaneDereferenceVc(pVc, "flushtemp");
  3001. if (rc != 0)
  3002. {
  3003. RELEASE_VC_LOCK(pVc);
  3004. }
  3005. break;
  3006. }
  3007. while (FALSE);
  3008. rc = AtmLaneDereferenceMacEntry(pMacEntry, "flush timer");
  3009. if (rc != 0)
  3010. {
  3011. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  3012. }
  3013. TRACEOUT(FlushTimeout);
  3014. return;
  3015. }
  3016. VOID
  3017. AtmLaneVcAgingTimeout(
  3018. IN PATMLANE_TIMER pTimer,
  3019. IN PVOID Context
  3020. )
  3021. /*++
  3022. Routine Description:
  3023. This is called when the VC aging timeout fires.
  3024. It will fire if this VC hasn't been used to transmit
  3025. a packet for the timeout period. The VC will be
  3026. closed unless it has had receive activity since the last
  3027. timeout. The data receive path sets a flag if a packet
  3028. has been received.
  3029. Arguments:
  3030. pTimer - Pointer to timer that went off
  3031. Context - Actually a pointer to a ATMLANE VC structure
  3032. Return Value:
  3033. None
  3034. --*/
  3035. {
  3036. PATMLANE_VC pVc;
  3037. ULONG rc;
  3038. PATMLANE_ELAN pElan;
  3039. TRACEIN(VcAgingTimeout);
  3040. do
  3041. {
  3042. pVc = (PATMLANE_VC)Context;
  3043. STRUCT_ASSERT(pVc, atmlane_vc);
  3044. ASSERT(IS_FLAG_SET(pVc->Flags, VC_TYPE_MASK, VC_TYPE_SVC));
  3045. ACQUIRE_VC_LOCK(pVc);
  3046. pElan = pVc->pElan;
  3047. //
  3048. // Continue only if VC still active
  3049. // Otherwise dereference, unlock it, and return
  3050. //
  3051. if (!(IS_FLAG_SET(pVc->Flags,
  3052. VC_CALL_STATE_MASK,
  3053. VC_CALL_STATE_ACTIVE)))
  3054. {
  3055. rc = AtmLaneDereferenceVc(pVc, "aging timer");
  3056. if (rc > 0)
  3057. {
  3058. RELEASE_VC_LOCK(pVc);
  3059. }
  3060. break;
  3061. }
  3062. //
  3063. // Continue only if the ELAN isn't going down
  3064. // Otherwise dereference, unlock it, and return
  3065. //
  3066. if (ELAN_STATE_OPERATIONAL != pElan->AdminState)
  3067. {
  3068. rc = AtmLaneDereferenceVc(pVc, "aging timer");
  3069. if (rc > 0)
  3070. {
  3071. RELEASE_VC_LOCK(pVc);
  3072. }
  3073. break;
  3074. }
  3075. //
  3076. // If received activity is non-zero,
  3077. // clear flag, restart aging timer, release lock
  3078. // and return
  3079. //
  3080. if (pVc->ReceiveActivity != 0)
  3081. {
  3082. pVc->ReceiveActivity = 0;
  3083. // timer reference still on VC no need to re-reference
  3084. AtmLaneStartTimer(
  3085. pElan,
  3086. &pVc->AgingTimer,
  3087. AtmLaneVcAgingTimeout,
  3088. pVc->AgingTime,
  3089. (PVOID)pVc
  3090. );
  3091. DBGP((1, "%d Vc %x aging timer refreshed due to receive activity\n",
  3092. pVc->pElan->ElanNumber,
  3093. pVc));
  3094. RELEASE_VC_LOCK(pVc);
  3095. break;
  3096. }
  3097. //
  3098. // VC is to be closed
  3099. //
  3100. DBGP((1, "%d Vc %x aged out\n",
  3101. pVc->pElan->ElanNumber,
  3102. pVc));
  3103. DBGP((3, "VcAgingTimeout: Vc %x RefCount %d Flags %x pAtmEntry %x\n",
  3104. pVc, pVc->RefCount, pVc->Flags, pVc->pAtmEntry));
  3105. //
  3106. // Remove timer reference and return if refcount goes to zero
  3107. //
  3108. rc = AtmLaneDereferenceVc(pVc, "aging timer");
  3109. if (rc == 0)
  3110. {
  3111. break;
  3112. }
  3113. //
  3114. // Take this VC out of the VC list for this ATM destination
  3115. // and return if refcount goes to zero
  3116. //
  3117. if (pVc->pAtmEntry != NULL_PATMLANE_ATM_ENTRY)
  3118. {
  3119. if (AtmLaneUnlinkVcFromAtmEntry(pVc))
  3120. {
  3121. rc = AtmLaneDereferenceVc(pVc, "atm");
  3122. if (rc == 0)
  3123. {
  3124. break;
  3125. }
  3126. }
  3127. }
  3128. //
  3129. // Close this VC
  3130. //
  3131. AtmLaneCloseCall(pVc);
  3132. //
  3133. // The VC lock is released in CloseCall
  3134. //
  3135. } while (FALSE);
  3136. TRACEOUT(VcAgingTimeout);
  3137. return;
  3138. }
  3139. VOID
  3140. AtmLaneShutdownElan(
  3141. IN PATMLANE_ELAN pElan LOCKIN NOLOCKOUT,
  3142. IN BOOLEAN Restart
  3143. )
  3144. /*++
  3145. Routine Description:
  3146. This routine will "shutdown" an ELAN prior to it going back
  3147. to the Initial state or driver shutdown. The caller is
  3148. expected to hold the ELAN lock and it will be released here.
  3149. Arguments:
  3150. pElan - Pointer to an ATMLANE Elan structure.
  3151. Restart - If TRUE ELAN should restart at Initial state.
  3152. If FALSE ELAN should not restart.
  3153. Return Value:
  3154. None
  3155. --*/
  3156. {
  3157. PATMLANE_ATM_ENTRY pAtmEntry;
  3158. PATMLANE_ATM_ENTRY pNextAtmEntry;
  3159. PATMLANE_MAC_ENTRY pMacEntry;
  3160. ULONG rc;
  3161. ULONG i;
  3162. BOOLEAN WasCancelled;
  3163. NDIS_STATUS Status;
  3164. NDIS_HANDLE NdisAfHandle;
  3165. BOOLEAN bTempRef;
  3166. TRACEIN(ShutdownElan);
  3167. STRUCT_ASSERT(pElan, atmlane_elan);
  3168. //
  3169. // Add a temp ref
  3170. //
  3171. bTempRef = TRUE;
  3172. AtmLaneReferenceElan(pElan, "tempshutdown");
  3173. do
  3174. {
  3175. DBGP((0, "%d ShutDownElan pElan %p/%x, Ref %d State %d, Restart %d\n",
  3176. pElan->ElanNumber, pElan, pElan->Flags, pElan->RefCount, pElan->State,
  3177. Restart));
  3178. //
  3179. // If state already == SHUTDOWN nothing to do
  3180. //
  3181. if (ELAN_STATE_SHUTDOWN == pElan->State)
  3182. {
  3183. RELEASE_ELAN_LOCK(pElan);
  3184. break;
  3185. }
  3186. //
  3187. // If we are transitioning from operational to shutdown,
  3188. // and our miniport is active, then indicate a media disconnect
  3189. // event.
  3190. //
  3191. if (pElan->State == ELAN_STATE_OPERATIONAL &&
  3192. pElan->MiniportAdapterHandle != NULL)
  3193. {
  3194. NdisMIndicateStatus(
  3195. pElan->MiniportAdapterHandle,
  3196. NDIS_STATUS_MEDIA_DISCONNECT,
  3197. NULL,
  3198. 0);
  3199. NdisMIndicateStatusComplete(pElan->MiniportAdapterHandle);
  3200. }
  3201. //
  3202. // Change state to shutdown. If restarting state will
  3203. // be changed back to init after cleanup below.
  3204. //
  3205. pElan->AdminState = ELAN_STATE_SHUTDOWN;
  3206. pElan->State = ELAN_STATE_SHUTDOWN;
  3207. //
  3208. // Wait for any pending OpenAF operation to finish.
  3209. //
  3210. while (pElan->Flags & ELAN_OPENING_AF)
  3211. {
  3212. RELEASE_ELAN_LOCK(pElan);
  3213. DBGP((0, "%d: Shutdown Elan %p/%x is opening AF\n",
  3214. pElan->ElanNumber, pElan, pElan->Flags));
  3215. (VOID)WAIT_ON_BLOCK_STRUCT(&pElan->AfBlock);
  3216. ACQUIRE_ELAN_LOCK(pElan);
  3217. }
  3218. NdisAfHandle = pElan->NdisAfHandle;
  3219. pElan->NdisAfHandle = NULL;
  3220. if (Restart)
  3221. {
  3222. pElan->Flags |= ELAN_NEEDS_RESTART;
  3223. }
  3224. //
  3225. // Are we waiting for MiniportInitialize to run and finish?
  3226. // If so, try to cancel IMInit.
  3227. //
  3228. if (pElan->Flags & ELAN_MINIPORT_INIT_PENDING)
  3229. {
  3230. RELEASE_ELAN_LOCK(pElan);
  3231. Status = NdisIMCancelInitializeDeviceInstance(
  3232. pAtmLaneGlobalInfo->MiniportDriverHandle,
  3233. &pElan->CfgDeviceName);
  3234. DBGP((0, "%d ShutdownElan Elan %p/%x, Ref %d, CancelInit returned %x\n",
  3235. pElan->ElanNumber, pElan, pElan->Flags, pElan->RefCount, Status));
  3236. if (Status == NDIS_STATUS_SUCCESS)
  3237. {
  3238. //
  3239. // Canceled the IMInit process.
  3240. //
  3241. ACQUIRE_ELAN_LOCK(pElan);
  3242. pElan->Flags &= ~ELAN_MINIPORT_INIT_PENDING;
  3243. }
  3244. else
  3245. {
  3246. //
  3247. // Our MiniportInit function -will- be called.
  3248. // Wait for it to finish.
  3249. //
  3250. (VOID)WAIT_ON_BLOCK_STRUCT(&pElan->InitBlock);
  3251. DBGP((2, "%d: Shutdown ELAN %p, Flags %x, woke up from InitBlock\n",
  3252. pElan->ElanNumber, pElan, pElan->Flags));
  3253. ACQUIRE_ELAN_LOCK(pElan);
  3254. ASSERT((pElan->Flags & ELAN_MINIPORT_INIT_PENDING) == 0);
  3255. }
  3256. }
  3257. //
  3258. // Stop any timers running on the elan.
  3259. //
  3260. if (AtmLaneStopTimer(&pElan->Timer, pElan))
  3261. {
  3262. rc = AtmLaneDereferenceElan(pElan, "timer"); // Timer ref
  3263. ASSERT(rc > 0);
  3264. }
  3265. if (NULL != pElan->pDelayedEvent)
  3266. {
  3267. BOOLEAN TimerCancelled;
  3268. NdisCancelTimer(
  3269. &pElan->pDelayedEvent->DelayTimer,
  3270. &TimerCancelled);
  3271. DBGP((0, "ATMLANE: %d ShutdownElan %p, DelayedEvent %p, Cancelled %d\n",
  3272. pElan->ElanNumber,
  3273. pElan,
  3274. pElan->pDelayedEvent,
  3275. TimerCancelled));
  3276. if (TimerCancelled)
  3277. {
  3278. FREE_MEM(pElan->pDelayedEvent);
  3279. pElan->pDelayedEvent = NULL;
  3280. rc = AtmLaneDereferenceElan(pElan, "delayeventcancel");
  3281. ASSERT(rc > 0);
  3282. }
  3283. }
  3284. RELEASE_ELAN_LOCK(pElan);
  3285. //
  3286. // Deregister all SAPs.
  3287. //
  3288. AtmLaneDeregisterSaps(pElan);
  3289. //
  3290. // Abort all MAC table entries.
  3291. //
  3292. for (i = 0; i < ATMLANE_MAC_TABLE_SIZE; i++)
  3293. {
  3294. ACQUIRE_ELAN_MAC_TABLE_LOCK(pElan);
  3295. while (pElan->pMacTable[i] != NULL_PATMLANE_MAC_ENTRY)
  3296. {
  3297. pMacEntry = pElan->pMacTable[i];
  3298. //
  3299. // Place a temp ref so that this won't go away
  3300. // when we release the MAC table lock.
  3301. //
  3302. ACQUIRE_MAC_ENTRY_LOCK_DPC(pMacEntry);
  3303. AtmLaneReferenceMacEntry(pMacEntry, "ShutDownTemp");
  3304. RELEASE_MAC_ENTRY_LOCK_DPC(pMacEntry);
  3305. RELEASE_ELAN_MAC_TABLE_LOCK(pElan);
  3306. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  3307. //
  3308. // Remove the temp ref
  3309. //
  3310. rc = AtmLaneDereferenceMacEntry(pMacEntry, "ShutDownTemp");
  3311. if (rc != 0)
  3312. {
  3313. AtmLaneAbortMacEntry(pMacEntry);
  3314. //
  3315. // MAC Entry Lock is released within the above.
  3316. //
  3317. }
  3318. //
  3319. // else the MAC entry is gone.
  3320. //
  3321. ACQUIRE_ELAN_MAC_TABLE_LOCK(pElan);
  3322. }
  3323. RELEASE_ELAN_MAC_TABLE_LOCK(pElan);
  3324. }
  3325. //
  3326. // Abort all ATM Entries.
  3327. //
  3328. // First, run through the list and reference
  3329. // all of them first, so that we don't
  3330. // skip to an invalid pointer when aborting the entries.
  3331. //
  3332. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  3333. for (pAtmEntry = pElan->pAtmEntryList;
  3334. pAtmEntry != NULL_PATMLANE_ATM_ENTRY;
  3335. pAtmEntry = pNextAtmEntry)
  3336. {
  3337. ACQUIRE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  3338. pAtmEntry->Flags |= ATM_ENTRY_WILL_ABORT;
  3339. AtmLaneReferenceAtmEntry(pAtmEntry, "tempS");
  3340. pNextAtmEntry = pAtmEntry->pNext;
  3341. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  3342. }
  3343. //
  3344. // Now, do the actual abort.
  3345. //
  3346. pAtmEntry = pElan->pAtmEntryList;
  3347. while (pAtmEntry != NULL_PATMLANE_ATM_ENTRY)
  3348. {
  3349. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  3350. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  3351. pNextAtmEntry = pAtmEntry->pNext;
  3352. AtmLaneInvalidateAtmEntry(pAtmEntry);
  3353. //
  3354. // The ATM Entry lock is released within the above.
  3355. //
  3356. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  3357. pAtmEntry = pNextAtmEntry;
  3358. }
  3359. //
  3360. // Remove all temp references.
  3361. //
  3362. for (pAtmEntry = pElan->pAtmEntryList;
  3363. pAtmEntry != NULL_PATMLANE_ATM_ENTRY;
  3364. pAtmEntry = pNextAtmEntry)
  3365. {
  3366. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  3367. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  3368. ASSERT(pAtmEntry->Flags & ATM_ENTRY_WILL_ABORT);
  3369. pAtmEntry->Flags &= ~ATM_ENTRY_WILL_ABORT;
  3370. pNextAtmEntry = pAtmEntry->pNext;
  3371. rc = AtmLaneDereferenceAtmEntry(pAtmEntry,"tempS");
  3372. if (rc != 0)
  3373. {
  3374. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  3375. }
  3376. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  3377. }
  3378. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  3379. //
  3380. // Remove the temp ref
  3381. //
  3382. STRUCT_ASSERT(pElan, atmlane_elan);
  3383. bTempRef = FALSE;
  3384. ACQUIRE_ELAN_LOCK(pElan);
  3385. rc = AtmLaneDereferenceElan(pElan, "tempshutdown");
  3386. if (rc == 0)
  3387. {
  3388. break;
  3389. }
  3390. RELEASE_ELAN_LOCK(pElan);
  3391. if (NULL != NdisAfHandle)
  3392. {
  3393. Status = NdisClCloseAddressFamily(NdisAfHandle);
  3394. if (NDIS_STATUS_PENDING != Status)
  3395. {
  3396. AtmLaneCloseAfCompleteHandler(Status, (NDIS_HANDLE)pElan);
  3397. }
  3398. }
  3399. else
  3400. {
  3401. AtmLaneContinueShutdownElan(pElan);
  3402. }
  3403. } while (FALSE);
  3404. if (bTempRef)
  3405. {
  3406. ACQUIRE_ELAN_LOCK(pElan);
  3407. rc = AtmLaneDereferenceElan(pElan, "tempshutdown");
  3408. if (rc != 0)
  3409. {
  3410. RELEASE_ELAN_LOCK(pElan);
  3411. }
  3412. }
  3413. TRACEOUT(ShutdownElan);
  3414. return;
  3415. }
  3416. VOID
  3417. AtmLaneContinueShutdownElan(
  3418. IN PATMLANE_ELAN pElan
  3419. )
  3420. /*++
  3421. Routine Description:
  3422. This routine continues the shutting down process for an ELAN,
  3423. after the Af handle with the Call Manager has been closed.
  3424. Arguments:
  3425. pElan - the ELAN being shutdown.
  3426. Return Value:
  3427. None.
  3428. --*/
  3429. {
  3430. ULONG rc;
  3431. TRACEIN(ContinueShutdownElan);
  3432. DBGP((0, "%d ContinueShutdown ELAN %x Flags 0x%x State %d\n",
  3433. pElan->ElanNumber,
  3434. pElan,
  3435. pElan->Flags,
  3436. pElan->State));
  3437. do
  3438. {
  3439. if (pElan->Flags & ELAN_NEEDS_RESTART)
  3440. {
  3441. ACQUIRE_ELAN_LOCK(pElan);
  3442. //
  3443. // Change state to INIT
  3444. //
  3445. pElan->AdminState = ELAN_STATE_OPERATIONAL;
  3446. pElan->State = ELAN_STATE_INIT;
  3447. pElan->RetriesLeft = 4;
  3448. pElan->Flags &= ~ELAN_NEEDS_RESTART;
  3449. //
  3450. // Clear out the local ATM address so that we start off the
  3451. // ELAN properly when we obtain it from the Call manager.
  3452. //
  3453. NdisZeroMemory(&pElan->AtmAddress, sizeof(ATM_ADDRESS));
  3454. //
  3455. // Empty the event queue and schedule a restart in a little while
  3456. //
  3457. AtmLaneDrainElanEventQueue(pElan);
  3458. AtmLaneQueueElanEventAfterDelay(pElan, ELAN_EVENT_START, 0, 2*1000);
  3459. RELEASE_ELAN_LOCK(pElan);
  3460. }
  3461. else
  3462. {
  3463. //
  3464. // Completely remove the ELAN
  3465. //
  3466. AtmLaneUnlinkElanFromAdapter(pElan);
  3467. ACQUIRE_ELAN_LOCK(pElan);
  3468. //
  3469. // Add workitem reference and remove adapter reference
  3470. //
  3471. AtmLaneReferenceElan(pElan, "workitem");
  3472. rc = AtmLaneDereferenceElan(pElan, "adapter");
  3473. //
  3474. // We are here for one of the following reasons:
  3475. //
  3476. // 1. Unbinding from an ATM adapter
  3477. // 2. The CM asked us to shut down the AF open on an ATM adapter
  3478. // 3. The virtual miniport was halted.
  3479. //
  3480. // If it isn't case (3), then we should make sure that the miniport
  3481. // gets halted, by calling NdisIMDeInitializeDeviceInstance.
  3482. //
  3483. if (pElan->MiniportAdapterHandle != NULL)
  3484. {
  3485. DBGP((1, "%d ContinueShutdown: pElan x%x, scheduling NdisIMDeInit, Handle %x\n",
  3486. pElan->ElanNumber, pElan, pElan->MiniportAdapterHandle));
  3487. //
  3488. // Schedule a PASSIVE_LEVEL thread to call
  3489. // NdisIMInitializeDeviceInstance
  3490. //
  3491. NdisInitializeWorkItem(
  3492. &pElan->NdisWorkItem,
  3493. AtmLaneDeinitializeMiniportDevice,
  3494. pElan);
  3495. // workitem reference already on Elan from above
  3496. NdisScheduleWorkItem(&pElan->NdisWorkItem);
  3497. RELEASE_ELAN_LOCK(pElan);
  3498. }
  3499. else
  3500. {
  3501. //
  3502. // Just remove workitem reference and unlock if Elan still around
  3503. //
  3504. rc = AtmLaneDereferenceElan(pElan, "workitem");
  3505. if (rc > 0)
  3506. RELEASE_ELAN_LOCK(pElan);
  3507. }
  3508. }
  3509. break;
  3510. }
  3511. while (FALSE);
  3512. TRACEOUT(ContinueShutdownElan);
  3513. return;
  3514. }
  3515. VOID
  3516. AtmLaneGetProtocolConfiguration(
  3517. IN NDIS_HANDLE AdapterConfigHandle,
  3518. IN PATMLANE_ADAPTER pAdapter
  3519. )
  3520. /*++
  3521. Routine Description:
  3522. This routine will attempt to get any ATMLANE protocol specific
  3523. configuration information optionally stored under an adapter's
  3524. registry parameters.
  3525. Arguments:
  3526. AdapterConfigHandle - the handle that was returned by
  3527. AtmLaneOpenAdapterConfiguration.
  3528. pAdapter - Pointer to ATMLANE adapter structure.
  3529. Return Value:
  3530. None.
  3531. --*/
  3532. {
  3533. NDIS_STATUS Status;
  3534. PNDIS_CONFIGURATION_PARAMETER ParameterValue;
  3535. ATM_ADDRESS LecsAddress;
  3536. NDIS_STRING ValueName;
  3537. PATMLANE_NAME * ppNext;
  3538. PATMLANE_NAME pName;
  3539. PWSTR pTempStr;
  3540. USHORT StrLength;
  3541. TRACEIN(GetProtocolConfiguration);
  3542. //
  3543. // Get the UpperBindings parameter (it will only exist on Memphis)
  3544. //
  3545. NdisInitUnicodeString(&ValueName, ATMLANE_UPPERBINDINGS_STRING);
  3546. NdisReadConfiguration(
  3547. &Status,
  3548. &ParameterValue,
  3549. AdapterConfigHandle,
  3550. &ValueName,
  3551. NdisParameterString);
  3552. if (NDIS_STATUS_SUCCESS == Status)
  3553. {
  3554. // Copy the string into adapter struct
  3555. (VOID)AtmLaneCopyUnicodeString(
  3556. &(pAdapter->CfgUpperBindings),
  3557. &(ParameterValue->ParameterData.StringData),
  3558. TRUE,
  3559. FALSE);
  3560. DBGP((1, "GetProtocolConfiguration: UpperBindings %s\n",
  3561. UnicodeToString(&pAdapter->CfgUpperBindings)));
  3562. //
  3563. // Existence of this parameter is a definite clue we're running
  3564. // on Memphis/Win98
  3565. //
  3566. pAdapter->RunningOnMemphis = TRUE;
  3567. }
  3568. //
  3569. // Get the ElanName parameter (it will only exist on Memphis)
  3570. //
  3571. NdisInitUnicodeString(&ValueName, ATMLANE_ELANNAME_STRING);
  3572. NdisReadConfiguration(
  3573. &Status,
  3574. &ParameterValue,
  3575. AdapterConfigHandle,
  3576. &ValueName,
  3577. NdisParameterString);
  3578. if (NDIS_STATUS_SUCCESS == Status)
  3579. {
  3580. // Copy the string into adapter struct
  3581. (VOID)AtmLaneCopyUnicodeString(
  3582. &(pAdapter->CfgElanName),
  3583. &(ParameterValue->ParameterData.StringData),
  3584. TRUE,
  3585. FALSE);
  3586. DBGP((1, "GetProtocolConfiguration: ElanName %s\n",
  3587. UnicodeToString(&pAdapter->CfgElanName)));
  3588. //
  3589. // Existence of this parameter is definite clue we're running
  3590. // on Memphis/Win98
  3591. //
  3592. pAdapter->RunningOnMemphis = TRUE;
  3593. }
  3594. //
  3595. // If on Win98 we have to parse the upper bindings and elan name strings
  3596. //
  3597. if (pAdapter->RunningOnMemphis)
  3598. {
  3599. // cut up the upper bindings string
  3600. ppNext = &(pAdapter->UpperBindingsList);
  3601. pTempStr = AtmLaneStrTok(pAdapter->CfgUpperBindings.Buffer, L',', &StrLength);
  3602. do
  3603. {
  3604. *ppNext = NULL;
  3605. if (pTempStr == NULL)
  3606. {
  3607. break;
  3608. }
  3609. ALLOC_MEM(&pName, sizeof(ATMLANE_NAME));
  3610. if (pName == NULL)
  3611. {
  3612. break;
  3613. }
  3614. pName->Name.Buffer = pTempStr;
  3615. pName->Name.MaximumLength = StrLength+1;
  3616. pName->Name.Length = StrLength;
  3617. *ppNext = pName;
  3618. ppNext = &(pName->pNext);
  3619. pTempStr = AtmLaneStrTok(NULL, L',', &StrLength);
  3620. } while (TRUE);
  3621. // cut up the elan name string
  3622. ppNext = &(pAdapter->ElanNameList);
  3623. pTempStr = AtmLaneStrTok(pAdapter->CfgElanName.Buffer, L',', &StrLength);
  3624. do
  3625. {
  3626. *ppNext = NULL;
  3627. if (pTempStr == NULL)
  3628. {
  3629. break;
  3630. }
  3631. ALLOC_MEM(&pName, sizeof(ATMLANE_NAME));
  3632. if (pName == NULL)
  3633. {
  3634. break;
  3635. }
  3636. pName->Name.Buffer = pTempStr;
  3637. pName->Name.MaximumLength = StrLength+1;
  3638. pName->Name.Length = StrLength;
  3639. *ppNext = pName;
  3640. ppNext = &(pName->pNext);
  3641. pTempStr = AtmLaneStrTok(NULL, L',', &StrLength);
  3642. } while (TRUE);
  3643. }
  3644. TRACEOUT(GetProtocolConfiguration);
  3645. return;
  3646. }
  3647. VOID
  3648. AtmLaneGetElanConfiguration(
  3649. IN PNDIS_STRING pElanKey,
  3650. IN PATMLANE_ELAN pElan
  3651. )
  3652. /*++
  3653. Routine Description:
  3654. This routine will first initialize the configuration parameters
  3655. for the specified ELAN. Then it will attempt to get any ELAN
  3656. configuration information optionally stored under the ELAN's
  3657. registry key.
  3658. Arguments:
  3659. pElanKey - UNICODE string containing ELAN's
  3660. registry key
  3661. Return Value:
  3662. None.
  3663. --*/
  3664. {
  3665. NDIS_STATUS Status;
  3666. PNDIS_CONFIGURATION_PARAMETER ParameterValue;
  3667. NDIS_STRING ValueName;
  3668. ANSI_STRING TempAnsiString;
  3669. ATM_ADDRESS LecsAddress;
  3670. NDIS_HANDLE AdapterConfigHandle;
  3671. NDIS_HANDLE ElanListConfigHandle;
  3672. NDIS_HANDLE ElanConfigHandle;
  3673. NDIS_HANDLE CommonConfigHandle;
  3674. NDIS_STRING ElanListKeyName;
  3675. PATMLANE_NAME pName;
  3676. ULONG Index;
  3677. TRACEIN(GetElanConfiguration);
  3678. //
  3679. // Init handles to null for proper cleanup later
  3680. //
  3681. AdapterConfigHandle = NULL_NDIS_HANDLE;
  3682. ElanListConfigHandle = NULL_NDIS_HANDLE;
  3683. ElanConfigHandle = NULL_NDIS_HANDLE;
  3684. //
  3685. // Init some defaults
  3686. //
  3687. pElan->CfgUseLecs = TRUE;
  3688. pElan->CfgDiscoverLecs = TRUE;
  3689. pElan->CfgLecsAddress = gWellKnownLecsAddress;
  3690. do
  3691. {
  3692. //
  3693. // Open the AtmLane protocol configuration section for this adapter.
  3694. // This must succeed on NT and Win98.
  3695. //
  3696. NdisOpenProtocolConfiguration(
  3697. &Status,
  3698. &AdapterConfigHandle,
  3699. &pElan->pAdapter->ConfigString
  3700. );
  3701. if (NDIS_STATUS_SUCCESS != Status)
  3702. {
  3703. AdapterConfigHandle = NULL_NDIS_HANDLE;
  3704. DBGP((0, "GetElanConfiguration: OpenProtocolConfiguration failed\n"));
  3705. Status = NDIS_STATUS_OPEN_FAILED;
  3706. break;
  3707. }
  3708. //
  3709. // If running on Win98 we will get ELAN config info from the
  3710. // adapter's parameters. For NT we will get ELAN config info
  3711. // from the ELAN's own parameters.
  3712. //
  3713. if (pElan->pAdapter->RunningOnMemphis)
  3714. {
  3715. //
  3716. // Use the adapter's config handle
  3717. //
  3718. CommonConfigHandle = AdapterConfigHandle;
  3719. }
  3720. else
  3721. {
  3722. //
  3723. // Open the Elan List configuration key.
  3724. //
  3725. NdisInitUnicodeString(&ElanListKeyName, ATMLANE_ELANLIST_STRING);
  3726. NdisOpenConfigurationKeyByName(
  3727. &Status,
  3728. AdapterConfigHandle,
  3729. &ElanListKeyName,
  3730. &ElanListConfigHandle);
  3731. if (NDIS_STATUS_SUCCESS != Status)
  3732. {
  3733. ElanListConfigHandle = NULL_NDIS_HANDLE;
  3734. DBGP((0, "GetElanConfiguration: Failed open of ElanList key\n"));
  3735. Status = NDIS_STATUS_FAILURE;
  3736. break;
  3737. }
  3738. //
  3739. // Open ELAN key
  3740. //
  3741. NdisOpenConfigurationKeyByName(
  3742. &Status,
  3743. ElanListConfigHandle,
  3744. pElanKey,
  3745. &ElanConfigHandle);
  3746. if (NDIS_STATUS_SUCCESS != Status)
  3747. {
  3748. ElanConfigHandle = NULL_NDIS_HANDLE;
  3749. DBGP((0, "GetElanConfiguration: Failed open of ELAN key\n"));
  3750. Status = NDIS_STATUS_FAILURE;
  3751. break;
  3752. }
  3753. //
  3754. // Use the ELAN's config handle
  3755. //
  3756. CommonConfigHandle = ElanConfigHandle;
  3757. }
  3758. //
  3759. // Get the UseLECS parameter
  3760. //
  3761. NdisInitUnicodeString(&ValueName, ATMLANE_USELECS_STRING);
  3762. NdisReadConfiguration(
  3763. &Status,
  3764. &ParameterValue,
  3765. CommonConfigHandle,
  3766. &ValueName,
  3767. NdisParameterInteger);
  3768. if (NDIS_STATUS_SUCCESS == Status)
  3769. {
  3770. pElan->CfgUseLecs =
  3771. (ParameterValue->ParameterData.IntegerData == 0) ? FALSE : TRUE;
  3772. DBGP((1, "%d UseLECS = %s\n",
  3773. pElan->ElanNumber,
  3774. pElan->CfgUseLecs?"TRUE":"FALSE"));
  3775. }
  3776. //
  3777. // Get the DiscoverLECS parameter
  3778. //
  3779. NdisInitUnicodeString(&ValueName, ATMLANE_DISCOVERLECS_STRING);
  3780. NdisReadConfiguration(
  3781. &Status,
  3782. &ParameterValue,
  3783. CommonConfigHandle,
  3784. &ValueName,
  3785. NdisParameterInteger);
  3786. if (NDIS_STATUS_SUCCESS == Status)
  3787. {
  3788. pElan->CfgDiscoverLecs =
  3789. (ParameterValue->ParameterData.IntegerData == 0) ? FALSE : TRUE;
  3790. DBGP((1, "%d DiscoverLECS = %s\n",
  3791. pElan->ElanNumber,
  3792. pElan->CfgDiscoverLecs?"TRUE":"FALSE"));
  3793. }
  3794. //
  3795. // Get the LECS Address (only if Discover LECS is FALSE)
  3796. //
  3797. if (FALSE == pElan->CfgDiscoverLecs)
  3798. {
  3799. NdisInitUnicodeString(&ValueName, ATMLANE_LECSADDR_STRING);
  3800. NdisReadConfiguration(
  3801. &Status,
  3802. &ParameterValue,
  3803. CommonConfigHandle,
  3804. &ValueName,
  3805. NdisParameterString);
  3806. if (NDIS_STATUS_SUCCESS == Status)
  3807. {
  3808. NdisConvertStringToAtmAddress(
  3809. &Status,
  3810. &ParameterValue->ParameterData.StringData,
  3811. &LecsAddress);
  3812. if (NDIS_STATUS_SUCCESS == Status)
  3813. {
  3814. pElan->CfgLecsAddress = LecsAddress;
  3815. DBGP((1, "%d LECSAddr = %s\n",
  3816. pElan->ElanNumber,
  3817. AtmAddrToString(pElan->CfgLecsAddress.Address)));
  3818. }
  3819. }
  3820. }
  3821. //
  3822. // Get the DeviceName parameter (different on NT5 and Memphis/Win98)
  3823. //
  3824. if (!pElan->pAdapter->RunningOnMemphis)
  3825. {
  3826. //
  3827. // NT5
  3828. //
  3829. NdisInitUnicodeString(&ValueName, ATMLANE_DEVICE_STRING);
  3830. NdisReadConfiguration(
  3831. &Status,
  3832. &ParameterValue,
  3833. ElanConfigHandle,
  3834. &ValueName,
  3835. NdisParameterString);
  3836. if (NDIS_STATUS_SUCCESS == Status)
  3837. {
  3838. //
  3839. // Copy into Elan struct.
  3840. //
  3841. (VOID)AtmLaneCopyUnicodeString(
  3842. &(pElan->CfgDeviceName),
  3843. &(ParameterValue->ParameterData.StringData),
  3844. TRUE,
  3845. FALSE);
  3846. }
  3847. }
  3848. else
  3849. {
  3850. //
  3851. // Memphis/Win98
  3852. //
  3853. //
  3854. // Index to this elan's device name string
  3855. //
  3856. pName = pElan->pAdapter->UpperBindingsList;
  3857. Index = pElan->ElanNumber;
  3858. while (Index > 0)
  3859. {
  3860. ASSERT(pName != NULL);
  3861. pName = pName->pNext;
  3862. Index--;
  3863. }
  3864. //
  3865. // Copy it to the Elan CfgDeviceName string
  3866. //
  3867. (VOID)AtmLaneCopyUnicodeString(
  3868. &(pElan->CfgDeviceName),
  3869. &(pName->Name),
  3870. TRUE,
  3871. FALSE);
  3872. }
  3873. DBGP((1, "%d Device Name = %s\n",
  3874. pElan->ElanNumber,
  3875. UnicodeToString(&pElan->CfgDeviceName)));
  3876. //
  3877. // Get the ELANName Parameter (different on NT5 and Memphis/Win98
  3878. //
  3879. if (!pElan->pAdapter->RunningOnMemphis)
  3880. {
  3881. //
  3882. // NT5
  3883. //
  3884. NdisInitUnicodeString(&ValueName, ATMLANE_ELANNAME_STRING);
  3885. NdisReadConfiguration(
  3886. &Status,
  3887. &ParameterValue,
  3888. ElanConfigHandle,
  3889. &ValueName,
  3890. NdisParameterString);
  3891. if (NDIS_STATUS_SUCCESS != Status)
  3892. {
  3893. NDIS_STRING DefaultNameString = NDIS_STRING_CONST("");
  3894. //
  3895. // Copy into the Elan data structure.
  3896. //
  3897. if (!AtmLaneCopyUnicodeString(
  3898. &(pElan->CfgElanName),
  3899. &DefaultNameString,
  3900. TRUE,
  3901. FALSE))
  3902. {
  3903. Status = NDIS_STATUS_RESOURCES;
  3904. break;
  3905. }
  3906. Status = NDIS_STATUS_SUCCESS;
  3907. }
  3908. else
  3909. {
  3910. //
  3911. // Copy into the Elan data structure.
  3912. //
  3913. if (!AtmLaneCopyUnicodeString(
  3914. &(pElan->CfgElanName),
  3915. &(ParameterValue->ParameterData.StringData),
  3916. TRUE,
  3917. FALSE))
  3918. {
  3919. Status = NDIS_STATUS_RESOURCES;
  3920. break;
  3921. }
  3922. }
  3923. //
  3924. // Convert it to ANSI and copy into run-time Elan variable
  3925. //
  3926. TempAnsiString.Length = 0;
  3927. TempAnsiString.MaximumLength = 32;
  3928. TempAnsiString.Buffer = pElan->ElanName;
  3929. NdisUnicodeStringToAnsiString(
  3930. &TempAnsiString,
  3931. &pElan->CfgElanName);
  3932. pElan->ElanNameSize = (UCHAR) TempAnsiString.Length;
  3933. }
  3934. else
  3935. {
  3936. //
  3937. // Memphis/Win98
  3938. //
  3939. DBGP((2, "GetElanConfiguration: Getting Elan Name for Win98\n"));
  3940. //
  3941. // Index to this elan's name string
  3942. //
  3943. pName = pElan->pAdapter->ElanNameList;
  3944. Index = pElan->ElanNumber;
  3945. while (Index > 0 && pName != NULL)
  3946. {
  3947. pName = pName->pNext;
  3948. Index--;
  3949. }
  3950. //
  3951. // Copy it to the Elan CfgElanName string
  3952. //
  3953. if (pName != NULL)
  3954. {
  3955. DBGP((2, "GetElanConfiguration: Using Elan Name at 0x%x\n", pName->Name.Buffer));
  3956. (VOID)AtmLaneCopyUnicodeString(
  3957. &(pElan->CfgElanName),
  3958. &(pName->Name),
  3959. TRUE,
  3960. FALSE);
  3961. //
  3962. // Convert it to ANSI and copy into run-time Elan variable
  3963. //
  3964. TempAnsiString.Length = 0;
  3965. TempAnsiString.MaximumLength = 32;
  3966. TempAnsiString.Buffer = pElan->ElanName;
  3967. NdisUnicodeStringToAnsiString(
  3968. &TempAnsiString,
  3969. &pName->Name);
  3970. pElan->ElanNameSize = (UCHAR) TempAnsiString.Length;
  3971. }
  3972. }
  3973. DBGP((1, "%d ELAN Name = %s\n",
  3974. pElan->ElanNumber,
  3975. UnicodeToString(&pElan->CfgElanName)));
  3976. //
  3977. // Get the LAN type.
  3978. //
  3979. pElan->CfgLanType = LANE_LANTYPE_UNSPEC;
  3980. NdisInitUnicodeString(&ValueName, ATMLANE_LANTYPE_STRING);
  3981. NdisReadConfiguration(
  3982. &Status,
  3983. &ParameterValue,
  3984. CommonConfigHandle,
  3985. &ValueName,
  3986. NdisParameterInteger);
  3987. if (NDIS_STATUS_SUCCESS == Status)
  3988. {
  3989. pElan->CfgLanType = (UCHAR) ParameterValue->ParameterData.IntegerData;
  3990. DBGP((1, "%d LAN Type = %u\n",
  3991. ParameterValue->ParameterData.IntegerData));
  3992. }
  3993. if (pElan->CfgLanType > LANE_LANTYPE_TR)
  3994. {
  3995. pElan->CfgLanType = LANE_LANTYPE_UNSPEC;
  3996. }
  3997. DBGP((1, "%d LAN Type = %u\n", pElan->ElanNumber, pElan->CfgLanType));
  3998. //
  3999. // Get the Max Frame Size.
  4000. //
  4001. pElan->CfgMaxFrameSizeCode = LANE_MAXFRAMESIZE_CODE_UNSPEC;
  4002. NdisInitUnicodeString(&ValueName, ATMLANE_MAXFRAMESIZE_STRING);
  4003. NdisReadConfiguration(
  4004. &Status,
  4005. &ParameterValue,
  4006. CommonConfigHandle,
  4007. &ValueName,
  4008. NdisParameterInteger);
  4009. if (NDIS_STATUS_SUCCESS == Status)
  4010. {
  4011. pElan->CfgMaxFrameSizeCode = (UCHAR) ParameterValue->ParameterData.IntegerData;
  4012. }
  4013. if (pElan->CfgMaxFrameSizeCode > LANE_MAXFRAMESIZE_CODE_18190)
  4014. {
  4015. pElan->CfgMaxFrameSizeCode = LANE_MAXFRAMESIZE_CODE_UNSPEC;
  4016. }
  4017. DBGP((1, "%d MaxFrameSize Code = %u\n",
  4018. pElan->ElanNumber,
  4019. pElan->CfgMaxFrameSizeCode));
  4020. //
  4021. // Get the LES Address
  4022. //
  4023. NdisZeroMemory(&pElan->CfgLesAddress, sizeof(ATM_ADDRESS));
  4024. NdisInitUnicodeString(&ValueName, ATMLANE_LESADDR_STRING);
  4025. NdisReadConfiguration(
  4026. &Status,
  4027. &ParameterValue,
  4028. CommonConfigHandle,
  4029. &ValueName,
  4030. NdisParameterString);
  4031. if (NDIS_STATUS_SUCCESS == Status)
  4032. {
  4033. NdisConvertStringToAtmAddress(
  4034. &Status,
  4035. &ParameterValue->ParameterData.StringData,
  4036. &pElan->CfgLesAddress);
  4037. DBGP((1, "%d LESAddr = %s\n",
  4038. pElan->ElanNumber,
  4039. AtmAddrToString(pElan->CfgLesAddress.Address)));
  4040. }
  4041. //
  4042. // Get the HeaderBufSize
  4043. //
  4044. pElan->HeaderBufSize = DEF_HEADER_BUF_SIZE;
  4045. NdisInitUnicodeString(&ValueName, ATMLANE_HEADERBUFSIZE_STRING);
  4046. NdisReadConfiguration(
  4047. &Status,
  4048. &ParameterValue,
  4049. CommonConfigHandle,
  4050. &ValueName,
  4051. NdisParameterInteger);
  4052. if (NDIS_STATUS_SUCCESS == Status)
  4053. {
  4054. pElan->HeaderBufSize = ParameterValue->ParameterData.IntegerData;
  4055. }
  4056. if (pElan->HeaderBufSize == 0)
  4057. {
  4058. DBGP((0, "HeaderBufSize overridden to default value %d!\n",
  4059. DEF_HEADER_BUF_SIZE));
  4060. pElan->HeaderBufSize = DEF_HEADER_BUF_SIZE;
  4061. }
  4062. //
  4063. // Round the "real" HeaderBufSize up to mult of 4.
  4064. //
  4065. pElan->RealHeaderBufSize = (((pElan->HeaderBufSize + 3) / 4) * 4);
  4066. //
  4067. // Get the MaxHeaderBufs
  4068. //
  4069. pElan->MaxHeaderBufs = DEF_MAX_HEADER_BUFS;
  4070. NdisInitUnicodeString(&ValueName, ATMLANE_MAXHEADERBUFS_STRING);
  4071. NdisReadConfiguration(
  4072. &Status,
  4073. &ParameterValue,
  4074. CommonConfigHandle,
  4075. &ValueName,
  4076. NdisParameterInteger);
  4077. if (NDIS_STATUS_SUCCESS == Status)
  4078. {
  4079. pElan->MaxHeaderBufs = ParameterValue->ParameterData.IntegerData;
  4080. }
  4081. if (pElan->MaxHeaderBufs == 0)
  4082. {
  4083. DBGP((0, "MaxHeaderBufs overridden to default value %d!\n",
  4084. DEF_MAX_HEADER_BUFS));
  4085. pElan->MaxHeaderBufs = DEF_MAX_HEADER_BUFS;
  4086. }
  4087. //
  4088. // Make max pad buffers same as header buffers
  4089. //
  4090. pElan->MaxPadBufs = pElan->MaxHeaderBufs;
  4091. //
  4092. // PadBufSize not configurable - but make it multiple of 4
  4093. //
  4094. pElan->PadBufSize = MAX(LANE_MIN_ETHPACKET, LANE_MIN_TRPACKET);
  4095. pElan->PadBufSize = (((pElan->PadBufSize + 3) / 4) * 4);
  4096. //
  4097. // ProtocolBufSize not configurable.
  4098. //
  4099. pElan->ProtocolBufSize = ROUND_OFF(DEF_PROTOCOL_BUF_SIZE);
  4100. //
  4101. // Get the MaxProtocolBufs
  4102. //
  4103. pElan->MaxProtocolBufs = DEF_MAX_PROTOCOL_BUFS;
  4104. NdisInitUnicodeString(&ValueName, ATMLANE_MAXPROTOCOLBUFS_STRING);
  4105. NdisReadConfiguration(
  4106. &Status,
  4107. &ParameterValue,
  4108. CommonConfigHandle,
  4109. &ValueName,
  4110. NdisParameterInteger);
  4111. if (NDIS_STATUS_SUCCESS == Status)
  4112. {
  4113. pElan->MaxProtocolBufs = ParameterValue->ParameterData.IntegerData;
  4114. }
  4115. if (pElan->MaxProtocolBufs == 0)
  4116. {
  4117. DBGP((0, "MaxProtocolBufs overridden to default value %d!\n",
  4118. DEF_MAX_PROTOCOL_BUFS));
  4119. pElan->MaxProtocolBufs = DEF_MAX_PROTOCOL_BUFS;
  4120. }
  4121. } while (FALSE);
  4122. //
  4123. // Close config handles
  4124. //
  4125. if (NULL_NDIS_HANDLE != ElanConfigHandle)
  4126. {
  4127. NdisCloseConfiguration(ElanConfigHandle);
  4128. ElanConfigHandle = NULL_NDIS_HANDLE;
  4129. }
  4130. if (NULL_NDIS_HANDLE != ElanListConfigHandle)
  4131. {
  4132. NdisCloseConfiguration(ElanListConfigHandle);
  4133. ElanListConfigHandle = NULL_NDIS_HANDLE;
  4134. }
  4135. if (NULL_NDIS_HANDLE != AdapterConfigHandle)
  4136. {
  4137. NdisCloseConfiguration(AdapterConfigHandle);
  4138. AdapterConfigHandle = NULL_NDIS_HANDLE;
  4139. }
  4140. TRACEOUT(GetElanConfiguration);
  4141. return;
  4142. }
  4143. VOID
  4144. AtmLaneQueueElanEventAfterDelay(
  4145. IN PATMLANE_ELAN pElan,
  4146. IN ULONG Event,
  4147. IN NDIS_STATUS EventStatus,
  4148. IN ULONG DelayMs
  4149. )
  4150. /*++
  4151. Routine Description:
  4152. Queue an ELAN event on the ELAN's event queue after
  4153. a specified delay. Caller is assumed to hold the ELAN
  4154. lock.
  4155. Arguments:
  4156. pElan - Pointer to ELAN structure.
  4157. Event - Event code.
  4158. EventStatus - Status related to event.
  4159. DelayMs - Time to wait before queueing this event.
  4160. Return Value:
  4161. None.
  4162. --*/
  4163. {
  4164. PATMLANE_DELAYED_EVENT pDelayedEvent;
  4165. PATMLANE_EVENT pEvent;
  4166. TRACEIN(QueueElanEventAfterDelay);
  4167. do
  4168. {
  4169. //
  4170. // If the ELAN is being shut down, don't queue any events.
  4171. //
  4172. if (ELAN_STATE_SHUTDOWN == pElan->AdminState)
  4173. {
  4174. DBGP((0, "QueueElanEventAfterDelay: Not queuing event (ELAN shutdown)\n"));
  4175. break;
  4176. }
  4177. if (NULL != pElan->pDelayedEvent)
  4178. {
  4179. DBGP((0, "QueueElanEventAfterDelay: Not queueing event %d (ELAN %x/%x already has one)\n",
  4180. Event, pElan, pElan->Flags));
  4181. DBGP((0, "QueueElanEventAfterDelay: ELAN %x: existing event %d\n",
  4182. pElan, pElan->pDelayedEvent->DelayedEvent.Event));
  4183. //
  4184. // Make sure we don't drop an ELAN_EVENT_STOP on the floor!
  4185. //
  4186. if (Event == ELAN_EVENT_STOP)
  4187. {
  4188. pElan->pDelayedEvent->DelayedEvent.Event = ELAN_EVENT_STOP;
  4189. }
  4190. break;
  4191. }
  4192. //
  4193. // Alloc an event struct and a timer struct.
  4194. //
  4195. ALLOC_MEM(&pDelayedEvent, sizeof(ATMLANE_DELAYED_EVENT));
  4196. if ((PATMLANE_DELAYED_EVENT)NULL == pDelayedEvent)
  4197. {
  4198. DBGP((0, "QueueElanEventAfterDelay: Event object alloc failed\n"));
  4199. break;
  4200. }
  4201. //
  4202. // Stash event data in event struct
  4203. //
  4204. pEvent = &pDelayedEvent->DelayedEvent;
  4205. pEvent->Event = Event;
  4206. pEvent->EventStatus = EventStatus;
  4207. //
  4208. // Remember the ELAN.
  4209. //
  4210. pDelayedEvent->pElan = pElan;
  4211. //
  4212. // Stash a pointer to this delayed event in the ELAN
  4213. //
  4214. pElan->pDelayedEvent = pDelayedEvent;
  4215. //
  4216. // Reference the ELAN so that it doesn't go away for the
  4217. // duration this delayed event is alive.
  4218. //
  4219. AtmLaneReferenceElan(pElan, "delayevent");
  4220. //
  4221. // Set up the timer to fire after the specified delay.
  4222. //
  4223. NdisInitializeTimer(&pDelayedEvent->DelayTimer,
  4224. AtmLaneQueueDelayedElanEvent,
  4225. (PVOID)pDelayedEvent);
  4226. NdisSetTimer(&pDelayedEvent->DelayTimer, DelayMs);
  4227. } while (FALSE);
  4228. TRACEOUT(QueueElanEventAfterDelay);
  4229. return;
  4230. }
  4231. VOID
  4232. AtmLaneQueueDelayedElanEvent(
  4233. IN PVOID SystemSpecific1,
  4234. IN PVOID TimerContext,
  4235. IN PVOID SystemSpecific2,
  4236. IN PVOID SystemSpecific3
  4237. )
  4238. /*++
  4239. Routine Description:
  4240. This is the routine fired off after a delay in order to
  4241. queue an event on an ELAN. The event is queued now.
  4242. Arguments:
  4243. SystemSpecific[1-3] - Ignored
  4244. TimerContext - Actually a pointer to the delayed event structure
  4245. Return Value:
  4246. None.
  4247. --*/
  4248. {
  4249. PATMLANE_DELAYED_EVENT pDelayedEvent;
  4250. PATMLANE_EVENT pEvent;
  4251. PATMLANE_ELAN pElan;
  4252. ULONG rc;
  4253. TRACEIN(QueueDelayedElanEvent);
  4254. pDelayedEvent = (PATMLANE_DELAYED_EVENT)TimerContext;
  4255. do
  4256. {
  4257. pElan = pDelayedEvent->pElan;
  4258. ACQUIRE_ELAN_LOCK(pElan);
  4259. pElan->pDelayedEvent = NULL;
  4260. //
  4261. // Take out the delay event reference.
  4262. //
  4263. rc = AtmLaneDereferenceElan(pElan, "delayevent");
  4264. if (rc == 0)
  4265. {
  4266. break;
  4267. }
  4268. pEvent = &pDelayedEvent->DelayedEvent;
  4269. AtmLaneQueueElanEvent(pElan, pEvent->Event, pEvent->EventStatus);
  4270. RELEASE_ELAN_LOCK(pElan);
  4271. }
  4272. while (FALSE);
  4273. FREE_MEM(pDelayedEvent);
  4274. TRACEOUT(QueueDelayedElanEvent);
  4275. return;
  4276. }
  4277. VOID
  4278. AtmLaneQueueElanEvent(
  4279. IN PATMLANE_ELAN pElan,
  4280. IN ULONG Event,
  4281. IN NDIS_STATUS EventStatus
  4282. )
  4283. /*++
  4284. Routine Description:
  4285. Queue an ELAN event on the ELAN's event queue and if
  4286. not already scheduled, schedule the handler. Caller
  4287. is assumed to hold ELAN's lock.
  4288. Arguments:
  4289. pElan - Pointer to ELAN structure.
  4290. Event - Event code.
  4291. EventStatus - Status related to event.
  4292. Return Value:
  4293. None.
  4294. --*/
  4295. {
  4296. PATMLANE_EVENT pEvent;
  4297. TRACEIN(AtmLaneQueueElanEvent);
  4298. do
  4299. {
  4300. //
  4301. // If the ELAN is being shut down, don't queue any events.
  4302. //
  4303. if (ELAN_STATE_SHUTDOWN == pElan->AdminState)
  4304. {
  4305. if ((Event != ELAN_EVENT_START) &&
  4306. (Event != ELAN_EVENT_RESTART))
  4307. {
  4308. DBGP((0, "%d: QueueElanEvent: Not queuing event %d (ELAN shutdown)\n", pElan->ElanNumber, Event));
  4309. break;
  4310. }
  4311. }
  4312. //
  4313. // Alloc an event struct
  4314. //
  4315. ALLOC_MEM(&pEvent, sizeof(ATMLANE_EVENT));
  4316. if ((PATMLANE_EVENT)NULL == pEvent)
  4317. {
  4318. DBGP((0, "QueueElanEvent: Event object alloc failed\n"));
  4319. break;
  4320. }
  4321. //
  4322. // Stash event data in event struct
  4323. //
  4324. pEvent->Event = Event;
  4325. pEvent->EventStatus = EventStatus;
  4326. //
  4327. // Queue it at tail, reference Elan, and if required, schedule
  4328. // work item to handle it.
  4329. //
  4330. InsertTailList(&pElan->EventQueue, &pEvent->Link);
  4331. AtmLaneReferenceElan(pElan, "event");
  4332. if ((pElan->Flags & ELAN_EVENT_WORK_ITEM_SET) == 0)
  4333. {
  4334. NDIS_STATUS Status;
  4335. AtmLaneReferenceElan(pElan, "workitemevent");
  4336. pElan->Flags |= ELAN_EVENT_WORK_ITEM_SET;
  4337. NdisInitializeWorkItem(&pElan->EventWorkItem, AtmLaneEventHandler, pElan);
  4338. Status = NdisScheduleWorkItem(&pElan->EventWorkItem);
  4339. ASSERT(Status == NDIS_STATUS_SUCCESS);
  4340. }
  4341. } while (FALSE);
  4342. TRACEOUT(QueueElanEvent);
  4343. return;
  4344. }
  4345. PATMLANE_EVENT
  4346. AtmLaneDequeueElanEvent(
  4347. IN PATMLANE_ELAN pElan
  4348. )
  4349. /*++
  4350. Routine Description:
  4351. Remove an ELAN event from the head of the ELAN's
  4352. event queue. Caller is assumed to hold ELAN's lock.
  4353. Caller is responsible for freeing event object.
  4354. Arguments:
  4355. pElan - Pointer to ELAN structure.
  4356. Return Value:
  4357. Pointer to removed ELAN event or NULL if queue empty.
  4358. --*/
  4359. {
  4360. PLIST_ENTRY p;
  4361. PATMLANE_EVENT pEvent;
  4362. TRACEIN(DequeueElanEvent);
  4363. if (!IsListEmpty(&pElan->EventQueue))
  4364. {
  4365. p = RemoveHeadList(&pElan->EventQueue);
  4366. pEvent = CONTAINING_RECORD(p, ATMLANE_EVENT, Link);
  4367. (VOID)AtmLaneDereferenceElan(pElan, "event");
  4368. }
  4369. else
  4370. {
  4371. pEvent = NULL;
  4372. }
  4373. TRACEIN(DequeueElanEvent);
  4374. return pEvent;
  4375. }
  4376. VOID
  4377. AtmLaneDrainElanEventQueue(
  4378. IN PATMLANE_ELAN pElan
  4379. )
  4380. /*++
  4381. Routine Description:
  4382. Remove all ELAN events from the ELAN's event queue.
  4383. Caller is assumed to hold ELAN's lock.
  4384. Arguments:
  4385. pElan - Pointer to ELAN structure.
  4386. Return Value:
  4387. None.
  4388. --*/
  4389. {
  4390. BOOLEAN WasCancelled;
  4391. PATMLANE_EVENT pEvent;
  4392. TRACEIN(DrainElanEventQueue);
  4393. while ((pEvent = AtmLaneDequeueElanEvent(pElan)) != NULL)
  4394. {
  4395. DBGP((0, "%d Drained event %x, Status %x from Elan %x\n",
  4396. pElan->ElanNumber,
  4397. pEvent->Event,
  4398. pEvent->EventStatus,
  4399. pElan));
  4400. FREE_MEM(pEvent);
  4401. }
  4402. TRACEIN(DrainElanEventQueue);
  4403. return;
  4404. }