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

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