Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5587 lines
118 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. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_START, Status);
  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. BOOLEAN bAtmEntryAlloced = FALSE;
  1678. TRACEIN(ConnectToServer);
  1679. do
  1680. {
  1681. switch (ServerType)
  1682. {
  1683. case ATM_ENTRY_TYPE_LECS:
  1684. //
  1685. // Create the ATM Entry
  1686. //
  1687. pAtmEntry = AtmLaneAllocateAtmEntry(pElan);
  1688. if (NULL_PATMLANE_ATM_ENTRY != pAtmEntry)
  1689. {
  1690. bAtmEntryAlloced = TRUE;
  1691. //
  1692. // Init ATM Entry
  1693. //
  1694. pAtmEntry->Type = ServerType;
  1695. NdisMoveMemory(
  1696. &pAtmEntry->AtmAddress,
  1697. &pElan->LecsAddress,
  1698. sizeof(ATM_ADDRESS));
  1699. //
  1700. // Add it to the Elan's list
  1701. //
  1702. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  1703. pElan->pLecsAtmEntry = pAtmEntry;
  1704. pAtmEntry->pNext = pElan->pAtmEntryList;
  1705. pElan->pAtmEntryList = pAtmEntry;
  1706. pElan->NumAtmEntries++;
  1707. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  1708. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  1709. }
  1710. break;
  1711. case ATM_ENTRY_TYPE_LES:
  1712. //
  1713. // Create the ATM Entry
  1714. //
  1715. pAtmEntry = AtmLaneAllocateAtmEntry(pElan);
  1716. if (NULL_PATMLANE_ATM_ENTRY != pAtmEntry)
  1717. {
  1718. bAtmEntryAlloced = TRUE;
  1719. //
  1720. // Init ATM Entry
  1721. //
  1722. pAtmEntry->Type = ServerType;
  1723. NdisMoveMemory(
  1724. &pAtmEntry->AtmAddress,
  1725. &pElan->LesAddress,
  1726. sizeof(ATM_ADDRESS));
  1727. //
  1728. // Add it to the Elan's list
  1729. //
  1730. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  1731. pElan->pLesAtmEntry = pAtmEntry;
  1732. pAtmEntry->pNext = pElan->pAtmEntryList;
  1733. pElan->pAtmEntryList = pAtmEntry;
  1734. pElan->NumAtmEntries++;
  1735. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  1736. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  1737. }
  1738. break;
  1739. case ATM_ENTRY_TYPE_BUS:
  1740. ASSERT(NULL_PATMLANE_ATM_ENTRY != pElan->pBusAtmEntry);
  1741. NdisMoveMemory(
  1742. &pElan->BusAddress,
  1743. &pElan->pBusAtmEntry->AtmAddress,
  1744. sizeof(ATM_ADDRESS));
  1745. pAtmEntry = pElan->pBusAtmEntry;
  1746. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  1747. break;
  1748. }
  1749. if (NULL_PATMLANE_ATM_ENTRY == pAtmEntry)
  1750. {
  1751. break;
  1752. }
  1753. //
  1754. // Call the Server
  1755. //
  1756. DBGP((1, "%d: ConnectToServer: pElan %x/ref %d, Type %d, pAtmEnt %x, Ref %d\n",
  1757. pElan->ElanNumber,
  1758. pElan,
  1759. pElan->RefCount,
  1760. ServerType,
  1761. pAtmEntry,
  1762. pAtmEntry->RefCount));
  1763. Status = AtmLaneMakeCall(pElan, pAtmEntry, UsePvc);
  1764. if (NDIS_STATUS_SUCCESS == Status)
  1765. {
  1766. //
  1767. // Call completed synchronously.
  1768. //
  1769. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_SVR_CALL_COMPLETE, Status);
  1770. break;
  1771. }
  1772. if (NDIS_STATUS_PENDING != Status)
  1773. {
  1774. //
  1775. // Call failed.
  1776. // Dereference Atm Entry (should delete it).
  1777. // Signal the elan state machine.
  1778. //
  1779. DBGP((1, "ConnectToServer: MakeCall Failed: Elan %p, Type %d, AtmEnt %p, Ref %d\n",
  1780. pElan,
  1781. ServerType,
  1782. pAtmEntry,
  1783. pAtmEntry->RefCount));
  1784. if (bAtmEntryAlloced)
  1785. {
  1786. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  1787. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "elan"); // Elan list reference
  1788. ASSERT(0 == rc);
  1789. }
  1790. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_SVR_CALL_COMPLETE, Status);
  1791. break;
  1792. }
  1793. }
  1794. while (FALSE);
  1795. TRACEOUT(ConnectToServer);
  1796. return;
  1797. }
  1798. VOID
  1799. AtmLaneInvalidateAtmEntry(
  1800. IN PATMLANE_ATM_ENTRY pAtmEntry LOCKIN NOLOCKOUT
  1801. )
  1802. /*++
  1803. Routine Description:
  1804. Invalidate an ATM Entry by unlinking it from MAC entries and
  1805. closing VC's on it.
  1806. Arguments:
  1807. pAtmEntry - The ATM Entry needing invalidating.
  1808. Return Value:
  1809. None
  1810. --*/
  1811. {
  1812. PATMLANE_MAC_ENTRY pMacEntry;
  1813. PATMLANE_MAC_ENTRY pNextMacEntry;
  1814. ULONG rc; // Ref Count of ATM Entry
  1815. INT MacEntriesUnlinked;
  1816. TRACEIN(InvalidateAtmEntry);
  1817. DBGP((1, "%d Del ATM %x: %s\n",
  1818. pAtmEntry->pElan->ElanNumber,
  1819. pAtmEntry,
  1820. AtmAddrToString(pAtmEntry->AtmAddress.Address)));
  1821. DBGP((3,
  1822. "InvalidateAtmEntry: pAtmEntry %x, pMacEntryList %x\n",
  1823. pAtmEntry,
  1824. pAtmEntry->pMacEntryList));
  1825. //
  1826. // Initialize.
  1827. //
  1828. MacEntriesUnlinked = 0;
  1829. //
  1830. // Take the MAC Entry list out of the ATM Entry.
  1831. //
  1832. pMacEntry = pAtmEntry->pMacEntryList;
  1833. pAtmEntry->pMacEntryList = NULL_PATMLANE_MAC_ENTRY;
  1834. //
  1835. // We let go of the ATM Entry lock here because we'll need
  1836. // to lock each MAC Entry in the above list, and we need to make
  1837. // sure that we don't deadlock.
  1838. //
  1839. // However, we make sure that the ATM Entry doesn't go away
  1840. // by adding a reference to it.
  1841. //
  1842. AtmLaneReferenceAtmEntry(pAtmEntry, "temp"); // Temp ref
  1843. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  1844. //
  1845. // Now unlink all MAC entries.
  1846. //
  1847. while (pMacEntry != NULL_PATMLANE_MAC_ENTRY)
  1848. {
  1849. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  1850. pNextMacEntry = pMacEntry->pNextToAtm;
  1851. //
  1852. // Remove the mapping.
  1853. //
  1854. pMacEntry->Flags = MAC_ENTRY_NEW;
  1855. pMacEntry->pAtmEntry = NULL_PATMLANE_ATM_ENTRY;
  1856. pMacEntry->pNextToAtm = NULL_PATMLANE_MAC_ENTRY;
  1857. //
  1858. // Remove the ATM Entry linkage reference.
  1859. //
  1860. if (AtmLaneDereferenceMacEntry(pMacEntry, "atm") != 0)
  1861. {
  1862. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  1863. }
  1864. //
  1865. // else the MAC Entry is gone
  1866. //
  1867. MacEntriesUnlinked++;
  1868. pMacEntry = pNextMacEntry;
  1869. }
  1870. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  1871. //
  1872. // Now dereference the ATM Entry as many times as we unliked
  1873. // MAC Entries from it.
  1874. //
  1875. while (MacEntriesUnlinked-- > 0)
  1876. {
  1877. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "mac"); // MAC Entry reference
  1878. ASSERT(rc != 0);
  1879. }
  1880. //
  1881. // Take out the reference we added at the beginning of
  1882. // this routine.
  1883. //
  1884. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "temp"); // Temp ref
  1885. //
  1886. // Close the SVCs attached to the ATM Entry.
  1887. // But do all this only if the ATM Entry
  1888. // hasn't been dereferenced away already.
  1889. //
  1890. if (rc != 0)
  1891. {
  1892. //
  1893. // The ATM Entry still exists.
  1894. // Close the VCs.
  1895. //
  1896. AtmLaneCloseVCsOnAtmEntry(pAtmEntry);
  1897. //
  1898. // The ATM Entry lock is released within the above.
  1899. //
  1900. }
  1901. //
  1902. // else the ATM Entry is gone
  1903. //
  1904. TRACEOUT(InvalidateAtmEntry);
  1905. return;
  1906. }
  1907. VOID
  1908. AtmLaneCloseVCsOnAtmEntry(
  1909. IN PATMLANE_ATM_ENTRY pAtmEntry LOCKIN NOLOCKOUT
  1910. )
  1911. /*++
  1912. Routine Description:
  1913. Close the (potentially two) VCs attached to an ATM Entry.
  1914. Arguments:
  1915. pAtmEntry - Pointer to ATM Entry on which we want to close SVCs.
  1916. Return Value:
  1917. None
  1918. --*/
  1919. {
  1920. PATMLANE_VC pVcList; // List of "Main" VCs on the ATM Entry
  1921. PATMLANE_VC pVc; // Main VC on the ATM Entry
  1922. PATMLANE_VC pVcIncomingList; // List of Optional incoming VCs on ATM Entry
  1923. PATMLANE_VC pVcIncoming; // Optional incoming VC on ATM Entry
  1924. PATMLANE_VC pNextVc; // Temp, for traversing VC lists.
  1925. ULONG rc; // Ref count on ATM Entry
  1926. TRACEIN(CloseVCsOnAtmEntry);
  1927. //
  1928. // Initialize.
  1929. //
  1930. rc = pAtmEntry->RefCount;
  1931. //
  1932. // Take out the Main VC list from the ATM Entry.
  1933. //
  1934. pVcList = pAtmEntry->pVcList;
  1935. pAtmEntry->pVcList = NULL_PATMLANE_VC;
  1936. //
  1937. // Deref the ATM Entry for each of the Main VCs.
  1938. //
  1939. for (pVc = pVcList;
  1940. NULL_PATMLANE_VC != pVc;
  1941. pVc = pNextVc)
  1942. {
  1943. ASSERT(rc != 0);
  1944. ACQUIRE_VC_LOCK(pVc);
  1945. pNextVc = pVc->pNextVc;
  1946. //
  1947. // Unlink this VC from the ATM Entry.
  1948. //
  1949. pVc->pAtmEntry = NULL_PATMLANE_ATM_ENTRY;
  1950. //
  1951. // Leave AtmEntry Reference on VC so it doesn't go away
  1952. //
  1953. RELEASE_VC_LOCK(pVc);
  1954. DBGP((1, "%d unlink VC %x/%x, Ref %d from ATM Entry %x\n",
  1955. pAtmEntry->pElan->ElanNumber,
  1956. pVc, pVc->Flags, pVc->RefCount,
  1957. pAtmEntry));
  1958. //
  1959. // Dereference the ATM Entry.
  1960. //
  1961. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "vc"); // VC reference
  1962. }
  1963. if (rc != 0)
  1964. {
  1965. //
  1966. // Take out the Incoming VC list from the ATM Entry.
  1967. //
  1968. pVcIncomingList = pAtmEntry->pVcIncoming;
  1969. pAtmEntry->pVcIncoming = NULL_PATMLANE_VC;
  1970. //
  1971. // Deref the ATM Entry for each of the Incoming VCs.
  1972. //
  1973. for (pVcIncoming = pVcIncomingList;
  1974. NULL_PATMLANE_VC != pVcIncoming;
  1975. pVcIncoming = pNextVc)
  1976. {
  1977. ASSERT(rc != 0);
  1978. ACQUIRE_VC_LOCK(pVcIncoming);
  1979. pNextVc = pVcIncoming->pNextVc;
  1980. //
  1981. // Unlink this VC from the ATM Entry.
  1982. //
  1983. pVcIncoming->pAtmEntry = NULL_PATMLANE_ATM_ENTRY;
  1984. //
  1985. // Leave AtmEntry Reference on VC so it doesn't go away
  1986. //
  1987. RELEASE_VC_LOCK(pVcIncoming);
  1988. DBGP((1, "%d unlink Incoming VC %x from ATM Entry %x\n",
  1989. pAtmEntry->pElan->ElanNumber,
  1990. pVcIncoming,
  1991. pAtmEntry));
  1992. //
  1993. // Dereference the ATM Entry.
  1994. //
  1995. rc = AtmLaneDereferenceAtmEntry(pAtmEntry, "vc"); // VC reference
  1996. }
  1997. }
  1998. else
  1999. {
  2000. pVcIncomingList = NULL_PATMLANE_VC;
  2001. }
  2002. if (rc != 0)
  2003. {
  2004. //
  2005. // The ATM Entry lives on. We don't need a lock to it anymore.
  2006. //
  2007. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  2008. }
  2009. //
  2010. // Now close the VC(s).
  2011. //
  2012. for (pVc = pVcList;
  2013. NULL_PATMLANE_VC != pVc;
  2014. pVc = pNextVc)
  2015. {
  2016. ACQUIRE_VC_LOCK(pVc);
  2017. pNextVc = pVc->pNextVc;
  2018. rc = AtmLaneDereferenceVc(pVc, "atm"); // ATM Entry reference
  2019. if (rc != 0)
  2020. {
  2021. AtmLaneCloseCall(pVc);
  2022. //
  2023. // The VC lock is released within the above.
  2024. //
  2025. }
  2026. //
  2027. // else the VC is gone.
  2028. //
  2029. }
  2030. for (pVcIncoming = pVcIncomingList;
  2031. NULL_PATMLANE_VC != pVcIncoming;
  2032. pVcIncoming = pNextVc)
  2033. {
  2034. ACQUIRE_VC_LOCK(pVcIncoming);
  2035. pNextVc = pVcIncoming->pNextVc;
  2036. rc = AtmLaneDereferenceVc(pVcIncoming, "atm"); // ATM Entry reference
  2037. if (rc != 0)
  2038. {
  2039. AtmLaneCloseCall(pVcIncoming);
  2040. //
  2041. // The VC lock is released within the above.
  2042. //
  2043. }
  2044. //
  2045. // else the VC is gone.
  2046. //
  2047. }
  2048. TRACEOUT(CloseVCsOnAtmEntry);
  2049. return;
  2050. }
  2051. VOID
  2052. AtmLaneGenerateMacAddr(
  2053. PATMLANE_ELAN pElan
  2054. )
  2055. /*++
  2056. Routine Description:
  2057. Generates a "virtual" MAC address for Elans after the first
  2058. Elan on an ATM interface.
  2059. Arguments:
  2060. pElan - Pointer to ATMLANE elan structure
  2061. Return Value:
  2062. None
  2063. --*/
  2064. {
  2065. TRACEIN(GenerateMacAddress);
  2066. //
  2067. // Start by using the real ATM card's MAC address
  2068. //
  2069. NdisMoveMemory(
  2070. &pElan->MacAddressEth,
  2071. &pElan->pAdapter->MacAddress,
  2072. sizeof(MAC_ADDRESS)
  2073. );
  2074. if (pElan->ElanNumber != 0)
  2075. {
  2076. //
  2077. // Not Elan number zero so generate a locally
  2078. // administered address by manipulating the first two bytes.
  2079. //
  2080. pElan->MacAddressEth.Byte[0] =
  2081. 0x02 | (((UCHAR)pElan->ElanNumber & 0x3f) << 2);
  2082. pElan->MacAddressEth.Byte[1] =
  2083. (pElan->pAdapter->MacAddress.Byte[1] & 0x3f) |
  2084. ((UCHAR)pElan->ElanNumber & 0x3f);
  2085. }
  2086. //
  2087. // Create the Token Ring version of the MAC Address
  2088. //
  2089. NdisMoveMemory(
  2090. &pElan->MacAddressTr,
  2091. &pElan->MacAddressEth,
  2092. sizeof(MAC_ADDRESS)
  2093. );
  2094. AtmLaneBitSwapMacAddr((PUCHAR)&pElan->MacAddressTr);
  2095. DBGP((1, "%d MacAddrEth %s\n",
  2096. pElan->ElanNumber, MacAddrToString(&pElan->MacAddressEth)));
  2097. DBGP((1, "%d MacAddrTr %s\n",
  2098. pElan->ElanNumber, MacAddrToString(&pElan->MacAddressTr)));
  2099. TRACEOUT(GenerateMacAddress);
  2100. return;
  2101. }
  2102. PATMLANE_MAC_ENTRY
  2103. AtmLaneSearchForMacAddress(
  2104. PATMLANE_ELAN pElan,
  2105. ULONG MacAddrType,
  2106. PMAC_ADDRESS pMacAddress,
  2107. BOOLEAN CreateNew
  2108. )
  2109. /*++
  2110. Routine Description:
  2111. Search for an MAC Address in the MAC Table. Optionally, create one
  2112. if a match is not found.
  2113. The caller is assumed to hold a lock to the MAC Table.
  2114. Arguments:
  2115. pElan - Pointer to ATMLANE Elan
  2116. MacAddrType - Type of MAC Addr (MAC vs RD)
  2117. pMacAddress - what we are looking for
  2118. CreateNew - Should a new entry be created if no match?
  2119. Return Value:
  2120. Pointer to a matching Mac Entry if found (or created anew).
  2121. --*/
  2122. {
  2123. ULONG HashIndex;
  2124. PATMLANE_MAC_ENTRY pMacEntry;
  2125. BOOLEAN Found;
  2126. TRACEIN(SearchForMacAddress);
  2127. HashIndex = ATMLANE_HASH(pMacAddress);
  2128. Found = FALSE;
  2129. pMacEntry = pElan->pMacTable[HashIndex];
  2130. //
  2131. // Go through the addresses in this hash list.
  2132. //
  2133. while (pMacEntry != NULL_PATMLANE_MAC_ENTRY)
  2134. {
  2135. if (!IS_FLAG_SET(
  2136. pMacEntry->Flags,
  2137. MAC_ENTRY_STATE_MASK,
  2138. MAC_ENTRY_ABORTING) &&
  2139. (MAC_ADDR_EQUAL(&pMacEntry->MacAddress, pMacAddress)) &&
  2140. (pMacEntry->MacAddrType == MacAddrType))
  2141. {
  2142. Found = TRUE;
  2143. break;
  2144. }
  2145. pMacEntry = pMacEntry->pNextEntry;
  2146. }
  2147. if (!Found && CreateNew && (pElan->AdminState != ELAN_STATE_SHUTDOWN))
  2148. {
  2149. pMacEntry = AtmLaneAllocateMacEntry(pElan);
  2150. if (pMacEntry != NULL_PATMLANE_MAC_ENTRY)
  2151. {
  2152. //
  2153. // Fill in this new entry.
  2154. //
  2155. NdisMoveMemory(&pMacEntry->MacAddress, pMacAddress, sizeof(MAC_ADDRESS));
  2156. pMacEntry->MacAddrType = MacAddrType;
  2157. AtmLaneReferenceMacEntry(pMacEntry, "table"); // Mac Table linkage
  2158. //
  2159. // Link it to the hash table.
  2160. //
  2161. pMacEntry->pNextEntry = pElan->pMacTable[HashIndex];
  2162. pElan->pMacTable[HashIndex] = pMacEntry;
  2163. pElan->NumMacEntries++;
  2164. DBGP((1, "%d New MAC %x: %s\n",
  2165. pElan->ElanNumber,
  2166. pMacEntry,
  2167. MacAddrToString(pMacAddress)));
  2168. }
  2169. else
  2170. {
  2171. DBGP((0, "SearchForMacAddress: alloc of new mac entry failed\n"));
  2172. }
  2173. }
  2174. TRACEOUT(SearchForMacAddress);
  2175. return (pMacEntry);
  2176. }
  2177. PATMLANE_ATM_ENTRY
  2178. AtmLaneSearchForAtmAddress(
  2179. IN PATMLANE_ELAN pElan,
  2180. IN PUCHAR pAtmAddress,
  2181. IN ULONG Type,
  2182. IN BOOLEAN CreateNew
  2183. )
  2184. /*++
  2185. Routine Description:
  2186. Search for an ATM Entry that matches the given ATM address and type.
  2187. Optionally, create one if there is no match.
  2188. NOTE: this routine references the ATM entry it returns. The caller
  2189. should deref it.
  2190. Arguments:
  2191. pElan - Pointer to ATMLANE Elan
  2192. pAtmAddress - ATM Address
  2193. Type - ATM Entry Type (Peer, LECS, LES, BUS)
  2194. CreateNew - Do we create a new entry if we don't find one?
  2195. Return Value:
  2196. Pointer to a matching ATM Entry if found (or created anew).
  2197. --*/
  2198. {
  2199. PATMLANE_ATM_ENTRY pAtmEntry;
  2200. BOOLEAN Found;
  2201. TRACEIN(SearchForAtmAddress);
  2202. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  2203. //
  2204. // Go through the list of ATM Entries on this interface.
  2205. //
  2206. Found = FALSE;
  2207. for (pAtmEntry = pElan->pAtmEntryList;
  2208. pAtmEntry != NULL_PATMLANE_ATM_ENTRY;
  2209. pAtmEntry = pAtmEntry->pNext)
  2210. {
  2211. //
  2212. // Compare the ATM Address and Type
  2213. //
  2214. if ((ATM_ADDR_EQUAL(pAtmAddress, pAtmEntry->AtmAddress.Address)) &&
  2215. (pAtmEntry->Type == Type) &&
  2216. ((pAtmEntry->Flags & ATM_ENTRY_WILL_ABORT) == 0))
  2217. {
  2218. Found = TRUE;
  2219. break;
  2220. }
  2221. }
  2222. if (!Found && CreateNew && (pElan->State != ELAN_STATE_SHUTDOWN))
  2223. {
  2224. pAtmEntry = AtmLaneAllocateAtmEntry(pElan);
  2225. if (pAtmEntry != NULL_PATMLANE_ATM_ENTRY)
  2226. {
  2227. //
  2228. // Fill in this new entry.
  2229. //
  2230. pAtmEntry->Flags = ATM_ENTRY_VALID;
  2231. //
  2232. // The ATM Address.
  2233. //
  2234. pAtmEntry->AtmAddress.AddressType = ATM_NSAP;
  2235. pAtmEntry->AtmAddress.NumberOfDigits = ATM_ADDRESS_LENGTH;
  2236. NdisMoveMemory(
  2237. pAtmEntry->AtmAddress.Address,
  2238. pAtmAddress,
  2239. ATM_ADDRESS_LENGTH);
  2240. //
  2241. // The Type.
  2242. //
  2243. pAtmEntry->Type = Type;
  2244. //
  2245. // Link in this entry to the Elan
  2246. //
  2247. pAtmEntry->pNext = pElan->pAtmEntryList;
  2248. pElan->pAtmEntryList = pAtmEntry;
  2249. pElan->NumAtmEntries++;
  2250. DBGP((1, "%d New ATM %x: %s\n",
  2251. pElan->ElanNumber,
  2252. pAtmEntry,
  2253. AtmAddrToString(pAtmAddress)));
  2254. }
  2255. }
  2256. //
  2257. // Reference this ATM entry so that it won't be derefed away
  2258. // before the caller gets to use this.
  2259. //
  2260. if (NULL_PATMLANE_ATM_ENTRY != pAtmEntry)
  2261. {
  2262. ACQUIRE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  2263. AtmLaneReferenceAtmEntry(pAtmEntry, "search");
  2264. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  2265. }
  2266. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  2267. TRACEOUT(SearchForAtmAddress);
  2268. return (pAtmEntry);
  2269. }
  2270. ULONG
  2271. AtmLaneMacAddrEqual(
  2272. PMAC_ADDRESS pMacAddr1,
  2273. PMAC_ADDRESS pMacAddr2
  2274. )
  2275. /*++
  2276. Routine Description:
  2277. Compares two 48bit(6 Byte) MAC Addresses.
  2278. Arguments:
  2279. pMacAddr1 - First MAC Address.
  2280. pMacAddr2 - Second MAC Address.
  2281. Return Value:
  2282. 1 if equal, 0 if not equal.
  2283. --*/
  2284. {
  2285. ULONG Result;
  2286. TRACEIN(MacAddrEqual);
  2287. //
  2288. // Assume not equal
  2289. //
  2290. Result = 0;
  2291. do
  2292. {
  2293. //
  2294. // Studies have shown the fifth byte to be
  2295. // the most unique on a network.
  2296. //
  2297. if (pMacAddr1->Byte[4] != pMacAddr2->Byte[4])
  2298. break;
  2299. if (pMacAddr1->Byte[5] != pMacAddr2->Byte[5])
  2300. break;
  2301. if (pMacAddr1->Byte[3] != pMacAddr2->Byte[3])
  2302. break;
  2303. if (pMacAddr1->Byte[2] != pMacAddr2->Byte[2])
  2304. break;
  2305. if (pMacAddr1->Byte[1] != pMacAddr2->Byte[1])
  2306. break;
  2307. if (pMacAddr1->Byte[0] != pMacAddr2->Byte[0])
  2308. break;
  2309. Result = 1;
  2310. break;
  2311. }
  2312. while (FALSE);
  2313. TRACEOUT(MacAddrEqual);
  2314. return Result;
  2315. }
  2316. VOID
  2317. AtmLaneAbortMacEntry(
  2318. IN PATMLANE_MAC_ENTRY pMacEntry
  2319. )
  2320. /*++
  2321. Routine Description:
  2322. Clean up and delete an Mac entry.
  2323. The caller is assumed to hold a lock to the Mac Entry,
  2324. which will be released here.
  2325. Arguments:
  2326. pMacEntry - Pointer to Mac Entry to be deleted.
  2327. Return Value:
  2328. None
  2329. --*/
  2330. {
  2331. PATMLANE_ELAN pElan;
  2332. PATMLANE_MAC_ENTRY * ppNextMacEntry;
  2333. ULONG rc;
  2334. BOOLEAN Found;
  2335. BOOLEAN TimerWasRunning;
  2336. ULONG HashIndex;
  2337. PNDIS_PACKET pNdisPacket;
  2338. TRACEIN(AbortMacEntry);
  2339. DBGP((1, "%d Del MAC %p: AtmEntry %p, NextToAtm %p, %s\n",
  2340. pMacEntry->pElan->ElanNumber,
  2341. pMacEntry, pMacEntry->pAtmEntry, pMacEntry->pNextToAtm,
  2342. MacAddrToString(&pMacEntry->MacAddress)));
  2343. //
  2344. // Initialize.
  2345. //
  2346. rc = pMacEntry->RefCount;
  2347. pElan = pMacEntry->pElan;
  2348. do
  2349. {
  2350. if (IS_FLAG_SET(
  2351. pMacEntry->Flags,
  2352. MAC_ENTRY_STATE_MASK,
  2353. MAC_ENTRY_ABORTING))
  2354. {
  2355. DBGP((1, "%d MAC %x already aborting\n",
  2356. pMacEntry->pElan->ElanNumber,
  2357. pMacEntry));
  2358. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2359. break;
  2360. }
  2361. //
  2362. // Set State to ABORTING
  2363. //
  2364. SET_FLAG(
  2365. pMacEntry->Flags,
  2366. MAC_ENTRY_STATE_MASK,
  2367. MAC_ENTRY_ABORTING);
  2368. //
  2369. // Put temp reference on mac entry
  2370. //
  2371. AtmLaneReferenceMacEntry(pMacEntry, "temp");
  2372. //
  2373. // Reacquire the desired locks in the right order.
  2374. //
  2375. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2376. ACQUIRE_ELAN_MAC_TABLE_LOCK(pElan);
  2377. ACQUIRE_MAC_ENTRY_LOCK_DPC(pMacEntry);
  2378. //
  2379. // Unlink this MAC Entry from the MAC Table
  2380. //
  2381. Found = FALSE;
  2382. HashIndex = ATMLANE_HASH(&pMacEntry->MacAddress);
  2383. ppNextMacEntry = &(pElan->pMacTable[HashIndex]);
  2384. while (*ppNextMacEntry != NULL_PATMLANE_MAC_ENTRY)
  2385. {
  2386. if (*ppNextMacEntry == pMacEntry)
  2387. {
  2388. //
  2389. // Make the predecessor point to the next
  2390. // in the list.
  2391. //
  2392. *ppNextMacEntry = pMacEntry->pNextEntry;
  2393. Found = TRUE;
  2394. pElan->NumMacEntries--;
  2395. break;
  2396. }
  2397. else
  2398. {
  2399. ppNextMacEntry = &((*ppNextMacEntry)->pNextEntry);
  2400. }
  2401. }
  2402. if (Found)
  2403. {
  2404. AtmLaneDereferenceMacEntry(pMacEntry, "table");
  2405. }
  2406. RELEASE_MAC_ENTRY_LOCK_DPC(pMacEntry);
  2407. RELEASE_ELAN_MAC_TABLE_LOCK(pElan);
  2408. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2409. //
  2410. // Unlink MAC Entry from the Atm Entry
  2411. //
  2412. if (pMacEntry->pAtmEntry != NULL_PATMLANE_ATM_ENTRY)
  2413. {
  2414. SET_FLAG(
  2415. pMacEntry->Flags,
  2416. MAC_ENTRY_STATE_MASK,
  2417. MAC_ENTRY_NEW);
  2418. Found = AtmLaneUnlinkMacEntryFromAtmEntry(pMacEntry);
  2419. pMacEntry->pAtmEntry = NULL_PATMLANE_ATM_ENTRY;
  2420. if (Found)
  2421. {
  2422. AtmLaneDereferenceMacEntry(pMacEntry, "atm");
  2423. }
  2424. }
  2425. //
  2426. // Stop Arp or Aging timer running on the MAC Entry.
  2427. //
  2428. TimerWasRunning = AtmLaneStopTimer(&(pMacEntry->Timer), pElan);
  2429. if (TimerWasRunning)
  2430. {
  2431. AtmLaneDereferenceMacEntry(pMacEntry, "timer");
  2432. }
  2433. //
  2434. // Stop Bus Timer
  2435. //
  2436. NdisCancelTimer(&pMacEntry->BusTimer, &TimerWasRunning);
  2437. if (TimerWasRunning)
  2438. {
  2439. AtmLaneDereferenceMacEntry(pMacEntry, "bus timer");
  2440. }
  2441. //
  2442. // Stop Flush Timer
  2443. //
  2444. TimerWasRunning = AtmLaneStopTimer(&pMacEntry->FlushTimer, pElan);
  2445. if (TimerWasRunning)
  2446. {
  2447. AtmLaneDereferenceMacEntry(pMacEntry, "flush timer");
  2448. }
  2449. //
  2450. // Now complete all packets hanging on the MacEntry
  2451. //
  2452. DBGP((1, "%d: Aborting MAC %x, Before: PktList %x, PktListCount %d\n",
  2453. pElan->ElanNumber, pMacEntry, pMacEntry->PacketList, pMacEntry->PacketListCount));
  2454. AtmLaneFreePacketQueue(pMacEntry, NDIS_STATUS_SUCCESS);
  2455. DBGP((1, "%d: Aborting MAC %x, After: PktList %x, PktListCount %d\n",
  2456. pElan->ElanNumber, pMacEntry, pMacEntry->PacketList, pMacEntry->PacketListCount));
  2457. //
  2458. // Remove temp reference and unlock if still around
  2459. //
  2460. rc = AtmLaneDereferenceMacEntry(pMacEntry, "temp");
  2461. if (rc > 0)
  2462. {
  2463. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2464. }
  2465. }
  2466. while (FALSE);
  2467. TRACEOUT(AbortMacEntry);
  2468. return;
  2469. }
  2470. VOID
  2471. AtmLaneMacEntryAgingTimeout(
  2472. IN PATMLANE_TIMER pTimer,
  2473. IN PVOID Context
  2474. )
  2475. /*++
  2476. Routine Description:
  2477. This routine is called if some time has passed since an
  2478. MAC entry was last validated.
  2479. If there is no VC associated with this MAC entry, delete it.
  2480. If there has been no sends on the entry since last validated, delete it.
  2481. Otherwise revalidate the entry by starting the ARP protocol.
  2482. Arguments:
  2483. pTimer - Pointer to timer that went off
  2484. Context - Actually a pointer to our ATMLANE Mac Entry structure
  2485. Return Value:
  2486. None
  2487. --*/
  2488. {
  2489. PATMLANE_MAC_ENTRY pMacEntry; // Mac Entry that has aged out
  2490. ULONG rc; // Ref count on Mac Entry
  2491. PATMLANE_VC pVc; // VC going to this Mac Entry
  2492. ULONG Flags; // Flags on above VC
  2493. PATMLANE_ELAN pElan;
  2494. PATMLANE_ATM_ENTRY pAtmEntry;
  2495. TRACEOUT(MacEntryAgingTimeout);
  2496. pMacEntry = (PATMLANE_MAC_ENTRY)Context;
  2497. STRUCT_ASSERT(pMacEntry, atmlane_mac);
  2498. do
  2499. {
  2500. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2501. DBGP((2, "MacEntryAgingTimeout: pMacEntry %x MacAddr %s\n",
  2502. pMacEntry, MacAddrToString(&pMacEntry->MacAddress)));
  2503. rc = AtmLaneDereferenceMacEntry(pMacEntry, "aging timer");
  2504. if (rc == 0)
  2505. {
  2506. break; // It's gone!
  2507. }
  2508. //
  2509. // Continue only if the Elan is not going down
  2510. //
  2511. pElan = pMacEntry->pElan;
  2512. if (ELAN_STATE_OPERATIONAL != pElan->AdminState)
  2513. {
  2514. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  2515. break;
  2516. }
  2517. pVc = NULL_PATMLANE_VC;
  2518. pAtmEntry = pMacEntry->pAtmEntry;
  2519. if (pAtmEntry != NULL_PATMLANE_ATM_ENTRY)
  2520. {
  2521. pVc = pAtmEntry->pVcList;
  2522. }
  2523. if (pVc != NULL_PATMLANE_VC &&
  2524. (pMacEntry->Flags & MAC_ENTRY_USED_FOR_SEND) != 0)
  2525. {
  2526. //
  2527. // There is a VC for this Mac Address and it's been
  2528. // used for a send in the last aging period.
  2529. // So we try to revalidate this Mac entry.
  2530. //
  2531. //
  2532. // Set state to AGED
  2533. //
  2534. SET_FLAG(
  2535. pMacEntry->Flags,
  2536. MAC_ENTRY_STATE_MASK,
  2537. MAC_ENTRY_AGED);
  2538. pMacEntry->Flags &= ~ MAC_ENTRY_USED_FOR_SEND;
  2539. //
  2540. // Send ARP Request
  2541. //
  2542. pMacEntry->RetriesLeft = pElan->MaxRetryCount;
  2543. AtmLaneReferenceMacEntry(pMacEntry, "timer");
  2544. AtmLaneStartTimer(
  2545. pElan,
  2546. &pMacEntry->Timer,
  2547. AtmLaneArpTimeout,
  2548. pElan->ArpResponseTime,
  2549. (PVOID)pMacEntry
  2550. );
  2551. AtmLaneSendArpRequest(pElan, pMacEntry);
  2552. //
  2553. // MAC Entry lock released in above
  2554. //
  2555. }
  2556. else
  2557. {
  2558. //
  2559. // No VC associated with this Mac Entry or
  2560. // it hasn't been used in last aging period.
  2561. // Delete it.
  2562. //
  2563. AtmLaneAbortMacEntry(pMacEntry);
  2564. //
  2565. // The Mac Entry lock is released in the above routine.
  2566. //
  2567. }
  2568. }
  2569. while (FALSE);
  2570. TRACEOUT(MacEntryAgingTimeout);
  2571. return;
  2572. }
  2573. VOID
  2574. AtmLaneArpTimeout(
  2575. IN PATMLANE_TIMER pTimer,
  2576. IN PVOID Context
  2577. )
  2578. /*++
  2579. Routine Description:
  2580. This is called when we time out waiting for a response to an ARP Request
  2581. we had sent ages ago in order to resolve/refresh an MAC entry.
  2582. Check if we have tried enough times. If we have retries left, send another
  2583. ARP Request.
  2584. If we have run out of retries, delete the MAC entry, and any VCs going to it.
  2585. Arguments:
  2586. pTimer - Pointer to timer that went off
  2587. Context - Actually a pointer to our ATMLANE MAC Entry structure
  2588. ContextValue - ignored
  2589. Return Value:
  2590. None
  2591. --*/
  2592. {
  2593. PATMLANE_MAC_ENTRY pMacEntry; // MAC Entry being ARP'ed for.
  2594. PATMLANE_VC pVc; // VC to this MAC destination
  2595. PATMLANE_ELAN pElan;
  2596. ULONG rc; // Ref Count on MAC Entry
  2597. ULONG IsBroadcast;
  2598. TRACEIN(ArpTimeout);
  2599. do
  2600. {
  2601. pMacEntry = (PATMLANE_MAC_ENTRY)Context;
  2602. STRUCT_ASSERT(pMacEntry, atmlane_mac);
  2603. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2604. pElan = pMacEntry->pElan;
  2605. DBGP((2, "ArpTimeout: Mac Entry %x\n", pMacEntry));
  2606. rc = AtmLaneDereferenceMacEntry(pMacEntry, "timer"); // Timer reference
  2607. if (rc == 0)
  2608. {
  2609. break; // It's gone!
  2610. }
  2611. //
  2612. // Retry if any retries left
  2613. //
  2614. if (pMacEntry->RetriesLeft != 0)
  2615. {
  2616. pMacEntry->RetriesLeft--;
  2617. AtmLaneReferenceMacEntry(pMacEntry, "timer");
  2618. AtmLaneStartTimer(
  2619. pElan,
  2620. &pMacEntry->Timer,
  2621. AtmLaneArpTimeout,
  2622. pElan->ArpResponseTime,
  2623. (PVOID)pMacEntry
  2624. );
  2625. AtmLaneSendArpRequest(pElan, pMacEntry);
  2626. //
  2627. // MAC Entry lock released in above
  2628. //
  2629. break;
  2630. }
  2631. //
  2632. // Is this the broadcast/BUS entry?
  2633. //
  2634. IsBroadcast = (pMacEntry->Flags & MAC_ENTRY_BROADCAST);
  2635. //
  2636. // We are out of retries. Abort the Mac Entry
  2637. //
  2638. AtmLaneAbortMacEntry(pMacEntry);
  2639. //
  2640. // lock is released in the above routine
  2641. //
  2642. if (IsBroadcast)
  2643. {
  2644. //
  2645. // Signal the event to the state machine
  2646. //
  2647. ACQUIRE_ELAN_LOCK(pElan);
  2648. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_ARP_RESPONSE, NDIS_STATUS_TIMEOUT);
  2649. RELEASE_ELAN_LOCK(pElan);
  2650. }
  2651. }
  2652. while (FALSE);
  2653. TRACEOUT(ArpTimeout);
  2654. return;
  2655. }
  2656. VOID
  2657. AtmLaneConfigureResponseTimeout(
  2658. IN PATMLANE_TIMER pTimer,
  2659. IN PVOID Context
  2660. )
  2661. /*++
  2662. Routine Description:
  2663. This is called when we time out waiting for a response
  2664. to an LE_CONFIGURE_REQUEST we sent to the LECS.
  2665. Arguments:
  2666. pTimer - Pointer to timer that went off
  2667. Context - Actually a pointer to our ATMLANE Elan structure
  2668. Return Value:
  2669. None
  2670. --*/
  2671. {
  2672. PATMLANE_ELAN pElan;
  2673. ULONG rc;
  2674. TRACEIN(ConfigureResponseTimeout);
  2675. pElan = (PATMLANE_ELAN)Context;
  2676. STRUCT_ASSERT(pElan, atmlane_elan);
  2677. do
  2678. {
  2679. ACQUIRE_ELAN_LOCK_DPC(pElan);
  2680. rc = AtmLaneDereferenceElan(pElan, "timer"); // Timer deref
  2681. if (rc == 0)
  2682. {
  2683. //
  2684. // The ELAN is gone.
  2685. //
  2686. break;
  2687. }
  2688. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_CONFIGURE_RESPONSE, NDIS_STATUS_TIMEOUT);
  2689. RELEASE_ELAN_LOCK_DPC(pElan);
  2690. }
  2691. while (FALSE);
  2692. TRACEOUT(ConfigureResponseTimeout);
  2693. return;
  2694. }
  2695. VOID
  2696. AtmLaneJoinResponseTimeout(
  2697. IN PATMLANE_TIMER pTimer,
  2698. IN PVOID Context
  2699. )
  2700. /*++
  2701. Routine Description:
  2702. This is called when we time out waiting for a response
  2703. to an LE_JOIN_REQUEST we sent to the LES.
  2704. Arguments:
  2705. pTimer - Pointer to timer that went off
  2706. Context - Actually a pointer to our ATMLANE Elan structure
  2707. Return Value:
  2708. None
  2709. --*/
  2710. {
  2711. PATMLANE_ELAN pElan;
  2712. ULONG rc;
  2713. TRACEIN(JoinResponseTimeout);
  2714. pElan = (PATMLANE_ELAN)Context;
  2715. STRUCT_ASSERT(pElan, atmlane_elan);
  2716. do
  2717. {
  2718. ACQUIRE_ELAN_LOCK_DPC(pElan);
  2719. rc = AtmLaneDereferenceElan(pElan, "timer"); // Timer deref
  2720. if (rc == 0)
  2721. {
  2722. //
  2723. // The ELAN is gone.
  2724. //
  2725. break;
  2726. }
  2727. AtmLaneQueueElanEvent(pElan, ELAN_EVENT_JOIN_RESPONSE, NDIS_STATUS_TIMEOUT);
  2728. RELEASE_ELAN_LOCK_DPC(pElan);
  2729. }
  2730. while (FALSE);
  2731. TRACEOUT(JoinResponseTimeout);
  2732. return;
  2733. }
  2734. VOID
  2735. AtmLaneInitializeMiniportDevice(
  2736. IN PNDIS_WORK_ITEM NdisWorkItem,
  2737. IN PVOID Context
  2738. )
  2739. {
  2740. PATMLANE_ELAN pElan;
  2741. ULONG rc;
  2742. BOOLEAN bDontBotherToInit;
  2743. NDIS_STATUS Status;
  2744. TRACEIN(InitializeMiniportDevice);
  2745. pElan = (PATMLANE_ELAN)Context;
  2746. STRUCT_ASSERT(pElan, atmlane_elan);
  2747. //
  2748. // If we are shutting down this ELAN (e.g. because we are
  2749. // unbinding from the ATM adapter), then don't bother to
  2750. // initiate MiniportInit.
  2751. //
  2752. ACQUIRE_ELAN_LOCK(pElan);
  2753. if (pElan->AdminState == ELAN_STATE_SHUTDOWN)
  2754. {
  2755. bDontBotherToInit = TRUE;
  2756. }
  2757. else
  2758. {
  2759. bDontBotherToInit = FALSE;
  2760. pElan->Flags |= ELAN_MINIPORT_INIT_PENDING;
  2761. INIT_BLOCK_STRUCT(&pElan->InitBlock);
  2762. }
  2763. RELEASE_ELAN_LOCK(pElan);
  2764. if (!bDontBotherToInit)
  2765. {
  2766. DBGP((1, "%d Miniport INITIALIZING Device %s\n",
  2767. pElan->ElanNumber,
  2768. UnicodeToString(&pElan->CfgDeviceName)));
  2769. Status = NdisIMInitializeDeviceInstanceEx(
  2770. pAtmLaneGlobalInfo->MiniportDriverHandle,
  2771. &pElan->CfgDeviceName,
  2772. (NDIS_HANDLE)pElan);
  2773. if (Status != NDIS_STATUS_SUCCESS)
  2774. {
  2775. DBGP((0, "%d IMInitializeDeviceInstanceEx failed on ELAN %p (%x)\n",
  2776. pElan->ElanNumber, pElan, Status));
  2777. ACQUIRE_ELAN_LOCK(pElan);
  2778. pElan->Flags &= ~ELAN_MINIPORT_INIT_PENDING;
  2779. SIGNAL_BLOCK_STRUCT(&pElan->InitBlock, NDIS_STATUS_SUCCESS);
  2780. RELEASE_ELAN_LOCK(pElan);
  2781. }
  2782. }
  2783. ACQUIRE_ELAN_LOCK(pElan);
  2784. rc = AtmLaneDereferenceElan(pElan, "workitem");
  2785. if (rc > 0)
  2786. {
  2787. RELEASE_ELAN_LOCK(pElan);
  2788. }
  2789. TRACEOUT(InitializeMiniportDevice);
  2790. return;
  2791. }
  2792. VOID
  2793. AtmLaneDeinitializeMiniportDevice(
  2794. IN PNDIS_WORK_ITEM NdisWorkItem,
  2795. IN PVOID Context
  2796. )
  2797. {
  2798. PATMLANE_ELAN pElan;
  2799. NDIS_STATUS Status;
  2800. ULONG rc;
  2801. NDIS_HANDLE AdapterHandle;
  2802. TRACEIN(DeinitializeMiniportDevice);
  2803. pElan = (PATMLANE_ELAN)Context;
  2804. STRUCT_ASSERT(pElan, atmlane_elan);
  2805. DBGP((1, "%d Miniport DEINITIALIZING, AdapterHandle %x, RefCount %d\n",
  2806. pElan->ElanNumber, pElan->MiniportAdapterHandle, pElan->RefCount));
  2807. ACQUIRE_ELAN_LOCK(pElan);
  2808. AdapterHandle = pElan->MiniportAdapterHandle;
  2809. RELEASE_ELAN_LOCK(pElan);
  2810. if (NULL != AdapterHandle)
  2811. {
  2812. DBGP((1, "Will call NdisIMDeInit %x\n", AdapterHandle));
  2813. Status = NdisIMDeInitializeDeviceInstance(AdapterHandle);
  2814. ASSERT(Status == NDIS_STATUS_SUCCESS);
  2815. //
  2816. // Our MHalt routine will be called at some point.
  2817. //
  2818. }
  2819. //
  2820. // else our MHalt routine was called already.
  2821. //
  2822. DBGP((0, "DeInit completing, pElan %x, RefCount %d, State %d\n",
  2823. pElan, pElan->RefCount, pElan->State));
  2824. ACQUIRE_ELAN_LOCK(pElan);
  2825. rc = AtmLaneDereferenceElan(pElan, "workitem");
  2826. if (rc > 0)
  2827. {
  2828. RELEASE_ELAN_LOCK(pElan);
  2829. }
  2830. TRACEOUT(DeinitializeMiniportDevice);
  2831. return;
  2832. }
  2833. VOID
  2834. AtmLaneReadyTimeout(
  2835. IN PATMLANE_TIMER pTimer,
  2836. IN PVOID Context
  2837. )
  2838. /*++
  2839. Routine Description:
  2840. This is called when we time out waiting for a ready indication
  2841. on a incoming data direct VC.
  2842. Arguments:
  2843. pTimer - Pointer to timer that went off
  2844. Context - Actually a pointer to an ATMLANE Vc structure
  2845. Return Value:
  2846. None
  2847. --*/
  2848. {
  2849. PATMLANE_VC pVc;
  2850. PATMLANE_ELAN pElan;
  2851. ULONG rc;
  2852. TRACEIN(AtmLaneReadyTimeout);
  2853. pVc = (PATMLANE_VC)Context;
  2854. STRUCT_ASSERT(pVc, atmlane_vc);
  2855. pElan = pVc->pElan;
  2856. STRUCT_ASSERT(pElan, atmlane_elan);
  2857. do
  2858. {
  2859. ACQUIRE_VC_LOCK(pVc);
  2860. //
  2861. // Remove ready timer reference
  2862. //
  2863. rc = AtmLaneDereferenceVc(pVc, "ready timer");
  2864. if (rc == 0)
  2865. {
  2866. break;
  2867. }
  2868. //
  2869. // Vc is still around, check state
  2870. //
  2871. if (!IS_FLAG_SET(
  2872. pVc->Flags,
  2873. VC_CALL_STATE_MASK,
  2874. VC_CALL_STATE_ACTIVE
  2875. ))
  2876. {
  2877. RELEASE_VC_LOCK(pVc);
  2878. break;
  2879. }
  2880. //
  2881. // Check if any retries left
  2882. //
  2883. if (pVc->RetriesLeft--)
  2884. {
  2885. //
  2886. // Start timer again
  2887. //
  2888. SET_FLAG(
  2889. pVc->Flags,
  2890. VC_READY_STATE_MASK,
  2891. VC_READY_WAIT
  2892. );
  2893. AtmLaneReferenceVc(pVc, "ready timer");
  2894. AtmLaneStartTimer(
  2895. pElan,
  2896. &pVc->ReadyTimer,
  2897. AtmLaneReadyTimeout,
  2898. pElan->ConnComplTimer,
  2899. pVc);
  2900. //
  2901. // Send Ready Query
  2902. //
  2903. AtmLaneSendReadyQuery(pElan, pVc);
  2904. //
  2905. // VC lock is released in above.
  2906. //
  2907. }
  2908. else
  2909. {
  2910. //
  2911. // Give up and mark as having received indication anyway
  2912. //
  2913. SET_FLAG(
  2914. pVc->Flags,
  2915. VC_READY_STATE_MASK,
  2916. VC_READY_INDICATED
  2917. );
  2918. RELEASE_VC_LOCK(pVc);
  2919. }
  2920. }
  2921. while (FALSE);
  2922. TRACEOUT(AtmLaneReadyTimeout);
  2923. return;
  2924. }
  2925. VOID
  2926. AtmLaneFlushTimeout(
  2927. IN PATMLANE_TIMER pTimer,
  2928. IN PVOID Context
  2929. )
  2930. /*++
  2931. Routine Description:
  2932. This is called when we time out waiting for a response to a FLUSH Request.
  2933. Arguments:
  2934. pTimer - Pointer to timer that went off
  2935. Context - Actually a pointer to a ATMLANE MAC Entry structure
  2936. Return Value:
  2937. None
  2938. --*/
  2939. {
  2940. PATMLANE_MAC_ENTRY pMacEntry;
  2941. PATMLANE_ATM_ENTRY pAtmEntry;
  2942. PATMLANE_VC pVc;
  2943. PNDIS_PACKET pNdisPacket;
  2944. ULONG rc;
  2945. TRACEIN(FlushTimeout);
  2946. pMacEntry = (PATMLANE_MAC_ENTRY)Context;
  2947. STRUCT_ASSERT(pMacEntry, atmlane_mac);
  2948. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  2949. do
  2950. {
  2951. if (!IS_FLAG_SET(
  2952. pMacEntry->Flags,
  2953. MAC_ENTRY_STATE_MASK,
  2954. MAC_ENTRY_FLUSHING))
  2955. {
  2956. DBGP((0, "%d FlushTimeout: MacEntry %p, bad state, Flags %x\n",
  2957. pMacEntry->pElan->ElanNumber,
  2958. pMacEntry,
  2959. pMacEntry->Flags));
  2960. break;
  2961. }
  2962. if (pMacEntry->pAtmEntry == NULL_PATMLANE_ATM_ENTRY)
  2963. {
  2964. DBGP((0, "%d FlushTimeout: Mac Entry %p, Flags %x, NULL AtmEntry\n",
  2965. pMacEntry->pElan->ElanNumber,
  2966. pMacEntry,
  2967. pMacEntry->Flags));
  2968. SET_FLAG(
  2969. pMacEntry->Flags,
  2970. MAC_ENTRY_STATE_MASK,
  2971. MAC_ENTRY_NEW);
  2972. break;
  2973. }
  2974. //
  2975. // Mark MAC Entry active
  2976. //
  2977. SET_FLAG(
  2978. pMacEntry->Flags,
  2979. MAC_ENTRY_STATE_MASK,
  2980. MAC_ENTRY_ACTIVE);
  2981. //
  2982. // Send any queued packets
  2983. //
  2984. if (pMacEntry->PacketList == (PNDIS_PACKET)NULL)
  2985. {
  2986. break;
  2987. }
  2988. pVc = pMacEntry->pAtmEntry->pVcList;
  2989. if (pVc == NULL_PATMLANE_VC)
  2990. {
  2991. break;
  2992. }
  2993. ACQUIRE_VC_LOCK(pVc);
  2994. //
  2995. // Make sure this VC doesn't go away.
  2996. //
  2997. AtmLaneReferenceVc(pVc, "flushtemp");
  2998. RELEASE_VC_LOCK(pVc);
  2999. while ((pNdisPacket = AtmLaneDequeuePacketFromHead(pMacEntry)) !=
  3000. (PNDIS_PACKET)NULL)
  3001. {
  3002. //
  3003. // Send it
  3004. //
  3005. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  3006. ACQUIRE_VC_LOCK(pVc);
  3007. AtmLaneSendPacketOnVc(pVc, pNdisPacket, TRUE);
  3008. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  3009. }
  3010. ACQUIRE_VC_LOCK(pVc);
  3011. rc = AtmLaneDereferenceVc(pVc, "flushtemp");
  3012. if (rc != 0)
  3013. {
  3014. RELEASE_VC_LOCK(pVc);
  3015. }
  3016. break;
  3017. }
  3018. while (FALSE);
  3019. rc = AtmLaneDereferenceMacEntry(pMacEntry, "flush timer");
  3020. if (rc != 0)
  3021. {
  3022. RELEASE_MAC_ENTRY_LOCK(pMacEntry);
  3023. }
  3024. TRACEOUT(FlushTimeout);
  3025. return;
  3026. }
  3027. VOID
  3028. AtmLaneVcAgingTimeout(
  3029. IN PATMLANE_TIMER pTimer,
  3030. IN PVOID Context
  3031. )
  3032. /*++
  3033. Routine Description:
  3034. This is called when the VC aging timeout fires.
  3035. It will fire if this VC hasn't been used to transmit
  3036. a packet for the timeout period. The VC will be
  3037. closed unless it has had receive activity since the last
  3038. timeout. The data receive path sets a flag if a packet
  3039. has been received.
  3040. Arguments:
  3041. pTimer - Pointer to timer that went off
  3042. Context - Actually a pointer to a ATMLANE VC structure
  3043. Return Value:
  3044. None
  3045. --*/
  3046. {
  3047. PATMLANE_VC pVc;
  3048. ULONG rc;
  3049. PATMLANE_ELAN pElan;
  3050. TRACEIN(VcAgingTimeout);
  3051. do
  3052. {
  3053. pVc = (PATMLANE_VC)Context;
  3054. STRUCT_ASSERT(pVc, atmlane_vc);
  3055. ASSERT(IS_FLAG_SET(pVc->Flags, VC_TYPE_MASK, VC_TYPE_SVC));
  3056. ACQUIRE_VC_LOCK(pVc);
  3057. pElan = pVc->pElan;
  3058. //
  3059. // Continue only if VC still active
  3060. // Otherwise dereference, unlock it, and return
  3061. //
  3062. if (!(IS_FLAG_SET(pVc->Flags,
  3063. VC_CALL_STATE_MASK,
  3064. VC_CALL_STATE_ACTIVE)))
  3065. {
  3066. rc = AtmLaneDereferenceVc(pVc, "aging timer");
  3067. if (rc > 0)
  3068. {
  3069. RELEASE_VC_LOCK(pVc);
  3070. }
  3071. break;
  3072. }
  3073. //
  3074. // Continue only if the ELAN isn't going down
  3075. // Otherwise dereference, unlock it, and return
  3076. //
  3077. if (ELAN_STATE_OPERATIONAL != pElan->AdminState)
  3078. {
  3079. rc = AtmLaneDereferenceVc(pVc, "aging timer");
  3080. if (rc > 0)
  3081. {
  3082. RELEASE_VC_LOCK(pVc);
  3083. }
  3084. break;
  3085. }
  3086. //
  3087. // If received activity is non-zero,
  3088. // clear flag, restart aging timer, release lock
  3089. // and return
  3090. //
  3091. if (pVc->ReceiveActivity != 0)
  3092. {
  3093. pVc->ReceiveActivity = 0;
  3094. // timer reference still on VC no need to re-reference
  3095. AtmLaneStartTimer(
  3096. pElan,
  3097. &pVc->AgingTimer,
  3098. AtmLaneVcAgingTimeout,
  3099. pVc->AgingTime,
  3100. (PVOID)pVc
  3101. );
  3102. DBGP((1, "%d Vc %x aging timer refreshed due to receive activity\n",
  3103. pVc->pElan->ElanNumber,
  3104. pVc));
  3105. RELEASE_VC_LOCK(pVc);
  3106. break;
  3107. }
  3108. //
  3109. // VC is to be closed
  3110. //
  3111. DBGP((1, "%d Vc %x aged out\n",
  3112. pVc->pElan->ElanNumber,
  3113. pVc));
  3114. DBGP((3, "VcAgingTimeout: Vc %x RefCount %d Flags %x pAtmEntry %x\n",
  3115. pVc, pVc->RefCount, pVc->Flags, pVc->pAtmEntry));
  3116. //
  3117. // Remove timer reference and return if refcount goes to zero
  3118. //
  3119. rc = AtmLaneDereferenceVc(pVc, "aging timer");
  3120. if (rc == 0)
  3121. {
  3122. break;
  3123. }
  3124. //
  3125. // Take this VC out of the VC list for this ATM destination
  3126. // and return if refcount goes to zero
  3127. //
  3128. if (pVc->pAtmEntry != NULL_PATMLANE_ATM_ENTRY)
  3129. {
  3130. if (AtmLaneUnlinkVcFromAtmEntry(pVc))
  3131. {
  3132. rc = AtmLaneDereferenceVc(pVc, "atm");
  3133. if (rc == 0)
  3134. {
  3135. break;
  3136. }
  3137. }
  3138. }
  3139. //
  3140. // Close this VC
  3141. //
  3142. AtmLaneCloseCall(pVc);
  3143. //
  3144. // The VC lock is released in CloseCall
  3145. //
  3146. } while (FALSE);
  3147. TRACEOUT(VcAgingTimeout);
  3148. return;
  3149. }
  3150. VOID
  3151. AtmLaneShutdownElan(
  3152. IN PATMLANE_ELAN pElan LOCKIN NOLOCKOUT,
  3153. IN BOOLEAN Restart
  3154. )
  3155. /*++
  3156. Routine Description:
  3157. This routine will "shutdown" an ELAN prior to it going back
  3158. to the Initial state or driver shutdown. The caller is
  3159. expected to hold the ELAN lock and it will be released here.
  3160. Arguments:
  3161. pElan - Pointer to an ATMLANE Elan structure.
  3162. Restart - If TRUE ELAN should restart at Initial state.
  3163. If FALSE ELAN should not restart.
  3164. Return Value:
  3165. None
  3166. --*/
  3167. {
  3168. PATMLANE_ATM_ENTRY pAtmEntry;
  3169. PATMLANE_ATM_ENTRY pNextAtmEntry;
  3170. PATMLANE_MAC_ENTRY pMacEntry;
  3171. ULONG rc;
  3172. ULONG i;
  3173. BOOLEAN WasCancelled;
  3174. NDIS_STATUS Status;
  3175. NDIS_HANDLE NdisAfHandle;
  3176. BOOLEAN bTempRef;
  3177. TRACEIN(ShutdownElan);
  3178. STRUCT_ASSERT(pElan, atmlane_elan);
  3179. //
  3180. // Add a temp ref
  3181. //
  3182. bTempRef = TRUE;
  3183. AtmLaneReferenceElan(pElan, "tempshutdown");
  3184. do
  3185. {
  3186. DBGP((0, "%d ShutDownElan pElan %p/%x, Ref %d State %d, Restart %d\n",
  3187. pElan->ElanNumber, pElan, pElan->Flags, pElan->RefCount, pElan->State,
  3188. Restart));
  3189. //
  3190. // If state already == SHUTDOWN nothing to do
  3191. //
  3192. if (ELAN_STATE_SHUTDOWN == pElan->State)
  3193. {
  3194. RELEASE_ELAN_LOCK(pElan);
  3195. break;
  3196. }
  3197. //
  3198. // If we are transitioning from operational to shutdown,
  3199. // and our miniport is active, then indicate a media disconnect
  3200. // event.
  3201. //
  3202. if (pElan->State == ELAN_STATE_OPERATIONAL &&
  3203. pElan->MiniportAdapterHandle != NULL)
  3204. {
  3205. NdisMIndicateStatus(
  3206. pElan->MiniportAdapterHandle,
  3207. NDIS_STATUS_MEDIA_DISCONNECT,
  3208. NULL,
  3209. 0);
  3210. NdisMIndicateStatusComplete(pElan->MiniportAdapterHandle);
  3211. }
  3212. //
  3213. // Change state to shutdown. If restarting state will
  3214. // be changed back to init after cleanup below.
  3215. //
  3216. pElan->AdminState = ELAN_STATE_SHUTDOWN;
  3217. pElan->State = ELAN_STATE_SHUTDOWN;
  3218. //
  3219. // Wait for any pending OpenAF operation to finish.
  3220. //
  3221. while (pElan->Flags & ELAN_OPENING_AF)
  3222. {
  3223. RELEASE_ELAN_LOCK(pElan);
  3224. DBGP((0, "%d: Shutdown Elan %p/%x is opening AF\n",
  3225. pElan->ElanNumber, pElan, pElan->Flags));
  3226. (VOID)WAIT_ON_BLOCK_STRUCT(&pElan->AfBlock);
  3227. ACQUIRE_ELAN_LOCK(pElan);
  3228. }
  3229. NdisAfHandle = pElan->NdisAfHandle;
  3230. pElan->NdisAfHandle = NULL;
  3231. if (Restart)
  3232. {
  3233. pElan->Flags |= ELAN_NEEDS_RESTART;
  3234. }
  3235. //
  3236. // Are we waiting for MiniportInitialize to run and finish?
  3237. // If so, try to cancel IMInit.
  3238. //
  3239. if (pElan->Flags & ELAN_MINIPORT_INIT_PENDING)
  3240. {
  3241. RELEASE_ELAN_LOCK(pElan);
  3242. Status = NdisIMCancelInitializeDeviceInstance(
  3243. pAtmLaneGlobalInfo->MiniportDriverHandle,
  3244. &pElan->CfgDeviceName);
  3245. DBGP((0, "%d ShutdownElan Elan %p/%x, Ref %d, CancelInit returned %x\n",
  3246. pElan->ElanNumber, pElan, pElan->Flags, pElan->RefCount, Status));
  3247. if (Status == NDIS_STATUS_SUCCESS)
  3248. {
  3249. //
  3250. // Canceled the IMInit process.
  3251. //
  3252. ACQUIRE_ELAN_LOCK(pElan);
  3253. pElan->Flags &= ~ELAN_MINIPORT_INIT_PENDING;
  3254. }
  3255. else
  3256. {
  3257. //
  3258. // Our MiniportInit function -will- be called.
  3259. // Wait for it to finish.
  3260. //
  3261. (VOID)WAIT_ON_BLOCK_STRUCT(&pElan->InitBlock);
  3262. DBGP((2, "%d: Shutdown ELAN %p, Flags %x, woke up from InitBlock\n",
  3263. pElan->ElanNumber, pElan, pElan->Flags));
  3264. ACQUIRE_ELAN_LOCK(pElan);
  3265. ASSERT((pElan->Flags & ELAN_MINIPORT_INIT_PENDING) == 0);
  3266. }
  3267. }
  3268. //
  3269. // Stop any timers running on the elan.
  3270. //
  3271. if (AtmLaneStopTimer(&pElan->Timer, pElan))
  3272. {
  3273. rc = AtmLaneDereferenceElan(pElan, "timer"); // Timer ref
  3274. ASSERT(rc > 0);
  3275. }
  3276. if (NULL != pElan->pDelayedEvent)
  3277. {
  3278. BOOLEAN TimerCancelled;
  3279. NdisCancelTimer(
  3280. &pElan->pDelayedEvent->DelayTimer,
  3281. &TimerCancelled);
  3282. DBGP((0, "ATMLANE: %d ShutdownElan %p, DelayedEvent %p, Cancelled %d\n",
  3283. pElan->ElanNumber,
  3284. pElan,
  3285. pElan->pDelayedEvent,
  3286. TimerCancelled));
  3287. if (TimerCancelled)
  3288. {
  3289. FREE_MEM(pElan->pDelayedEvent);
  3290. pElan->pDelayedEvent = NULL;
  3291. rc = AtmLaneDereferenceElan(pElan, "delayeventcancel");
  3292. ASSERT(rc > 0);
  3293. }
  3294. }
  3295. RELEASE_ELAN_LOCK(pElan);
  3296. //
  3297. // Deregister all SAPs.
  3298. //
  3299. AtmLaneDeregisterSaps(pElan);
  3300. //
  3301. // Abort all MAC table entries.
  3302. //
  3303. for (i = 0; i < ATMLANE_MAC_TABLE_SIZE; i++)
  3304. {
  3305. ACQUIRE_ELAN_MAC_TABLE_LOCK(pElan);
  3306. while (pElan->pMacTable[i] != NULL_PATMLANE_MAC_ENTRY)
  3307. {
  3308. pMacEntry = pElan->pMacTable[i];
  3309. //
  3310. // Place a temp ref so that this won't go away
  3311. // when we release the MAC table lock.
  3312. //
  3313. ACQUIRE_MAC_ENTRY_LOCK_DPC(pMacEntry);
  3314. AtmLaneReferenceMacEntry(pMacEntry, "ShutDownTemp");
  3315. RELEASE_MAC_ENTRY_LOCK_DPC(pMacEntry);
  3316. RELEASE_ELAN_MAC_TABLE_LOCK(pElan);
  3317. ACQUIRE_MAC_ENTRY_LOCK(pMacEntry);
  3318. //
  3319. // Remove the temp ref
  3320. //
  3321. rc = AtmLaneDereferenceMacEntry(pMacEntry, "ShutDownTemp");
  3322. if (rc != 0)
  3323. {
  3324. AtmLaneAbortMacEntry(pMacEntry);
  3325. //
  3326. // MAC Entry Lock is released within the above.
  3327. //
  3328. }
  3329. //
  3330. // else the MAC entry is gone.
  3331. //
  3332. ACQUIRE_ELAN_MAC_TABLE_LOCK(pElan);
  3333. }
  3334. RELEASE_ELAN_MAC_TABLE_LOCK(pElan);
  3335. }
  3336. //
  3337. // Abort all ATM Entries.
  3338. //
  3339. // First, run through the list and reference
  3340. // all of them first, so that we don't
  3341. // skip to an invalid pointer when aborting the entries.
  3342. //
  3343. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  3344. for (pAtmEntry = pElan->pAtmEntryList;
  3345. pAtmEntry != NULL_PATMLANE_ATM_ENTRY;
  3346. pAtmEntry = pNextAtmEntry)
  3347. {
  3348. ACQUIRE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  3349. pAtmEntry->Flags |= ATM_ENTRY_WILL_ABORT;
  3350. AtmLaneReferenceAtmEntry(pAtmEntry, "tempS");
  3351. pNextAtmEntry = pAtmEntry->pNext;
  3352. RELEASE_ATM_ENTRY_LOCK_DPC(pAtmEntry);
  3353. }
  3354. //
  3355. // Now, do the actual abort.
  3356. //
  3357. pAtmEntry = pElan->pAtmEntryList;
  3358. while (pAtmEntry != NULL_PATMLANE_ATM_ENTRY)
  3359. {
  3360. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  3361. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  3362. pNextAtmEntry = pAtmEntry->pNext;
  3363. AtmLaneInvalidateAtmEntry(pAtmEntry);
  3364. //
  3365. // The ATM Entry lock is released within the above.
  3366. //
  3367. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  3368. pAtmEntry = pNextAtmEntry;
  3369. }
  3370. //
  3371. // Remove all temp references.
  3372. //
  3373. for (pAtmEntry = pElan->pAtmEntryList;
  3374. pAtmEntry != NULL_PATMLANE_ATM_ENTRY;
  3375. pAtmEntry = pNextAtmEntry)
  3376. {
  3377. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  3378. ACQUIRE_ATM_ENTRY_LOCK(pAtmEntry);
  3379. ASSERT(pAtmEntry->Flags & ATM_ENTRY_WILL_ABORT);
  3380. pAtmEntry->Flags &= ~ATM_ENTRY_WILL_ABORT;
  3381. pNextAtmEntry = pAtmEntry->pNext;
  3382. rc = AtmLaneDereferenceAtmEntry(pAtmEntry,"tempS");
  3383. if (rc != 0)
  3384. {
  3385. RELEASE_ATM_ENTRY_LOCK(pAtmEntry);
  3386. }
  3387. ACQUIRE_ELAN_ATM_LIST_LOCK(pElan);
  3388. }
  3389. RELEASE_ELAN_ATM_LIST_LOCK(pElan);
  3390. //
  3391. // Remove the temp ref
  3392. //
  3393. STRUCT_ASSERT(pElan, atmlane_elan);
  3394. bTempRef = FALSE;
  3395. ACQUIRE_ELAN_LOCK(pElan);
  3396. rc = AtmLaneDereferenceElan(pElan, "tempshutdown");
  3397. if (rc == 0)
  3398. {
  3399. break;
  3400. }
  3401. RELEASE_ELAN_LOCK(pElan);
  3402. if (NULL != NdisAfHandle)
  3403. {
  3404. Status = NdisClCloseAddressFamily(NdisAfHandle);
  3405. if (NDIS_STATUS_PENDING != Status)
  3406. {
  3407. AtmLaneCloseAfCompleteHandler(Status, (NDIS_HANDLE)pElan);
  3408. }
  3409. }
  3410. else
  3411. {
  3412. AtmLaneContinueShutdownElan(pElan);
  3413. }
  3414. } while (FALSE);
  3415. if (bTempRef)
  3416. {
  3417. ACQUIRE_ELAN_LOCK(pElan);
  3418. rc = AtmLaneDereferenceElan(pElan, "tempshutdown");
  3419. if (rc != 0)
  3420. {
  3421. RELEASE_ELAN_LOCK(pElan);
  3422. }
  3423. }
  3424. TRACEOUT(ShutdownElan);
  3425. return;
  3426. }
  3427. VOID
  3428. AtmLaneContinueShutdownElan(
  3429. IN PATMLANE_ELAN pElan
  3430. )
  3431. /*++
  3432. Routine Description:
  3433. This routine continues the shutting down process for an ELAN,
  3434. after the Af handle with the Call Manager has been closed.
  3435. Arguments:
  3436. pElan - the ELAN being shutdown.
  3437. Return Value:
  3438. None.
  3439. --*/
  3440. {
  3441. ULONG rc;
  3442. TRACEIN(ContinueShutdownElan);
  3443. DBGP((0, "%d ContinueShutdown ELAN %x Flags 0x%x State %d\n",
  3444. pElan->ElanNumber,
  3445. pElan,
  3446. pElan->Flags,
  3447. pElan->State));
  3448. do
  3449. {
  3450. if (pElan->Flags & ELAN_NEEDS_RESTART)
  3451. {
  3452. ACQUIRE_ELAN_LOCK(pElan);
  3453. //
  3454. // Change state to INIT
  3455. //
  3456. pElan->AdminState = ELAN_STATE_OPERATIONAL;
  3457. pElan->State = ELAN_STATE_INIT;
  3458. pElan->RetriesLeft = 4;
  3459. pElan->Flags &= ~ELAN_NEEDS_RESTART;
  3460. //
  3461. // Clear out the local ATM address so that we start off the
  3462. // ELAN properly when we obtain it from the Call manager.
  3463. //
  3464. NdisZeroMemory(&pElan->AtmAddress, sizeof(ATM_ADDRESS));
  3465. //
  3466. // Empty the event queue and schedule a restart in a little while
  3467. //
  3468. AtmLaneDrainElanEventQueue(pElan);
  3469. AtmLaneQueueElanEventAfterDelay(pElan, ELAN_EVENT_START, 0, 2*1000);
  3470. RELEASE_ELAN_LOCK(pElan);
  3471. }
  3472. else
  3473. {
  3474. //
  3475. // Completely remove the ELAN
  3476. //
  3477. AtmLaneUnlinkElanFromAdapter(pElan);
  3478. ACQUIRE_ELAN_LOCK(pElan);
  3479. //
  3480. // Add workitem reference and remove adapter reference
  3481. //
  3482. AtmLaneReferenceElan(pElan, "workitem");
  3483. rc = AtmLaneDereferenceElan(pElan, "adapter");
  3484. //
  3485. // We are here for one of the following reasons:
  3486. //
  3487. // 1. Unbinding from an ATM adapter
  3488. // 2. The CM asked us to shut down the AF open on an ATM adapter
  3489. // 3. The virtual miniport was halted.
  3490. //
  3491. // If it isn't case (3), then we should make sure that the miniport
  3492. // gets halted, by calling NdisIMDeInitializeDeviceInstance.
  3493. //
  3494. if (pElan->MiniportAdapterHandle != NULL)
  3495. {
  3496. DBGP((1, "%d ContinueShutdown: pElan x%x, scheduling NdisIMDeInit, Handle %x\n",
  3497. pElan->ElanNumber, pElan, pElan->MiniportAdapterHandle));
  3498. //
  3499. // Schedule a PASSIVE_LEVEL thread to call
  3500. // NdisIMInitializeDeviceInstance
  3501. //
  3502. NdisInitializeWorkItem(
  3503. &pElan->NdisWorkItem,
  3504. AtmLaneDeinitializeMiniportDevice,
  3505. pElan);
  3506. // workitem reference already on Elan from above
  3507. NdisScheduleWorkItem(&pElan->NdisWorkItem);
  3508. RELEASE_ELAN_LOCK(pElan);
  3509. }
  3510. else
  3511. {
  3512. //
  3513. // Just remove workitem reference and unlock if Elan still around
  3514. //
  3515. rc = AtmLaneDereferenceElan(pElan, "workitem");
  3516. if (rc > 0)
  3517. RELEASE_ELAN_LOCK(pElan);
  3518. }
  3519. }
  3520. break;
  3521. }
  3522. while (FALSE);
  3523. TRACEOUT(ContinueShutdownElan);
  3524. return;
  3525. }
  3526. VOID
  3527. AtmLaneGetProtocolConfiguration(
  3528. IN NDIS_HANDLE AdapterConfigHandle,
  3529. IN PATMLANE_ADAPTER pAdapter
  3530. )
  3531. /*++
  3532. Routine Description:
  3533. This routine will attempt to get any ATMLANE protocol specific
  3534. configuration information optionally stored under an adapter's
  3535. registry parameters.
  3536. Arguments:
  3537. AdapterConfigHandle - the handle that was returned by
  3538. AtmLaneOpenAdapterConfiguration.
  3539. pAdapter - Pointer to ATMLANE adapter structure.
  3540. Return Value:
  3541. None.
  3542. --*/
  3543. {
  3544. NDIS_STATUS Status;
  3545. PNDIS_CONFIGURATION_PARAMETER ParameterValue;
  3546. ATM_ADDRESS LecsAddress;
  3547. NDIS_STRING ValueName;
  3548. PATMLANE_NAME * ppNext;
  3549. PATMLANE_NAME pName;
  3550. PWSTR pTempStr;
  3551. USHORT StrLength;
  3552. TRACEIN(GetProtocolConfiguration);
  3553. //
  3554. // Get the UpperBindings parameter (it will only exist on Memphis)
  3555. //
  3556. NdisInitUnicodeString(&ValueName, ATMLANE_UPPERBINDINGS_STRING);
  3557. NdisReadConfiguration(
  3558. &Status,
  3559. &ParameterValue,
  3560. AdapterConfigHandle,
  3561. &ValueName,
  3562. NdisParameterString);
  3563. if (NDIS_STATUS_SUCCESS == Status)
  3564. {
  3565. // Copy the string into adapter struct
  3566. (VOID)AtmLaneCopyUnicodeString(
  3567. &(pAdapter->CfgUpperBindings),
  3568. &(ParameterValue->ParameterData.StringData),
  3569. TRUE,
  3570. FALSE);
  3571. DBGP((1, "GetProtocolConfiguration: UpperBindings %s\n",
  3572. UnicodeToString(&pAdapter->CfgUpperBindings)));
  3573. //
  3574. // Existence of this parameter is a definite clue we're running
  3575. // on Memphis/Win98
  3576. //
  3577. pAdapter->RunningOnMemphis = TRUE;
  3578. }
  3579. //
  3580. // Get the ElanName parameter (it will only exist on Memphis)
  3581. //
  3582. NdisInitUnicodeString(&ValueName, ATMLANE_ELANNAME_STRING);
  3583. NdisReadConfiguration(
  3584. &Status,
  3585. &ParameterValue,
  3586. AdapterConfigHandle,
  3587. &ValueName,
  3588. NdisParameterString);
  3589. if (NDIS_STATUS_SUCCESS == Status)
  3590. {
  3591. // Copy the string into adapter struct
  3592. (VOID)AtmLaneCopyUnicodeString(
  3593. &(pAdapter->CfgElanName),
  3594. &(ParameterValue->ParameterData.StringData),
  3595. TRUE,
  3596. FALSE);
  3597. DBGP((1, "GetProtocolConfiguration: ElanName %s\n",
  3598. UnicodeToString(&pAdapter->CfgElanName)));
  3599. //
  3600. // Existence of this parameter is definite clue we're running
  3601. // on Memphis/Win98
  3602. //
  3603. pAdapter->RunningOnMemphis = TRUE;
  3604. }
  3605. //
  3606. // If on Win98 we have to parse the upper bindings and elan name strings
  3607. //
  3608. if (pAdapter->RunningOnMemphis)
  3609. {
  3610. // cut up the upper bindings string
  3611. ppNext = &(pAdapter->UpperBindingsList);
  3612. pTempStr = AtmLaneStrTok(pAdapter->CfgUpperBindings.Buffer, L',', &StrLength);
  3613. do
  3614. {
  3615. *ppNext = NULL;
  3616. if (pTempStr == NULL)
  3617. {
  3618. break;
  3619. }
  3620. ALLOC_MEM(&pName, sizeof(ATMLANE_NAME));
  3621. if (pName == NULL)
  3622. {
  3623. break;
  3624. }
  3625. pName->Name.Buffer = pTempStr;
  3626. pName->Name.MaximumLength = StrLength+1;
  3627. pName->Name.Length = StrLength;
  3628. *ppNext = pName;
  3629. ppNext = &(pName->pNext);
  3630. pTempStr = AtmLaneStrTok(NULL, L',', &StrLength);
  3631. } while (TRUE);
  3632. // cut up the elan name string
  3633. ppNext = &(pAdapter->ElanNameList);
  3634. pTempStr = AtmLaneStrTok(pAdapter->CfgElanName.Buffer, L',', &StrLength);
  3635. do
  3636. {
  3637. *ppNext = NULL;
  3638. if (pTempStr == NULL)
  3639. {
  3640. break;
  3641. }
  3642. ALLOC_MEM(&pName, sizeof(ATMLANE_NAME));
  3643. if (pName == NULL)
  3644. {
  3645. break;
  3646. }
  3647. pName->Name.Buffer = pTempStr;
  3648. pName->Name.MaximumLength = StrLength+1;
  3649. pName->Name.Length = StrLength;
  3650. *ppNext = pName;
  3651. ppNext = &(pName->pNext);
  3652. pTempStr = AtmLaneStrTok(NULL, L',', &StrLength);
  3653. } while (TRUE);
  3654. }
  3655. TRACEOUT(GetProtocolConfiguration);
  3656. return;
  3657. }
  3658. VOID
  3659. AtmLaneGetElanConfiguration(
  3660. IN PNDIS_STRING pElanKey,
  3661. IN PATMLANE_ELAN pElan
  3662. )
  3663. /*++
  3664. Routine Description:
  3665. This routine will first initialize the configuration parameters
  3666. for the specified ELAN. Then it will attempt to get any ELAN
  3667. configuration information optionally stored under the ELAN's
  3668. registry key.
  3669. Arguments:
  3670. pElanKey - UNICODE string containing ELAN's
  3671. registry key
  3672. Return Value:
  3673. None.
  3674. --*/
  3675. {
  3676. NDIS_STATUS Status;
  3677. PNDIS_CONFIGURATION_PARAMETER ParameterValue;
  3678. NDIS_STRING ValueName;
  3679. ANSI_STRING TempAnsiString;
  3680. ATM_ADDRESS LecsAddress;
  3681. NDIS_HANDLE AdapterConfigHandle;
  3682. NDIS_HANDLE ElanListConfigHandle;
  3683. NDIS_HANDLE ElanConfigHandle;
  3684. NDIS_HANDLE CommonConfigHandle;
  3685. NDIS_STRING ElanListKeyName;
  3686. PATMLANE_NAME pName;
  3687. ULONG Index;
  3688. TRACEIN(GetElanConfiguration);
  3689. //
  3690. // Init handles to null for proper cleanup later
  3691. //
  3692. AdapterConfigHandle = NULL_NDIS_HANDLE;
  3693. ElanListConfigHandle = NULL_NDIS_HANDLE;
  3694. ElanConfigHandle = NULL_NDIS_HANDLE;
  3695. //
  3696. // Init some defaults
  3697. //
  3698. pElan->CfgUseLecs = TRUE;
  3699. pElan->CfgDiscoverLecs = TRUE;
  3700. pElan->CfgLecsAddress = gWellKnownLecsAddress;
  3701. do
  3702. {
  3703. //
  3704. // Open the AtmLane protocol configuration section for this adapter.
  3705. // This must succeed on NT and Win98.
  3706. //
  3707. NdisOpenProtocolConfiguration(
  3708. &Status,
  3709. &AdapterConfigHandle,
  3710. &pElan->pAdapter->ConfigString
  3711. );
  3712. if (NDIS_STATUS_SUCCESS != Status)
  3713. {
  3714. AdapterConfigHandle = NULL_NDIS_HANDLE;
  3715. DBGP((0, "GetElanConfiguration: OpenProtocolConfiguration failed\n"));
  3716. Status = NDIS_STATUS_OPEN_FAILED;
  3717. break;
  3718. }
  3719. //
  3720. // If running on Win98 we will get ELAN config info from the
  3721. // adapter's parameters. For NT we will get ELAN config info
  3722. // from the ELAN's own parameters.
  3723. //
  3724. if (pElan->pAdapter->RunningOnMemphis)
  3725. {
  3726. //
  3727. // Use the adapter's config handle
  3728. //
  3729. CommonConfigHandle = AdapterConfigHandle;
  3730. }
  3731. else
  3732. {
  3733. //
  3734. // Open the Elan List configuration key.
  3735. //
  3736. NdisInitUnicodeString(&ElanListKeyName, ATMLANE_ELANLIST_STRING);
  3737. NdisOpenConfigurationKeyByName(
  3738. &Status,
  3739. AdapterConfigHandle,
  3740. &ElanListKeyName,
  3741. &ElanListConfigHandle);
  3742. if (NDIS_STATUS_SUCCESS != Status)
  3743. {
  3744. ElanListConfigHandle = NULL_NDIS_HANDLE;
  3745. DBGP((0, "GetElanConfiguration: Failed open of ElanList key\n"));
  3746. Status = NDIS_STATUS_FAILURE;
  3747. break;
  3748. }
  3749. //
  3750. // Open ELAN key
  3751. //
  3752. NdisOpenConfigurationKeyByName(
  3753. &Status,
  3754. ElanListConfigHandle,
  3755. pElanKey,
  3756. &ElanConfigHandle);
  3757. if (NDIS_STATUS_SUCCESS != Status)
  3758. {
  3759. ElanConfigHandle = NULL_NDIS_HANDLE;
  3760. DBGP((0, "GetElanConfiguration: Failed open of ELAN key\n"));
  3761. Status = NDIS_STATUS_FAILURE;
  3762. break;
  3763. }
  3764. //
  3765. // Use the ELAN's config handle
  3766. //
  3767. CommonConfigHandle = ElanConfigHandle;
  3768. }
  3769. //
  3770. // Get the UseLECS parameter
  3771. //
  3772. NdisInitUnicodeString(&ValueName, ATMLANE_USELECS_STRING);
  3773. NdisReadConfiguration(
  3774. &Status,
  3775. &ParameterValue,
  3776. CommonConfigHandle,
  3777. &ValueName,
  3778. NdisParameterInteger);
  3779. if (NDIS_STATUS_SUCCESS == Status)
  3780. {
  3781. pElan->CfgUseLecs =
  3782. (ParameterValue->ParameterData.IntegerData == 0) ? FALSE : TRUE;
  3783. DBGP((1, "%d UseLECS = %s\n",
  3784. pElan->ElanNumber,
  3785. pElan->CfgUseLecs?"TRUE":"FALSE"));
  3786. }
  3787. //
  3788. // Get the DiscoverLECS parameter
  3789. //
  3790. NdisInitUnicodeString(&ValueName, ATMLANE_DISCOVERLECS_STRING);
  3791. NdisReadConfiguration(
  3792. &Status,
  3793. &ParameterValue,
  3794. CommonConfigHandle,
  3795. &ValueName,
  3796. NdisParameterInteger);
  3797. if (NDIS_STATUS_SUCCESS == Status)
  3798. {
  3799. pElan->CfgDiscoverLecs =
  3800. (ParameterValue->ParameterData.IntegerData == 0) ? FALSE : TRUE;
  3801. DBGP((1, "%d DiscoverLECS = %s\n",
  3802. pElan->ElanNumber,
  3803. pElan->CfgDiscoverLecs?"TRUE":"FALSE"));
  3804. }
  3805. //
  3806. // Get the LECS Address (only if Discover LECS is FALSE)
  3807. //
  3808. if (FALSE == pElan->CfgDiscoverLecs)
  3809. {
  3810. NdisInitUnicodeString(&ValueName, ATMLANE_LECSADDR_STRING);
  3811. NdisReadConfiguration(
  3812. &Status,
  3813. &ParameterValue,
  3814. CommonConfigHandle,
  3815. &ValueName,
  3816. NdisParameterString);
  3817. if (NDIS_STATUS_SUCCESS == Status)
  3818. {
  3819. NdisConvertStringToAtmAddress(
  3820. &Status,
  3821. &ParameterValue->ParameterData.StringData,
  3822. &LecsAddress);
  3823. if (NDIS_STATUS_SUCCESS == Status)
  3824. {
  3825. pElan->CfgLecsAddress = LecsAddress;
  3826. DBGP((1, "%d LECSAddr = %s\n",
  3827. pElan->ElanNumber,
  3828. AtmAddrToString(pElan->CfgLecsAddress.Address)));
  3829. }
  3830. }
  3831. }
  3832. //
  3833. // Get the DeviceName parameter (different on NT5 and Memphis/Win98)
  3834. //
  3835. if (!pElan->pAdapter->RunningOnMemphis)
  3836. {
  3837. //
  3838. // NT5
  3839. //
  3840. NdisInitUnicodeString(&ValueName, ATMLANE_DEVICE_STRING);
  3841. NdisReadConfiguration(
  3842. &Status,
  3843. &ParameterValue,
  3844. ElanConfigHandle,
  3845. &ValueName,
  3846. NdisParameterString);
  3847. if (NDIS_STATUS_SUCCESS == Status)
  3848. {
  3849. //
  3850. // Copy into Elan struct.
  3851. //
  3852. (VOID)AtmLaneCopyUnicodeString(
  3853. &(pElan->CfgDeviceName),
  3854. &(ParameterValue->ParameterData.StringData),
  3855. TRUE,
  3856. FALSE);
  3857. }
  3858. }
  3859. else
  3860. {
  3861. //
  3862. // Memphis/Win98
  3863. //
  3864. //
  3865. // Index to this elan's device name string
  3866. //
  3867. pName = pElan->pAdapter->UpperBindingsList;
  3868. Index = pElan->ElanNumber;
  3869. while (Index > 0)
  3870. {
  3871. ASSERT(pName != NULL);
  3872. pName = pName->pNext;
  3873. Index--;
  3874. }
  3875. //
  3876. // Copy it to the Elan CfgDeviceName string
  3877. //
  3878. (VOID)AtmLaneCopyUnicodeString(
  3879. &(pElan->CfgDeviceName),
  3880. &(pName->Name),
  3881. TRUE,
  3882. FALSE);
  3883. }
  3884. DBGP((1, "%d Device Name = %s\n",
  3885. pElan->ElanNumber,
  3886. UnicodeToString(&pElan->CfgDeviceName)));
  3887. //
  3888. // Get the ELANName Parameter (different on NT5 and Memphis/Win98
  3889. //
  3890. if (!pElan->pAdapter->RunningOnMemphis)
  3891. {
  3892. //
  3893. // NT5
  3894. //
  3895. NdisInitUnicodeString(&ValueName, ATMLANE_ELANNAME_STRING);
  3896. NdisReadConfiguration(
  3897. &Status,
  3898. &ParameterValue,
  3899. ElanConfigHandle,
  3900. &ValueName,
  3901. NdisParameterString);
  3902. if (NDIS_STATUS_SUCCESS != Status)
  3903. {
  3904. NDIS_STRING DefaultNameString = NDIS_STRING_CONST("");
  3905. //
  3906. // Copy into the Elan data structure.
  3907. //
  3908. if (!AtmLaneCopyUnicodeString(
  3909. &(pElan->CfgElanName),
  3910. &DefaultNameString,
  3911. TRUE,
  3912. FALSE))
  3913. {
  3914. Status = NDIS_STATUS_RESOURCES;
  3915. break;
  3916. }
  3917. Status = NDIS_STATUS_SUCCESS;
  3918. }
  3919. else
  3920. {
  3921. //
  3922. // Copy into the Elan data structure.
  3923. //
  3924. if (!AtmLaneCopyUnicodeString(
  3925. &(pElan->CfgElanName),
  3926. &(ParameterValue->ParameterData.StringData),
  3927. TRUE,
  3928. FALSE))
  3929. {
  3930. Status = NDIS_STATUS_RESOURCES;
  3931. break;
  3932. }
  3933. }
  3934. //
  3935. // Convert it to ANSI and copy into run-time Elan variable
  3936. //
  3937. TempAnsiString.Length = 0;
  3938. TempAnsiString.MaximumLength = 32;
  3939. TempAnsiString.Buffer = pElan->ElanName;
  3940. NdisUnicodeStringToAnsiString(
  3941. &TempAnsiString,
  3942. &pElan->CfgElanName);
  3943. pElan->ElanNameSize = (UCHAR) TempAnsiString.Length;
  3944. }
  3945. else
  3946. {
  3947. //
  3948. // Memphis/Win98
  3949. //
  3950. DBGP((2, "GetElanConfiguration: Getting Elan Name for Win98\n"));
  3951. //
  3952. // Index to this elan's name string
  3953. //
  3954. pName = pElan->pAdapter->ElanNameList;
  3955. Index = pElan->ElanNumber;
  3956. while (Index > 0 && pName != NULL)
  3957. {
  3958. pName = pName->pNext;
  3959. Index--;
  3960. }
  3961. //
  3962. // Copy it to the Elan CfgElanName string
  3963. //
  3964. if (pName != NULL)
  3965. {
  3966. DBGP((2, "GetElanConfiguration: Using Elan Name at 0x%x\n", pName->Name.Buffer));
  3967. (VOID)AtmLaneCopyUnicodeString(
  3968. &(pElan->CfgElanName),
  3969. &(pName->Name),
  3970. TRUE,
  3971. FALSE);
  3972. //
  3973. // Convert it to ANSI and copy into run-time Elan variable
  3974. //
  3975. TempAnsiString.Length = 0;
  3976. TempAnsiString.MaximumLength = 32;
  3977. TempAnsiString.Buffer = pElan->ElanName;
  3978. NdisUnicodeStringToAnsiString(
  3979. &TempAnsiString,
  3980. &pName->Name);
  3981. pElan->ElanNameSize = (UCHAR) TempAnsiString.Length;
  3982. }
  3983. }
  3984. DBGP((1, "%d ELAN Name = %s\n",
  3985. pElan->ElanNumber,
  3986. UnicodeToString(&pElan->CfgElanName)));
  3987. //
  3988. // Get the LAN type.
  3989. //
  3990. pElan->CfgLanType = LANE_LANTYPE_UNSPEC;
  3991. NdisInitUnicodeString(&ValueName, ATMLANE_LANTYPE_STRING);
  3992. NdisReadConfiguration(
  3993. &Status,
  3994. &ParameterValue,
  3995. CommonConfigHandle,
  3996. &ValueName,
  3997. NdisParameterInteger);
  3998. if (NDIS_STATUS_SUCCESS == Status)
  3999. {
  4000. pElan->CfgLanType = (UCHAR) ParameterValue->ParameterData.IntegerData;
  4001. DBGP((1, "%d LAN Type = %u\n",
  4002. ParameterValue->ParameterData.IntegerData));
  4003. }
  4004. if (pElan->CfgLanType > LANE_LANTYPE_TR)
  4005. {
  4006. pElan->CfgLanType = LANE_LANTYPE_UNSPEC;
  4007. }
  4008. DBGP((1, "%d LAN Type = %u\n", pElan->ElanNumber, pElan->CfgLanType));
  4009. //
  4010. // Get the Max Frame Size.
  4011. //
  4012. pElan->CfgMaxFrameSizeCode = LANE_MAXFRAMESIZE_CODE_UNSPEC;
  4013. NdisInitUnicodeString(&ValueName, ATMLANE_MAXFRAMESIZE_STRING);
  4014. NdisReadConfiguration(
  4015. &Status,
  4016. &ParameterValue,
  4017. CommonConfigHandle,
  4018. &ValueName,
  4019. NdisParameterInteger);
  4020. if (NDIS_STATUS_SUCCESS == Status)
  4021. {
  4022. pElan->CfgMaxFrameSizeCode = (UCHAR) ParameterValue->ParameterData.IntegerData;
  4023. }
  4024. if (pElan->CfgMaxFrameSizeCode > LANE_MAXFRAMESIZE_CODE_18190)
  4025. {
  4026. pElan->CfgMaxFrameSizeCode = LANE_MAXFRAMESIZE_CODE_UNSPEC;
  4027. }
  4028. DBGP((1, "%d MaxFrameSize Code = %u\n",
  4029. pElan->ElanNumber,
  4030. pElan->CfgMaxFrameSizeCode));
  4031. //
  4032. // Get the LES Address
  4033. //
  4034. NdisZeroMemory(&pElan->CfgLesAddress, sizeof(ATM_ADDRESS));
  4035. NdisInitUnicodeString(&ValueName, ATMLANE_LESADDR_STRING);
  4036. NdisReadConfiguration(
  4037. &Status,
  4038. &ParameterValue,
  4039. CommonConfigHandle,
  4040. &ValueName,
  4041. NdisParameterString);
  4042. if (NDIS_STATUS_SUCCESS == Status)
  4043. {
  4044. NdisConvertStringToAtmAddress(
  4045. &Status,
  4046. &ParameterValue->ParameterData.StringData,
  4047. &pElan->CfgLesAddress);
  4048. DBGP((1, "%d LESAddr = %s\n",
  4049. pElan->ElanNumber,
  4050. AtmAddrToString(pElan->CfgLesAddress.Address)));
  4051. }
  4052. //
  4053. // Get the HeaderBufSize
  4054. //
  4055. pElan->HeaderBufSize = DEF_HEADER_BUF_SIZE;
  4056. //
  4057. // Round the "real" HeaderBufSize up to mult of 4.
  4058. //
  4059. pElan->RealHeaderBufSize = (((pElan->HeaderBufSize + 3) / 4) * 4);
  4060. //
  4061. // Get the MaxHeaderBufs
  4062. //
  4063. pElan->MaxHeaderBufs = DEF_MAX_HEADER_BUFS;
  4064. //
  4065. // Make max pad buffers same as header buffers
  4066. //
  4067. pElan->MaxPadBufs = pElan->MaxHeaderBufs;
  4068. //
  4069. // PadBufSize not configurable - but make it multiple of 4
  4070. //
  4071. pElan->PadBufSize = MAX(LANE_MIN_ETHPACKET, LANE_MIN_TRPACKET);
  4072. pElan->PadBufSize = (((pElan->PadBufSize + 3) / 4) * 4);
  4073. //
  4074. // ProtocolBufSize not configurable.
  4075. //
  4076. pElan->ProtocolBufSize = ROUND_OFF(DEF_PROTOCOL_BUF_SIZE);
  4077. //
  4078. // Get the MaxProtocolBufs
  4079. //
  4080. pElan->MaxProtocolBufs = DEF_MAX_PROTOCOL_BUFS;
  4081. } while (FALSE);
  4082. //
  4083. // Close config handles
  4084. //
  4085. if (NULL_NDIS_HANDLE != ElanConfigHandle)
  4086. {
  4087. NdisCloseConfiguration(ElanConfigHandle);
  4088. ElanConfigHandle = NULL_NDIS_HANDLE;
  4089. }
  4090. if (NULL_NDIS_HANDLE != ElanListConfigHandle)
  4091. {
  4092. NdisCloseConfiguration(ElanListConfigHandle);
  4093. ElanListConfigHandle = NULL_NDIS_HANDLE;
  4094. }
  4095. if (NULL_NDIS_HANDLE != AdapterConfigHandle)
  4096. {
  4097. NdisCloseConfiguration(AdapterConfigHandle);
  4098. AdapterConfigHandle = NULL_NDIS_HANDLE;
  4099. }
  4100. TRACEOUT(GetElanConfiguration);
  4101. return;
  4102. }
  4103. VOID
  4104. AtmLaneQueueElanEventAfterDelay(
  4105. IN PATMLANE_ELAN pElan,
  4106. IN ULONG Event,
  4107. IN NDIS_STATUS EventStatus,
  4108. IN ULONG DelayMs
  4109. )
  4110. /*++
  4111. Routine Description:
  4112. Queue an ELAN event on the ELAN's event queue after
  4113. a specified delay. Caller is assumed to hold the ELAN
  4114. lock.
  4115. Arguments:
  4116. pElan - Pointer to ELAN structure.
  4117. Event - Event code.
  4118. EventStatus - Status related to event.
  4119. DelayMs - Time to wait before queueing this event.
  4120. Return Value:
  4121. None.
  4122. --*/
  4123. {
  4124. PATMLANE_DELAYED_EVENT pDelayedEvent;
  4125. PATMLANE_EVENT pEvent;
  4126. TRACEIN(QueueElanEventAfterDelay);
  4127. do
  4128. {
  4129. //
  4130. // If the ELAN is being shut down, don't queue any events.
  4131. //
  4132. if (ELAN_STATE_SHUTDOWN == pElan->AdminState)
  4133. {
  4134. DBGP((0, "QueueElanEventAfterDelay: Not queuing event (ELAN shutdown)\n"));
  4135. break;
  4136. }
  4137. if (NULL != pElan->pDelayedEvent)
  4138. {
  4139. DBGP((0, "QueueElanEventAfterDelay: Not queueing event %d (ELAN %x/%x already has one)\n",
  4140. Event, pElan, pElan->Flags));
  4141. DBGP((0, "QueueElanEventAfterDelay: ELAN %x: existing event %d\n",
  4142. pElan, pElan->pDelayedEvent->DelayedEvent.Event));
  4143. //
  4144. // Make sure we don't drop an ELAN_EVENT_STOP on the floor!
  4145. //
  4146. if (Event == ELAN_EVENT_STOP)
  4147. {
  4148. pElan->pDelayedEvent->DelayedEvent.Event = ELAN_EVENT_STOP;
  4149. }
  4150. break;
  4151. }
  4152. //
  4153. // Alloc an event struct and a timer struct.
  4154. //
  4155. ALLOC_MEM(&pDelayedEvent, sizeof(ATMLANE_DELAYED_EVENT));
  4156. if ((PATMLANE_DELAYED_EVENT)NULL == pDelayedEvent)
  4157. {
  4158. DBGP((0, "QueueElanEventAfterDelay: Event object alloc failed\n"));
  4159. break;
  4160. }
  4161. //
  4162. // Stash event data in event struct
  4163. //
  4164. pEvent = &pDelayedEvent->DelayedEvent;
  4165. pEvent->Event = Event;
  4166. pEvent->EventStatus = EventStatus;
  4167. //
  4168. // Remember the ELAN.
  4169. //
  4170. pDelayedEvent->pElan = pElan;
  4171. //
  4172. // Stash a pointer to this delayed event in the ELAN
  4173. //
  4174. pElan->pDelayedEvent = pDelayedEvent;
  4175. //
  4176. // Reference the ELAN so that it doesn't go away for the
  4177. // duration this delayed event is alive.
  4178. //
  4179. AtmLaneReferenceElan(pElan, "delayevent");
  4180. //
  4181. // Set up the timer to fire after the specified delay.
  4182. //
  4183. NdisInitializeTimer(&pDelayedEvent->DelayTimer,
  4184. AtmLaneQueueDelayedElanEvent,
  4185. (PVOID)pDelayedEvent);
  4186. NdisSetTimer(&pDelayedEvent->DelayTimer, DelayMs);
  4187. } while (FALSE);
  4188. TRACEOUT(QueueElanEventAfterDelay);
  4189. return;
  4190. }
  4191. VOID
  4192. AtmLaneQueueDelayedElanEvent(
  4193. IN PVOID SystemSpecific1,
  4194. IN PVOID TimerContext,
  4195. IN PVOID SystemSpecific2,
  4196. IN PVOID SystemSpecific3
  4197. )
  4198. /*++
  4199. Routine Description:
  4200. This is the routine fired off after a delay in order to
  4201. queue an event on an ELAN. The event is queued now.
  4202. Arguments:
  4203. SystemSpecific[1-3] - Ignored
  4204. TimerContext - Actually a pointer to the delayed event structure
  4205. Return Value:
  4206. None.
  4207. --*/
  4208. {
  4209. PATMLANE_DELAYED_EVENT pDelayedEvent;
  4210. PATMLANE_EVENT pEvent;
  4211. PATMLANE_ELAN pElan;
  4212. ULONG rc;
  4213. TRACEIN(QueueDelayedElanEvent);
  4214. pDelayedEvent = (PATMLANE_DELAYED_EVENT)TimerContext;
  4215. do
  4216. {
  4217. pElan = pDelayedEvent->pElan;
  4218. ACQUIRE_ELAN_LOCK(pElan);
  4219. pElan->pDelayedEvent = NULL;
  4220. //
  4221. // Take out the delay event reference.
  4222. //
  4223. rc = AtmLaneDereferenceElan(pElan, "delayevent");
  4224. if (rc == 0)
  4225. {
  4226. break;
  4227. }
  4228. pEvent = &pDelayedEvent->DelayedEvent;
  4229. AtmLaneQueueElanEvent(pElan, pEvent->Event, pEvent->EventStatus);
  4230. RELEASE_ELAN_LOCK(pElan);
  4231. }
  4232. while (FALSE);
  4233. FREE_MEM(pDelayedEvent);
  4234. TRACEOUT(QueueDelayedElanEvent);
  4235. return;
  4236. }
  4237. VOID
  4238. AtmLaneQueueElanEvent(
  4239. IN PATMLANE_ELAN pElan,
  4240. IN ULONG Event,
  4241. IN NDIS_STATUS EventStatus
  4242. )
  4243. /*++
  4244. Routine Description:
  4245. Queue an ELAN event on the ELAN's event queue and if
  4246. not already scheduled, schedule the handler. Caller
  4247. is assumed to hold ELAN's lock.
  4248. Arguments:
  4249. pElan - Pointer to ELAN structure.
  4250. Event - Event code.
  4251. EventStatus - Status related to event.
  4252. Return Value:
  4253. None.
  4254. --*/
  4255. {
  4256. PATMLANE_EVENT pEvent;
  4257. TRACEIN(AtmLaneQueueElanEvent);
  4258. do
  4259. {
  4260. //
  4261. // If the ELAN is being shut down, don't queue any events.
  4262. //
  4263. if (ELAN_STATE_SHUTDOWN == pElan->AdminState)
  4264. {
  4265. if ((Event != ELAN_EVENT_START) &&
  4266. (Event != ELAN_EVENT_RESTART))
  4267. {
  4268. DBGP((0, "%d: QueueElanEvent: Not queuing event %d (ELAN shutdown)\n", pElan->ElanNumber, Event));
  4269. break;
  4270. }
  4271. }
  4272. //
  4273. // Alloc an event struct
  4274. //
  4275. ALLOC_MEM(&pEvent, sizeof(ATMLANE_EVENT));
  4276. if ((PATMLANE_EVENT)NULL == pEvent)
  4277. {
  4278. DBGP((0, "QueueElanEvent: Event object alloc failed\n"));
  4279. break;
  4280. }
  4281. //
  4282. // Stash event data in event struct
  4283. //
  4284. pEvent->Event = Event;
  4285. pEvent->EventStatus = EventStatus;
  4286. //
  4287. // Queue it at tail, reference Elan, and if required, schedule
  4288. // work item to handle it.
  4289. //
  4290. InsertTailList(&pElan->EventQueue, &pEvent->Link);
  4291. AtmLaneReferenceElan(pElan, "event");
  4292. if ((pElan->Flags & ELAN_EVENT_WORK_ITEM_SET) == 0)
  4293. {
  4294. NDIS_STATUS Status;
  4295. AtmLaneReferenceElan(pElan, "workitemevent");
  4296. pElan->Flags |= ELAN_EVENT_WORK_ITEM_SET;
  4297. NdisInitializeWorkItem(&pElan->EventWorkItem, AtmLaneEventHandler, pElan);
  4298. Status = NdisScheduleWorkItem(&pElan->EventWorkItem);
  4299. ASSERT(Status == NDIS_STATUS_SUCCESS);
  4300. }
  4301. } while (FALSE);
  4302. TRACEOUT(QueueElanEvent);
  4303. return;
  4304. }
  4305. PATMLANE_EVENT
  4306. AtmLaneDequeueElanEvent(
  4307. IN PATMLANE_ELAN pElan
  4308. )
  4309. /*++
  4310. Routine Description:
  4311. Remove an ELAN event from the head of the ELAN's
  4312. event queue. Caller is assumed to hold ELAN's lock.
  4313. Caller is responsible for freeing event object.
  4314. Arguments:
  4315. pElan - Pointer to ELAN structure.
  4316. Return Value:
  4317. Pointer to removed ELAN event or NULL if queue empty.
  4318. --*/
  4319. {
  4320. PLIST_ENTRY p;
  4321. PATMLANE_EVENT pEvent;
  4322. TRACEIN(DequeueElanEvent);
  4323. if (!IsListEmpty(&pElan->EventQueue))
  4324. {
  4325. p = RemoveHeadList(&pElan->EventQueue);
  4326. pEvent = CONTAINING_RECORD(p, ATMLANE_EVENT, Link);
  4327. (VOID)AtmLaneDereferenceElan(pElan, "event");
  4328. }
  4329. else
  4330. {
  4331. pEvent = NULL;
  4332. }
  4333. TRACEIN(DequeueElanEvent);
  4334. return pEvent;
  4335. }
  4336. VOID
  4337. AtmLaneDrainElanEventQueue(
  4338. IN PATMLANE_ELAN pElan
  4339. )
  4340. /*++
  4341. Routine Description:
  4342. Remove all ELAN events from the ELAN's event queue.
  4343. Caller is assumed to hold ELAN's lock.
  4344. Arguments:
  4345. pElan - Pointer to ELAN structure.
  4346. Return Value:
  4347. None.
  4348. --*/
  4349. {
  4350. BOOLEAN WasCancelled;
  4351. PATMLANE_EVENT pEvent;
  4352. TRACEIN(DrainElanEventQueue);
  4353. while ((pEvent = AtmLaneDequeueElanEvent(pElan)) != NULL)
  4354. {
  4355. DBGP((0, "%d Drained event %x, Status %x from Elan %x\n",
  4356. pElan->ElanNumber,
  4357. pEvent->Event,
  4358. pEvent->EventStatus,
  4359. pElan));
  4360. FREE_MEM(pEvent);
  4361. }
  4362. TRACEIN(DrainElanEventQueue);
  4363. return;
  4364. }