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

1511 lines
30 KiB

  1. /*++
  2. Copyright (c) 1997 FORE Systems, Inc.
  3. Copyright (c) 1997 Microsoft Corporation
  4. Module Name:
  5. adapter.c
  6. Abstract:
  7. Handlers for adapter events.
  8. Author:
  9. Larry Cleeton, FORE Systems (v-lcleet)
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. NDIS_STATUS
  17. AtmLanePnPEventHandler(
  18. IN NDIS_HANDLE ProtocolBindingContext,
  19. IN PNET_PNP_EVENT pNetPnPEvent
  20. )
  21. /*++
  22. Routine Description:
  23. Handler for PnP Events.
  24. Arguments:
  25. ProtocolBindingContext - Handle to protocol's adapter binding context.
  26. Actually a pointer to our adapter struct.
  27. pNetPnPEvent - Pointer to PnP Event structure describing the event.
  28. Return Value:
  29. Status of handling the event.
  30. --*/
  31. {
  32. NDIS_STATUS Status;
  33. PATMLANE_ADAPTER pAdapter;
  34. PNET_DEVICE_POWER_STATE pPowerState = (PNET_DEVICE_POWER_STATE)pNetPnPEvent->Buffer;
  35. #if DEBUG_IRQL
  36. KIRQL EntryIrql;
  37. #endif
  38. GET_ENTRY_IRQL(EntryIrql);
  39. TRACEIN(PnPEventHandler);
  40. // Extract the adapter struct pointer - this will be NULL for
  41. // global reconfig messages.
  42. pAdapter = (PATMLANE_ADAPTER)ProtocolBindingContext;
  43. switch (pNetPnPEvent->NetEvent)
  44. {
  45. case NetEventSetPower:
  46. DBGP((1, "PnPEventHandler: NetEventSetPower\n"));
  47. switch (*pPowerState)
  48. {
  49. case NetDeviceStateD0:
  50. Status = NDIS_STATUS_SUCCESS;
  51. break;
  52. default:
  53. //
  54. // We can't suspend, so we ask NDIS to unbind us by
  55. // returning this status:
  56. //
  57. Status = NDIS_STATUS_NOT_SUPPORTED;
  58. break;
  59. }
  60. break;
  61. case NetEventQueryPower:
  62. DBGP((1, "PnPEventHandler: NetEventQueryPower succeeding\n"));
  63. Status = NDIS_STATUS_SUCCESS;
  64. break;
  65. case NetEventQueryRemoveDevice:
  66. DBGP((1, "PnPEventHandler: NetEventQueryRemoveDevice succeeding\n"));
  67. Status = NDIS_STATUS_SUCCESS;
  68. break;
  69. case NetEventCancelRemoveDevice:
  70. DBGP((1, "PnPEventHandler: NetEventCancelRemoveDevice succeeding\n"));
  71. Status = NDIS_STATUS_SUCCESS;
  72. break;
  73. case NetEventBindList:
  74. DBGP((1, "PnPEventHandler: NetEventBindList not supported\n"));
  75. Status = NDIS_STATUS_NOT_SUPPORTED;
  76. break;
  77. case NetEventMaximum:
  78. DBGP((1, "PnPEventHandler: NetEventMaximum not supported\n"));
  79. Status = NDIS_STATUS_NOT_SUPPORTED;
  80. break;
  81. case NetEventReconfigure:
  82. DBGP((1, "PnPEventHandler: NetEventReconfigure\n"));
  83. Status = AtmLaneReconfigureHandler(pAdapter, pNetPnPEvent);
  84. break;
  85. default:
  86. DBGP((1, "PnPEventHandler: Unknown event 0x%x not supported\n",
  87. pNetPnPEvent->NetEvent));
  88. Status = NDIS_STATUS_NOT_SUPPORTED;
  89. break;
  90. }
  91. TRACEOUT(PnPEventHandler);
  92. CHECK_EXIT_IRQL(EntryIrql);
  93. return Status;
  94. }
  95. VOID
  96. AtmLaneBindAdapterHandler(
  97. OUT PNDIS_STATUS pStatus,
  98. IN NDIS_HANDLE BindContext,
  99. IN PNDIS_STRING pDeviceName,
  100. IN PVOID SystemSpecific1,
  101. IN PVOID SystemSpecific2
  102. )
  103. /*++
  104. Routine Description:
  105. Handler for BindAdapter event from NDIS.
  106. Arguments:
  107. Status - Points to a variable to return the status
  108. of the bind operation.
  109. BindContext - NDIS supplied handle to be used in call to
  110. NdisCompleteBindAdapter.
  111. pDeviceName - Points to a counted, zero-terminated Unicode
  112. string naming the adapter to open.
  113. SystemSpecific1 - Registry path pointer to be used in call to
  114. NdisOpenProtocolConfiguration.
  115. SystemSpecific2 - Reserved.
  116. Return Value:
  117. None.
  118. --*/
  119. {
  120. PATMLANE_ADAPTER pAdapter;
  121. PATMLANE_ELAN pElan;
  122. NDIS_STATUS Status;
  123. NDIS_STATUS OutputStatus;
  124. NDIS_STATUS OpenStatus;
  125. NDIS_MEDIUM Media;
  126. UINT MediumIndex;
  127. ULONG rc;
  128. #if DEBUG_IRQL
  129. KIRQL EntryIrql;
  130. #endif
  131. GET_ENTRY_IRQL(EntryIrql);
  132. TRACEIN(BindAdapterHandler);
  133. do
  134. {
  135. //
  136. // Initialize for error clean-up.
  137. //
  138. Status = NDIS_STATUS_SUCCESS;
  139. pAdapter = NULL_PATMLANE_ADAPTER;
  140. if (AtmLaneIsDeviceAlreadyBound(pDeviceName))
  141. {
  142. DBGP((0, "BindAdapterHandler: duplicate bind to %ws\n", pDeviceName->Buffer));
  143. Status = NDIS_STATUS_NOT_ACCEPTED;
  144. break;
  145. }
  146. //
  147. // Allocate Adapter structure.
  148. //
  149. pAdapter = AtmLaneAllocAdapter(pDeviceName, SystemSpecific1);
  150. if (NULL_PATMLANE_ADAPTER == pAdapter)
  151. {
  152. DBGP((0, "BindAdapterHandler: Allocate of adapter struct failed\n"));
  153. Status = NDIS_STATUS_RESOURCES;
  154. break;
  155. }
  156. //
  157. // Put open adapter reference on the Adapter struct.
  158. //
  159. (VOID)AtmLaneReferenceAdapter(pAdapter, "openadapter");
  160. //
  161. // Save bind context
  162. //
  163. pAdapter->BindContext = BindContext;
  164. //
  165. // Open the Adapter.
  166. //
  167. INIT_BLOCK_STRUCT(&(pAdapter->Block));
  168. INIT_BLOCK_STRUCT(&(pAdapter->OpenBlock));
  169. pAdapter->Flags |= ADAPTER_FLAGS_OPEN_IN_PROGRESS;
  170. Media = NdisMediumAtm;
  171. NdisOpenAdapter(
  172. &Status,
  173. &OpenStatus,
  174. &(pAdapter->NdisAdapterHandle),
  175. &(MediumIndex),
  176. &Media,
  177. 1,
  178. pAtmLaneGlobalInfo->NdisProtocolHandle,
  179. (NDIS_HANDLE)pAdapter,
  180. pDeviceName,
  181. 0,
  182. (PSTRING)NULL);
  183. if (Status == NDIS_STATUS_PENDING)
  184. {
  185. //
  186. // Wait for completion.
  187. //
  188. Status = WAIT_ON_BLOCK_STRUCT(&(pAdapter->Block));
  189. }
  190. if (Status != NDIS_STATUS_SUCCESS)
  191. {
  192. DBGP((0, "BindAdapterHandler: NdisOpenAdapter failed, status %x\n",
  193. Status));
  194. break;
  195. }
  196. //
  197. // Get info from Adapter
  198. //
  199. AtmLaneGetAdapterInfo(pAdapter);
  200. //
  201. // Allow an AF notification thread to proceed now.
  202. //
  203. ACQUIRE_ADAPTER_LOCK(pAdapter);
  204. pAdapter->Flags &= ~ADAPTER_FLAGS_OPEN_IN_PROGRESS;
  205. SIGNAL_BLOCK_STRUCT(&pAdapter->OpenBlock, NDIS_STATUS_SUCCESS);
  206. RELEASE_ADAPTER_LOCK(pAdapter);
  207. break;
  208. } while (FALSE);
  209. //
  210. // If bad status then cleanup.
  211. //
  212. if (NDIS_STATUS_SUCCESS != Status)
  213. {
  214. //
  215. // Dereference the Adapter struct if it exists
  216. //
  217. if (NULL_PATMLANE_ADAPTER != pAdapter)
  218. {
  219. rc = AtmLaneDereferenceAdapter(pAdapter, "openadapter");
  220. ASSERT(rc == 0);
  221. }
  222. DBGP((0, "BindAdapterHandler: Bad status %x\n", Status));
  223. }
  224. //
  225. // Output Status
  226. //
  227. *pStatus = Status;
  228. TRACEOUT(BindAdapterHandler);
  229. CHECK_EXIT_IRQL(EntryIrql);
  230. return;
  231. }
  232. VOID
  233. AtmLaneUnbindAdapterHandler(
  234. OUT PNDIS_STATUS pStatus,
  235. IN NDIS_HANDLE ProtocolBindingContext,
  236. IN NDIS_HANDLE UnbindContext
  237. )
  238. /*++
  239. Routine Description:
  240. Handler for UnBindAdapter event from NDIS.
  241. Arguments:
  242. Status - Points to a variable to return the status
  243. of the unbind operation.
  244. ProtocolBindingContext - Specifies the handle to a protocol-allocated context area
  245. in which the protocol driver maintains per-binding runtime
  246. state. The driver supplied this handle when it called
  247. NdisOpenAdapter.
  248. UnbindContext - Specifies a handle, supplied by NDIS, that the protocol
  249. passes subsequently to NdisCompleteUnbindAdapter.
  250. Return Value:
  251. None.
  252. --*/
  253. {
  254. PATMLANE_ADAPTER pAdapter;
  255. PATMLANE_ELAN pElan;
  256. PLIST_ENTRY p;
  257. PATMLANE_ATM_ENTRY pAtmEntry;
  258. PATMLANE_ATM_ENTRY pNextAtmEntry;
  259. PATMLANE_MAC_ENTRY pMacEntry;
  260. ULONG rc;
  261. ULONG i;
  262. BOOLEAN WasCancelled;
  263. BOOLEAN CompleteUnbind;
  264. #if DEBUG_IRQL
  265. KIRQL EntryIrql;
  266. #endif
  267. GET_ENTRY_IRQL(EntryIrql);
  268. TRACEIN(UnbindAdapterHandler);
  269. pAdapter = (PATMLANE_ADAPTER)ProtocolBindingContext;
  270. STRUCT_ASSERT(pAdapter, atmlane_adapter);
  271. DBGP((0, "UnbindAdapterHandler: pAdapter %p, UnbindContext %x\n",
  272. pAdapter, UnbindContext));
  273. *pStatus = NDIS_STATUS_PENDING;
  274. //
  275. // Save the unbind context for a possible later call to
  276. // NdisCompleteUnbindAdapter.
  277. //
  278. ACQUIRE_ADAPTER_LOCK(pAdapter);
  279. pAdapter->UnbindContext = UnbindContext;
  280. pAdapter->Flags |= ADAPTER_FLAGS_UNBINDING;
  281. while (pAdapter->Flags & ADAPTER_FLAGS_BOOTSTRAP_IN_PROGRESS)
  282. {
  283. RELEASE_ADAPTER_LOCK(pAdapter);
  284. (VOID)WAIT_ON_BLOCK_STRUCT(&pAdapter->UnbindBlock);
  285. ACQUIRE_ADAPTER_LOCK(pAdapter);
  286. }
  287. if (IsListEmpty(&pAdapter->ElanList))
  288. {
  289. CompleteUnbind = TRUE;
  290. }
  291. else
  292. {
  293. //
  294. // We will complete the unbind later.
  295. //
  296. pAdapter->Flags |= ADAPTER_FLAGS_UNBIND_COMPLETE_PENDING;
  297. CompleteUnbind = FALSE;
  298. }
  299. RELEASE_ADAPTER_LOCK(pAdapter);
  300. //
  301. // If there are no elans on this adapter, we are done.
  302. //
  303. if (CompleteUnbind)
  304. {
  305. AtmLaneCompleteUnbindAdapter(pAdapter);
  306. CHECK_EXIT_IRQL(EntryIrql);
  307. return;
  308. }
  309. //
  310. // Shutdown each ELAN
  311. //
  312. ACQUIRE_ADAPTER_LOCK(pAdapter);
  313. p = pAdapter->ElanList.Flink;
  314. while (p != &pAdapter->ElanList)
  315. {
  316. pElan = CONTAINING_RECORD(p, ATMLANE_ELAN, Link);
  317. STRUCT_ASSERT(pElan, atmlane_elan);
  318. ACQUIRE_ELAN_LOCK(pElan);
  319. AtmLaneReferenceElan(pElan, "tempUnbind");
  320. RELEASE_ELAN_LOCK(pElan);
  321. p = p->Flink;
  322. }
  323. RELEASE_ADAPTER_LOCK(pAdapter);
  324. p = pAdapter->ElanList.Flink;
  325. while (p != &pAdapter->ElanList)
  326. {
  327. pElan = CONTAINING_RECORD(p, ATMLANE_ELAN, Link);
  328. STRUCT_ASSERT(pElan, atmlane_elan);
  329. //
  330. // get next pointer before elan goes away
  331. //
  332. p = p->Flink;
  333. //
  334. // Kill the ELAN
  335. //
  336. ACQUIRE_ELAN_LOCK(pElan);
  337. rc = AtmLaneDereferenceElan(pElan, "tempUnbind");
  338. if (rc != 0)
  339. {
  340. AtmLaneShutdownElan(pElan, FALSE);
  341. }
  342. }
  343. TRACEOUT(UnbindAdapterHandler);
  344. CHECK_EXIT_IRQL(EntryIrql);
  345. return;
  346. }
  347. VOID
  348. AtmLaneCompleteUnbindAdapter(
  349. IN PATMLANE_ADAPTER pAdapter
  350. )
  351. /*++
  352. Routine Description:
  353. Complete the process of adapter unbinding. All Elans on this
  354. adapter are assumed to have been removed.
  355. We start it off by calling NdisCloseAdapter. Action continues
  356. in our CloseAdapterComplete routine.
  357. Arguments:
  358. pAdapter - Pointer to the adapter being unbound.
  359. Return Value:
  360. None
  361. --*/
  362. {
  363. NDIS_STATUS Status;
  364. #if DEBUG_IRQL
  365. KIRQL EntryIrql;
  366. #endif
  367. GET_ENTRY_IRQL(EntryIrql);
  368. TRACEIN(CompleteUnbindAdapter);
  369. DBGP((3, "CompleteUnbindAdapter: pAdapter %x, AdapterHandle %x\n",
  370. pAdapter, pAdapter->NdisAdapterHandle));
  371. ASSERT(pAdapter->NdisAdapterHandle != NULL);
  372. pAdapter->Flags |= ADAPTER_FLAGS_CLOSE_IN_PROGRESS;
  373. NdisCloseAdapter(
  374. &Status,
  375. pAdapter->NdisAdapterHandle
  376. );
  377. if (Status != NDIS_STATUS_PENDING)
  378. {
  379. AtmLaneCloseAdapterCompleteHandler(
  380. (NDIS_HANDLE)pAdapter,
  381. Status
  382. );
  383. }
  384. TRACEOUT(CompleteUnbindAdapter);
  385. CHECK_EXIT_IRQL(EntryIrql);
  386. return;
  387. }
  388. VOID
  389. AtmLaneOpenAdapterCompleteHandler(
  390. IN NDIS_HANDLE ProtocolBindingContext,
  391. IN NDIS_STATUS Status,
  392. IN NDIS_STATUS OpenErrorStatus
  393. )
  394. /*++
  395. Routine Description:
  396. This is called by NDIS when a previous call to NdisOpenAdapter
  397. that had pended has completed. The thread that called NdisOpenAdapter
  398. would have blocked itself, so we simply wake it up now.
  399. Arguments:
  400. ProtocolBindingContext - Our context for this adapter binding, which
  401. is a pointer to an ATMLANE Adapter structure.
  402. Status - Status of OpenAdapter
  403. OpenErrorStatus - Error code in case of failure.
  404. Return Value:
  405. None
  406. --*/
  407. {
  408. PATMLANE_ADAPTER pAdapter;
  409. #if DEBUG_IRQL
  410. KIRQL EntryIrql;
  411. #endif
  412. GET_ENTRY_IRQL(EntryIrql);
  413. TRACEIN(OpenAdapterCompleteHandler);
  414. pAdapter = (PATMLANE_ADAPTER)ProtocolBindingContext;
  415. STRUCT_ASSERT(pAdapter, atmlane_adapter);
  416. SIGNAL_BLOCK_STRUCT(&(pAdapter->Block), Status);
  417. TRACEOUT(OpenAdapterCompleteHandler);
  418. CHECK_EXIT_IRQL(EntryIrql);
  419. return;
  420. }
  421. VOID
  422. AtmLaneCloseAdapterCompleteHandler(
  423. IN NDIS_HANDLE ProtocolBindingContext,
  424. IN NDIS_STATUS Status
  425. )
  426. /*++
  427. Routine Description:
  428. This is called by NDIS when a previous call to NdisCloseAdapter
  429. that had pended has completed. The thread that called NdisCloseAdapter
  430. would have blocked itself, so we simply wake it up now.
  431. Arguments:
  432. ProtocolBindingContext - Our context for this adapter binding, which
  433. is a pointer to an ATMLANE Adapter structure.
  434. Status - Status of CloseAdapter
  435. Return Value:
  436. None
  437. --*/
  438. {
  439. PATMLANE_ADAPTER pAdapter;
  440. NDIS_HANDLE UnbindContext;
  441. ULONG rc;
  442. #if DEBUG_IRQL
  443. KIRQL EntryIrql;
  444. #endif
  445. GET_ENTRY_IRQL(EntryIrql);
  446. TRACEIN(CloseAdapterCompleteHandler);
  447. pAdapter = (PATMLANE_ADAPTER)ProtocolBindingContext;
  448. STRUCT_ASSERT(pAdapter, atmlane_adapter);
  449. pAdapter->Flags &= ~ADAPTER_FLAGS_CLOSE_IN_PROGRESS;
  450. pAdapter->NdisAdapterHandle = NULL;
  451. UnbindContext = pAdapter->UnbindContext;
  452. DBGP((0, "CloseAdapterComplete: pAdapter %x, UnbindContext %x\n",
  453. pAdapter, UnbindContext));
  454. //
  455. // Dereference the Adapter (should free structure)
  456. //
  457. ACQUIRE_ADAPTER_LOCK(pAdapter);
  458. rc = AtmLaneDereferenceAdapter(pAdapter, "openadapter");
  459. ASSERT(rc == 0);
  460. //
  461. // If NDIS had requested us to Unbind, complete the
  462. // request now.
  463. //
  464. if (UnbindContext != (NDIS_HANDLE)NULL)
  465. {
  466. NdisCompleteUnbindAdapter(
  467. UnbindContext,
  468. NDIS_STATUS_SUCCESS
  469. );
  470. }
  471. else
  472. {
  473. //
  474. // We initiated the unbind from our Unload handler,
  475. // which would have been waiting for us to complete.
  476. // Wake up that thread now.
  477. //
  478. SIGNAL_BLOCK_STRUCT(&(pAtmLaneGlobalInfo->Block), NDIS_STATUS_SUCCESS);
  479. }
  480. TRACEOUT(CloseAdapterCompleteHandler);
  481. CHECK_EXIT_IRQL(EntryIrql);
  482. return;
  483. }
  484. VOID
  485. AtmLaneResetCompleteHandler(
  486. IN NDIS_HANDLE ProtocolBindingContext,
  487. IN NDIS_STATUS Status
  488. )
  489. /*++
  490. Routine Description:
  491. This routine is called when the miniport indicates that a Reset
  492. operation has just completed. We ignore this event.
  493. Arguments:
  494. ProtocolBindingContext - Our context for this adapter binding, which
  495. is a pointer to an ATMLANE Adapter structure.
  496. Status - Status of the reset operation.
  497. Return Value:
  498. None
  499. --*/
  500. {
  501. PATMLANE_ADAPTER pAdapter;
  502. TRACEIN(ResetCompleteHandler);
  503. pAdapter = (PATMLANE_ADAPTER)ProtocolBindingContext;
  504. STRUCT_ASSERT(pAdapter, atmlane_adapter);
  505. DBGP((3, "Reset Complete on Adapter %x\n", pAdapter));
  506. TRACEOUT(ResetCompleteHandler);
  507. return;
  508. }
  509. VOID
  510. AtmLaneRequestCompleteHandler(
  511. IN NDIS_HANDLE ProtocolBindingContext,
  512. IN PNDIS_REQUEST pNdisRequest,
  513. IN NDIS_STATUS Status
  514. )
  515. /*++
  516. Routine Description:
  517. This is called by NDIS when a previous call we made to NdisRequest() has
  518. completed. We would be blocked on our adapter structure, waiting for this
  519. to happen -- wake up the blocked thread.
  520. Arguments:
  521. ProtocolBindingContext - Pointer to our Adapter structure
  522. pNdisRequest - The request that completed
  523. Status - Status of the request.
  524. Return Value:
  525. None
  526. --*/
  527. {
  528. PATMLANE_ADAPTER pAdapter;
  529. #if DEBUG_IRQL
  530. KIRQL EntryIrql;
  531. #endif
  532. GET_ENTRY_IRQL(EntryIrql);
  533. TRACEIN(RequestCompleteHandler);
  534. pAdapter = (PATMLANE_ADAPTER)ProtocolBindingContext;
  535. STRUCT_ASSERT(pAdapter, atmlane_adapter);
  536. SIGNAL_BLOCK_STRUCT(&(pAdapter->Block), Status);
  537. TRACEOUT(RequestCompleteHandler);
  538. CHECK_EXIT_IRQL(EntryIrql);
  539. return;
  540. }
  541. VOID
  542. AtmLaneReceiveCompleteHandler(
  543. IN NDIS_HANDLE ProtocolBindingContext
  544. )
  545. /*++
  546. Routine Description:
  547. This is currently ignored.
  548. Arguments:
  549. ProtocolBindingContext - Our context for this adapter binding, which
  550. is a pointer to an ATMLANE Adapter structure.
  551. Return Value:
  552. None
  553. --*/
  554. {
  555. PATMLANE_ADAPTER pAdapter;
  556. PATMLANE_ELAN pElan;
  557. PLIST_ENTRY Entry;
  558. TRACEIN(ReceiveCompleteHandler);
  559. TRACEOUT(ReceiveCompleteHandler);
  560. return;
  561. }
  562. VOID
  563. AtmLaneStatusHandler(
  564. IN NDIS_HANDLE ProtocolBindingContext,
  565. IN NDIS_STATUS GeneralStatus,
  566. IN PVOID pStatusBuffer,
  567. IN UINT StatusBufferSize
  568. )
  569. /*++
  570. Routine Description:
  571. This routine is called when the miniport indicates an adapter-wide
  572. status change. We ignore this.
  573. Arguments:
  574. <Ignored>
  575. Return Value:
  576. None
  577. --*/
  578. {
  579. TRACEIN(StatusHandler);
  580. DBGP((3, "StatusHandler: ProtocolBindContext %x, Status %x\n",
  581. ProtocolBindingContext,
  582. GeneralStatus));
  583. TRACEOUT(StatusHandler);
  584. return;
  585. }
  586. VOID
  587. AtmLaneStatusCompleteHandler(
  588. IN NDIS_HANDLE ProtocolBindingContext
  589. )
  590. /*++
  591. Routine Description:
  592. This routine is called when the miniport wants to tell us about
  593. completion of a status change (?). Ignore this.
  594. Arguments:
  595. <Ignored>
  596. Return Value:
  597. None
  598. --*/
  599. {
  600. TRACEIN(StatusCompleteHandler);
  601. DBGP((3, "StatusCompleteHandler: ProtocolBindingContext %x\n",
  602. ProtocolBindingContext));
  603. TRACEOUT(StatusCompleteHandler);
  604. return;
  605. }
  606. VOID
  607. AtmLaneCoSendCompleteHandler(
  608. IN NDIS_STATUS Status,
  609. IN NDIS_HANDLE ProtocolVcContext,
  610. IN PNDIS_PACKET pNdisPacket
  611. )
  612. /*++
  613. Routine Description:
  614. This routine is called by NDIS when the ATM miniport is finished
  615. with a packet we had previously sent via NdisCoSendPackets.
  616. If packet originated within ATMLANE it is freed here.
  617. If packet originated in protocol above the virtual miniport
  618. the packet must be put back in it's original condition and
  619. returned to the protocol.
  620. Arguments:
  621. Status - Status of the NdisCoSendPackets.
  622. ProtocolVcContext - Our context for the VC on which the packet was sent
  623. (i.e. pointer to ATMLANE VC).
  624. pNdisPacket - The packet whose "send" is being completed.
  625. Return Value:
  626. None
  627. --*/
  628. {
  629. PATMLANE_VC pVc;
  630. PATMLANE_ELAN pElan;
  631. UINT TotalLength;
  632. BOOLEAN OwnerIsLane;
  633. PNDIS_BUFFER pNdisBuffer;
  634. PNDIS_PACKET pProtNdisPacket;
  635. ULONG rc;
  636. #if DEBUG_IRQL
  637. KIRQL EntryIrql;
  638. #endif
  639. GET_ENTRY_IRQL(EntryIrql);
  640. TRACEIN(CoSendCompleteHandler);
  641. TRACELOGWRITE((&TraceLog, TL_COSENDCMPLTIN, pNdisPacket, Status));
  642. TRACELOGWRITEPKT((&TraceLog, pNdisPacket));
  643. pVc = (PATMLANE_VC)ProtocolVcContext;
  644. STRUCT_ASSERT(pVc, atmlane_vc)
  645. ACQUIRE_VC_LOCK(pVc);
  646. pElan = pVc->pElan;
  647. STRUCT_ASSERT(pElan, atmlane_elan);
  648. rc = AtmLaneDereferenceVc(pVc, "sendpkt");
  649. if (rc > 0)
  650. {
  651. pVc->OutstandingSends--;
  652. if ((pVc->OutstandingSends == 0) &&
  653. (IS_FLAG_SET(pVc->Flags,
  654. VC_CLOSE_STATE_MASK,
  655. VC_CLOSE_STATE_CLOSING)))
  656. {
  657. DBGP((1, "CoSendComplete: Vc %p, closing call\n", pVc));
  658. AtmLaneCloseCall(pVc);
  659. //
  660. // VC lock is released above.
  661. //
  662. }
  663. else
  664. {
  665. RELEASE_VC_LOCK(pVc);
  666. }
  667. }
  668. #if SENDLIST
  669. //
  670. // Remove packet from send list if there
  671. //
  672. NdisAcquireSpinLock(&pElan->SendListLock);
  673. {
  674. PNDIS_PACKET *ppNextPkt;
  675. BOOLEAN Found = FALSE;
  676. ppNextPkt = &(pElan->pSendList);
  677. while (*ppNextPkt != (PNDIS_PACKET)NULL)
  678. {
  679. if (*ppNextPkt == pNdisPacket)
  680. {
  681. *ppNextPkt = PSEND_RSVD(pNdisPacket)->pNextInSendList;
  682. Found = TRUE;
  683. break;
  684. }
  685. else
  686. {
  687. ppNextPkt = &(PSEND_RSVD((*ppNextPkt))->pNextInSendList);
  688. }
  689. }
  690. if (!Found)
  691. {
  692. DBGP((0, "CoSendCompleteHandler: Pkt %x Duplicate Completion\n", pNdisPacket));
  693. NdisReleaseSpinLock(&pElan->SendListLock);
  694. goto skipit;
  695. }
  696. }
  697. NdisReleaseSpinLock(&pElan->SendListLock);
  698. #endif // SENDLIST
  699. #if PROTECT_PACKETS
  700. //
  701. // Lock the packet
  702. //
  703. ACQUIRE_SENDPACKET_LOCK(pNdisPacket);
  704. //
  705. // Mark it as having been completed by miniport.
  706. // Remember completion status.
  707. //
  708. ASSERT((PSEND_RSVD(pNdisPacket)->Flags & PACKET_RESERVED_COMPLETED) == 0);
  709. PSEND_RSVD(pNdisPacket)->Flags |= PACKET_RESERVED_COMPLETED;
  710. PSEND_RSVD(pNdisPacket)->CompletionStatus = Status;
  711. //
  712. // Complete the packet only if the call to NdisCoSendPackets
  713. // for this packet has returned. Otherwise it will be completed
  714. // when NdisCoSendPackets returns.
  715. //
  716. if ((PSEND_RSVD(pNdisPacket)->Flags & PACKET_RESERVED_COSENDRETURNED) != 0)
  717. {
  718. AtmLaneCompleteSendPacket(pElan, pNdisPacket, Status);
  719. //
  720. // packet lock released in above
  721. //
  722. }
  723. else
  724. {
  725. RELEASE_SENDPACKET_LOCK(pNdisPacket);
  726. }
  727. #else // PROTECT_PACKETS
  728. AtmLaneCompleteSendPacket(pElan, pNdisPacket, Status);
  729. #endif // PROTECT_PACKETS
  730. #if SENDLIST
  731. skipit:
  732. #endif
  733. TRACELOGWRITE((&TraceLog, TL_COSENDCMPLTOUT, pNdisPacket));
  734. TRACEOUT(CoSendCompleteHandler);
  735. CHECK_EXIT_IRQL(EntryIrql);
  736. return;
  737. }
  738. VOID
  739. AtmLaneCoStatusHandler(
  740. IN NDIS_HANDLE ProtocolBindingContext,
  741. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  742. IN NDIS_STATUS GeneralStatus,
  743. IN PVOID pStatusBuffer,
  744. IN UINT StatusBufferSize
  745. )
  746. /*++
  747. Routine Description:
  748. This routine is called when the miniport indicates a status
  749. change, possibly on a VC. Ignore this.
  750. Arguments:
  751. <Ignored>
  752. Return Value:
  753. None
  754. --*/
  755. {
  756. TRACEIN(CoStatusHandler);
  757. DBGP((3, "CoStatusHandler: ProtocolBindingContext %x "
  758. "ProtocolVcContext %x, Status %x\n",
  759. ProtocolBindingContext,
  760. ProtocolVcContext,
  761. GeneralStatus));
  762. TRACEOUT(CoStatusHandler);
  763. return;
  764. }
  765. NDIS_STATUS
  766. AtmLaneSendAdapterNdisRequest(
  767. IN PATMLANE_ADAPTER pAdapter,
  768. IN PNDIS_REQUEST pNdisRequest,
  769. IN NDIS_REQUEST_TYPE RequestType,
  770. IN NDIS_OID Oid,
  771. IN PVOID pBuffer,
  772. IN ULONG BufferLength
  773. )
  774. /*++
  775. Routine Description:
  776. Send an NDIS (non-Connection Oriented) request to the Miniport.
  777. Initialize the NDIS_REQUEST structure, link the supplied buffer to it,
  778. and send the request. If the request does not pend, we call our
  779. completion routine from here.
  780. Arguments:
  781. pAdapter - Pointer to our Adapter structure representing
  782. the adapter to which the request is to be sent
  783. pNdisRequest - Pointer to NDIS request structure
  784. RequestType - Set/Query information
  785. Oid - OID to be passed in the request
  786. pBuffer - place for value(s)
  787. BufferLength - length of above
  788. Return Value:
  789. Status of the NdisRequest.
  790. --*/
  791. {
  792. NDIS_STATUS Status;
  793. TRACEIN(SendAdapterNdisRequest);
  794. //
  795. // Fill in the NDIS Request structure
  796. //
  797. pNdisRequest->RequestType = RequestType;
  798. if (RequestType == NdisRequestQueryInformation)
  799. {
  800. pNdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
  801. pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = pBuffer;
  802. pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = BufferLength;
  803. pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
  804. pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = BufferLength;
  805. }
  806. else
  807. {
  808. pNdisRequest->DATA.SET_INFORMATION.Oid = Oid;
  809. pNdisRequest->DATA.SET_INFORMATION.InformationBuffer = pBuffer;
  810. pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength = BufferLength;
  811. pNdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
  812. pNdisRequest->DATA.SET_INFORMATION.BytesNeeded = 0;
  813. }
  814. INIT_BLOCK_STRUCT(&(pAdapter->Block));
  815. NdisRequest(
  816. &Status,
  817. pAdapter->NdisAdapterHandle,
  818. pNdisRequest);
  819. if (Status == NDIS_STATUS_PENDING)
  820. {
  821. Status = WAIT_ON_BLOCK_STRUCT(&(pAdapter->Block));
  822. }
  823. TRACEOUT(SendAdapterNdisRequest);
  824. return (Status);
  825. }
  826. VOID
  827. AtmLaneGetAdapterInfo(
  828. IN PATMLANE_ADAPTER pAdapter
  829. )
  830. /*++
  831. Routine Description:
  832. Query an adapter for hardware-specific information that we need:
  833. - burnt in hardware address (ESI part)
  834. - Max packet size
  835. - line rate
  836. Arguments:
  837. pAdapter - Pointer to ATMLANE adapter structure
  838. Return Value:
  839. None
  840. --*/
  841. {
  842. NDIS_STATUS Status;
  843. NDIS_REQUEST NdisRequest;
  844. ULONG Value;
  845. TRACEIN(GetAdapterInfo);
  846. //
  847. // Initialize.
  848. //
  849. NdisZeroMemory(&pAdapter->MacAddress, sizeof(MAC_ADDRESS));
  850. //
  851. // MAC Address:
  852. //
  853. Status = AtmLaneSendAdapterNdisRequest(
  854. pAdapter,
  855. &NdisRequest,
  856. NdisRequestQueryInformation,
  857. OID_ATM_HW_CURRENT_ADDRESS,
  858. (PVOID)&(pAdapter->MacAddress),
  859. sizeof(MAC_ADDRESS)
  860. );
  861. if (NDIS_STATUS_SUCCESS != Status)
  862. {
  863. DBGP((0, "GetAdapterInfo: OID_ATM_HW_CURRENT_ADDRESS failed\n"));
  864. }
  865. else
  866. {
  867. DBGP((1, "GetAdapterInfo: ATM card MacAddr %s\n",
  868. MacAddrToString(&pAdapter->MacAddress)));
  869. }
  870. //
  871. // Max Frame Size:
  872. //
  873. Status = AtmLaneSendAdapterNdisRequest(
  874. pAdapter,
  875. &NdisRequest,
  876. NdisRequestQueryInformation,
  877. OID_ATM_MAX_AAL5_PACKET_SIZE,
  878. (PVOID)&(pAdapter->MaxAAL5PacketSize),
  879. sizeof(ULONG)
  880. );
  881. if (NDIS_STATUS_SUCCESS != Status)
  882. {
  883. DBGP((0, "GetAdapterInfo: OID_ATM_MAX_AAL5_PACKET_SIZE failed\n"));
  884. //
  885. // Use the default.
  886. //
  887. pAdapter->MaxAAL5PacketSize = ATMLANE_DEF_MAX_AAL5_PDU_SIZE;
  888. }
  889. if (pAdapter->MaxAAL5PacketSize > ATMLANE_DEF_MAX_AAL5_PDU_SIZE)
  890. {
  891. pAdapter->MaxAAL5PacketSize = ATMLANE_DEF_MAX_AAL5_PDU_SIZE;
  892. }
  893. DBGP((1, "GetAdapterInfo: MaxAAL5PacketSize %d\n", pAdapter->MaxAAL5PacketSize));
  894. //
  895. // Link speed:
  896. //
  897. Status = AtmLaneSendAdapterNdisRequest(
  898. pAdapter,
  899. &NdisRequest,
  900. NdisRequestQueryInformation,
  901. OID_GEN_CO_LINK_SPEED,
  902. (PVOID)(&(pAdapter->LinkSpeed)),
  903. sizeof(NDIS_CO_LINK_SPEED)
  904. );
  905. if ((NDIS_STATUS_SUCCESS != Status) ||
  906. (0 == pAdapter->LinkSpeed.Inbound) ||
  907. (0 == pAdapter->LinkSpeed.Outbound))
  908. {
  909. DBGP((0, "GetAdapterInfo: OID_GEN_CO_LINK_SPEED failed\n"));
  910. //
  911. // Default and assume data rate for 155.52Mbps SONET
  912. //
  913. pAdapter->LinkSpeed.Outbound = pAdapter->LinkSpeed.Inbound = ATM_USER_DATA_RATE_SONET_155;
  914. }
  915. DBGP((1, "GetAdapterInfo: Outbound Linkspeed %d\n", pAdapter->LinkSpeed.Outbound));
  916. DBGP((1, "GetAdapterInfo: Inbound Linkspeed %d\n", pAdapter->LinkSpeed.Inbound));
  917. TRACEOUT(GetAdapterInfo);
  918. return;
  919. }
  920. UINT
  921. AtmLaneCoReceivePacketHandler(
  922. IN NDIS_HANDLE ProtocolBindingContext,
  923. IN NDIS_HANDLE ProtocolVcContext,
  924. IN PNDIS_PACKET pNdisPacket
  925. )
  926. /*++
  927. Routine Description:
  928. This is routine is called when a packet is received on a VC owned
  929. by the ATMLANE module. It is dispatched based on the VC type.
  930. Arguments:
  931. ProtocolBindingContext - Actually a pointer to our Adapter structure
  932. ProtocolVcContext - Actually a pointer to our VC structure
  933. pNdisPacket - NDIS packet being received.
  934. Return Value:
  935. 0 - if packet is a LANE Control Packet or undesired data packet.
  936. 1 - if data packet indicated up to protocol.
  937. --*/
  938. {
  939. PATMLANE_ELAN pElan;
  940. PATMLANE_VC pVc;
  941. UINT TotalLength; // Total bytes in packet
  942. PNDIS_BUFFER pNdisBuffer; // Pointer to first buffer
  943. UINT BufferLength;
  944. UINT IsNonUnicast; // Is this to a non-unicast destn MAC addr?
  945. BOOLEAN RetainIt; // Should we hang on to this packet?
  946. static ULONG Count = 0;
  947. #if DEBUG_IRQL
  948. KIRQL EntryIrql;
  949. #endif
  950. GET_ENTRY_IRQL(EntryIrql);
  951. TRACEIN(CoReceivePacketHandler);
  952. pVc = (PATMLANE_VC)ProtocolVcContext;
  953. STRUCT_ASSERT(pVc, atmlane_vc);
  954. pElan = pVc->pElan;
  955. STRUCT_ASSERT(pElan, atmlane_elan);
  956. // if ((++Count % 10) == 0)
  957. // DBGP((0, "%d Packets Received\n", Count));
  958. DBGP((2, "CoReceivePacketHandler: pVc %x Pkt %x\n", pVc, pNdisPacket));
  959. TRACELOGWRITE((&TraceLog,
  960. TL_CORECVPACKET,
  961. pNdisPacket,
  962. pVc));
  963. //
  964. // Initialize
  965. //
  966. RetainIt = FALSE; // default to discarding received packet
  967. if (ELAN_STATE_OPERATIONAL == pElan->AdminState)
  968. {
  969. switch(pVc->LaneType)
  970. {
  971. case VC_LANE_TYPE_CONFIG_DIRECT:
  972. AtmLaneConfigureResponseHandler(pElan, pVc, pNdisPacket);
  973. break;
  974. case VC_LANE_TYPE_CONTROL_DIRECT:
  975. case VC_LANE_TYPE_CONTROL_DISTRIBUTE:
  976. AtmLaneControlPacketHandler(pElan, pVc, pNdisPacket);
  977. break;
  978. case VC_LANE_TYPE_DATA_DIRECT:
  979. case VC_LANE_TYPE_MULTI_SEND:
  980. case VC_LANE_TYPE_MULTI_FORWARD:
  981. if (ELAN_STATE_OPERATIONAL == pElan->State)
  982. {
  983. RetainIt = AtmLaneDataPacketHandler(pElan, pVc, pNdisPacket);
  984. }
  985. else
  986. {
  987. DBGP((0, "%d Dropping Pkt %x cuz Elan %x state is %d\n",
  988. pElan->ElanNumber,
  989. pNdisPacket,
  990. pElan,
  991. pElan->State));
  992. }
  993. break;
  994. default:
  995. DBGP((0, "CoReceivePacketHandler: pVc %x Type UNKNOWN!\n", pVc));
  996. break;
  997. }
  998. }
  999. TRACEOUT(CoReceivePacketHandler);
  1000. CHECK_EXIT_IRQL(EntryIrql);
  1001. return (RetainIt);
  1002. }
  1003. VOID
  1004. AtmLaneUnloadProtocol(
  1005. VOID
  1006. )
  1007. /*++
  1008. Routine Description:
  1009. Unloads the ATMLANE protocol module. We unbind from all adapters,
  1010. and deregister from NDIS as a protocol.
  1011. Arguments:
  1012. None.
  1013. Return Value:
  1014. None
  1015. --*/
  1016. {
  1017. NDIS_STATUS Status;
  1018. PATMLANE_ADAPTER pAdapter;
  1019. #if DEBUG_IRQL
  1020. KIRQL EntryIrql;
  1021. #endif
  1022. GET_ENTRY_IRQL(EntryIrql);
  1023. TRACEIN(UnloadProtocol);
  1024. Status = NDIS_STATUS_SUCCESS;
  1025. ACQUIRE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  1026. //
  1027. // Until adapter list is empty...
  1028. //
  1029. while (!IsListEmpty(&pAtmLaneGlobalInfo->AdapterList))
  1030. {
  1031. //
  1032. // Keep grabbing the first one on the list.
  1033. //
  1034. pAdapter = CONTAINING_RECORD(
  1035. pAtmLaneGlobalInfo->AdapterList.Flink,
  1036. ATMLANE_ADAPTER,
  1037. Link
  1038. );
  1039. STRUCT_ASSERT(pAdapter, atmlane_adapter);
  1040. RELEASE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  1041. DBGP((3, "UnloadProtocol: will unbind adapter %x\n", pAdapter));
  1042. INIT_BLOCK_STRUCT(&(pAtmLaneGlobalInfo->Block));
  1043. //
  1044. // unbind which should delete the adapter struct
  1045. // and remove it from global list
  1046. //
  1047. AtmLaneUnbindAdapterHandler(
  1048. &Status,
  1049. (NDIS_HANDLE)pAdapter,
  1050. (NDIS_HANDLE)NULL // No UnbindContext ==> Don't complete NdisUnbind
  1051. );
  1052. if (NDIS_STATUS_PENDING == Status)
  1053. {
  1054. //
  1055. // Wait for the unbind to complete
  1056. //
  1057. (VOID)WAIT_ON_BLOCK_STRUCT(&(pAtmLaneGlobalInfo->Block));
  1058. }
  1059. ACQUIRE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  1060. }
  1061. RELEASE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  1062. FREE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  1063. FREE_BLOCK_STRUCT(&(pAtmArpGlobalInfo->Block));
  1064. #if 0
  1065. AuditShutdown();
  1066. #endif
  1067. if (pAtmLaneGlobalInfo->SpecialNdisDeviceHandle)
  1068. {
  1069. DBGP((0, "Deregistering device from UnloadProtocol\n"));
  1070. Status = NdisMDeregisterDevice(pAtmLaneGlobalInfo->SpecialNdisDeviceHandle);
  1071. pAtmLaneGlobalInfo->SpecialNdisDeviceHandle = NULL;
  1072. ASSERT(NDIS_STATUS_SUCCESS == Status);
  1073. }
  1074. if (pAtmLaneGlobalInfo->NdisProtocolHandle)
  1075. {
  1076. DBGP((0, "UnloadProtocol: NdisDeregisterProtocol now, "
  1077. "NdisProtocolHandle %x\n",
  1078. pAtmLaneGlobalInfo->NdisProtocolHandle));
  1079. NdisDeregisterProtocol(
  1080. &Status,
  1081. pAtmLaneGlobalInfo->NdisProtocolHandle
  1082. );
  1083. pAtmLaneGlobalInfo->NdisProtocolHandle = NULL;
  1084. }
  1085. ASSERT(NDIS_STATUS_SUCCESS == Status);
  1086. TRACEIN(UnloadProtocol);
  1087. CHECK_EXIT_IRQL(EntryIrql);
  1088. return;
  1089. }
  1090. //
  1091. // Dummy handlers so that a debug build won't complain
  1092. //
  1093. VOID
  1094. AtmLaneSendCompleteHandler(
  1095. IN NDIS_HANDLE ProtocolBindingContext,
  1096. IN PNDIS_PACKET Packet,
  1097. IN NDIS_STATUS Status
  1098. )
  1099. {
  1100. }
  1101. VOID
  1102. AtmLaneTransferDataCompleteHandler(
  1103. IN NDIS_HANDLE ProtocolBindingContext,
  1104. IN PNDIS_PACKET Packet,
  1105. IN NDIS_STATUS Status,
  1106. IN UINT BytesTransferred
  1107. )
  1108. {
  1109. }
  1110. NDIS_STATUS
  1111. AtmLaneReceiveHandler(
  1112. IN NDIS_HANDLE ProtocolBindingContext,
  1113. IN NDIS_HANDLE MacReceiveContext,
  1114. IN PVOID HeaderBuffer,
  1115. IN UINT HeaderBufferSize,
  1116. IN PVOID LookAheadBuffer,
  1117. IN UINT LookaheadBufferSize,
  1118. IN UINT PacketSize
  1119. )
  1120. {
  1121. return(NDIS_STATUS_FAILURE);
  1122. }
  1123. BOOLEAN
  1124. AtmLaneIsDeviceAlreadyBound(
  1125. IN PNDIS_STRING pDeviceName
  1126. )
  1127. /*++
  1128. Routine Description:
  1129. Check if we have already bound to a device (adapter).
  1130. Arguments:
  1131. pDeviceName - Points to device name to be checked.
  1132. Return Value:
  1133. TRUE iff we already have an Adapter structure representing
  1134. this device.
  1135. --*/
  1136. {
  1137. PATMLANE_ADAPTER pAdapter;
  1138. BOOLEAN bFound = FALSE;
  1139. PLIST_ENTRY pListEntry;
  1140. ACQUIRE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  1141. for (pListEntry = pAtmLaneGlobalInfo->AdapterList.Flink;
  1142. pListEntry != &(pAtmLaneGlobalInfo->AdapterList);
  1143. pListEntry = pListEntry->Flink)
  1144. {
  1145. //
  1146. // Keep grabbing the first one on the list.
  1147. //
  1148. pAdapter = CONTAINING_RECORD(
  1149. pListEntry,
  1150. ATMLANE_ADAPTER,
  1151. Link
  1152. );
  1153. if ((pDeviceName->Length == pAdapter->DeviceName.Length) &&
  1154. (memcmp(pDeviceName->Buffer,
  1155. pAdapter->DeviceName.Buffer,
  1156. pDeviceName->Length) == 0))
  1157. {
  1158. bFound = TRUE;
  1159. break;
  1160. }
  1161. }
  1162. RELEASE_GLOBAL_LOCK(pAtmLaneGlobalInfo);
  1163. return (bFound);
  1164. }