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.

4832 lines
140 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. nd.c
  5. Abstract:
  6. ARP1394 ndis handlers (excluding connection-oriented handlers).
  7. Revision History:
  8. Who When What
  9. -------- -------- ----------------------------------------------
  10. josephj 12-01-98 Created, adapting code from atmarpc.sys
  11. Notes:
  12. --*/
  13. #include <precomp.h>
  14. //
  15. // File-specific debugging defaults.
  16. //
  17. #define TM_CURRENT TM_ND
  18. //=========================================================================
  19. // L O C A L P R O T O T Y P E S
  20. //=========================================================================
  21. // ARP1394_BIND_PARAMS is used when creating an adapter object.
  22. //
  23. typedef struct
  24. {
  25. PNDIS_STRING pDeviceName;
  26. PNDIS_STRING pArpConfigName;
  27. PVOID IpConfigHandle;
  28. NDIS_HANDLE BindContext;
  29. } ARP1394_BIND_PARAMS;
  30. NDIS_STATUS
  31. arpPnPReconfigHandler(
  32. IN ARP1394_ADAPTER * pAdapter,
  33. IN PNET_PNP_EVENT pNetPnPEvent
  34. );
  35. ENetAddr
  36. arpGetSecondaryMacAddress (
  37. IN ENetAddr EthernetMacAddress
  38. );
  39. NDIS_STATUS
  40. arpGetEuidTopologyWorkItem(
  41. struct _ARP1394_WORK_ITEM* pWorkItem,
  42. PRM_OBJECT_HEADER pObj ,
  43. PRM_STACK_RECORD pSR
  44. );
  45. VOID
  46. arpAddBackupTasks (
  47. IN ARP1394_GLOBALS* pGlobals,
  48. UINT Num
  49. );
  50. VOID
  51. arpRemoveBackupTasks (
  52. IN ARP1394_GLOBALS* pGlobals,
  53. UINT Num
  54. );
  55. NDIS_STATUS
  56. arpNdSetPower (
  57. ARP1394_ADAPTER *pAdapter,
  58. PNET_DEVICE_POWER_STATE pPowerState,
  59. PRM_STACK_RECORD pSR
  60. );
  61. NDIS_STATUS
  62. arpResume (
  63. IN ARP1394_ADAPTER* pAdapter,
  64. IN ARP_RESUME_CAUSE Cause,
  65. IN PRM_STACK_RECORD pSR
  66. );
  67. const ENetAddr DummyENet = {0xba,0xdb,0xad,0xba,0xdb,0xad};
  68. //=========================================================================
  69. // N D I S H A N D L E R S
  70. //=========================================================================
  71. INT
  72. ArpNdBindAdapter(
  73. OUT PNDIS_STATUS pStatus,
  74. IN NDIS_HANDLE BindContext,
  75. IN PNDIS_STRING pDeviceName,
  76. IN PVOID SystemSpecific1,
  77. IN PVOID SystemSpecific2
  78. )
  79. /*++
  80. Routine Description:
  81. This is called by TCPIP when it has an adapter for which there is a
  82. binding to the ARP client.
  83. We first allocate an Adapter structure. Then we open our configuration
  84. section for this adapter and save the handle in the Adapter structure.
  85. Finally, we open the adapter.
  86. We don't do anything more for this adapter until NDIS notifies us of
  87. the presence of a Call manager (via our AfRegisterNotify handler).
  88. Arguments:
  89. pStatus - Place to return status of this call
  90. BindContext - NDIS-supplied Bind context. IF this is NULL,
  91. we are calling ourselves to open an adapter in
  92. Ethernet emulation (bridge) mode.
  93. pDeviceName - The name of the adapter we are requested to bind to
  94. SystemSpecific1 - Opaque to us; to be used to access configuration info
  95. SystemSpecific2 - Opaque to us; not used.
  96. Return Value:
  97. Always TRUE. We set *pStatus to an error code if something goes wrong before we
  98. call NdisOpenAdapter, otherwise NDIS_STATUS_PENDING.
  99. --*/
  100. {
  101. NDIS_STATUS Status;
  102. ARP1394_ADAPTER * pAdapter;
  103. #if DBG
  104. KIRQL EntryIrql = KeGetCurrentIrql();
  105. #endif // DBG
  106. ENTER("BindAdapter", 0x5460887b)
  107. RM_DECLARE_STACK_RECORD(sr)
  108. TIMESTAMP("==>BindAdapter");
  109. do
  110. {
  111. PRM_TASK pTask;
  112. ARP1394_BIND_PARAMS BindParams;
  113. // Setup initialization parameters
  114. //
  115. BindParams.pDeviceName = pDeviceName;
  116. BindParams.pArpConfigName = (PNDIS_STRING) SystemSpecific1;
  117. BindParams.IpConfigHandle = SystemSpecific2;
  118. BindParams.BindContext = BindContext;
  119. // Allocate and initialize adapter object.
  120. // This also sets up ref counts for all linkages, plus one
  121. // tempref for us, which we must deref when done.
  122. //
  123. Status = RM_CREATE_AND_LOCK_OBJECT_IN_GROUP(
  124. &ArpGlobals.adapters.Group,
  125. pDeviceName, // Key
  126. &BindParams, // Init params
  127. &((PRM_OBJECT_HEADER)pAdapter),
  128. NULL, // pfCreated
  129. &sr
  130. );
  131. if (FAIL(Status))
  132. {
  133. TR_WARN(("FATAL: Couldn't create adapter object\n"));
  134. pAdapter = NULL;
  135. break;
  136. }
  137. // Allocate task to complete the initialization.
  138. // The task is tmp ref'd for us, and we must deref it when we're done here.
  139. // We implicitly do this by calling RmStartTask below.
  140. //
  141. Status = arpAllocateTask(
  142. &pAdapter->Hdr, // pParentObject,
  143. arpTaskInitializeAdapter, // pfnHandler,
  144. 0, // Timeout,
  145. "Task: Initialize Adapter", // szDescription
  146. &pTask,
  147. &sr
  148. );
  149. if (FAIL(Status))
  150. {
  151. pTask = NULL;
  152. break;
  153. }
  154. UNLOCKOBJ(pAdapter, &sr);
  155. // Start the task to complete this initialization.
  156. // NO locks must be held at this time.
  157. // RmStartTask expect's a tempref on the task, which it deref's when done.
  158. // RmStartTask will free the task automatically, whether it completes
  159. // synchronously or asynchronously.
  160. //
  161. Status = RmStartTask(pTask, 0, &sr);
  162. LOCKOBJ(pAdapter, &sr);
  163. } while(FALSE);
  164. if (pAdapter)
  165. {
  166. UNLOCKOBJ(pAdapter, &sr);
  167. if (!PEND(Status) && FAIL(Status))
  168. {
  169. // At this point the adapter should be a "zombie object."
  170. //
  171. ASSERTEX(RM_IS_ZOMBIE(pAdapter), pAdapter);
  172. }
  173. RmTmpDereferenceObject(&pAdapter->Hdr, &sr);
  174. }
  175. *pStatus = Status;
  176. #if DBG
  177. {
  178. KIRQL ExitIrql = KeGetCurrentIrql();
  179. TR_INFO(("Exiting. EntryIrql=%lu, ExitIrql = %lu\n", EntryIrql, ExitIrql));
  180. }
  181. #endif //DBG
  182. RM_ASSERT_CLEAR(&sr);
  183. EXIT()
  184. TIMESTAMP("<==BindAdapter");
  185. return 0;
  186. }
  187. VOID
  188. ArpNdUnbindAdapter(
  189. OUT PNDIS_STATUS pStatus,
  190. IN NDIS_HANDLE ProtocolBindingContext,
  191. IN NDIS_HANDLE UnbindContext
  192. )
  193. /*++
  194. Routine Description:
  195. This routine is called by NDIS when it wants us to unbind
  196. from an adapter. Or, this may be called from within our Unload
  197. handler. We undo the sequence of operations we performed
  198. in our BindAdapter handler.
  199. Arguments:
  200. pStatus - Place to return status of this operation
  201. ProtocolBindingContext - Our context for this adapter binding, which
  202. is a pointer to an ATMARP Adapter structure.
  203. UnbindContext - This is NULL if this routine is called from
  204. within our Unload handler. Otherwise (i.e.
  205. NDIS called us), we retain this for later use
  206. when calling NdisCompleteUnbindAdapter.
  207. Return Value:
  208. None. We set *pStatus to NDIS_STATUS_PENDING always.
  209. --*/
  210. {
  211. ENTER("UnbindAdapter", 0x6bff4ab5)
  212. ARP1394_ADAPTER * pAdapter = (ARP1394_ADAPTER*) ProtocolBindingContext;
  213. RM_DECLARE_STACK_RECORD(sr)
  214. TIMESTAMP("==>UnbindAdapter");
  215. // Get adapter lock and tmpref it.
  216. LOCKOBJ(pAdapter, &sr);
  217. RmTmpReferenceObject(&pAdapter->Hdr, &sr);
  218. do
  219. {
  220. NDIS_STATUS Status;
  221. PRM_TASK pTask;
  222. if (CHECK_POWER_STATE(pAdapter,ARPAD_POWER_LOW_POWER)== TRUE)
  223. {
  224. //
  225. // Set the flag in case we are in the scenario wherein our Open Af has
  226. // not completed but we need to unbind. This can happen when the machine
  227. // is resuming from a low power state
  228. //
  229. pAdapter->PoMgmt.bReceivedUnbind = TRUE;;
  230. }
  231. // Allocate task to complete the unbind.
  232. //
  233. Status = arpAllocateTask(
  234. &pAdapter->Hdr, // pParentObject,
  235. arpTaskShutdownAdapter, // pfnHandler,
  236. 0, // Timeout,
  237. "Task: Shutdown Adapter", // szDescription
  238. &pTask,
  239. &sr
  240. );
  241. if (FAIL(Status))
  242. {
  243. // Ugly situation. We'll just leave things as they are...
  244. //
  245. pTask = NULL;
  246. TR_WARN(("FATAL: couldn't allocate unbind task!\n"));
  247. break;
  248. }
  249. // Start the task to complete the unbind.
  250. // No locks must be held. RmStartTask uses up the tmpref on the task
  251. // which was added by arpAllocateTask.
  252. //
  253. UNLOCKOBJ(pAdapter, &sr);
  254. Status = RmStartTask(pTask, (UINT_PTR) UnbindContext, &sr);
  255. LOCKOBJ(pAdapter, &sr);
  256. } while(FALSE);
  257. UNLOCKOBJ(pAdapter, &sr);
  258. RmTmpDereferenceObject(&pAdapter->Hdr, &sr);
  259. *pStatus = NDIS_STATUS_PENDING;
  260. RM_ASSERT_CLEAR(&sr);
  261. TIMESTAMP("<==UnbindAdapter");
  262. EXIT()
  263. }
  264. VOID
  265. ArpNdOpenAdapterComplete(
  266. IN NDIS_HANDLE ProtocolBindingContext,
  267. IN NDIS_STATUS Status,
  268. IN NDIS_STATUS OpenErrorStatus
  269. )
  270. /*++
  271. Routine Description:
  272. This is called by NDIS when a previous call to NdisOpenAdapter
  273. that had pended has completed. We now complete the BindAdapter
  274. that lead to this.
  275. Arguments:
  276. ProtocolBindingContext - Our context for this adapter binding, which
  277. is a pointer to an ARP1394_ADAPTER structure.
  278. Status - Status of OpenAdapter
  279. OpenErrorStatus - Error code in case of failure.
  280. --*/
  281. {
  282. ENTER("OpenAdapterComplete", 0x06d9342c)
  283. ARP1394_ADAPTER * pAdapter = (ARP1394_ADAPTER*) ProtocolBindingContext;
  284. RM_DECLARE_STACK_RECORD(sr)
  285. TIMESTAMP("==>OpenAdapterComplete");
  286. // We expect a nonzero task here (the bind task), which we unpend.
  287. // No need to grab locks or anything at this stage.
  288. //
  289. {
  290. TR_INFO((
  291. "BindCtxt=0x%p, status=0x%p, OpenErrStatus=0x%p",
  292. ProtocolBindingContext,
  293. Status,
  294. OpenErrorStatus
  295. ));
  296. // We don't pass on OpenErrorStatus, so we have just the status
  297. // to pass on, which we do directly as the UINT_PTR "Param".
  298. //
  299. RmResumeTask(pAdapter->bind.pSecondaryTask, (UINT_PTR) Status, &sr);
  300. }
  301. RM_ASSERT_CLEAR(&sr)
  302. EXIT()
  303. TIMESTAMP("<==OpenAdapterComplete");
  304. }
  305. VOID
  306. ArpNdCloseAdapterComplete(
  307. IN NDIS_HANDLE ProtocolBindingContext,
  308. IN NDIS_STATUS Status
  309. )
  310. /*++
  311. Routine Description:
  312. This is called by NDIS when a previous call to NdisCloseAdapter
  313. that had pended has completed. The task that called NdisCloseAdapter
  314. would have suspended itself, so we simply resume it now.
  315. Arguments:
  316. ProtocolBindingContext - Our context for this adapter binding, which
  317. is a pointer to an ARP1394_ADAPTER structure.
  318. Status - Status of CloseAdapter
  319. Return Value:
  320. None
  321. --*/
  322. {
  323. ENTER("CloseAdapterComplete", 0x889d22eb)
  324. ARP1394_ADAPTER * pAdapter = (ARP1394_ADAPTER*) ProtocolBindingContext;
  325. RM_DECLARE_STACK_RECORD(sr)
  326. TIMESTAMP("==>CloseAdapterComplete");
  327. // We expect a nonzero task here (UNbind task), which we unpend.
  328. // No need to grab locks or anything at this stage.
  329. //
  330. RmResumeTask(pAdapter->bind.pSecondaryTask, (UINT_PTR) Status, &sr);
  331. TIMESTAMP("<==CloseAdapterComplete");
  332. RM_ASSERT_CLEAR(&sr)
  333. EXIT()
  334. }
  335. VOID
  336. ArpNdResetComplete(
  337. IN NDIS_HANDLE ProtocolBindingContext,
  338. IN NDIS_STATUS Status
  339. )
  340. /*++
  341. Routine Description:
  342. This routine is called when the miniport indicates that a Reset
  343. operation has just completed. We ignore this event.
  344. Arguments:
  345. ProtocolBindingContext - Our context for this adapter binding, which
  346. is a pointer to our Adapter structure.
  347. Status - Status of the reset operation.
  348. Return Value:
  349. None
  350. --*/
  351. {
  352. TIMESTAMP("===ResetComplete");
  353. }
  354. VOID
  355. ArpNdReceiveComplete(
  356. IN NDIS_HANDLE ProtocolBindingContext
  357. )
  358. /*++
  359. Routine Description:
  360. This is called by NDIS when the miniport is done with receiving
  361. a bunch of packets, meaning that it is now time to start processing
  362. them. We simply pass this on to IP.
  363. Arguments:
  364. ProtocolBindingContext - Our context for this adapter binding, which
  365. is a pointer to an ARP1394_ADAPTER structure.
  366. Return Value:
  367. None
  368. --*/
  369. {
  370. PARP1394_ADAPTER pAdapter;
  371. PARP1394_INTERFACE pIF;
  372. pAdapter = (PARP1394_ADAPTER)ProtocolBindingContext;
  373. pIF = pAdapter->pIF;
  374. //
  375. // WARNING: for perf reasons, we don't do the clean thing of
  376. // locking the adapter, refing pIF, unlocking the adapter,
  377. // calling pIF->ip.RcvCmpltHandler, then derefing pIF.
  378. //
  379. if ((pIF != NULL) && (pIF->ip.Context != NULL))
  380. {
  381. #if MILLEN
  382. ASSERT_PASSIVE();
  383. #endif // MILLEN
  384. pIF->ip.RcvCmpltHandler();
  385. }
  386. }
  387. VOID
  388. ArpNdRequestComplete(
  389. IN NDIS_HANDLE ProtocolBindingContext,
  390. IN PNDIS_REQUEST pNdisRequest,
  391. IN NDIS_STATUS Status
  392. )
  393. /*++
  394. Routine Description:
  395. This is called by NDIS when a previous call we made to NdisRequest() has
  396. completed.
  397. Arguments:
  398. ProtocolBindingContext - Pointer to our Adapter structure
  399. pNdisRequest - The request that completed
  400. Status - Status of the request.
  401. Return Value:
  402. None
  403. --*/
  404. {
  405. PARP_NDIS_REQUEST pArpNdisRequest;
  406. PRM_TASK pTask;
  407. ENTER("ArpNdRequestComplete", 0x8cdf7a6d)
  408. RM_DECLARE_STACK_RECORD(sr)
  409. pArpNdisRequest = CONTAINING_RECORD(pNdisRequest, ARP_NDIS_REQUEST, Request);
  410. pTask = pArpNdisRequest->pTask;
  411. pArpNdisRequest->Status = Status;
  412. if (pTask == NULL)
  413. {
  414. NdisSetEvent(&pArpNdisRequest->Event);
  415. }
  416. else
  417. {
  418. RmResumeTask(pTask, (UINT_PTR) Status, &sr);
  419. }
  420. EXIT()
  421. }
  422. VOID
  423. ArpNdStatus(
  424. IN NDIS_HANDLE ProtocolBindingContext,
  425. IN NDIS_STATUS GeneralStatus,
  426. IN PVOID pStatusBuffer,
  427. IN UINT StatusBufferSize
  428. )
  429. /*++
  430. Routine Description:
  431. This routine is called when the miniport indicates an adapter-wide
  432. status change. We ignore this.
  433. Arguments:
  434. <Ignored>
  435. --*/
  436. {
  437. }
  438. VOID
  439. ArpNdStatusComplete(
  440. IN NDIS_HANDLE ProtocolBindingContext
  441. )
  442. /*++
  443. Routine Description:
  444. This routine is called when the miniport wants to tell us about
  445. completion of a status change (?). Ignore this.
  446. Arguments:
  447. <Ignored>
  448. Return Value:
  449. None
  450. --*/
  451. {
  452. }
  453. VOID
  454. ArpNdSendComplete(
  455. IN NDIS_HANDLE ProtocolBindingContext,
  456. IN PNDIS_PACKET pNdisPacket,
  457. IN NDIS_STATUS Status
  458. )
  459. /*++
  460. Routine Description:
  461. This is the Connection-less Send Complete handler, which signals
  462. completion of such a Send. Since we don't ever use this feature,
  463. we don't expect this routine to be called.
  464. Arguments:
  465. <Ignored>
  466. Return Value:
  467. None
  468. --*/
  469. {
  470. ASSERT(FALSE);
  471. }
  472. NDIS_STATUS
  473. ArpNdReceive (
  474. NDIS_HANDLE ProtocolBindingContext,
  475. NDIS_HANDLE Context,
  476. VOID *Header,
  477. UINT HeaderSize,
  478. VOID *Data,
  479. UINT Size,
  480. UINT TotalSize
  481. )
  482. /*++
  483. TODO: We need to support this for ICS, because MILL NDIS calls this
  484. handler to indicate packets which have the STATUS_RESOURCES bit set.
  485. --*/
  486. {
  487. return NDIS_STATUS_NOT_RECOGNIZED;
  488. }
  489. INT
  490. ArpNdReceivePacket (
  491. NDIS_HANDLE ProtocolBindingContext,
  492. PNDIS_PACKET Packet
  493. )
  494. {
  495. return 0; // We return 0 because no one hangs on to this packet.
  496. }
  497. NDIS_STATUS
  498. ArpNdPnPEvent(
  499. IN NDIS_HANDLE ProtocolBindingContext,
  500. IN PNET_PNP_EVENT pNetPnPEvent
  501. )
  502. /*++
  503. Routine Description:
  504. This is the NDIS entry point called when NDIS wants to inform
  505. us about a PNP/PM event happening on an adapter. If the event
  506. is for us, we consume it. Otherwise, we pass this event along
  507. to IP along the first Interface on this adapter.
  508. When IP is done with it, it will call our IfPnPEventComplete
  509. routine.
  510. Arguments:
  511. ProtocolBindingContext - Our context for this adapter binding, which
  512. is a pointer to an ARP1394_ADAPTER structure.
  513. pNetPnPEvent - Pointer to the event.
  514. Return Value:
  515. None
  516. --*/
  517. {
  518. ENTER("PnPEvent", 0x2a517a8c)
  519. ARP1394_ADAPTER * pAdapter = (ARP1394_ADAPTER*) ProtocolBindingContext;
  520. ARP1394_INTERFACE * pIF = NULL;
  521. NDIS_STATUS Status;
  522. PIP_PNP_RECONFIG_REQUEST pIpReconfigReq;
  523. ULONG Length;
  524. RM_DECLARE_STACK_RECORD(sr)
  525. do
  526. {
  527. pIpReconfigReq = (PIP_PNP_RECONFIG_REQUEST)pNetPnPEvent->Buffer;
  528. Length = pNetPnPEvent->BufferLength;
  529. TIMESTAMP1("==>PnPEvent 0x%lx", pNetPnPEvent->NetEvent);
  530. //
  531. // Do we have a binding context?
  532. //
  533. if (pAdapter == NULL)
  534. {
  535. Status = NDIS_STATUS_FAILURE;
  536. break;
  537. }
  538. //
  539. // Is this directed to us?
  540. //
  541. if (pNetPnPEvent->NetEvent == NetEventReconfigure)
  542. {
  543. if (Length < sizeof(IP_PNP_RECONFIG_REQUEST))
  544. {
  545. Status = NDIS_STATUS_RESOURCES;
  546. break;
  547. }
  548. if (pIpReconfigReq->arpConfigOffset != 0)
  549. {
  550. Status = arpPnPReconfigHandler(pAdapter, pNetPnPEvent);
  551. break;
  552. }
  553. }
  554. //
  555. // 01/21/2000 JosephJ: The NIC1394 MCM doesn't close AF's when it's shut
  556. // down by NDIS during a powering down event. So
  557. // we work around this by claiming not to support
  558. // PnP Power so that NDIS closes US as well.
  559. //
  560. if (pNetPnPEvent->NetEvent == NetEventSetPower)
  561. {
  562. PNET_DEVICE_POWER_STATE pPowerState;
  563. pPowerState = (PNET_DEVICE_POWER_STATE) pNetPnPEvent->Buffer;
  564. Status = arpNdSetPower (pAdapter, pPowerState,&sr );
  565. if (Status != NDIS_STATUS_SUCCESS)
  566. {
  567. break;
  568. }
  569. }
  570. else
  571. {
  572. TIMESTAMPX("===PnPEvent (not SetPower)");
  573. }
  574. //
  575. // This belongs to IP....
  576. //
  577. {
  578. LOCKOBJ(pAdapter, &sr);
  579. pIF = pAdapter->pIF;
  580. if ((pIF != NULL) && (pIF->ip.Context != NULL))
  581. {
  582. RmTmpReferenceObject(&pIF->Hdr, &sr);
  583. UNLOCKOBJ(pAdapter, &sr);
  584. Status = pIF->ip.PnPEventHandler(
  585. pIF->ip.Context,
  586. pNetPnPEvent
  587. );
  588. RmTmpDereferenceObject(&pIF->Hdr, &sr);
  589. }
  590. else
  591. {
  592. UNLOCKOBJ(pAdapter, &sr);
  593. Status = NDIS_STATUS_SUCCESS;
  594. }
  595. }
  596. }
  597. while (FALSE);
  598. TR_INFO((" pIF 0x%x, pEvent 0x%x, Evt 0x%x, Status 0x%x\n",
  599. pIF, pNetPnPEvent, pNetPnPEvent->NetEvent, Status));
  600. RM_ASSERT_CLEAR(&sr)
  601. EXIT()
  602. TIMESTAMP("<==PnPEvent");
  603. return Status;
  604. }
  605. VOID
  606. ArpNdUnloadProtocol(
  607. VOID
  608. )
  609. /*++
  610. Routine Description:
  611. Unloads our protocol module. We unbind from all adapters,
  612. and deregister from NDIS as a protocol.
  613. Arguments:
  614. None.
  615. Return Value:
  616. None
  617. --*/
  618. {
  619. ENTER("UnloadProtocol", 0x8143fec5)
  620. RM_DECLARE_STACK_RECORD(sr)
  621. TIMESTAMP("==>UnloadProtocol");
  622. RmUnloadAllGenericResources(&ArpGlobals.Hdr, &sr);
  623. RM_ASSERT_CLEAR(&sr)
  624. TIMESTAMP("<==UnloadProtocol");
  625. EXIT()
  626. return;
  627. }
  628. NDIS_STATUS
  629. arpTaskInitializeAdapter(
  630. IN struct _RM_TASK * pTask,
  631. IN RM_TASK_OPERATION Code,
  632. IN UINT_PTR UserParam,
  633. IN PRM_STACK_RECORD pSR
  634. )
  635. /*++
  636. Routine Description:
  637. Task handler responsible for initializing an adapter.
  638. Arguments:
  639. UserParam for (Code == RM_TASKOP_START) : unused
  640. --*/
  641. {
  642. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  643. ARP1394_ADAPTER * pAdapter = (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pTask);
  644. PTASK_ADAPTERINIT pAdapterInitTask;
  645. enum
  646. {
  647. STAGE_BecomePrimaryTask,
  648. STAGE_ActivateAdapterComplete,
  649. STAGE_DeactivateAdapterComplete,
  650. STAGE_End
  651. } Stage;
  652. ENTER("TaskInitializeAdapter", 0xb6ada31d)
  653. pAdapterInitTask = (PTASK_ADAPTERINIT) pTask;
  654. ASSERT(sizeof(TASK_ADAPTERINIT) <= sizeof(ARP1394_TASK));
  655. //
  656. // Message normalizing code
  657. //
  658. switch(Code)
  659. {
  660. case RM_TASKOP_START:
  661. Stage = STAGE_BecomePrimaryTask;
  662. break;
  663. case RM_TASKOP_PENDCOMPLETE:
  664. Status = (NDIS_STATUS) UserParam;
  665. ASSERT(!PEND(Status));
  666. Stage = RM_PEND_CODE(pTask);
  667. break;
  668. case RM_TASKOP_END:
  669. Status = (NDIS_STATUS) UserParam;
  670. Stage= STAGE_End;
  671. break;
  672. default:
  673. ASSERT(FALSE);
  674. return NDIS_STATUS_FAILURE; // ** EARLY RETURN **
  675. }
  676. ASSERTEX(!PEND(Status), pTask);
  677. switch(Stage)
  678. {
  679. case STAGE_BecomePrimaryTask:
  680. {
  681. // If there is a primary task, pend on it, else make ourselves
  682. // the primary task.
  683. //
  684. LOCKOBJ(pAdapter, pSR);
  685. if (pAdapter->bind.pPrimaryTask == NULL)
  686. {
  687. arpSetPrimaryAdapterTask(pAdapter, pTask, ARPAD_PS_INITING, pSR);
  688. UNLOCKOBJ(pAdapter, pSR);
  689. }
  690. else
  691. {
  692. PRM_TASK pOtherTask = pAdapter->bind.pPrimaryTask;
  693. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  694. UNLOCKOBJ(pAdapter, pSR);
  695. RmPendTaskOnOtherTask(
  696. pTask,
  697. STAGE_BecomePrimaryTask, // we'll try again...
  698. pOtherTask,
  699. pSR
  700. );
  701. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  702. Status = NDIS_STATUS_PENDING;
  703. break;
  704. }
  705. //
  706. // We're now the primary task. Since we're starting out,
  707. // there should be NO activate/deactivate task.
  708. // (Note: we don't bother getting the adapter lock for these asserts).
  709. //
  710. ASSERT(pAdapter->bind.pPrimaryTask == pTask);
  711. ASSERT(pAdapter->bind.pSecondaryTask == NULL);
  712. //
  713. // Allocate and start the activate adapter task.
  714. //
  715. {
  716. PRM_TASK pActivateTask;
  717. Status = arpAllocateTask(
  718. &pAdapter->Hdr, // pParentObject,
  719. arpTaskActivateAdapter, // pfnHandler,
  720. 0, // Timeout,
  721. "Task: Activate Adapter(init)", // szDescription
  722. &pActivateTask,
  723. pSR
  724. );
  725. if (FAIL(Status))
  726. {
  727. pActivateTask = NULL;
  728. TR_WARN(("FATAL: couldn't alloc activate task!\n"));
  729. }
  730. else
  731. {
  732. RmPendTaskOnOtherTask(
  733. pTask,
  734. STAGE_ActivateAdapterComplete,
  735. pActivateTask, // task to pend on
  736. pSR
  737. );
  738. // RmStartTask uses up the tmpref on the task
  739. // which was added by arpAllocateTask.
  740. //
  741. Status = RmStartTask(
  742. pActivateTask,
  743. 0, // UserParam (unused)
  744. pSR
  745. );
  746. }
  747. }
  748. }
  749. if (PEND(Status)) break;
  750. // FALL THROUGH TO NEXT STAGE
  751. case STAGE_ActivateAdapterComplete:
  752. {
  753. //
  754. // We've run the active-adapter task. On failure, we need to
  755. // cleanup state by calling the deactivate-adapter task.
  756. //
  757. // Save away the failure code for later...
  758. //
  759. pAdapterInitTask->ReturnStatus = Status;
  760. if (FAIL(Status))
  761. {
  762. PRM_TASK pDeactivateTask;
  763. Status = arpAllocateTask(
  764. &pAdapter->Hdr, // pParentObject,
  765. arpTaskDeactivateAdapter, // pfnHandler,
  766. 0, // Timeout,
  767. "Task: Deactivate Adapter(init)", // szDescription
  768. &pDeactivateTask,
  769. pSR
  770. );
  771. if (FAIL(Status))
  772. {
  773. pDeactivateTask = NULL;
  774. ASSERT(FALSE); // TODO: use special dealloc task pool for this.
  775. TR_WARN(("FATAL: couldn't alloc deactivate task!\n"));
  776. }
  777. else
  778. {
  779. RmPendTaskOnOtherTask(
  780. pTask,
  781. STAGE_DeactivateAdapterComplete,
  782. pDeactivateTask, // task to pend on
  783. pSR
  784. );
  785. // RmStartTask uses up the tmpref on the task
  786. // which was added by arpAllocateTask.
  787. //
  788. Status = RmStartTask(
  789. pDeactivateTask,
  790. 0, // UserParam (unused)
  791. pSR
  792. );
  793. }
  794. }
  795. }
  796. break;
  797. case STAGE_DeactivateAdapterComplete:
  798. {
  799. //
  800. // We've completed the deactivate adapter task which we started
  801. // because of some init-adapter failure.
  802. //
  803. // In general, we don't expect the deactivate task to return failure.
  804. //
  805. ASSERT(!FAIL(Status));
  806. // We expect the original status of the init to be a failure (that's
  807. // why we started the deinit in the first place!
  808. //
  809. ASSERT(FAIL(pAdapterInitTask->ReturnStatus));
  810. Status = pAdapterInitTask->ReturnStatus;
  811. }
  812. break;
  813. case STAGE_End:
  814. {
  815. NDIS_HANDLE BindContext;
  816. BOOLEAN BridgeEnabled = ARP_BRIDGE_ENABLED(pAdapter);
  817. //
  818. // We HAVE to be the primary task at this point, becase we simply
  819. // wait and retry until we become one.
  820. //
  821. // Clear the primary task in the adapter object.
  822. //
  823. LOCKOBJ(pAdapter, pSR);
  824. {
  825. ULONG InitState;
  826. InitState = FAIL(Status) ? ARPAD_PS_FAILEDINIT : ARPAD_PS_INITED;
  827. arpClearPrimaryAdapterTask(pAdapter, pTask, InitState, pSR);
  828. }
  829. BindContext = pAdapter->bind.BindContext;
  830. UNLOCKOBJ(pAdapter, pSR);
  831. // On failure, pAdapter should be deallocated.
  832. //
  833. if (FAIL(Status))
  834. {
  835. if(RM_IS_ZOMBIE(pAdapter))
  836. {
  837. TR_WARN(("END: pAdapter is already deallocated.\n"));
  838. }
  839. else
  840. {
  841. //
  842. // On failure, free the adapter here itself, because we're
  843. // not going to call the shutdown task.
  844. //
  845. RmFreeObjectInGroup(
  846. &ArpGlobals.adapters.Group,
  847. &(pAdapter->Hdr),
  848. NULL, // NULL pTask == synchronous.
  849. pSR
  850. );
  851. }
  852. }
  853. if (!BridgeEnabled)
  854. {
  855. // Signal IP that the bind is complete.
  856. //
  857. TIMESTAMP("===Calling IP's BindComplete routine");
  858. RM_ASSERT_NOLOCKS(pSR);
  859. ArpGlobals.ip.pBindCompleteRtn(
  860. Status,
  861. BindContext
  862. );
  863. }
  864. }
  865. break;
  866. default:
  867. {
  868. ASSERTEX(!"Unknown task op", pTask);
  869. }
  870. break;
  871. } // switch (Code)
  872. RM_ASSERT_NOLOCKS(pSR);
  873. EXIT()
  874. return Status;
  875. }
  876. NDIS_STATUS
  877. arpTaskShutdownAdapter(
  878. IN struct _RM_TASK * pTask,
  879. IN RM_TASK_OPERATION Code,
  880. IN UINT_PTR UserParam,
  881. IN PRM_STACK_RECORD pSR
  882. )
  883. /*++
  884. Routine Description:
  885. Task handler responsible for shutting down an IP interface.
  886. Arguments:
  887. UserParam for (Code == RM_TASKOP_START) : UnbindContext
  888. --*/
  889. {
  890. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  891. ARP1394_ADAPTER * pAdapter = (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pTask);
  892. TASK_ADAPTERSHUTDOWN *pMyTask = (TASK_ADAPTERSHUTDOWN*) pTask;
  893. enum
  894. {
  895. STAGE_BecomePrimaryTask,
  896. STAGE_DeactivateAdapterComplete,
  897. STAGE_End
  898. } Stage;
  899. ENTER("TaskShutdownAdapter", 0xe262e828)
  900. //
  901. // Message normalizing code
  902. //
  903. switch(Code)
  904. {
  905. case RM_TASKOP_START:
  906. Stage = STAGE_BecomePrimaryTask;
  907. // Save away the UnbindContext (which we get as UserParam) in
  908. // the task's private context, for use later.
  909. //
  910. pMyTask->pUnbindContext = (NDIS_HANDLE) UserParam;
  911. break;
  912. case RM_TASKOP_PENDCOMPLETE:
  913. Status = (NDIS_STATUS) UserParam;
  914. ASSERT(!PEND(Status));
  915. Stage = RM_PEND_CODE(pTask);
  916. break;
  917. case RM_TASKOP_END:
  918. Status = (NDIS_STATUS) UserParam;
  919. Stage= STAGE_End;
  920. break;
  921. default:
  922. ASSERT(FALSE);
  923. return NDIS_STATUS_FAILURE; // ** EARLY RETURN **
  924. }
  925. ASSERTEX(!PEND(Status), pTask);
  926. switch(Stage)
  927. {
  928. case STAGE_BecomePrimaryTask:
  929. {
  930. // If there is a primary task, pend on it, else make ourselves
  931. // the primary task.
  932. // We could get in this situation if someone does a
  933. // "net stop arp1394" while we're in the middle of initializing or
  934. // shutting down the adapter.
  935. //
  936. //
  937. LOCKOBJ(pAdapter, pSR);
  938. if (pAdapter->bind.pPrimaryTask == NULL)
  939. {
  940. arpSetPrimaryAdapterTask(pAdapter, pTask, ARPAD_PS_DEINITING, pSR);
  941. UNLOCKOBJ(pAdapter, pSR);
  942. }
  943. else
  944. {
  945. PRM_TASK pOtherTask = pAdapter->bind.pPrimaryTask;
  946. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  947. UNLOCKOBJ(pAdapter, pSR);
  948. RmPendTaskOnOtherTask(
  949. pTask,
  950. STAGE_BecomePrimaryTask, // we'll try again...
  951. pOtherTask,
  952. pSR
  953. );
  954. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  955. Status = NDIS_STATUS_PENDING;
  956. break;
  957. }
  958. //
  959. // We're now the primary task. Since we're starting out,
  960. // there should be NO activate/deactivate task.
  961. // (Note: we don't bother getting the adapter lock for these asserts).
  962. //
  963. ASSERT(pAdapter->bind.pPrimaryTask == pTask);
  964. ASSERT(pAdapter->bind.pSecondaryTask == NULL);
  965. //
  966. // Allocate and start the deactivate adapter task.
  967. //
  968. {
  969. PRM_TASK pDeactivateTask;
  970. Status = arpAllocateTask(
  971. &pAdapter->Hdr, // pParentObject,
  972. arpTaskDeactivateAdapter, // pfnHandler,
  973. 0, // Timeout,
  974. "Task: Deactivate Adapter(shutdown)", // szDescription
  975. &pDeactivateTask,
  976. pSR
  977. );
  978. if (FAIL(Status))
  979. {
  980. pDeactivateTask = NULL;
  981. TR_WARN(("FATAL: couldn't alloc deactivate task!\n"));
  982. }
  983. else
  984. {
  985. RmPendTaskOnOtherTask(
  986. pTask,
  987. STAGE_DeactivateAdapterComplete,
  988. pDeactivateTask, // task to pend on
  989. pSR
  990. );
  991. // RmStartTask uses up the tmpref on the task
  992. // which was added by arpAllocateTask.
  993. //
  994. Status = RmStartTask(
  995. pDeactivateTask,
  996. 0, // UserParam (unused)
  997. pSR
  998. );
  999. }
  1000. }
  1001. }
  1002. break;
  1003. case STAGE_DeactivateAdapterComplete:
  1004. {
  1005. // Nothing to do here -- we clean up in STAGE_End.
  1006. //
  1007. break;
  1008. }
  1009. case STAGE_End:
  1010. {
  1011. //
  1012. // We HAVE to be the primary task at this point, becase we simply
  1013. // wait and retry until we become one.
  1014. //
  1015. ASSERT(pAdapter->bind.pPrimaryTask == pTask);
  1016. // Clear the primary task in the adapter object.
  1017. //
  1018. LOCKOBJ(pAdapter, pSR);
  1019. arpClearPrimaryAdapterTask(pAdapter, pTask, ARPAD_PS_DEINITED, pSR);
  1020. UNLOCKOBJ(pAdapter, pSR);
  1021. if(RM_IS_ZOMBIE(pAdapter))
  1022. {
  1023. TR_WARN(("END: pAdapter is already deallocated.\n"));
  1024. }
  1025. else
  1026. {
  1027. // Free the adapter.
  1028. // (pAdapter will be allocated, but it will be in a "zombie" state).
  1029. //
  1030. RmFreeObjectInGroup(
  1031. &ArpGlobals.adapters.Group,
  1032. &(pAdapter->Hdr),
  1033. NULL, // NULL pTask == synchronous.
  1034. pSR
  1035. );
  1036. }
  1037. // If there is an unbind-context, signal NDIS that the unbind is
  1038. // complete.
  1039. //
  1040. if (pMyTask->pUnbindContext)
  1041. {
  1042. TR_WARN(("END: Calling NdisCompleteUnbindAdapter. Status= 0x%lx\n",
  1043. Status));
  1044. RM_ASSERT_NOLOCKS(pSR);
  1045. TIMESTAMP("===Calling NdisCompleteUnbindAdapter");
  1046. NdisCompleteUnbindAdapter(
  1047. pMyTask->pUnbindContext,
  1048. Status
  1049. );
  1050. }
  1051. }
  1052. break;
  1053. default:
  1054. {
  1055. ASSERTEX(!"Unknown task op", pTask);
  1056. }
  1057. break;
  1058. } // switch (Code)
  1059. RM_ASSERT_NOLOCKS(pSR);
  1060. EXIT()
  1061. return Status;
  1062. }
  1063. NDIS_STATUS
  1064. arpTaskActivateAdapter(
  1065. IN struct _RM_TASK * pTask,
  1066. IN RM_TASK_OPERATION Code,
  1067. IN UINT_PTR UserParam,
  1068. IN PRM_STACK_RECORD pSR
  1069. )
  1070. /*++
  1071. Routine Description:
  1072. Task handler responsible for initializing an adapter.
  1073. Arguments:
  1074. UserParam for (Code == RM_TASKOP_START) : unused
  1075. --*/
  1076. {
  1077. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1078. ARP1394_ADAPTER * pAdapter = (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pTask);
  1079. enum
  1080. {
  1081. PEND_OpenAdapter,
  1082. PEND_GetAdapterInfo
  1083. };
  1084. ENTER("arpTaskActivateAdapter", 0xb6ada31d)
  1085. switch(Code)
  1086. {
  1087. case RM_TASKOP_START:
  1088. {
  1089. #if MILLEN
  1090. NDIS_MEDIUM Medium = NdisMedium802_3;
  1091. #else // !MILLEN
  1092. NDIS_MEDIUM Medium = NdisMedium802_3;
  1093. #endif // !MILLEN
  1094. UINT SelMediumIndex = 0;
  1095. NDIS_STATUS OpenStatus;
  1096. //
  1097. // Allocate Backup Tasks
  1098. //
  1099. arpAddBackupTasks (&ArpGlobals,ARP1394_BACKUP_TASKS);
  1100. // Set ourselves as the secondary task.
  1101. //
  1102. LOCKOBJ(pAdapter, pSR);
  1103. arpSetSecondaryAdapterTask(pAdapter, pTask, ARPAD_AS_ACTIVATING, pSR);
  1104. UNLOCKOBJ(pAdapter, pSR);
  1105. //
  1106. // Suspend task and call NdisOpenAdapter...
  1107. //
  1108. RmSuspendTask(pTask, PEND_OpenAdapter, pSR);
  1109. RM_ASSERT_NOLOCKS(pSR);
  1110. NdisOpenAdapter(
  1111. &Status,
  1112. &OpenStatus,
  1113. &pAdapter->bind.AdapterHandle,
  1114. &SelMediumIndex, // selected medium index
  1115. &Medium, // Array of medium types
  1116. 1, // Size of Media list
  1117. ArpGlobals.ndis.ProtocolHandle,
  1118. (NDIS_HANDLE)pAdapter, // our adapter bind context
  1119. &pAdapter->bind.DeviceName, // pDeviceName
  1120. 0, // Open options
  1121. (PSTRING)NULL // Addressing Info...
  1122. );
  1123. if (Status != NDIS_STATUS_PENDING)
  1124. {
  1125. ArpNdOpenAdapterComplete(
  1126. (NDIS_HANDLE)pAdapter,
  1127. Status,
  1128. OpenStatus
  1129. );
  1130. }
  1131. Status = NDIS_STATUS_PENDING;
  1132. }
  1133. break;
  1134. case RM_TASKOP_PENDCOMPLETE:
  1135. {
  1136. PTASK_ADAPTERACTIVATE pAdapterInitTask;
  1137. pAdapterInitTask = (PTASK_ADAPTERACTIVATE) pTask;
  1138. Status = (NDIS_STATUS) UserParam;
  1139. ASSERT(!PEND(Status));
  1140. ASSERT(sizeof(TASK_ADAPTERACTIVATE) <= sizeof(ARP1394_TASK));
  1141. switch(RM_PEND_CODE(pTask))
  1142. {
  1143. case PEND_OpenAdapter:
  1144. //
  1145. // The open adapter operation is complete. Get adapter
  1146. // information and notify IP on success. On failure,
  1147. // shutdown the adapter if required, and notify IP of
  1148. // the failure.
  1149. //
  1150. if (FAIL(Status))
  1151. {
  1152. // Set adapter handle to null -- it may not be hull.
  1153. // even though the open adapter has succeeded.
  1154. //
  1155. pAdapter->bind.AdapterHandle = NULL;
  1156. break;
  1157. }
  1158. // Successfully opened the adapter.
  1159. // Now get adapter information from miniport.
  1160. // (We use the TASK_ADAPTERINIT.ArpNdisRequest field,
  1161. // which is defined specifically for this use).
  1162. //
  1163. Status = arpPrepareAndSendNdisRequest(
  1164. pAdapter,
  1165. &pAdapterInitTask->ArpNdisRequest,
  1166. NULL, // pTask - Finish the request synchronously
  1167. PEND_GetAdapterInfo,
  1168. OID_1394_LOCAL_NODE_INFO,
  1169. &pAdapterInitTask->LocalNodeInfo,
  1170. sizeof(pAdapterInitTask->LocalNodeInfo),
  1171. NdisRequestQueryInformation,
  1172. pSR
  1173. );
  1174. ASSERT(!PEND(Status));
  1175. if (PEND(Status)) break;
  1176. // FALL THROUGH on synchronous completion of arpGetAdapterInfo...
  1177. case PEND_GetAdapterInfo:
  1178. //
  1179. // Done with getting adapter info.
  1180. // We need to switch to passive before going further
  1181. //
  1182. if (!ARP_ATPASSIVE())
  1183. {
  1184. // We're not at passive level, but we need to be when we
  1185. // call IP's add interface. So we switch to passive...
  1186. // NOTE: we specify completion code PEND_GetAdapterInfo
  1187. // because we want to get back here (except
  1188. // we'll be at passive).
  1189. //
  1190. RmSuspendTask(pTask, PEND_GetAdapterInfo, pSR);
  1191. RmResumeTaskAsync(
  1192. pTask,
  1193. Status,
  1194. &pAdapterInitTask->WorkItem,
  1195. pSR
  1196. );
  1197. Status = NDIS_STATUS_PENDING;
  1198. break;
  1199. }
  1200. if (Status == NDIS_STATUS_SUCCESS)
  1201. {
  1202. //
  1203. // Copy over adapter info into pAdapter->info...
  1204. // Then read configuration information.
  1205. //
  1206. LOCKOBJ(pAdapter, pSR);
  1207. ARP_ZEROSTRUCT(&pAdapter->info);
  1208. // OID_GEN_CO_VENDOR_DESCRIPTION
  1209. //
  1210. pAdapter->info.szDescription = "NIC1394";
  1211. pAdapter->info.DescriptionLength = sizeof("NIC1394");
  1212. // TODO -- when you do the real stuff, remember to free it.
  1213. // Max Frame size
  1214. // TODO: fill in the real adapter's MTU.
  1215. //
  1216. pAdapter->info.MTU = ARP1394_ADAPTER_MTU;
  1217. pAdapter->info.LocalUniqueID =
  1218. pAdapterInitTask->LocalNodeInfo.UniqueID;
  1219. {
  1220. UINT MaxRec;
  1221. UINT MaxSpeedCode;
  1222. MaxSpeedCode =
  1223. pAdapterInitTask->LocalNodeInfo.MaxRecvSpeed;
  1224. MaxRec =
  1225. pAdapterInitTask->LocalNodeInfo.MaxRecvBlockSize;
  1226. #if DBG
  1227. while ( !IP1394_IS_VALID_MAXREC(MaxRec)
  1228. || !IP1394_IS_VALID_SSPD(MaxSpeedCode)
  1229. || MaxSpeedCode == 0)
  1230. {
  1231. TR_WARN(("FATAL: Invalid maxrec(0x%x) or sspd(0x%x)!\n",
  1232. MaxRec,
  1233. MaxSpeedCode
  1234. ));
  1235. TR_WARN((" &maxrec=0x%p, &sspd=0x%p\n",
  1236. &MaxRec,
  1237. &MaxSpeedCode
  1238. ));
  1239. DbgBreakPoint();
  1240. }
  1241. TR_WARN(("Selected maxrec=0x%x and sspd=0x%x.\n",
  1242. MaxRec,
  1243. MaxSpeedCode
  1244. ));
  1245. #endif // DBG
  1246. pAdapter->info.MaxRec = MaxRec;
  1247. pAdapter->info.MaxSpeedCode = MaxSpeedCode;
  1248. }
  1249. // B TODO: we should get this from the NIC -- add
  1250. // to the IOCTL OR query the adapter for its
  1251. // MAC address.
  1252. // For now we put a hardcoded MAC address.
  1253. //
  1254. #define ARP_FAKE_ETH_ADDRESS(_AdapterNum) \
  1255. { \
  1256. 0x02 | (((UCHAR)(_AdapterNum) & 0x3f) << 2), \
  1257. ((UCHAR)(_AdapterNum) & 0x3f), \
  1258. 0,0,0,0 \
  1259. }
  1260. #define ARP_DEF_LOCAL_ETH_ADDRESS \
  1261. ARP_FAKE_ETH_ADDRESS(0x1)
  1262. UNLOCKOBJ(pAdapter, pSR);
  1263. //
  1264. // Query the adapter for its Mac Addrees
  1265. //
  1266. {
  1267. ENetAddr LocalEthAddr;
  1268. ARP_NDIS_REQUEST ArpNdisRequest;
  1269. ARP_ZEROSTRUCT (&ArpNdisRequest);
  1270. Status = arpPrepareAndSendNdisRequest(
  1271. pAdapter,
  1272. &ArpNdisRequest,
  1273. NULL, // pTask (NULL==BLOCK)
  1274. 0, // unused
  1275. OID_802_3_CURRENT_ADDRESS,
  1276. &LocalEthAddr,
  1277. sizeof(LocalEthAddr),
  1278. NdisRequestQueryInformation,
  1279. pSR
  1280. );
  1281. if (Status == NDIS_STATUS_SUCCESS)
  1282. {
  1283. pAdapter->info.EthernetMacAddress = LocalEthAddr;
  1284. }
  1285. else
  1286. {
  1287. //
  1288. // Failure means that we have failed to bind
  1289. break;
  1290. }
  1291. }
  1292. //
  1293. // Query the adapter for its Speed
  1294. //
  1295. {
  1296. NDIS_CO_LINK_SPEED CoLinkSpeed;
  1297. ARP_NDIS_REQUEST ArpNdisRequest;
  1298. ARP_ZEROSTRUCT (&ArpNdisRequest);
  1299. Status = arpPrepareAndSendNdisRequest(
  1300. pAdapter,
  1301. &ArpNdisRequest,
  1302. NULL, // pTask (NULL==BLOCK)
  1303. 0, // unused
  1304. OID_GEN_CO_LINK_SPEED,
  1305. &CoLinkSpeed,
  1306. sizeof(CoLinkSpeed),
  1307. NdisRequestQueryInformation,
  1308. pSR
  1309. );
  1310. if (Status == NDIS_STATUS_SUCCESS)
  1311. {
  1312. //
  1313. // if nic1394 is in ethernet mode- it will fill in only one ULONG
  1314. // therefore rchoose outbound because it is the first ulong
  1315. // Multiply by 100 - thats what ethArp does.
  1316. //
  1317. pAdapter->info.Speed= (CoLinkSpeed.Outbound *100);
  1318. }
  1319. else
  1320. {
  1321. //
  1322. // Failure means that we have failed to bind
  1323. break;
  1324. }
  1325. }
  1326. // Query the adapter for its Table of RemoteNodes
  1327. //
  1328. Status = arpGetEuidTopologyWorkItem(NULL, &pAdapter->Hdr, pSR);
  1329. if (Status != NDIS_STATUS_SUCCESS)
  1330. {
  1331. break;
  1332. }
  1333. // Read Adapter Configuration Information
  1334. //
  1335. Status = arpCfgReadAdapterConfiguration(pAdapter, pSR);
  1336. if (Status != NDIS_STATUS_SUCCESS)
  1337. {
  1338. break;
  1339. }
  1340. }
  1341. //
  1342. // NOTE: if we fail, a higher level task is responsible
  1343. // for "running the compensating transaction", i.e., running
  1344. // arpTaskDeactivateAdapter.
  1345. //
  1346. // end case PEND_OpenAdapter, PEND_GetAdapterInfo
  1347. break;
  1348. default:
  1349. {
  1350. ASSERTEX(!"Unknown pend op", pTask);
  1351. }
  1352. break;
  1353. } // end switch(RM_PEND_CODE(pTask))
  1354. } // case RM_TASKOP_PENDCOMPLETE
  1355. break;
  1356. case RM_TASKOP_END:
  1357. {
  1358. Status = (NDIS_STATUS) UserParam;
  1359. // We're done -- the status had better not be pending!
  1360. //
  1361. ASSERTEX(!PEND(Status), pTask);
  1362. // Clear ourselves as the secondary task in the adapter object.
  1363. //
  1364. {
  1365. ULONG InitState;
  1366. LOCKOBJ(pAdapter, pSR);
  1367. InitState = FAIL(Status)
  1368. ? ARPAD_AS_FAILEDACTIVATE
  1369. : ARPAD_AS_ACTIVATED;
  1370. arpClearSecondaryAdapterTask(pAdapter, pTask, InitState, pSR);
  1371. UNLOCKOBJ(pAdapter, pSR);
  1372. }
  1373. }
  1374. break;
  1375. default:
  1376. {
  1377. ASSERTEX(!"Unknown task op", pTask);
  1378. }
  1379. break;
  1380. } // switch (Code)
  1381. RM_ASSERT_NOLOCKS(pSR);
  1382. EXIT()
  1383. return Status;
  1384. }
  1385. NDIS_STATUS
  1386. arpTaskDeactivateAdapter(
  1387. IN struct _RM_TASK * pTask,
  1388. IN RM_TASK_OPERATION Code,
  1389. IN UINT_PTR UserParam,
  1390. IN PRM_STACK_RECORD pSR
  1391. )
  1392. /*++
  1393. Routine Description:
  1394. Task handler responsible for shutting down an IP interface.
  1395. Arguments:
  1396. UserParam for (Code == RM_TASKOP_START) : UnbindContext
  1397. --*/
  1398. {
  1399. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1400. ARP1394_ADAPTER * pAdapter = (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pTask);
  1401. BOOLEAN fContinueShutdown = FALSE;
  1402. enum
  1403. {
  1404. PEND_ShutdownIF,
  1405. PEND_CloseAdapter
  1406. };
  1407. ENTER("arpTaskDeactivateAdapter", 0xe262e828)
  1408. switch(Code)
  1409. {
  1410. case RM_TASKOP_START:
  1411. {
  1412. LOCKOBJ(pAdapter, pSR);
  1413. arpSetSecondaryAdapterTask(pAdapter, pTask, ARPAD_AS_DEACTIVATING, pSR);
  1414. UNLOCKOBJ(pAdapter, pSR);
  1415. fContinueShutdown = TRUE;
  1416. }
  1417. break;
  1418. case RM_TASKOP_PENDCOMPLETE:
  1419. {
  1420. switch(RM_PEND_CODE(pTask))
  1421. {
  1422. case PEND_CloseAdapter:
  1423. {
  1424. //
  1425. // The close adapter operation is complete. Free the the
  1426. // adapter and if there is an unbind context, notify NDIS
  1427. // of unbind completion.
  1428. //
  1429. ASSERTEX(pAdapter->bind.AdapterHandle == NULL, pAdapter);
  1430. Status = (NDIS_STATUS) UserParam;
  1431. //
  1432. // free the back up tasks allocated in Task Activate Adapter
  1433. //
  1434. arpRemoveBackupTasks (&ArpGlobals,ARP1394_BACKUP_TASKS);
  1435. // Status of the completed operation can't itself be pending!
  1436. //
  1437. ASSERT(Status != NDIS_STATUS_PENDING);
  1438. }
  1439. break;
  1440. case PEND_ShutdownIF:
  1441. {
  1442. //
  1443. // Closing the IF is complete, continue with the rest
  1444. // of the shutdown procedure..
  1445. //
  1446. ASSERTEX(pAdapter->pIF == NULL, pAdapter);
  1447. fContinueShutdown = TRUE;
  1448. }
  1449. break;
  1450. }
  1451. }
  1452. break;
  1453. case RM_TASKOP_END:
  1454. {
  1455. Status = (NDIS_STATUS) UserParam;
  1456. // Clear the secondary task in the adapter object.
  1457. //
  1458. LOCKOBJ(pAdapter, pSR);
  1459. arpClearSecondaryAdapterTask(pAdapter, pTask, ARPAD_AS_DEACTIVATED, pSR);
  1460. UNLOCKOBJ(pAdapter, pSR);
  1461. }
  1462. break;
  1463. default:
  1464. {
  1465. ASSERTEX(!"Unknown task op", pTask);
  1466. }
  1467. break;
  1468. } // switch (Code)
  1469. if (fContinueShutdown)
  1470. {
  1471. do {
  1472. NDIS_HANDLE NdisAdapterHandle;
  1473. LOCKOBJ(pAdapter, pSR);
  1474. // If required, shutdown interface...
  1475. //
  1476. if (pAdapter->pIF)
  1477. {
  1478. PARP1394_INTERFACE pIF = pAdapter->pIF;
  1479. RmTmpReferenceObject(&pIF->Hdr, pSR);
  1480. UNLOCKOBJ(pAdapter, pSR);
  1481. arpDeinitIf(
  1482. pIF,
  1483. pTask,
  1484. PEND_ShutdownIF,
  1485. pSR
  1486. );
  1487. RmTmpDereferenceObject(&pIF->Hdr, pSR);
  1488. Status = NDIS_STATUS_PENDING;
  1489. break;
  1490. }
  1491. ASSERT(pAdapter->pIF == NULL);
  1492. NdisAdapterHandle = pAdapter->bind.AdapterHandle;
  1493. pAdapter->bind.AdapterHandle = NULL;
  1494. UNLOCKOBJ(pAdapter, pSR);
  1495. if (NdisAdapterHandle != NULL)
  1496. {
  1497. //
  1498. // Suspend task and call NdisCloseAdapter...
  1499. //
  1500. RmSuspendTask(pTask, PEND_CloseAdapter, pSR);
  1501. RM_ASSERT_NOLOCKS(pSR);
  1502. NdisCloseAdapter(
  1503. &Status,
  1504. NdisAdapterHandle
  1505. );
  1506. if (Status != NDIS_STATUS_PENDING)
  1507. {
  1508. ArpNdCloseAdapterComplete(
  1509. (NDIS_HANDLE)pAdapter,
  1510. Status
  1511. );
  1512. }
  1513. Status = NDIS_STATUS_PENDING;
  1514. }
  1515. } while (FALSE);
  1516. }
  1517. RM_ASSERT_NOLOCKS(pSR);
  1518. EXIT()
  1519. return Status;
  1520. }
  1521. NDIS_STATUS
  1522. arpPnPReconfigHandler(
  1523. IN PARP1394_ADAPTER pAdapter,
  1524. IN PNET_PNP_EVENT pNetPnPEvent
  1525. )
  1526. /*++
  1527. Routine Description:
  1528. Handle a reconfig message on the specified adapter. If no adapter
  1529. is specified, it is a global parameter that has changed.
  1530. Arguments:
  1531. pAdapter - Pointer to our adapter structure
  1532. pNetPnPEvent - Pointer to reconfig event
  1533. Return Value:
  1534. NDIS_STATUS_SUCCESS always, for now.
  1535. --*/
  1536. {
  1537. ENTER("PnPReconfig", 0x39bae883)
  1538. NDIS_STATUS Status;
  1539. RM_DECLARE_STACK_RECORD(sr)
  1540. Status = NDIS_STATUS_FAILURE;
  1541. do
  1542. {
  1543. PIP_PNP_RECONFIG_REQUEST pIpReconfigReq;
  1544. PARP1394_INTERFACE pIF;
  1545. pIpReconfigReq = (PIP_PNP_RECONFIG_REQUEST)pNetPnPEvent->Buffer;
  1546. OBJLOG2(
  1547. pAdapter,
  1548. "AtmArpPnPReconfig: pIpReconfig 0x%x, arpConfigOffset 0x%x\n",
  1549. pIpReconfigReq,
  1550. pIpReconfigReq->arpConfigOffset
  1551. );
  1552. if(pIpReconfigReq->arpConfigOffset == 0)
  1553. {
  1554. // Invalid structure.
  1555. //
  1556. ASSERT(!"Invalid pIpReconfigReq");
  1557. break;
  1558. }
  1559. //
  1560. // Since we support only one IF per adapter, and it's extra work
  1561. // to verify the string, we completely ignore the contents
  1562. // of the pnp event, and instead just start reconfiguration on the
  1563. // SINGLE IF associated with pAdapter.
  1564. //
  1565. LOCKOBJ(pAdapter, &sr);
  1566. pIF = pAdapter->pIF;
  1567. if (pIF != NULL)
  1568. {
  1569. RmTmpReferenceObject(&pIF->Hdr, &sr);
  1570. }
  1571. UNLOCKOBJ(pAdapter, &sr);
  1572. if (pIF == NULL) break;
  1573. //
  1574. // We've found the IF this reconfig request applies to. Let's
  1575. // start reconfiguration on this IF...
  1576. //
  1577. Status = arpTryReconfigureIf(pIF, pNetPnPEvent, &sr);
  1578. RmTmpDereferenceObject(&pIF->Hdr, &sr);
  1579. } while (FALSE);
  1580. return Status;
  1581. }
  1582. PRM_OBJECT_HEADER
  1583. arpAdapterCreate(
  1584. PRM_OBJECT_HEADER pParentObject,
  1585. PVOID pCreateParams,
  1586. PRM_STACK_RECORD psr
  1587. )
  1588. /*++
  1589. Routine Description:
  1590. Allocate and initialize an object of type ARP1394_ADAPTER.
  1591. Arguments:
  1592. pParentObject - Object that is to be the parent of the adapter.
  1593. pCreateParams - Actually a pointer to a ARP1394_BIND_PARAMS structure,
  1594. which contains information required to create the adapter.
  1595. Return Value:
  1596. Pointer to the allocated and initialized object on success.
  1597. NULL otherwise.
  1598. --*/
  1599. {
  1600. ARP1394_ADAPTER * pA;
  1601. ARP1394_BIND_PARAMS *pBindParams = (ARP1394_BIND_PARAMS*) pCreateParams;
  1602. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1603. ENTER("arpAdapterCreate", 0xaa25c606)
  1604. ARP_ALLOCSTRUCT(pA, MTAG_ADAPTER);
  1605. do
  1606. {
  1607. if (pA == NULL)
  1608. {
  1609. break;
  1610. }
  1611. ARP_ZEROSTRUCT(pA);
  1612. // Create up-cased version of the DeviceName and save it.
  1613. //
  1614. // WARNING: On MILLEN, this is actually an ANSI string. However,
  1615. // arpCopyUnicodeString works fine even if it's an ANSI string.
  1616. //
  1617. Status = arpCopyUnicodeString(
  1618. &(pA->bind.DeviceName),
  1619. pBindParams->pDeviceName,
  1620. TRUE // Upcase
  1621. );
  1622. if (FAIL(Status))
  1623. {
  1624. pA->bind.DeviceName.Buffer=NULL; // so we don't try to free it later
  1625. break;
  1626. }
  1627. //
  1628. // Determine if we're being created in Ethernet Emulation ("Bridge") mode
  1629. // We're created in bridge mode if the BindContext is NULL.
  1630. //
  1631. if (pBindParams->BindContext != NULL)
  1632. {
  1633. //
  1634. // NOTE: We ONLY read configuration if we're operation in
  1635. // normal (Not BRIDGE) mode.
  1636. //
  1637. Status = arpCopyUnicodeString(
  1638. &(pA->bind.ConfigName),
  1639. pBindParams->pArpConfigName,
  1640. FALSE // Don't upcase
  1641. );
  1642. if (FAIL(Status))
  1643. {
  1644. pA->bind.ConfigName.Buffer=NULL; // so we don't try to free it later
  1645. break;
  1646. }
  1647. }
  1648. pA->bind.BindContext = pBindParams->BindContext;
  1649. pA->bind.IpConfigHandle = pBindParams->IpConfigHandle;
  1650. RmInitializeLock(
  1651. &pA->Lock,
  1652. LOCKLEVEL_ADAPTER
  1653. );
  1654. RmInitializeHeader(
  1655. pParentObject,
  1656. &pA->Hdr,
  1657. MTAG_ADAPTER,
  1658. &pA->Lock,
  1659. &ArpGlobals_AdapterStaticInfo,
  1660. NULL,
  1661. psr
  1662. );
  1663. if (pBindParams->BindContext == NULL)
  1664. {
  1665. TR_WARN(("pAdapter 0x%p created in BRIDGE mode!\n", pA));
  1666. ARP_ENABLE_BRIDGE(pA);
  1667. }
  1668. }
  1669. while(FALSE);
  1670. if (FAIL(Status))
  1671. {
  1672. if (pA != NULL)
  1673. {
  1674. arpAdapterDelete ((PRM_OBJECT_HEADER) pA, psr);
  1675. pA = NULL;
  1676. }
  1677. }
  1678. EXIT()
  1679. return (PRM_OBJECT_HEADER) pA;
  1680. }
  1681. NDIS_STATUS
  1682. arpTryReconfigureIf(
  1683. PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  1684. PNET_PNP_EVENT pNetPnPEvent, // OPTIONAL
  1685. PRM_STACK_RECORD pSR
  1686. )
  1687. /*++
  1688. Routine Description:
  1689. Try to start reconfiguration of the specified IF.
  1690. Some special cases:
  1691. - If the IF is currently being shutdown, we will synchronously succeed. Why?
  1692. Because we don't need to do anything more and it's not an error condition.
  1693. - If the IF is currently being started, we (asychronously) wait until
  1694. the starting is complete, then shut it down and restart it.
  1695. - If the IF is currently UP, we shut it down and restart it.
  1696. Arguments:
  1697. pIF - The interface to be shutdown/restarted.
  1698. pNetPnPEvent - OPTIONAL Ndis pnp event to be completed when the
  1699. reconfiguration operation is over. This is optional because
  1700. this function can also be called from elsewhere, in particular,
  1701. from the ioctl admin utility.
  1702. Return Value:
  1703. NDIS_STATUS_SUCCESS -- on synchronous success.
  1704. NDIS_STATUS_FAILURE -- on synchronous failure.
  1705. NDIS_STATUS_PENDING -- if completion is going to happen asynchronously.
  1706. --*/
  1707. {
  1708. NDIS_STATUS Status;
  1709. PRM_TASK pTask;
  1710. ENTER("arpTryReconfigureIf", 0x65a0bb61)
  1711. RM_ASSERT_NOLOCKS(pSR);
  1712. do
  1713. {
  1714. if (CHECK_IF_PRIMARY_STATE(pIF, ARPIF_PS_DEINITING)
  1715. || CHECK_IF_PRIMARY_STATE(pIF, ARPIF_PS_DEINITED))
  1716. {
  1717. Status = NDIS_STATUS_SUCCESS;
  1718. break;
  1719. }
  1720. LOCKOBJ(pIF, pSR);
  1721. UNLOCKOBJ(pIF, pSR);
  1722. Status = arpAllocateTask(
  1723. &pIF->Hdr, // pParentObject,
  1724. arpTaskReinitInterface, // pfnHandler,
  1725. 0, // Timeout,
  1726. "Task: DeactivateInterface(reconfig)",// szDescription
  1727. &pTask,
  1728. pSR
  1729. );
  1730. if (FAIL(Status))
  1731. {
  1732. OBJLOG0(pIF, ("Couldn't alloc reinit IF task!\n"));
  1733. }
  1734. else
  1735. {
  1736. // Save away pNetPnPEvent in the task structure and start the task.
  1737. //
  1738. PTASK_REINIT_IF pReinitTask = (PTASK_REINIT_IF) pTask;
  1739. ASSERT(sizeof(*pReinitTask)<=sizeof(ARP1394_TASK));
  1740. pReinitTask->pNetPnPEvent = pNetPnPEvent;
  1741. (void)RmStartTask(pTask, 0, pSR);
  1742. Status = NDIS_STATUS_PENDING;
  1743. }
  1744. } while (FALSE);
  1745. EXIT()
  1746. return Status;
  1747. }
  1748. NDIS_STATUS
  1749. arpPrepareAndSendNdisRequest(
  1750. IN PARP1394_ADAPTER pAdapter,
  1751. IN PARP_NDIS_REQUEST pArpNdisRequest,
  1752. IN PRM_TASK pTask, // OPTIONAL
  1753. IN UINT PendCode,
  1754. IN NDIS_OID Oid,
  1755. IN PVOID pBuffer,
  1756. IN ULONG BufferLength,
  1757. IN NDIS_REQUEST_TYPE RequestType,
  1758. IN PRM_STACK_RECORD pSR
  1759. )
  1760. /*++
  1761. Routine Description:
  1762. Send an NDIS Request to query an adapter for information.
  1763. If the request pends, block on the ATMARP Adapter structure
  1764. till it completes.
  1765. Arguments:
  1766. pAdapter - Points to ATMARP Adapter structure
  1767. pNdisRequest - Pointer to UNITIALIZED NDIS request structure
  1768. pTask - OPTIONAL Task. If NULL, we block until the operation
  1769. completes.
  1770. PendCode - PendCode to suspend pTask
  1771. Oid - OID to be passed in the request
  1772. pBuffer - place for value(s)
  1773. BufferLength - length of above
  1774. Return Value:
  1775. The NDIS status of the request.
  1776. --*/
  1777. {
  1778. NDIS_STATUS Status;
  1779. PNDIS_REQUEST pNdisRequest = &pArpNdisRequest->Request;
  1780. ARP_ZEROSTRUCT(pArpNdisRequest);
  1781. //
  1782. // Fill in the NDIS Request structure
  1783. //
  1784. if (RequestType == NdisRequestQueryInformation)
  1785. {
  1786. pNdisRequest->RequestType = NdisRequestQueryInformation;
  1787. pNdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
  1788. pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = pBuffer;
  1789. pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = BufferLength;
  1790. pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
  1791. pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = BufferLength;
  1792. }
  1793. else
  1794. {
  1795. ASSERT(RequestType == NdisRequestSetInformation);
  1796. pNdisRequest->RequestType = NdisRequestSetInformation;
  1797. pNdisRequest->DATA.SET_INFORMATION.Oid = Oid;
  1798. pNdisRequest->DATA.SET_INFORMATION.InformationBuffer = pBuffer;
  1799. pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength = BufferLength;
  1800. pNdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
  1801. pNdisRequest->DATA.SET_INFORMATION.BytesNeeded = BufferLength;
  1802. }
  1803. if (pTask == NULL)
  1804. {
  1805. // We might potentially wait.
  1806. //
  1807. ASSERT_PASSIVE();
  1808. NdisInitializeEvent(&pArpNdisRequest->Event);
  1809. NdisRequest(
  1810. &Status,
  1811. pAdapter->bind.AdapterHandle,
  1812. pNdisRequest
  1813. );
  1814. if (PEND(Status))
  1815. {
  1816. NdisWaitEvent(&pArpNdisRequest->Event, 0);
  1817. Status = pArpNdisRequest->Status;
  1818. }
  1819. }
  1820. else
  1821. {
  1822. pArpNdisRequest->pTask = pTask;
  1823. RmSuspendTask(pTask, PendCode, pSR);
  1824. NdisRequest(
  1825. &Status,
  1826. pAdapter->bind.AdapterHandle,
  1827. pNdisRequest
  1828. );
  1829. if (!PEND(Status))
  1830. {
  1831. RmUnsuspendTask(pTask, pSR);
  1832. }
  1833. }
  1834. return Status;
  1835. }
  1836. ENetAddr
  1837. arpGetSecondaryMacAddress (
  1838. IN ENetAddr EthernetMacAddress
  1839. )
  1840. /*++
  1841. When we are in the bridge mode, we pretend that there is
  1842. only one other Ethernet Card out there on the net. Therefore
  1843. only one Ethernet Address needs to be generated.
  1844. For now we simply add one to the Local Adapter's Ethernet
  1845. address and generate it
  1846. --*/
  1847. {
  1848. ENetAddr NewAddress = EthernetMacAddress; // copy
  1849. //
  1850. // randomize the returned Mac Address
  1851. // by xor ing the address with a random
  1852. // 0x0d3070b17715 (a random number)
  1853. //
  1854. NewAddress.addr[0] ^= 0x00;
  1855. NewAddress.addr[1] ^= 0x2f;
  1856. NewAddress.addr[2] ^= 0x61;
  1857. NewAddress.addr[3] ^= 0x7c;
  1858. NewAddress.addr[4] ^= 0x91;
  1859. NewAddress.addr[5] ^= 0x30;
  1860. // Set the locally administered bit
  1861. // and clear the multicast bit.
  1862. NewAddress.addr[0] &= 0x20;
  1863. return NewAddress;
  1864. }
  1865. NDIS_STATUS
  1866. arpGetEuidTopology (
  1867. IN PARP1394_ADAPTER pAdapter,
  1868. IN PRM_STACK_RECORD pSR
  1869. )
  1870. /*++
  1871. Queues A workitem to get the EuidTopology
  1872. --*/
  1873. {
  1874. ENTER ("arpGetEuidTopology ",0x97a0abcb)
  1875. PARP1394_WORK_ITEM pWorkItem = NULL;
  1876. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1877. BOOLEAN fQueueWorkItem = FALSE;
  1878. do
  1879. {
  1880. if (pAdapter->fQueryAddress == TRUE)
  1881. {
  1882. break;
  1883. }
  1884. LOCKOBJ (pAdapter, pSR);
  1885. if (pAdapter->fQueryAddress == FALSE)
  1886. {
  1887. pAdapter->fQueryAddress = TRUE;
  1888. fQueueWorkItem = TRUE;
  1889. }
  1890. else
  1891. {
  1892. fQueueWorkItem = FALSE;
  1893. }
  1894. UNLOCKOBJ(pAdapter, pSR);
  1895. if (fQueueWorkItem == FALSE)
  1896. {
  1897. break;
  1898. }
  1899. Status = ARP_ALLOCSTRUCT(pWorkItem, MTAG_ARP_GENERIC);
  1900. if (Status != NDIS_STATUS_SUCCESS || pWorkItem == NULL)
  1901. {
  1902. pWorkItem = NULL;
  1903. break;
  1904. }
  1905. arpQueueWorkItem (pWorkItem,
  1906. arpGetEuidTopologyWorkItem,
  1907. &pAdapter->Hdr,
  1908. pSR);
  1909. } while (FALSE);
  1910. EXIT()
  1911. return Status;
  1912. }
  1913. VOID
  1914. arpQueueWorkItem (
  1915. PARP1394_WORK_ITEM pWorkItem,
  1916. ARP_WORK_ITEM_PROC pFunc,
  1917. PRM_OBJECT_HEADER pHdr,
  1918. PRM_STACK_RECORD pSR
  1919. )
  1920. /*++
  1921. Sends a request to get the bus topology . Only used in bridge mode
  1922. For now only Adapter's are passed in as pHdr
  1923. --*/
  1924. {
  1925. ENTER("arpQueueWorkItem",0xa1de6752)
  1926. PNDIS_WORK_ITEM pNdisWorkItem = &pWorkItem->u.NdisWorkItem;
  1927. PARP1394_ADAPTER pAdapter = (PARP1394_ADAPTER)pHdr;
  1928. BOOLEAN fStartWorkItem = FALSE;
  1929. LOCKOBJ(pAdapter, pSR);
  1930. if (CHECK_AD_PRIMARY_STATE(pAdapter, ARPAD_PS_INITED ) == TRUE)
  1931. {
  1932. #if RM_EXTRA_CHECKING
  1933. RM_DECLARE_STACK_RECORD(sr)
  1934. RmLinkToExternalEx(
  1935. pHdr, // pHdr
  1936. 0x5a2fd7ca, // LUID
  1937. (UINT_PTR)pWorkItem, // External entity
  1938. ARPASSOC_WORK_ITEM, // AssocID
  1939. " Outstanding WorkItem",
  1940. &sr
  1941. );
  1942. #else // !RM_EXTRA_CHECKING
  1943. RmLinkToExternalFast(pHdr);
  1944. #endif // !RM_EXTRA_CHECKING
  1945. fStartWorkItem = TRUE;
  1946. }
  1947. UNLOCKOBJ(pAdapter, pSR);
  1948. if (fStartWorkItem == TRUE)
  1949. {
  1950. NdisInitializeWorkItem ( pNdisWorkItem ,arpGenericWorkItem, pHdr);
  1951. pWorkItem->pFunc = pFunc;
  1952. NdisScheduleWorkItem(pNdisWorkItem );
  1953. }
  1954. EXIT()
  1955. }
  1956. VOID
  1957. arpGenericWorkItem(
  1958. struct _NDIS_WORK_ITEM * pWorkItem,
  1959. PVOID pContext
  1960. )
  1961. /*++
  1962. Generic workitem finction. Takes care of the reference on the pObj
  1963. --*/
  1964. {
  1965. PARP1394_WORK_ITEM pArpWorkItem = (ARP1394_WORK_ITEM*)pWorkItem;
  1966. PRM_OBJECT_HEADER pObj = (PRM_OBJECT_HEADER)pContext;
  1967. RM_DECLARE_STACK_RECORD(sr)
  1968. pArpWorkItem->pFunc (pArpWorkItem, pObj, &sr);
  1969. #if RM_EXTRA_CHECKING
  1970. {
  1971. RmUnlinkFromExternalEx(pObj,
  1972. 0x548c9d54,
  1973. (UINT_PTR)pWorkItem,
  1974. ARPASSOC_WORK_ITEM,
  1975. &sr
  1976. );
  1977. }
  1978. #else
  1979. RmUnlinkFromExternalFast(pObj);
  1980. #endif
  1981. }
  1982. NDIS_STATUS
  1983. arpGetEuidTopologyWorkItem(
  1984. struct _ARP1394_WORK_ITEM* pWorkItem,
  1985. PRM_OBJECT_HEADER pObj,
  1986. PRM_STACK_RECORD pSR
  1987. )
  1988. /*++
  1989. workitem to get the topology of the bus .. The WorkItem structure can be null;
  1990. --*/
  1991. {
  1992. PARP1394_ADAPTER pAdapter = (PARP1394_ADAPTER)pObj;
  1993. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1994. ARP_NDIS_REQUEST ArpRequest;
  1995. EUID_TOPOLOGY EuidTopology;
  1996. //
  1997. // Return if the adapter is not active
  1998. //
  1999. if (CHECK_AD_PRIMARY_STATE(pAdapter, ARPAD_PS_DEINITING ) ==TRUE)
  2000. {
  2001. ASSERT (CHECK_AD_PRIMARY_STATE(pAdapter, ARPAD_PS_DEINITING ) ==FALSE);
  2002. return NDIS_STATUS_FAILURE; // early return
  2003. }
  2004. //
  2005. // Initialize the structures
  2006. //
  2007. ARP_ZEROSTRUCT(&ArpRequest);
  2008. ARP_ZEROSTRUCT(&EuidTopology);
  2009. //Send the request down
  2010. //
  2011. Status = \
  2012. arpPrepareAndSendNdisRequest(pAdapter,
  2013. &ArpRequest,
  2014. NULL, //IN PRM_TASK pTask,
  2015. 0, //IN UINT PendCode,
  2016. OID_1394_QUERY_EUID_NODE_MAP,
  2017. &EuidTopology,
  2018. sizeof (EuidTopology),
  2019. NdisRequestQueryInformation ,
  2020. pSR
  2021. );
  2022. if (Status == NDIS_STATUS_SUCCESS)
  2023. {
  2024. NdisMoveMemory (&pAdapter->EuidMap, &EuidTopology, sizeof (pAdapter->EuidMap));
  2025. }
  2026. pAdapter->fQueryAddress = FALSE;
  2027. return Status;
  2028. }
  2029. VOID
  2030. arpNdProcessBusReset(
  2031. IN PARP1394_ADAPTER pAdapter
  2032. )
  2033. /*++
  2034. If the adapter is in the Bridge mode, it will query the
  2035. adapter for the bus topology
  2036. --*/
  2037. {
  2038. ENTER("arpNdProcessBusReset ",0x48e7659a)
  2039. BOOLEAN BridgeEnabled = ARP_BRIDGE_ENABLED(pAdapter);
  2040. RM_DECLARE_STACK_RECORD(SR)
  2041. if (BridgeEnabled == TRUE)
  2042. {
  2043. arpGetEuidTopology (pAdapter, &SR);
  2044. }
  2045. EXIT()
  2046. }
  2047. VOID
  2048. arpRemoveBackupTasks (
  2049. IN ARP1394_GLOBALS* pGlobals,
  2050. UINT Num
  2051. )
  2052. /*++
  2053. Removes Num tasks to be used as a backup. However, the number is only a
  2054. approximate value as the back up tasks could be in use
  2055. --*/
  2056. {
  2057. PSLIST_HEADER pListHead = &pGlobals->BackupTasks;
  2058. PNDIS_SPIN_LOCK pLock = &pGlobals->BackupTaskLock;
  2059. UINT i=0;
  2060. for (i = 0;i <Num;i++)
  2061. {
  2062. PSLIST_ENTRY pEntry;
  2063. pEntry = NdisInterlockedPopEntrySList(pListHead, pLock );
  2064. if (pEntry != NULL)
  2065. {
  2066. TASK_BACKUP* pTask;
  2067. ARP1394_TASK *pATask;
  2068. pTask = CONTAINING_RECORD (pEntry, TASK_BACKUP, List);
  2069. pATask = (ARP1394_TASK*)pTask;
  2070. ARP_FREE (pATask);
  2071. pGlobals->NumTasks --;
  2072. }
  2073. }
  2074. }
  2075. VOID
  2076. arpAddBackupTasks (
  2077. IN ARP1394_GLOBALS* pGlobals,
  2078. UINT Num
  2079. )
  2080. /*++
  2081. Adds Num tasks to be used as a backup.
  2082. We are modifying pGlobals without holding the lock
  2083. --*/
  2084. {
  2085. PSLIST_HEADER pListHead = &pGlobals->BackupTasks;
  2086. PNDIS_SPIN_LOCK pLock = &pGlobals->BackupTaskLock;
  2087. UINT i=0;
  2088. for (i = 0;i <Num;i++)
  2089. {
  2090. ARP1394_TASK *pATask=NULL;
  2091. ARP_ALLOCSTRUCT(pATask, MTAG_TASK); // TODO use lookaside lists.
  2092. if (pATask != NULL)
  2093. {
  2094. NdisInterlockedPushEntrySList(pListHead,&pATask->Backup.List, pLock);
  2095. pGlobals->NumTasks ++;
  2096. }
  2097. }
  2098. }
  2099. VOID
  2100. arpAllocateBackupTasks (
  2101. ARP1394_GLOBALS* pGlobals
  2102. )
  2103. /*++
  2104. Allocates 4 Tasks to be used as a backup in lowmem conditions
  2105. --*/
  2106. {
  2107. PSLIST_HEADER pListHead = &pGlobals->BackupTasks;
  2108. PNDIS_SPIN_LOCK pLock = &pGlobals->BackupTaskLock;
  2109. NdisInitializeSListHead (pListHead);
  2110. NdisAllocateSpinLock(pLock);
  2111. arpAddBackupTasks (pGlobals, 4);
  2112. }
  2113. VOID
  2114. arpFreeBackupTasks (
  2115. ARP1394_GLOBALS* pGlobals
  2116. )
  2117. /*++
  2118. Free all the backup tasks hanging off the adapter object
  2119. Since this is only called from the Unload handler, the code
  2120. presumes that all tasks are complete
  2121. We are modifying pGlobals without holding a lock
  2122. --*/
  2123. {
  2124. PSLIST_HEADER pListHead = &pGlobals->BackupTasks;
  2125. PNDIS_SPIN_LOCK pLock = &pGlobals->BackupTaskLock;
  2126. PSLIST_ENTRY pEntry = NULL;
  2127. do
  2128. {
  2129. pEntry = NdisInterlockedPopEntrySList(pListHead, pLock );
  2130. if (pEntry != NULL)
  2131. {
  2132. TASK_BACKUP* pTask;
  2133. ARP1394_TASK *pATask;
  2134. pTask = CONTAINING_RECORD (pEntry, TASK_BACKUP, List);
  2135. pATask = (ARP1394_TASK*)pTask;
  2136. ARP_FREE (pATask);
  2137. pGlobals->NumTasks --;
  2138. }
  2139. } while (pEntry != NULL);
  2140. ASSERT (pGlobals->NumTasks == 0);
  2141. }
  2142. ARP1394_TASK *
  2143. arpGetBackupTask (
  2144. ARP1394_GLOBALS* pGlobals
  2145. )
  2146. /*++
  2147. Removes a task from the Back up task list and returns it
  2148. --*/
  2149. {
  2150. PSLIST_HEADER pListHead = &pGlobals->BackupTasks;
  2151. PNDIS_SPIN_LOCK pLock = &pGlobals->BackupTaskLock;
  2152. PSLIST_ENTRY pEntry = NULL;
  2153. TASK_BACKUP* pTask = NULL;
  2154. pEntry = NdisInterlockedPopEntrySList(pListHead, pLock);
  2155. if (pEntry != NULL)
  2156. {
  2157. pTask = CONTAINING_RECORD (pEntry, TASK_BACKUP, List);
  2158. NdisZeroMemory ( pTask, sizeof (ARP1394_TASK));
  2159. MARK_TASK_AS_BACKUP(&pTask->Hdr);
  2160. }
  2161. return (ARP1394_TASK*)pTask;
  2162. }
  2163. VOID
  2164. arpReturnBackupTask (
  2165. IN ARP1394_TASK* pTask
  2166. )
  2167. //
  2168. // We can always return the task to the Slist because we are gauranteed that it
  2169. // will be present until all the interfaces are unloaded.
  2170. //
  2171. {
  2172. // re-insert the task
  2173. PSLIST_HEADER pListHead = &ArpGlobals.BackupTasks;
  2174. PNDIS_SPIN_LOCK pLock = &ArpGlobals.BackupTaskLock;
  2175. PTASK_BACKUP pBkTask = (PTASK_BACKUP ) pTask;
  2176. NdisInterlockedPushEntrySList(pListHead, &pBkTask->List, pLock);
  2177. }
  2178. NDIS_STATUS
  2179. arpTaskCloseCallLowPower(
  2180. IN PRM_TASK pTask,
  2181. IN RM_TASK_OPERATION Code,
  2182. IN UINT_PTR UserParam, // Unused
  2183. IN PRM_STACK_RECORD pSR
  2184. )
  2185. /*++
  2186. This function will close all the open VCs.
  2187. This will allow the 1394 miniport to power down without any problem
  2188. It will also have to close the Address Families.
  2189. This function will also have to return synchronously.
  2190. --*/
  2191. {
  2192. ENTER("arpTaskLowPower", 0x922f875b)
  2193. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2194. PARPCB_DEST pDest = (ARPCB_DEST*)RM_PARENT_OBJECT(pTask);
  2195. TASK_SET_POWER_CALL *pCloseCallTask = (TASK_SET_POWER_CALL *) pTask;
  2196. enum
  2197. {
  2198. PEND_CleanupVcComplete,
  2199. };
  2200. switch(Code)
  2201. {
  2202. case RM_TASKOP_START:
  2203. {
  2204. LOCKOBJ(pDest,pSR);
  2205. if (arpNeedToCleanupDestVc(pDest))
  2206. {
  2207. PRM_TASK pCleanupCallTask = pDest->VcHdr.pCleanupCallTask;
  2208. // If there is already an official cleanup-vc task, we pend on it.
  2209. // Other wise we allocate our own, pend on it, and start it.
  2210. //
  2211. if (pCleanupCallTask != NULL)
  2212. {
  2213. TR_WARN((
  2214. "Cleanup-vc task %p exists; pending on it.\n",
  2215. pCleanupCallTask));
  2216. RmTmpReferenceObject(&pCleanupCallTask->Hdr, pSR);
  2217. UNLOCKOBJ(pDest, pSR);
  2218. RmPendTaskOnOtherTask(
  2219. pTask,
  2220. PEND_CleanupVcComplete,
  2221. pCleanupCallTask,
  2222. pSR
  2223. );
  2224. RmTmpDereferenceObject(&pCleanupCallTask->Hdr, pSR);
  2225. Status = NDIS_STATUS_PENDING;
  2226. break;
  2227. }
  2228. else
  2229. {
  2230. //
  2231. // Start the call cleanup task and pend on int.
  2232. //
  2233. UNLOCKOBJ(pDest, pSR);
  2234. RM_ASSERT_NOLOCKS(pSR);
  2235. Status = arpAllocateTask(
  2236. &pDest->Hdr, // pParentObject,
  2237. arpTaskCleanupCallToDest, // pfnHandler,
  2238. 0, // Timeout,
  2239. "Task: CleanupCall on UnloadDest", // szDescription
  2240. &pCleanupCallTask,
  2241. pSR
  2242. );
  2243. if (FAIL(Status))
  2244. {
  2245. TR_WARN(("FATAL: couldn't alloc cleanup call task!\n"));
  2246. }
  2247. else
  2248. {
  2249. RmPendTaskOnOtherTask(
  2250. pTask,
  2251. PEND_CleanupVcComplete,
  2252. pCleanupCallTask, // task to pend on
  2253. pSR
  2254. );
  2255. // RmStartTask uses up the tmpref on the task
  2256. // which was added by arpAllocateTask.
  2257. //
  2258. Status = RmStartTask(
  2259. pCleanupCallTask,
  2260. 0, // UserParam (unused)
  2261. pSR
  2262. );
  2263. }
  2264. break;
  2265. }
  2266. }
  2267. //
  2268. // We're here because there is no async unload work to be done.
  2269. // We simply return and finish synchronous cleanup in the END
  2270. // handler for this task.
  2271. //
  2272. Status = NDIS_STATUS_SUCCESS;
  2273. } // START
  2274. break;
  2275. case RM_TASKOP_PENDCOMPLETE:
  2276. {
  2277. switch(RM_PEND_CODE(pTask))
  2278. {
  2279. case PEND_CleanupVcComplete:
  2280. {
  2281. //
  2282. // There was vc-cleanup to be done, but how it's
  2283. // complete. We should be able to synchronously clean up
  2284. // this task now
  2285. //
  2286. #if DBG
  2287. LOCKOBJ(pDest, pSR);
  2288. ASSERTEX(!arpNeedToCleanupDestVc(pDest), pDest);
  2289. UNLOCKOBJ(pDest, pSR);
  2290. #endif DBG
  2291. Status = NDIS_STATUS_SUCCESS;
  2292. }
  2293. break;
  2294. default:
  2295. {
  2296. ASSERTEX(!"Unknown pend op", pTask);
  2297. }
  2298. break;
  2299. }
  2300. }
  2301. break;
  2302. case RM_TASKOP_END:
  2303. {
  2304. ULONG DestRemaining;
  2305. PCALL_COUNT pCount = pCloseCallTask->pCount;
  2306. ASSERT (pCount != NULL);
  2307. if (SetLowPower == pCloseCallTask->Cause )
  2308. {
  2309. DestRemaining = NdisInterlockedDecrement (&pCount->DestCount);
  2310. if ( 0 == DestRemaining )
  2311. {
  2312. NdisSetEvent (&pCount ->VcEvent);
  2313. }
  2314. }
  2315. }
  2316. break;
  2317. default:
  2318. {
  2319. ASSERTEX(!"Unknown task op", pTask);
  2320. }
  2321. break;
  2322. } // switch (Code)
  2323. RmUnlockAll(pSR);
  2324. RM_ASSERT_NOLOCKS(pSR);
  2325. EXIT()
  2326. return Status;
  2327. }
  2328. INT
  2329. arpCloseAllVcOnDest(
  2330. PRM_OBJECT_HEADER pHdr,
  2331. PVOID pvContext, // Unused
  2332. PRM_STACK_RECORD pSR
  2333. )
  2334. /*++
  2335. --*/
  2336. {
  2337. ENTER ("arpCloseAllVcOnDest", 0xf19a83d5)
  2338. PARPCB_DEST pDest = (PARPCB_DEST) pHdr;
  2339. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2340. PTASK_SET_POWER_CALL pTask = NULL;
  2341. PCALL_COUNT pCloseCall = (PCALL_COUNT) pvContext;
  2342. do
  2343. {
  2344. NdisInterlockedIncrement(&pCloseCall->DestCount);
  2345. Status = arpAllocateTask(
  2346. &pDest->Hdr, // pParentObject,
  2347. arpTaskCloseCallLowPower, // pfnHandler,
  2348. 0, // Timeout,
  2349. "Task: Set Power Cleanup VC", // szDescrip.
  2350. &(PRM_TASK)pTask,
  2351. pSR
  2352. );
  2353. if (Status != NDIS_STATUS_SUCCESS || pTask == NULL)
  2354. {
  2355. pTask = NULL;
  2356. break;
  2357. }
  2358. pTask->Cause = SetLowPower;
  2359. pTask->pCount = pCloseCall;
  2360. RmStartTask((PRM_TASK)pTask, 0,pSR);
  2361. } while (FALSE);
  2362. if (Status != NDIS_STATUS_SUCCESS)
  2363. {
  2364. ULONG DestRemaining;
  2365. DestRemaining = NdisInterlockedDecrement (&pCloseCall->DestCount);
  2366. if ( 0 == DestRemaining )
  2367. {
  2368. NdisSetEvent (&pCloseCall->VcEvent);
  2369. }
  2370. }
  2371. return TRUE; // continue to enumerate
  2372. }
  2373. VOID
  2374. arpLowPowerCloseAllCalls (
  2375. ARP1394_INTERFACE *pIF,
  2376. PRM_STACK_RECORD pSR
  2377. )
  2378. {
  2379. CALL_COUNT CloseCallCount;
  2380. //
  2381. // The Dest Count will be used to make sure that this thread waits for
  2382. // all the Close Calls to complete.
  2383. //
  2384. NdisInitializeEvent (&CloseCallCount.VcEvent);
  2385. CloseCallCount.DestCount= 0;
  2386. //
  2387. // First we go through all the Dests and close calls on them
  2388. //
  2389. RmWeakEnumerateObjectsInGroup(&pIF->DestinationGroup,
  2390. arpCloseAllVcOnDest,
  2391. &CloseCallCount,
  2392. pSR);
  2393. if (CloseCallCount.DestCount != 0)
  2394. {
  2395. NdisWaitEvent (&CloseCallCount.VcEvent, 0);
  2396. }
  2397. return;
  2398. }
  2399. NDIS_STATUS
  2400. arpTaskCloseVcAndAF (
  2401. IN struct _RM_TASK * pTask,
  2402. IN RM_TASK_OPERATION Code,
  2403. IN UINT_PTR UserParam,
  2404. IN PRM_STACK_RECORD pSR
  2405. )
  2406. /*++
  2407. Routine Description:
  2408. This task does the work that is common between SetLowPower and and
  2409. the Resume failure case
  2410. As its name suggests, it simply closes all the VCs and Af.
  2411. Its parent task is either a shutdown task or a Set Power task.
  2412. As the 2 parents of this task are serialized w.r.t each other,
  2413. there is no need for any serialization within this task.
  2414. Arguments:
  2415. UserParam for (Code == RM_TASKOP_START) : unused
  2416. --*/
  2417. {
  2418. ENTER("arpTaskCloseVcAndAF ", 0xc7c9ad6b)
  2419. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2420. ARP1394_ADAPTER* pAdapter = (ARP1394_ADAPTER*)RM_PARENT_OBJECT(pTask);
  2421. TASK_POWER * pTaskPower = (TASK_POWER*) pTask;
  2422. ARP1394_INTERFACE * pIF = pAdapter->pIF;
  2423. ULONG Stage;
  2424. enum
  2425. {
  2426. STAGE_Start,
  2427. STAGE_StopMaintenanceTask,
  2428. STAGE_CleanupVcComplete,
  2429. STAGE_CloseDestinationGroup,
  2430. STAGE_SwitchedToPassive,
  2431. STAGE_CloseAF,
  2432. STAGE_End
  2433. };
  2434. switch(Code)
  2435. {
  2436. case RM_TASKOP_START:
  2437. Stage = STAGE_Start;
  2438. break;
  2439. case RM_TASKOP_PENDCOMPLETE:
  2440. Status = (NDIS_STATUS) UserParam;
  2441. ASSERT(!PEND(Status));
  2442. Stage = RM_PEND_CODE(pTask);
  2443. break;
  2444. case RM_TASKOP_END:
  2445. Status = (NDIS_STATUS) UserParam;
  2446. Stage= STAGE_End;
  2447. break;
  2448. default:
  2449. ASSERT(FALSE);
  2450. return NDIS_STATUS_FAILURE; // ** EARLY RETURN **
  2451. }
  2452. switch(Stage)
  2453. {
  2454. case STAGE_Start:
  2455. {
  2456. //
  2457. // Stop the IF maintenance task if it's running.
  2458. //
  2459. Status = arpTryStopIfMaintenanceTask(
  2460. pIF,
  2461. pTask,
  2462. STAGE_StopMaintenanceTask,
  2463. pSR
  2464. );
  2465. if (PEND(Status)) break;
  2466. }
  2467. // FALL THROUGH
  2468. case STAGE_StopMaintenanceTask:
  2469. {
  2470. LOCKOBJ(pIF, pSR);
  2471. TIMESTAMP("===CloseVC and AF:MaintenanceTask stopped");
  2472. // Unlink the explicit reference of the broadcast channel destination
  2473. // from the interface.
  2474. //
  2475. if (pIF->pBroadcastDest != NULL)
  2476. {
  2477. PARPCB_DEST pBroadcastDest = pIF->pBroadcastDest;
  2478. pIF->pBroadcastDest = NULL;
  2479. // NOTE: We're unlinking the two with the IF lock (which is
  2480. // is the same as the pBroadcastDest's lock) held.
  2481. // This is OK to do.
  2482. //
  2483. #if RM_EXTRA_CHECKING
  2484. RmUnlinkObjectsEx(
  2485. &pIF->Hdr,
  2486. &pBroadcastDest->Hdr,
  2487. 0x66bda49b,
  2488. ARPASSOC_LINK_IF_OF_BCDEST,
  2489. ARPASSOC_LINK_BCDEST_OF_IF,
  2490. pSR
  2491. );
  2492. #else // !RM_EXTRA_CHECKING
  2493. RmUnlinkObjects(&pIF->Hdr, &pBroadcastDest->Hdr, pSR);
  2494. #endif // !RM_EXTRA_CHECKING
  2495. }
  2496. //
  2497. // If the VC state needs cleaning up, we need to get a task
  2498. // going to clean it up. Other wise we fake the completion of this
  2499. // stage so that we move on to the next...
  2500. //
  2501. if (pIF->recvinfo.VcHdr.NdisVcHandle == NULL)
  2502. {
  2503. UNLOCKOBJ(pIF, pSR);
  2504. Status = NDIS_STATUS_SUCCESS;
  2505. }
  2506. else
  2507. {
  2508. PRM_TASK pCleanupCallTask = pIF->recvinfo.VcHdr.pCleanupCallTask;
  2509. // If there is already an official cleanup-vc task, we pend on it.
  2510. // Other wise we allocate our own, pend on it, and start it.
  2511. //
  2512. if (pCleanupCallTask != NULL)
  2513. {
  2514. TR_WARN((
  2515. "IF %p Cleanup-vc task %p exists; pending on it.\n",
  2516. pIF,
  2517. pCleanupCallTask));
  2518. RmTmpReferenceObject(&pCleanupCallTask->Hdr, pSR);
  2519. UNLOCKOBJ(pIF, pSR);
  2520. RmPendTaskOnOtherTask(
  2521. pTask,
  2522. STAGE_CleanupVcComplete,
  2523. pCleanupCallTask,
  2524. pSR
  2525. );
  2526. RmTmpDereferenceObject(&pCleanupCallTask->Hdr, pSR);
  2527. Status = NDIS_STATUS_PENDING;
  2528. }
  2529. else
  2530. {
  2531. //
  2532. // Start the call cleanup task and pend on int.
  2533. //
  2534. UNLOCKOBJ(pIF, pSR);
  2535. Status = arpAllocateTask(
  2536. &pIF->Hdr, // pParentObject,
  2537. arpTaskCleanupRecvFifoCall, // pfnHandler,
  2538. 0, // Timeout,
  2539. "Task: CleanupRecvFifo on Set LowPower ", // szDescrip.
  2540. &pCleanupCallTask,
  2541. pSR
  2542. );
  2543. if (FAIL(Status))
  2544. {
  2545. // Couldn't allocate task.
  2546. //
  2547. TR_WARN(("FATAL: couldn't alloc cleanup call task!\n"));
  2548. }
  2549. else
  2550. {
  2551. Status = RmPendTaskOnOtherTask(
  2552. pTask,
  2553. STAGE_CleanupVcComplete,
  2554. pCleanupCallTask,
  2555. pSR
  2556. );
  2557. ASSERT(!FAIL(Status));
  2558. // RmStartTask uses up the tmpref on the task
  2559. // which was added by arpAllocateTask.
  2560. //
  2561. Status = RmStartTask(
  2562. pCleanupCallTask,
  2563. 0, // UserParam (unused)
  2564. pSR
  2565. );
  2566. // We rely on pending status to decide whether
  2567. // or not to fall through to the next stage.
  2568. //
  2569. Status = NDIS_STATUS_PENDING;
  2570. }
  2571. }
  2572. }
  2573. }
  2574. if (PEND(Status)) break;
  2575. // FALL THROUGH
  2576. case STAGE_CleanupVcComplete:
  2577. {
  2578. TIMESTAMP("===Set LowPower:RecvFifo cleanup complete");
  2579. // Initiate unload of all the items in the DestinationGroup.
  2580. //
  2581. // If we are going to low power state, then close all the VC's
  2582. // on these Destinations
  2583. //
  2584. arpLowPowerCloseAllCalls (pIF, pSR);
  2585. //
  2586. // Unlink the special "destination VCs". This is executed on both
  2587. // Low power and unbind.
  2588. //
  2589. LOCKOBJ(pIF, pSR);
  2590. TIMESTAMP("===Set LowPower:Destination objects cleaned up.");
  2591. if (pIF->pMultiChannelDest != NULL)
  2592. {
  2593. PARPCB_DEST pMultiChannelDest = pIF->pMultiChannelDest;
  2594. pIF->pMultiChannelDest = NULL;
  2595. // NOTE: We're unlinking the two with the IF lock (which is
  2596. // is the same as the pBroadcastDest's lock) held.
  2597. // This is OK to do.
  2598. //
  2599. #if RM_EXTRA_CHECKING
  2600. RmUnlinkObjectsEx(
  2601. &pIF->Hdr,
  2602. &pMultiChannelDest->Hdr,
  2603. 0xf28090bd,
  2604. ARPASSOC_LINK_IF_OF_MCDEST,
  2605. ARPASSOC_LINK_MCDEST_OF_IF,
  2606. pSR
  2607. );
  2608. #else // !RM_EXTRA_CHECKING
  2609. RmUnlinkObjects(&pIF->Hdr, &pMultiChannelDest->Hdr, pSR);
  2610. #endif // !RM_EXTRA_CHECKING
  2611. }
  2612. if (pIF->pEthernetDest != NULL)
  2613. {
  2614. PARPCB_DEST pEthernetDest = pIF->pEthernetDest;
  2615. pIF->pEthernetDest = NULL;
  2616. // NOTE: We're unlinking the two with the IF lock (which is
  2617. // is the same as the pBroadcastDest's lock) held.
  2618. // This is OK to do.
  2619. //
  2620. #if RM_EXTRA_CHECKING
  2621. RmUnlinkObjectsEx(
  2622. &pIF->Hdr,
  2623. &pEthernetDest->Hdr,
  2624. 0xf8eedcd1,
  2625. ARPASSOC_LINK_IF_OF_ETHDEST,
  2626. ARPASSOC_LINK_ETHDEST_OF_IF,
  2627. pSR
  2628. );
  2629. #else // !RM_EXTRA_CHECKING
  2630. RmUnlinkObjects(&pIF->Hdr, &pEthernetDest->Hdr, pSR);
  2631. #endif // !RM_EXTRA_CHECKING
  2632. }
  2633. UNLOCKOBJ(pIF, pSR);
  2634. // If required, switch to passive. This check should obviously be done
  2635. // without any locks held!
  2636. if (!ARP_ATPASSIVE())
  2637. {
  2638. // We're not at passive level, but we need to be..
  2639. // . So we switch to passive...
  2640. //
  2641. RmSuspendTask(pTask, STAGE_SwitchedToPassive, pSR);
  2642. RmResumeTaskAsync(pTask, 0, &pTaskPower->WorkItem, pSR);
  2643. Status = NDIS_STATUS_PENDING;
  2644. }
  2645. else
  2646. {
  2647. Status = NDIS_STATUS_SUCCESS;
  2648. }
  2649. }
  2650. if (PEND(Status)) break;
  2651. // FALL THROUGH
  2652. case STAGE_SwitchedToPassive:
  2653. {
  2654. NDIS_HANDLE NdisAfHandle;
  2655. // We're now switched to passive
  2656. //
  2657. ASSERT(ARP_ATPASSIVE());
  2658. //
  2659. // We're done with all VCs, etc. Time to close the AF, if it's open.
  2660. //
  2661. LOCKOBJ(pTask, pSR);
  2662. NdisAfHandle = pIF->ndis.AfHandle;
  2663. pIF->ndis.AfHandle = NULL;
  2664. pAdapter->PoMgmt.bReceivedAf = FALSE;
  2665. UNLOCKOBJ(pTask, pSR);
  2666. if (NdisAfHandle == NULL)
  2667. {
  2668. Status = NDIS_STATUS_SUCCESS;
  2669. }
  2670. else
  2671. {
  2672. //
  2673. // (Debug) Delete the association we added when the
  2674. // address family was opened.
  2675. //
  2676. DBG_DELASSOC(
  2677. &pIF->Hdr, // pObject
  2678. NdisAfHandle, // Instance1
  2679. NULL, // Instance2
  2680. ARPASSOC_IF_OPENAF, // AssociationID
  2681. pSR
  2682. );
  2683. //
  2684. // Suspend task and call NdisCloseAdapter...
  2685. //
  2686. pIF->PoMgmt.pAfPendingTask = pTask;
  2687. RmSuspendTask(pTask, STAGE_CloseAF, pSR);
  2688. RM_ASSERT_NOLOCKS(pSR);
  2689. TIMESTAMP("===DeinitIF: Calling NdisClCloseAddressFamily");
  2690. Status = NdisClCloseAddressFamily(
  2691. NdisAfHandle
  2692. );
  2693. if (Status != NDIS_STATUS_PENDING)
  2694. {
  2695. ArpCoCloseAfComplete(
  2696. Status,
  2697. (NDIS_HANDLE)pIF
  2698. );
  2699. Status = NDIS_STATUS_PENDING;
  2700. }
  2701. }
  2702. }
  2703. if (PEND(Status)) break;
  2704. // FALL THROUGH
  2705. case STAGE_CloseAF:
  2706. {
  2707. //
  2708. // The close AF operation is complete.
  2709. // We've not got anything else to do.
  2710. //
  2711. TIMESTAMP("===Set Low Power: Done with CloseAF");
  2712. // Recover the last status ...
  2713. //
  2714. pIF->PoMgmt.pAfPendingTask =NULL;
  2715. Status = (NDIS_STATUS) UserParam;
  2716. // Status of the completed operation can't itself be pending!
  2717. //
  2718. ASSERT(Status != NDIS_STATUS_PENDING);
  2719. //
  2720. // By returning Status != pending, we implicitly complete
  2721. // this task.
  2722. //
  2723. }
  2724. break;
  2725. case STAGE_End:
  2726. {
  2727. TIMESTAMP("===Set Low Power done: All done!");
  2728. // Force status to be success as a transition to LowPower
  2729. // cannot fail
  2730. //
  2731. Status = NDIS_STATUS_SUCCESS;
  2732. }
  2733. break;
  2734. default:
  2735. {
  2736. ASSERTEX(!"Unknown task op", pTask);
  2737. }
  2738. break;
  2739. } // switch (Stage)
  2740. RM_ASSERT_NOLOCKS(pSR);
  2741. EXIT()
  2742. return Status;
  2743. }
  2744. NDIS_STATUS
  2745. arpTaskLowPower(
  2746. IN struct _RM_TASK * pTask,
  2747. IN RM_TASK_OPERATION Code,
  2748. IN UINT_PTR UserParam,
  2749. IN PRM_STACK_RECORD pSR
  2750. )
  2751. /*++
  2752. Routine Description:
  2753. Task handler responsible for setting an adapter to low power state
  2754. (but leaving it allocated and linked to the adapter).
  2755. This task will close all the VCs, AF. However it will leave the Interface
  2756. registered with IP and will not delete either the RemoteIP or DEST structures.
  2757. This task is a primary Interface task. This task is serialized with the Bind
  2758. , Unbind tasks
  2759. Arguments:
  2760. UserParam for (Code == RM_TASKOP_START) : unused
  2761. --*/
  2762. {
  2763. NDIS_STATUS Status;
  2764. PARP1394_INTERFACE pIF;
  2765. PTASK_POWER pTaskPower;
  2766. UINT Stage;
  2767. PARP1394_ADAPTER pAdapter;
  2768. enum
  2769. {
  2770. STAGE_Start,
  2771. STAGE_BecomePrimaryTask,
  2772. STAGE_ExistingPrimaryTaskComplete,
  2773. STAGE_CleanupVcAfComplete,
  2774. STAGE_End
  2775. };
  2776. ENTER("arpTaskLowPower", 0x1a34699e)
  2777. Status = NDIS_STATUS_FAILURE;
  2778. pAdapter = (PARP1394_ADAPTER) RM_PARENT_OBJECT(pTask);
  2779. pIF = pAdapter->pIF;
  2780. pTaskPower = (PTASK_POWER) pTask;
  2781. //
  2782. // Message normalizing code
  2783. //
  2784. switch(Code)
  2785. {
  2786. case RM_TASKOP_START:
  2787. Stage = STAGE_Start;
  2788. break;
  2789. case RM_TASKOP_PENDCOMPLETE:
  2790. Status = (NDIS_STATUS) UserParam;
  2791. ASSERT(!PEND(Status));
  2792. Stage = RM_PEND_CODE(pTask);
  2793. break;
  2794. case RM_TASKOP_END:
  2795. Status = (NDIS_STATUS) UserParam;
  2796. Stage= STAGE_End;
  2797. break;
  2798. default:
  2799. ASSERT(FALSE);
  2800. return NDIS_STATUS_FAILURE; // ** EARLY RETURN **
  2801. }
  2802. switch(Stage)
  2803. {
  2804. case STAGE_Start:
  2805. {
  2806. // There should NOT be another activate/deactivate task running
  2807. // on this interface. We fail the SetPower if we receive it in
  2808. // while we are activating or deactivating the task
  2809. //
  2810. TIMESTAMP("===Set Power Low Starting");
  2811. if (pIF->pActDeactTask != NULL ||
  2812. (CHECK_IF_PRIMARY_STATE(pIF, ARPIF_PS_INITED) != TRUE))
  2813. {
  2814. UNLOCKOBJ(pIF, pSR);
  2815. *pTaskPower->pStatus = NDIS_STATUS_NOT_SUPPORTED;
  2816. Status = NDIS_STATUS_FAILURE;
  2817. break;
  2818. }
  2819. // FALL THROUGH
  2820. }
  2821. case STAGE_BecomePrimaryTask:
  2822. {
  2823. //
  2824. // Next, we try and set ourselves as the primary Adapter Task.
  2825. // This ensures that bind,unbind, and Set Power Tasks are all serialized.
  2826. //
  2827. LOCKOBJ(pAdapter, pSR);
  2828. if (pAdapter->bind.pPrimaryTask == NULL)
  2829. {
  2830. ULONG CurrentInitState = GET_AD_PRIMARY_STATE(pAdapter);
  2831. // Do not change the Init state of the Adapter. However,
  2832. // mark the adapter as transitioning to a low power state
  2833. //
  2834. pTaskPower->PrevState = CurrentInitState;
  2835. arpSetPrimaryAdapterTask(pAdapter, pTask, CurrentInitState, pSR);
  2836. //
  2837. // Set the Power State to Low Power. This will block all
  2838. // outstanding sends
  2839. //
  2840. SET_POWER_STATE (pAdapter, ARPAD_POWER_LOW_POWER);
  2841. UNLOCKOBJ(pAdapter, pSR);
  2842. }
  2843. else
  2844. {
  2845. PRM_TASK pOtherTask = pAdapter->bind.pPrimaryTask;
  2846. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  2847. UNLOCKOBJ(pAdapter, pSR);
  2848. RmPendTaskOnOtherTask(
  2849. pTask,
  2850. STAGE_BecomePrimaryTask, // we'll try again...
  2851. pOtherTask,
  2852. pSR
  2853. );
  2854. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  2855. Status = NDIS_STATUS_PENDING;
  2856. break;
  2857. }
  2858. }
  2859. if (PEND(Status)) break;
  2860. // FALL THROUGH
  2861. case STAGE_ExistingPrimaryTaskComplete:
  2862. {
  2863. PRM_TASK pCloseVCAndAfTask = NULL;
  2864. //
  2865. // Stop the IF maintenance task if it's running.
  2866. //
  2867. Status = arpAllocateTask(
  2868. &pAdapter->Hdr, // pParentObject,
  2869. arpTaskCloseVcAndAF , // pfnHandler,
  2870. 0, // Timeout,
  2871. "Task: Close VC and AF on SetPower", // szDescrip.
  2872. &pCloseVCAndAfTask ,
  2873. pSR
  2874. );
  2875. if (FAIL(Status))
  2876. {
  2877. // Couldn't allocate task.
  2878. //
  2879. TR_WARN(("FATAL: couldn't alloc cleanup call task!\n"));
  2880. break;
  2881. }
  2882. else
  2883. {
  2884. Status = RmPendTaskOnOtherTask(
  2885. pTask,
  2886. STAGE_CleanupVcAfComplete,
  2887. pCloseVCAndAfTask,
  2888. pSR
  2889. );
  2890. ASSERT(!FAIL(Status));
  2891. // RmStartTask uses up the tmpref on the task
  2892. // which was added by arpAllocateTask.
  2893. //
  2894. Status = RmStartTask(
  2895. pCloseVCAndAfTask,
  2896. 0, // UserParam (unused)
  2897. pSR
  2898. );
  2899. }
  2900. if (PEND(Status)) break;
  2901. }
  2902. break;
  2903. case STAGE_CleanupVcAfComplete:
  2904. {
  2905. //
  2906. // The close AF operation is complete.
  2907. // We've not got anything else to do.
  2908. //
  2909. TIMESTAMP("===Set LowPower: Done with CloseAF");
  2910. // Recover the last status ...
  2911. //
  2912. Status = (NDIS_STATUS) UserParam;
  2913. //
  2914. // Status of the completed operation can't itself be pending!
  2915. //
  2916. ASSERT(Status == NDIS_STATUS_SUCCESS);
  2917. //
  2918. // By returning Status != pending, we implicitly complete
  2919. // this task.
  2920. //
  2921. }
  2922. break;
  2923. case STAGE_End:
  2924. {
  2925. //
  2926. // We are done with all async aspects of setting the Low Power state
  2927. // Set the event so that the original Low Power thread can return.
  2928. //
  2929. TIMESTAMP("===Set Low Power done: All done!");
  2930. // Recover the last status ...
  2931. //
  2932. Status = (NDIS_STATUS) UserParam;
  2933. *pTaskPower->pStatus = Status;
  2934. LOCKOBJ (pAdapter, pSR);
  2935. arpClearPrimaryAdapterTask(pAdapter, pTask, pTaskPower->PrevState ,pSR);
  2936. UNLOCKOBJ (pAdapter, pSR);
  2937. NdisSetEvent (&pAdapter->PoMgmt.Complete);
  2938. }
  2939. break;
  2940. default:
  2941. {
  2942. ASSERTEX(!"Unknown task op", pTask);
  2943. }
  2944. break;
  2945. } // switch (Stage)
  2946. RM_ASSERT_NOLOCKS(pSR);
  2947. EXIT()
  2948. return Status;
  2949. }
  2950. NDIS_STATUS
  2951. arpMakeCallOnDest(
  2952. IN PARPCB_REMOTE_IP pRemoteIp,
  2953. IN PARPCB_DEST pDest,
  2954. IN PRM_TASK pTaskToPend,
  2955. IN ULONG PEND_StageMakeCallComplete,
  2956. IN PRM_STACK_RECORD pSR
  2957. )
  2958. /*++
  2959. This function will do a make call on a particular task.
  2960. It will also pend pTaskToPend on that make call
  2961. --*/
  2962. {
  2963. ENTER("arpTaskLowPower", 0x922f875b)
  2964. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  2965. do
  2966. {
  2967. if (pRemoteIp->pDest != pDest)
  2968. {
  2969. Status = NDIS_STATUS_FAILURE;
  2970. break;
  2971. }
  2972. if (pDest->VcHdr.pMakeCallTask != NULL )
  2973. {
  2974. //
  2975. // There is an existing task. Pend on it.
  2976. //
  2977. PRM_TASK pOtherTask = pDest->VcHdr.pMakeCallTask;
  2978. RM_DBG_ASSERT_LOCKED(&pRemoteIp->Hdr, pSR);
  2979. TR_WARN(("MakeCall task %p exists; pending on it.\n", pOtherTask));
  2980. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  2981. DBGMARK(0x0c387a9f);
  2982. UNLOCKOBJ(pRemoteIp, pSR);
  2983. RmPendTaskOnOtherTask(
  2984. pTaskToPend,
  2985. PEND_StageMakeCallComplete,
  2986. pOtherTask,
  2987. pSR
  2988. );
  2989. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  2990. Status = NDIS_STATUS_PENDING;
  2991. }
  2992. else
  2993. {
  2994. DBGMARK(0xe9f37ba9);
  2995. //
  2996. // There is no pMakeCallTask. If it makes sense to start one, we do...
  2997. // Note that checking ARP_CAN_SEND_ON_DEST strictly-speaking requires
  2998. // at-least a read-lock on the IF send lock. However, we don't need
  2999. // precision here -- as long as we don't miss making a call when we
  3000. // should (which we won't) we are ok.
  3001. //
  3002. if (!ARP_CAN_SEND_ON_DEST(pDest) && pDest->VcHdr.pCleanupCallTask==NULL)
  3003. {
  3004. PRM_TASK pMakeCallTask;
  3005. //
  3006. // Let's start a MakeCall task and pend on it.
  3007. //
  3008. Status = arpAllocateTask(
  3009. &pDest->Hdr, // pParentObject
  3010. arpTaskMakeCallToDest, // pfnHandler
  3011. 0, // Timeout
  3012. "Task: SendFifoMakeCall", // szDescription
  3013. &pMakeCallTask,
  3014. pSR
  3015. );
  3016. if (FAIL(Status))
  3017. {
  3018. // Couldn't allocate task. We fail with STATUS_RESOURCES
  3019. //
  3020. Status = NDIS_STATUS_RESOURCES;
  3021. }
  3022. else
  3023. {
  3024. UNLOCKOBJ(pRemoteIp, pSR);
  3025. RmPendTaskOnOtherTask(
  3026. pTaskToPend,
  3027. PEND_StageMakeCallComplete,
  3028. pMakeCallTask,
  3029. pSR
  3030. );
  3031. (VOID)RmStartTask(
  3032. pMakeCallTask,
  3033. 0, // UserParam (unused)
  3034. pSR
  3035. );
  3036. Status = NDIS_STATUS_PENDING;
  3037. }
  3038. }
  3039. else
  3040. {
  3041. // Calls is ready to do. We finish sending off the packets in
  3042. // the END handler.
  3043. //
  3044. Status = NDIS_STATUS_SUCCESS;
  3045. }
  3046. }
  3047. } while (FALSE);
  3048. RmUnlockAll(pSR);
  3049. EXIT()
  3050. return Status;
  3051. }
  3052. NDIS_STATUS
  3053. arpTaskStartGenericVCs (
  3054. IN PRM_TASK pTask,
  3055. IN RM_TASK_OPERATION Code,
  3056. IN UINT_PTR UserParam, // Unused
  3057. IN PRM_STACK_RECORD pSR
  3058. )
  3059. /*++
  3060. This function will close all the open VCs.
  3061. This will allow the 1394 miniport to power down without any problem
  3062. It will also have to close the Address Families.
  3063. This function will also have to return synchronously.
  3064. --*/
  3065. {
  3066. ENTER("arpTaskStartGenericVCs", 0x75780ca6)
  3067. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  3068. ARP1394_ADAPTER* pAdapter = (ARP1394_ADAPTER*)RM_PARENT_OBJECT(pTask);
  3069. TASK_POWER * pTaskPower = (TASK_POWER*) pTask;
  3070. ARP1394_INTERFACE * pIF = pAdapter->pIF;
  3071. enum
  3072. {
  3073. PEND_OpenAF,
  3074. PEND_SetupBroadcastChannel,
  3075. PEND_SetupReceiveVc,
  3076. PEND_SetupMultiChannel,
  3077. PEND_SetupEthernetVc,
  3078. PEND_StartedVC
  3079. };
  3080. switch(Code)
  3081. {
  3082. case RM_TASKOP_START:
  3083. {
  3084. CO_ADDRESS_FAMILY AddressFamily;
  3085. //
  3086. // This task is inherently serialized as its parent task is serialized.
  3087. //
  3088. LOCKOBJ (pIF, pSR);
  3089. if (pIF->pActDeactTask != NULL)
  3090. {
  3091. // This should never happen, because the Activate task is
  3092. // always started by an active primary task, and at most one primary
  3093. // task is active at any point of time.
  3094. //
  3095. ASSERTEX(!"start: activate/deactivate task exists!", pIF);
  3096. Status = NDIS_STATUS_FAILURE;
  3097. UNLOCKOBJ(pIF, pSR);
  3098. break;
  3099. }
  3100. UNLOCKOBJ (pIF,pSR);
  3101. //
  3102. // Now Open the Address Family.
  3103. //
  3104. NdisZeroMemory(&AddressFamily, sizeof(AddressFamily));
  3105. AddressFamily.AddressFamily = CO_ADDRESS_FAMILY_1394;
  3106. AddressFamily.MajorVersion = NIC1394_AF_CURRENT_MAJOR_VERSION;
  3107. AddressFamily.MinorVersion = NIC1394_AF_CURRENT_MINOR_VERSION;
  3108. pIF->PoMgmt.pAfPendingTask = pTask;
  3109. RmSuspendTask(pTask, PEND_OpenAF, pSR);
  3110. RM_ASSERT_NOLOCKS(pSR);
  3111. TIMESTAMP("===ActivateIF: Calling NdisClOpenAddressFamily");
  3112. Status = NdisClOpenAddressFamily(
  3113. pIF->ndis.AdapterHandle,
  3114. &AddressFamily,
  3115. (NDIS_HANDLE)pIF,
  3116. &ArpGlobals.ndis.CC,
  3117. sizeof(ArpGlobals.ndis.CC),
  3118. &(pIF->ndis.AfHandle)
  3119. );
  3120. if (Status != NDIS_STATUS_PENDING)
  3121. {
  3122. ArpCoOpenAfComplete(
  3123. Status,
  3124. (NDIS_HANDLE)pIF,
  3125. pIF->ndis.AfHandle
  3126. );
  3127. }
  3128. Status = NDIS_STATUS_PENDING;
  3129. }
  3130. break;
  3131. case RM_TASKOP_PENDCOMPLETE:
  3132. {
  3133. pTaskPower->LastStage = (RM_PEND_CODE(pTask));
  3134. Status = (NDIS_STATUS) UserParam;
  3135. switch(RM_PEND_CODE(pTask))
  3136. {
  3137. case PEND_OpenAF:
  3138. {
  3139. PARPCB_DEST pBroadcastDest;
  3140. pIF->PoMgmt.pAfPendingTask = NULL;
  3141. if (FAIL(Status))
  3142. {
  3143. //
  3144. // OpenAF failed...
  3145. //
  3146. break;
  3147. }
  3148. //
  3149. // Successfully opened the address family and waited for
  3150. // connect status.
  3151. // Now setup the broadcast channel VC.
  3152. //
  3153. //
  3154. TR_INFO(("Interface: 0x%p, Got NdisAfHandle: 0x%p\n",
  3155. pIF, pIF->ndis.AfHandle));
  3156. //
  3157. // Let's create a destination object representing the
  3158. // broadcast channel, and make a call to it.
  3159. //
  3160. Status = arpSetupSpecialDest(
  3161. pIF,
  3162. NIC1394AddressType_Channel, // This means bcast channel.
  3163. pTask, // pParentTask
  3164. PEND_SetupBroadcastChannel, // PendCode
  3165. &pBroadcastDest,
  3166. pSR
  3167. );
  3168. // Should either fail or pend -- never return success.
  3169. //
  3170. ASSERT(Status != NDIS_STATUS_SUCCESS);
  3171. if (!PEND(Status))
  3172. {
  3173. OBJLOG0( pIF, "FATAL: Couldn't create BC dest entry.\n");
  3174. }
  3175. }
  3176. break;
  3177. case PEND_SetupBroadcastChannel:
  3178. {
  3179. PRM_TASK pMakeCallTask;
  3180. if (FAIL(Status))
  3181. {
  3182. //
  3183. // Couldn't setup the broadcast channel...
  3184. //
  3185. break;
  3186. }
  3187. //
  3188. // Successfully opened the address family.
  3189. // Now setup the receive FIFO VC.
  3190. //
  3191. //
  3192. // TR_INFO(("Interface: 0x%p, Got NdisAfHandle: 0x%p\n",
  3193. // pIF, pIF->ndis.AfHandle));
  3194. //
  3195. // Let's start a MakeCall task and pend on it.
  3196. //
  3197. Status = arpAllocateTask(
  3198. &pIF->Hdr, // pParentObject
  3199. arpTaskMakeRecvFifoCall, // pfnHandler
  3200. 0, // Timeout
  3201. "Task: MakeRecvFifoCall", // szDescription
  3202. &pMakeCallTask,
  3203. pSR
  3204. );
  3205. if (FAIL(Status))
  3206. {
  3207. // Couldn't allocate task. Let's do a fake completion of
  3208. // this stage...
  3209. //
  3210. RmSuspendTask(pTask, PEND_SetupReceiveVc, pSR);
  3211. RmResumeTask(pTask, (UINT_PTR) Status, pSR);
  3212. Status = NDIS_STATUS_PENDING;
  3213. break;
  3214. }
  3215. else
  3216. {
  3217. RmPendTaskOnOtherTask(
  3218. pTask,
  3219. PEND_SetupReceiveVc,
  3220. pMakeCallTask,
  3221. pSR
  3222. );
  3223. (VOID)RmStartTask(
  3224. pMakeCallTask,
  3225. 0, // UserParam (unused)
  3226. pSR
  3227. );
  3228. Status = NDIS_STATUS_PENDING;
  3229. }
  3230. }
  3231. break;
  3232. case PEND_SetupReceiveVc:
  3233. {
  3234. PARPCB_DEST pMultiChannelDest;
  3235. if (FAIL(Status))
  3236. {
  3237. TR_WARN(("FATAL: COULDN'T SETUP RECEIVE FIFO VC!\n"));
  3238. break;
  3239. }
  3240. //
  3241. // Let's create a destination object representing the
  3242. // multichannel vc, and make a call to it.
  3243. //
  3244. Status = arpSetupSpecialDest(
  3245. pIF,
  3246. NIC1394AddressType_MultiChannel,
  3247. pTask, // pParentTask
  3248. PEND_SetupMultiChannel, // PendCode
  3249. &pMultiChannelDest,
  3250. pSR
  3251. );
  3252. // Should either fail or pend -- never return success.
  3253. //
  3254. ASSERT(Status != NDIS_STATUS_SUCCESS);
  3255. if (!PEND(Status))
  3256. {
  3257. OBJLOG0( pIF, "FATAL: Couldn't create BC dest entry.\n");
  3258. }
  3259. else
  3260. {
  3261. //
  3262. // On pending, pMultiChannelDest contains a valid
  3263. // pDest which has been tmpref'd.
  3264. // Keep a pointer to the broadcast dest in the IF.
  3265. // and link the broadcast dest to the IF.
  3266. //
  3267. {
  3268. #if RM_EXTRA_CHECKING
  3269. RmLinkObjectsEx(
  3270. &pIF->Hdr,
  3271. &pMultiChannelDest->Hdr,
  3272. 0x34639a4c,
  3273. ARPASSOC_LINK_IF_OF_MCDEST,
  3274. " IF of MultiChannel Dest 0x%p (%s)\n",
  3275. ARPASSOC_LINK_MCDEST_OF_IF,
  3276. " MultiChannel Dest of IF 0x%p (%s)\n",
  3277. pSR
  3278. );
  3279. #else // !RM_EXTRA_CHECKING
  3280. RmLinkObjects(&pIF->Hdr, &pMultiChannelDest->Hdr,pSR);
  3281. #endif // !RM_EXTRA_CHECKING
  3282. LOCKOBJ(pIF, pSR);
  3283. ASSERT(pIF->pMultiChannelDest == NULL);
  3284. pIF->pMultiChannelDest = pMultiChannelDest;
  3285. UNLOCKOBJ(pIF, pSR);
  3286. // arpSetupSpecialDest ref'd pBroadcastDest.
  3287. //
  3288. RmTmpDereferenceObject(&pMultiChannelDest->Hdr, pSR);
  3289. }
  3290. }
  3291. }
  3292. break;
  3293. case PEND_SetupMultiChannel:
  3294. {
  3295. PARPCB_DEST pEthernetDest;
  3296. if (FAIL(Status))
  3297. {
  3298. TR_WARN(("COULDN'T SETUP MULTI-CHANNEL VC (IGNORING FAILURE)!\n"));
  3299. break;
  3300. }
  3301. //
  3302. // Let's create a destination object representing the
  3303. // ethernet, and make a call to it.
  3304. //
  3305. Status = arpSetupSpecialDest(
  3306. pIF,
  3307. NIC1394AddressType_Ethernet,
  3308. pTask, // pParentTask
  3309. PEND_SetupEthernetVc, // PendCode
  3310. &pEthernetDest,
  3311. pSR
  3312. );
  3313. // Should either fail or pend -- never return success.
  3314. //
  3315. ASSERT(Status != NDIS_STATUS_SUCCESS);
  3316. if (!PEND(Status))
  3317. {
  3318. OBJLOG0( pIF, "FATAL: Couldn't create BC dest entry.\n");
  3319. }
  3320. else
  3321. {
  3322. //
  3323. // On pending, pEthernetDest contains a valid
  3324. // pDest which has been tmpref'd.
  3325. // Keep a pointer to the broadcast dest in the IF.
  3326. // and link the broadcast dest to the IF.
  3327. //
  3328. {
  3329. #if RM_EXTRA_CHECKING
  3330. RmLinkObjectsEx(
  3331. &pIF->Hdr,
  3332. &pEthernetDest->Hdr,
  3333. 0xcea46d67,
  3334. ARPASSOC_LINK_IF_OF_ETHDEST,
  3335. " IF of Ethernet Dest 0x%p (%s)\n",
  3336. ARPASSOC_LINK_ETHDEST_OF_IF,
  3337. " Ethernet Dest of IF 0x%p (%s)\n",
  3338. pSR
  3339. );
  3340. #else // !RM_EXTRA_CHECKING
  3341. RmLinkObjects(&pIF->Hdr, &pEthernetDest->Hdr,pSR);
  3342. #endif // !RM_EXTRA_CHECKING
  3343. LOCKOBJ(pIF, pSR);
  3344. ASSERT(pIF->pEthernetDest == NULL);
  3345. pIF->pEthernetDest = pEthernetDest;
  3346. UNLOCKOBJ(pIF, pSR);
  3347. // arpSetupSpecialDest ref'd pBroadcastDest.
  3348. //
  3349. RmTmpDereferenceObject(&pEthernetDest->Hdr, pSR);
  3350. }
  3351. }
  3352. }
  3353. break;
  3354. case PEND_SetupEthernetVc:
  3355. {
  3356. if (FAIL(Status))
  3357. {
  3358. TR_WARN(("COULDN'T SETUP ETHERNET VC (IGNORING FAILURE)!\n"));
  3359. break;
  3360. }
  3361. if (!ARP_ATPASSIVE())
  3362. {
  3363. ASSERT(sizeof(TASK_ACTIVATE_IF)<=sizeof(ARP1394_TASK));
  3364. // We're not at passive level, but we need to be when we
  3365. // call IP's add interface. So we switch to passive...
  3366. // NOTE: we specify completion code PEND_SetupReceiveVc
  3367. // because we want to get back here (except
  3368. // we'll be at passive).
  3369. //
  3370. RmSuspendTask(pTask, PEND_SetupEthernetVc, pSR);
  3371. RmResumeTaskAsync(
  3372. pTask,
  3373. Status,
  3374. &((TASK_ACTIVATE_IF*)pTask)->WorkItem,
  3375. pSR
  3376. );
  3377. Status = NDIS_STATUS_PENDING;
  3378. break;
  3379. }
  3380. ASSERT(Status == NDIS_STATUS_SUCCESS);
  3381. //
  3382. // Successfully opened the address family and setup
  3383. // the recv VC.
  3384. if (!FAIL(Status))
  3385. {
  3386. //
  3387. // Start the maintenance task on this IF.
  3388. //
  3389. arpStartIfMaintenanceTask(pIF, pSR);
  3390. }
  3391. } // end case PEND_SetupEthernetVc
  3392. break;
  3393. default:
  3394. {
  3395. ASSERTEX(!"Unknown pend op", pTask);
  3396. }
  3397. break;
  3398. } // end switch(RM_PEND_CODE(pTask))
  3399. }
  3400. break;
  3401. case RM_TASKOP_END:
  3402. {
  3403. //
  3404. // Recover the last status ...
  3405. //
  3406. Status = (NDIS_STATUS) UserParam;
  3407. //
  3408. // Status of the completed operation can't itself be pending!
  3409. //
  3410. ASSERT(Status != NDIS_STATUS_PENDING);
  3411. }
  3412. break;
  3413. default:
  3414. {
  3415. ASSERTEX(!"Unknown task op", pTask);
  3416. }
  3417. break;
  3418. }
  3419. RM_ASSERT_NOLOCKS(pSR);
  3420. EXIT()
  3421. return Status;
  3422. }
  3423. NDIS_STATUS
  3424. arpTaskOnPower (
  3425. IN PRM_TASK pTask,
  3426. IN RM_TASK_OPERATION Code,
  3427. IN UINT_PTR UserParam, // Unused
  3428. IN PRM_STACK_RECORD pSR
  3429. )
  3430. /*++
  3431. Validates the event and passes it off to the correct function.
  3432. This presumes that the LowPowerTask has already run
  3433. It then waits for that function to finish its work.
  3434. --*/
  3435. {
  3436. ENTER("arpTaskOnPower", 0xccaf09cd)
  3437. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  3438. ARP1394_ADAPTER* pAdapter = (ARP1394_ADAPTER*)RM_PARENT_OBJECT(pTask);
  3439. TASK_POWER * pTaskPower = (TASK_POWER*) pTask;
  3440. ARP1394_INTERFACE * pIF = pAdapter->pIF;
  3441. ULONG Stage = 0;
  3442. enum
  3443. {
  3444. STAGE_Start,
  3445. STAGE_BecomePrimaryTask,
  3446. STAGE_ExistingPrimaryTaskComplete,
  3447. STAGE_StartGenericVCs,
  3448. PEND_DeinitIF,
  3449. STAGE_End
  3450. };
  3451. pTaskPower = (PTASK_POWER) pTask;
  3452. //
  3453. // Message normalizing code
  3454. //
  3455. switch(Code)
  3456. {
  3457. case RM_TASKOP_START:
  3458. Stage = STAGE_Start;
  3459. break;
  3460. case RM_TASKOP_PENDCOMPLETE:
  3461. Status = (NDIS_STATUS) UserParam;
  3462. ASSERT(!PEND(Status));
  3463. Stage = RM_PEND_CODE(pTask);
  3464. break;
  3465. case RM_TASKOP_END:
  3466. Status = (NDIS_STATUS) UserParam;
  3467. Stage= STAGE_End;
  3468. break;
  3469. default:
  3470. ASSERT(FALSE);
  3471. return NDIS_STATUS_FAILURE; // ** EARLY RETURN **
  3472. }
  3473. switch(Stage)
  3474. {
  3475. case STAGE_Start:
  3476. {
  3477. // There should NOT be another activate/deactivate task running
  3478. // on this interface. We fail the SetPower if we receive it in
  3479. // while we are activating or deactivating the task
  3480. //
  3481. TIMESTAMP("===Set Power ON Starting");
  3482. LOCKOBJ(pAdapter, pSR);
  3483. if (CHECK_AD_PRIMARY_STATE(pAdapter,ARPAD_PS_INITED) == FALSE)
  3484. {
  3485. break;
  3486. }
  3487. //
  3488. // Now, make this task the primary task on the adapter
  3489. //
  3490. if (pAdapter->bind.pPrimaryTask == NULL)
  3491. {
  3492. // Don't change the Init State of this adapter
  3493. //
  3494. ULONG CurrentInitState = GET_AD_PRIMARY_STATE(pAdapter);
  3495. arpSetPrimaryAdapterTask(pAdapter, pTask, CurrentInitState , pSR);
  3496. pAdapter->PoMgmt.bResuming = TRUE;
  3497. UNLOCKOBJ(pAdapter, pSR);
  3498. }
  3499. else
  3500. {
  3501. PRM_TASK pOtherTask = pAdapter->bind.pPrimaryTask;
  3502. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  3503. UNLOCKOBJ(pAdapter, pSR);
  3504. RmPendTaskOnOtherTask(
  3505. pTask,
  3506. STAGE_BecomePrimaryTask, // we'll try again...
  3507. pOtherTask,
  3508. pSR
  3509. );
  3510. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  3511. Status = NDIS_STATUS_PENDING;
  3512. break;
  3513. }
  3514. }
  3515. if (PEND(Status)) break;
  3516. // FALL THROUGH
  3517. case STAGE_ExistingPrimaryTaskComplete:
  3518. {
  3519. PRM_TASK pStartGenericVCs = NULL;
  3520. if (pIF->pActDeactTask != NULL)
  3521. {
  3522. // This should never happen, because the Activate task is
  3523. // always started by an active primary task, and at most one primary
  3524. // task is active at any point of time.
  3525. //
  3526. ASSERTEX(!"start: activate/deactivate task exists!", pIF);
  3527. Status = NDIS_STATUS_FAILURE;
  3528. break;
  3529. }
  3530. //
  3531. // Stop the IF maintenance task if it's running.
  3532. //
  3533. Status = arpAllocateTask(
  3534. &pAdapter->Hdr, // pParentObject,
  3535. arpTaskStartGenericVCs , // pfnHandler,
  3536. 0, // Timeout,
  3537. "Task: arpTaskStartGenericVCs", // szDescrip.
  3538. &pStartGenericVCs,
  3539. pSR
  3540. );
  3541. if (FAIL(Status))
  3542. {
  3543. // Couldn't allocate task.
  3544. //
  3545. TR_WARN(("FATAL: couldn't alloc start call task!\n"));
  3546. break;
  3547. }
  3548. else
  3549. {
  3550. Status = RmPendTaskOnOtherTask(
  3551. pTask,
  3552. STAGE_StartGenericVCs,
  3553. pStartGenericVCs,
  3554. pSR
  3555. );
  3556. ASSERT(!FAIL(Status));
  3557. // RmStartTask uses up the tmpref on the task
  3558. // which was added by arpAllocateTask.
  3559. //
  3560. Status = RmStartTask(
  3561. pStartGenericVCs,
  3562. 0, // UserParam (unused)
  3563. pSR
  3564. );
  3565. }
  3566. if (PEND(Status)) break;
  3567. }
  3568. break;
  3569. case STAGE_StartGenericVCs:
  3570. {
  3571. //
  3572. // The close AF operation is complete.
  3573. // We've not got anything else to do.
  3574. //
  3575. TIMESTAMP("===Set PowerOn: Created VCs");
  3576. // Recover the last status ...
  3577. //
  3578. Status = (NDIS_STATUS) UserParam;
  3579. if (Status != NDIS_STATUS_SUCCESS)
  3580. {
  3581. //
  3582. // Undo all the VCs, AFs and Task that
  3583. //have been created in arpTaskStartGenericVCs
  3584. //
  3585. pAdapter->PoMgmt.bFailedResume = TRUE;
  3586. arpDeinitIf(pIF, pTask,PEND_DeinitIF, pSR);
  3587. Status = NDIS_STATUS_PENDING;
  3588. }
  3589. }
  3590. break;
  3591. case PEND_DeinitIF:
  3592. {
  3593. //
  3594. // Set the Failure state on the adapter object here
  3595. //
  3596. //
  3597. // return Failure, so we can inform NDIS of the failure
  3598. //
  3599. Status = NDIS_STATUS_SUCCESS;
  3600. }
  3601. break;
  3602. case STAGE_End:
  3603. {
  3604. //
  3605. // We are done with all async aspects of setting the Low Power state
  3606. // Set the event so that the original Low Power thread can return.
  3607. //
  3608. TIMESTAMP("===Set Power On done: All done!");
  3609. LOCKOBJ (pAdapter, pSR);
  3610. if (Status== NDIS_STATUS_SUCCESS)
  3611. {
  3612. arpClearPrimaryAdapterTask (pAdapter, pTask, ARPAD_PS_INITED,pSR);
  3613. }
  3614. else
  3615. {
  3616. arpClearPrimaryAdapterTask (pAdapter, pTask, ARPAD_PS_FAILEDINIT,pSR);
  3617. }
  3618. SET_POWER_STATE(pAdapter, ARPAD_POWER_NORMAL);;
  3619. UNLOCKOBJ (pAdapter, pSR);
  3620. *pTaskPower->pStatus = Status;
  3621. NdisSetEvent (&pAdapter->PoMgmt.Complete);
  3622. }
  3623. break;
  3624. default:
  3625. {
  3626. ASSERTEX(!"Unknown task op", pTask);
  3627. }
  3628. break;
  3629. } // switch (Stage)
  3630. RM_ASSERT_NOLOCKS(pSR);
  3631. EXIT()
  3632. return Status;
  3633. }
  3634. NDIS_STATUS
  3635. arpStandby (
  3636. IN ARP1394_ADAPTER *pAdapter,
  3637. IN NET_DEVICE_POWER_STATE DeviceState,
  3638. IN PRM_STACK_RECORD pSR
  3639. )
  3640. /*++
  3641. arpStandby does the work for putting the adapter into standby.
  3642. It synchronously return Success, Failure or Not Supported.
  3643. If the Adapter structure has not inited, then this function returns
  3644. Not supported
  3645. --*/
  3646. {
  3647. PARP1394_INTERFACE pIF = pAdapter->pIF;
  3648. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  3649. PTASK_POWER pSetPowerTask = NULL;
  3650. NDIS_STATUS TaskStatus = NDIS_STATUS_FAILURE;
  3651. ENTER ("arpStandby ", 0x2087f71a)
  3652. do
  3653. {
  3654. //
  3655. // If we have been asked to standby before the Interface has initialized
  3656. // then we return NOT_SUPPORTED. This will cause NDIS to unbind the the ARP
  3657. // from the miniport .
  3658. //
  3659. if (pIF == NULL)
  3660. {
  3661. Status = NDIS_STATUS_NOT_SUPPORTED;
  3662. break;
  3663. }
  3664. if(!CHECK_IF_PRIMARY_STATE(pIF, ARPIF_PS_INITED))
  3665. {
  3666. Status = NDIS_STATUS_NOT_SUPPORTED;
  3667. break;
  3668. }
  3669. Status = arpAllocateTask(
  3670. &pAdapter->Hdr, // pParentObject
  3671. arpTaskLowPower, // pfnHandler
  3672. 0, // Timeout
  3673. "Task: Set Power Low", // szDescription
  3674. &(PRM_TASK)pSetPowerTask,
  3675. pSR
  3676. );
  3677. if (NDIS_STATUS_SUCCESS != Status || NULL == pSetPowerTask)
  3678. {
  3679. pSetPowerTask = NULL;
  3680. Status = NDIS_STATUS_NOT_SUPPORTED;
  3681. break;
  3682. }
  3683. pSetPowerTask->pStatus = &TaskStatus;
  3684. pSetPowerTask ->PowerState = DeviceState;
  3685. NdisInitializeEvent(&pAdapter->PoMgmt.Complete);
  3686. RmStartTask((PRM_TASK)pSetPowerTask,0,pSR);
  3687. NdisWaitEvent (&pAdapter->PoMgmt.Complete, 0);
  3688. //
  3689. // Set the variable for the wakeup
  3690. //
  3691. pAdapter->PoMgmt.bReceivedSetPowerD0= FALSE;
  3692. Status = NDIS_STATUS_SUCCESS;
  3693. break;
  3694. } while (FALSE);
  3695. EXIT();
  3696. return Status;
  3697. }
  3698. NDIS_STATUS
  3699. arpResume (
  3700. IN ARP1394_ADAPTER* pAdapter,
  3701. IN ARP_RESUME_CAUSE Cause,
  3702. IN PRM_STACK_RECORD pSR
  3703. )
  3704. /*++
  3705. This function manages the starting of the Resume Task.
  3706. The resume task can only be started once after receiving an AfNotify
  3707. and a Set Power.
  3708. However, an Unbind can come in and unbind the adapter in the middle of this.
  3709. This function does not start the resume if the adapter is already unbinding
  3710. --*/
  3711. {
  3712. BOOLEAN bSetPowerOnTask = FALSE;
  3713. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  3714. PTASK_POWER pSetPowerTask = NULL;
  3715. NDIS_STATUS TaskStatus;
  3716. ENTER ("arpResume", 0x3dddc538)
  3717. do
  3718. {
  3719. if (CHECK_POWER_STATE(pAdapter, ARPAD_POWER_NORMAL)== TRUE)
  3720. {
  3721. break;
  3722. }
  3723. LOCKOBJ (pAdapter, pSR);
  3724. if (Cause == Cause_SetPowerD0)
  3725. {
  3726. pAdapter->PoMgmt.bReceivedSetPowerD0 = TRUE;
  3727. }
  3728. //
  3729. // If we have already received an Unbind, then don't do anything.
  3730. //
  3731. if ( pAdapter->PoMgmt.bReceivedUnbind == FALSE)
  3732. {
  3733. //
  3734. // If we have not received an unbind,
  3735. // then this thread needs to all the work to
  3736. // reactivate the arp module.
  3737. //
  3738. bSetPowerOnTask = TRUE;
  3739. }
  3740. UNLOCKOBJ(pAdapter,pSR);
  3741. if (bSetPowerOnTask == FALSE)
  3742. {
  3743. break;
  3744. }
  3745. //
  3746. // Start the Set Power Task
  3747. //
  3748. Status = arpAllocateTask(
  3749. &pAdapter->Hdr, // pParentObject
  3750. arpTaskOnPower, // pfnHandler
  3751. 0, // Timeout
  3752. "Task: SetPower On", // szDescription
  3753. &(PRM_TASK)pSetPowerTask,
  3754. pSR
  3755. );
  3756. if (Status != NDIS_STATUS_SUCCESS || NULL == pSetPowerTask)
  3757. {
  3758. break;
  3759. }
  3760. pSetPowerTask->pStatus = &TaskStatus;
  3761. NdisResetEvent (&pAdapter->PoMgmt.Complete);
  3762. RmStartTask ((PRM_TASK)pSetPowerTask,0,pSR);
  3763. NdisWaitEvent (&pAdapter->PoMgmt.Complete, 0);
  3764. Status = TaskStatus;
  3765. } while (FALSE);
  3766. EXIT()
  3767. return Status;
  3768. }
  3769. NDIS_STATUS
  3770. arpNdSetPower (
  3771. ARP1394_ADAPTER *pAdapter,
  3772. PNET_DEVICE_POWER_STATE pPowerState,
  3773. PRM_STACK_RECORD pSR
  3774. )
  3775. /*++
  3776. Validates the event and passes it off to the correct function
  3777. --*/
  3778. {
  3779. ENTER("arpNdSetPower ", 0x21c4013a)
  3780. TASK_POWER *pSetPowerTask = NULL;
  3781. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  3782. NDIS_STATUS TaskStatus = NDIS_STATUS_NOT_SUPPORTED;
  3783. //
  3784. // The bridge is present.Close all the VCs if we are going to
  3785. // a low power or re-create all the VC if we are going to D0
  3786. //
  3787. if (NetDeviceStateD0 == (*pPowerState))
  3788. {
  3789. Status = arpResume(pAdapter, Cause_SetPowerD0, pSR);
  3790. }
  3791. else
  3792. {
  3793. Status = arpStandby(pAdapter, *pPowerState, pSR);
  3794. }
  3795. return Status;
  3796. }