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

11520 lines
330 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. co.c
  5. Abstract:
  6. ARP1394 connection-oriented handlers.
  7. Revision History:
  8. Who When What
  9. -------- -------- ----------------------------------------------
  10. josephj 12-01-98 Created
  11. Notes:
  12. --*/
  13. #include <precomp.h>
  14. //
  15. // File-specific debugging defaults.
  16. //
  17. #define TM_CURRENT TM_CO
  18. //=========================================================================
  19. // L O C A L P R O T O T Y P E S
  20. //
  21. // The following functions and typedefs are accessed only in this file.
  22. //
  23. //=========================================================================
  24. UINT
  25. arpRecvFifoReceivePacket(
  26. IN NDIS_HANDLE ProtocolBindingContext,
  27. IN NDIS_HANDLE ProtocolVcContext,
  28. IN PNDIS_PACKET pNdisPacket
  29. );
  30. VOID
  31. arpRecvFifoIncomingClose(
  32. IN NDIS_STATUS CloseStatus,
  33. IN NDIS_HANDLE ProtocolVcContext,
  34. IN PVOID pCloseData OPTIONAL,
  35. IN UINT Size OPTIONAL
  36. );
  37. VOID
  38. arpDestIncomingClose(
  39. IN NDIS_STATUS CloseStatus,
  40. IN NDIS_HANDLE ProtocolVcContext,
  41. IN PVOID pCloseData OPTIONAL,
  42. IN UINT Size OPTIONAL
  43. );
  44. VOID
  45. arpDestSendComplete(
  46. IN NDIS_STATUS Status,
  47. IN NDIS_HANDLE ProtocolVcContext,
  48. IN PNDIS_PACKET pNdisPacket
  49. );
  50. UINT
  51. arpDestReceivePacket(
  52. IN NDIS_HANDLE ProtocolBindingContext,
  53. IN NDIS_HANDLE ProtocolVcContext,
  54. IN PNDIS_PACKET pNdisPacket
  55. );
  56. NDIS_STATUS
  57. arpTaskUnloadEthDhcpEntry(
  58. IN struct _RM_TASK * pTask,
  59. IN RM_TASK_OPERATION Code,
  60. IN UINT_PTR UserParam,
  61. IN PRM_STACK_RECORD pSR
  62. );
  63. NDIS_STATUS
  64. arpInitializeIfPools(
  65. IN PARP1394_INTERFACE pIF,
  66. IN PRM_STACK_RECORD pSR
  67. );
  68. VOID
  69. arpDeInitializeIfPools(
  70. IN PARP1394_INTERFACE pIF,
  71. IN PRM_STACK_RECORD pSR
  72. );
  73. #if ARP_DEFERIFINIT
  74. MYBOOL
  75. arpIsAdapterConnected(
  76. IN PARP1394_ADAPTER pAdapter,
  77. IN PRM_STACK_RECORD pSR
  78. );
  79. #endif // ARP_DEFERIFINIT
  80. #if DBG
  81. VOID
  82. arpDbgDisplayMapping(
  83. IP_ADDRESS IpAddress,
  84. PNIC1394_DESTINATION pHwAddr,
  85. char * szPrefix
  86. );
  87. #define ARP_DUMP_MAPPING(_Ip, _Hw, _sz) \
  88. arpDbgDisplayMapping(_Ip, _Hw, _sz)
  89. #else // !DBG
  90. #define ARP_DUMP_MAPPING(_Ip, _Hw, _sz) \
  91. (0)
  92. #endif
  93. NDIS_STATUS
  94. arpSetupSpecialDest(
  95. IN PARP1394_INTERFACE pIF,
  96. IN NIC1394_ADDRESS_TYPE AddressType,
  97. IN PRM_TASK pParentTask,
  98. IN UINT PendCode,
  99. OUT PARPCB_DEST * ppSpecialDest,
  100. PRM_STACK_RECORD pSR
  101. );
  102. VOID
  103. arpTryAbortPrimaryIfTask(
  104. PARP1394_INTERFACE pIF,
  105. PRM_STACK_RECORD pSR
  106. );
  107. VOID
  108. arpDoLocalIpMaintenance(
  109. PARP1394_INTERFACE pIF,
  110. UINT CurrentTime,
  111. UINT SecondsSinceLastMaintenance,
  112. MYBOOL *pfProcessed,
  113. PRM_STACK_RECORD pSR
  114. );
  115. VOID
  116. arpDoRemoteIpMaintenance(
  117. PARP1394_INTERFACE pIF,
  118. UINT CurrentTime,
  119. UINT SecondsSinceLastMaintenance,
  120. MYBOOL *pfProcessed,
  121. PRM_STACK_RECORD pSR
  122. );
  123. VOID
  124. arpDoRemoteEthMaintenance(
  125. PARP1394_INTERFACE pIF,
  126. UINT CurrentTime,
  127. UINT SecondsSinceLastMaintenance,
  128. MYBOOL *pfProcessed,
  129. PRM_STACK_RECORD pSR
  130. );
  131. VOID
  132. arpDoMcapDbMaintenance(
  133. PARP1394_INTERFACE pIF,
  134. UINT CurrentTIme,
  135. UINT SecondsSinceLastMaintenance,
  136. MYBOOL *pfProcessed,
  137. PRM_STACK_RECORD pSR
  138. );
  139. VOID
  140. arpDoDhcpTableMaintenance(
  141. PARP1394_INTERFACE pIF,
  142. UINT CurrentTime,
  143. UINT SecondsSinceLastMaintenance,
  144. MYBOOL *pfProcessed,
  145. PRM_STACK_RECORD pSR
  146. );
  147. INT
  148. arpMaintainOneLocalIp(
  149. PRM_OBJECT_HEADER pHdr,
  150. PVOID pvContext,
  151. PRM_STACK_RECORD pSR
  152. );
  153. INT
  154. arpMaintainOneRemoteIp(
  155. PRM_OBJECT_HEADER pHdr,
  156. PVOID pvContext,
  157. PRM_STACK_RECORD pSR
  158. );
  159. INT
  160. arpMaintainOneRemoteEth(
  161. PRM_OBJECT_HEADER pHdr,
  162. PVOID pvContext,
  163. PRM_STACK_RECORD pSR
  164. );
  165. INT
  166. arpMaintainOneDhcpEntry(
  167. PRM_OBJECT_HEADER pHdr,
  168. PVOID pvContext, // Unused
  169. PRM_STACK_RECORD pSR
  170. );
  171. VOID
  172. arpUpdateLocalIpDest(
  173. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  174. IN PARPCB_LOCAL_IP pLocalIp,
  175. IN PARP_DEST_PARAMS pDestParams,
  176. PRM_STACK_RECORD pSR
  177. );
  178. UINT
  179. arpFindAssignedChannel(
  180. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  181. IN IP_ADDRESS IpAddress,
  182. IN UINT CurrentTime,
  183. PRM_STACK_RECORD pSR
  184. );
  185. UINT
  186. arpFindFreeChannel(
  187. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  188. PRM_STACK_RECORD pSR
  189. );
  190. VOID
  191. arpUpdateRemoteIpDest(
  192. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  193. IN PARPCB_REMOTE_IP pRemoteIp,
  194. IN PARP_DEST_PARAMS pDestParams,
  195. PRM_STACK_RECORD pSR
  196. );
  197. VOID
  198. arpRemoteDestDelete(
  199. PRM_OBJECT_HEADER pHdr,
  200. PRM_STACK_RECORD pSR
  201. );
  202. VOID
  203. arpRefreshArpEntry(
  204. PARPCB_REMOTE_IP pRemoteIp,
  205. PRM_STACK_RECORD pSR
  206. );
  207. INT
  208. arpMaintainArpCache(
  209. PRM_OBJECT_HEADER pHdr,
  210. PVOID pvContext, // Unused
  211. PRM_STACK_RECORD pSR
  212. );
  213. PRM_OBJECT_HEADER
  214. arpRemoteDestCreate(
  215. PRM_OBJECT_HEADER pParentObject,
  216. PVOID pCreateParams,
  217. PRM_STACK_RECORD pSR
  218. );
  219. PRM_OBJECT_HEADER
  220. arpDhcpTableEntryCreate(
  221. PRM_OBJECT_HEADER pParentObject,
  222. PVOID pCreateParams,
  223. PRM_STACK_RECORD pSR
  224. );
  225. VOID
  226. arpDhcpTableEntryDelete(
  227. PRM_OBJECT_HEADER pHdr,
  228. PRM_STACK_RECORD pSR
  229. );
  230. // ARP1394_INTERFACE_StaticInfo contains static information about
  231. // objects of type ARP1394_INTERFACE;
  232. //
  233. RM_STATIC_OBJECT_INFO
  234. ARP1394_INTERFACE_StaticInfo =
  235. {
  236. 0, // TypeUID
  237. 0, // TypeFlags
  238. "INTERFACE", // TypeName
  239. 0, // Timeout
  240. NULL, // pfnCreate
  241. arpObjectDelete, // pfnDelete
  242. NULL, // LockVerifier
  243. 0, // length of resource table
  244. NULL // Resource Table
  245. };
  246. // Specialized VC handlers for the RECEIVE_FIFO VC
  247. //
  248. ARP_STATIC_VC_INFO
  249. g_ArpRecvFifoVcStaticInfo =
  250. {
  251. // Description
  252. //
  253. "Recv FIFO VC", // Description
  254. //
  255. // Specialized VC handlers.
  256. //
  257. NULL, // NULL SendComplete handler.
  258. arpRecvFifoReceivePacket,
  259. arpRecvFifoIncomingClose,
  260. // VC_TYPE
  261. //
  262. ARPVCTYPE_RECV_FIFO,
  263. FALSE // FALSE == Is NOT Dest VC
  264. };
  265. // Specialized VC handlers for the BROADCAST VC
  266. //
  267. ARP_STATIC_VC_INFO
  268. g_ArpBroadcastChannelVcStaticInfo =
  269. {
  270. // Description
  271. //
  272. "Broadcast VC", // Description
  273. //
  274. // Specialized VC handlers.
  275. //
  276. // arpBroadcastChannelSendComplete,
  277. // arpBroadcastChannelReceivePacket,
  278. // arpBroadcastChannelIncomingClose,
  279. arpDestSendComplete,
  280. arpDestReceivePacket,
  281. arpDestIncomingClose,
  282. // VC_TYPE
  283. //
  284. ARPVCTYPE_BROADCAST_CHANNEL,
  285. TRUE // Is dest VC
  286. };
  287. // Specialized VC handlers for a send FIFO VC.
  288. //
  289. ARP_STATIC_VC_INFO
  290. g_ArpSendFifoVcStaticInfo =
  291. {
  292. // Description
  293. //
  294. "Send FIFO VC", // Description
  295. //
  296. // Specialized VC handlers.
  297. //
  298. // arpSendFifoSendComplete,
  299. // arpSendFifoIncomingClose,
  300. arpDestSendComplete,
  301. NULL, // NULL Recv Pkt handler.
  302. arpDestIncomingClose,
  303. // VC_TYPE
  304. //
  305. ARPVCTYPE_SEND_FIFO,
  306. TRUE // Is dest VC
  307. };
  308. // Specialized VC handlers for the MULTICHANNEL VC
  309. //
  310. ARP_STATIC_VC_INFO
  311. g_ArpMultiChannelVcStaticInfo =
  312. {
  313. // Description
  314. //
  315. "MultiChannel VC", // Description
  316. //
  317. // Specialized VC handlers.
  318. //
  319. NULL, // NULL Send complete handler.
  320. arpDestReceivePacket,
  321. arpDestIncomingClose,
  322. // arpMultiChannelReceivePacket,
  323. // arpMultiChannelIncomingClose,
  324. // VC_TYPE
  325. //
  326. ARPVCTYPE_MULTI_CHANNEL,
  327. TRUE // Is dest VC
  328. };
  329. // Specialized VC handlers for the ETHERNET VC
  330. //
  331. ARP_STATIC_VC_INFO
  332. g_ArpEthernetVcStaticInfo =
  333. {
  334. // Description
  335. //
  336. "Ethernet VC", // Description
  337. //
  338. // Specialized VC handlers.
  339. //
  340. // arpEthernetSendComplete,
  341. // arpEthernetIncomingClose,
  342. arpDestSendComplete,
  343. arpEthernetReceivePacket,
  344. arpDestIncomingClose,
  345. // VC_TYPE
  346. //
  347. ARPVCTYPE_ETHERNET,
  348. TRUE // Is dest VC
  349. };
  350. // Specialized VC handlers for RECV CHANNEL VCs
  351. //
  352. ARP_STATIC_VC_INFO
  353. g_ArpRecvChannelVcStaticInfo =
  354. {
  355. // Description
  356. //
  357. "Recv Channel VC", // Description
  358. //
  359. // Specialized VC handlers.
  360. //
  361. NULL, // NULL Send complete handler.
  362. // arpRecvChannelReceivePacket,
  363. // arpRecvChannelIncomingClose,
  364. arpDestReceivePacket,
  365. arpDestIncomingClose,
  366. // VC_TYPE
  367. //
  368. ARPVCTYPE_RECV_CHANNEL,
  369. TRUE // Is dest VC
  370. };
  371. // Specialized VC handlers for SEND CHANNEL VCs
  372. //
  373. ARP_STATIC_VC_INFO
  374. g_ArpSendChannelVcStaticInfo =
  375. {
  376. // Description
  377. //
  378. "Send Channel VC", // Description
  379. //
  380. // Specialized VC handlers.
  381. //
  382. // arpSendChannelSendComplete,
  383. // arpSendChannelIncomingClose,
  384. arpDestSendComplete,
  385. NULL, // NULL receive packet handler.
  386. arpDestIncomingClose,
  387. // VC_TYPE
  388. //
  389. ARPVCTYPE_SEND_CHANNEL,
  390. TRUE // Is dest VC
  391. };
  392. NDIS_STATUS
  393. arpCreateInterface(
  394. IN PARP1394_ADAPTER pAdapter,
  395. OUT PARP1394_INTERFACE *ppIF,
  396. IN PRM_STACK_RECORD pSR
  397. );
  398. VOID
  399. arpDeleteInterface(
  400. IN PARP1394_INTERFACE pIF,
  401. IN PRM_STACK_RECORD pSR
  402. );
  403. VOID
  404. arpActivateIf(
  405. PARP1394_INTERFACE pIF,
  406. PRM_TASK pCallingTask, // OPTIONAL
  407. UINT SuspendCode, // OPTIONAL
  408. PRM_STACK_RECORD pSR
  409. );
  410. VOID
  411. arpDeactivateIf(
  412. PARP1394_INTERFACE pIF,
  413. PRM_TASK pCallingTask, // OPTIONAL
  414. UINT SuspendCode, // OPTIONAL
  415. PRM_STACK_RECORD pSR
  416. );
  417. NDIS_STATUS
  418. arpCallIpAddInterface(
  419. IN ARP1394_INTERFACE* pIF,
  420. IN PRM_STACK_RECORD pSR
  421. );
  422. PRM_OBJECT_HEADER
  423. arpLocalIpCreate(
  424. PRM_OBJECT_HEADER pParentObject,
  425. PVOID pCreateParams,
  426. PRM_STACK_RECORD pSR
  427. );
  428. VOID
  429. arpLocalIpDelete(
  430. PRM_OBJECT_HEADER pHdr,
  431. PRM_STACK_RECORD pSR
  432. );
  433. PRM_OBJECT_HEADER
  434. arpRemoteIpCreate(
  435. PRM_OBJECT_HEADER pParentObject,
  436. PVOID pCreateParams,
  437. PRM_STACK_RECORD pSR
  438. );
  439. PRM_OBJECT_HEADER
  440. arpRemoteEthCreate(
  441. PRM_OBJECT_HEADER pParentObject,
  442. PVOID pCreateParams,
  443. PRM_STACK_RECORD pSR
  444. );
  445. VOID
  446. arpRemoteIpDelete(
  447. PRM_OBJECT_HEADER pHdr,
  448. PRM_STACK_RECORD pSR
  449. );
  450. VOID
  451. arpRemoteEthDelete(
  452. PRM_OBJECT_HEADER pHdr,
  453. PRM_STACK_RECORD pSR
  454. );
  455. PRM_OBJECT_HEADER
  456. arpDestinationCreate(
  457. PRM_OBJECT_HEADER pParentObject,
  458. PVOID pCreateParams,
  459. PRM_STACK_RECORD pSR
  460. );
  461. VOID
  462. arpDestinationDelete(
  463. PRM_OBJECT_HEADER pHdr,
  464. PRM_STACK_RECORD pSR
  465. );
  466. VOID
  467. arpAddStaticArpEntries(
  468. IN ARP1394_INTERFACE *pIF,
  469. IN PRM_STACK_RECORD pSR
  470. );
  471. MYBOOL
  472. arpNeedToCleanupDestVc(
  473. ARPCB_DEST *pDest // LOCKING LOCKOUT
  474. );
  475. VOID
  476. arpDeinitDestination(
  477. PARPCB_DEST pDest,
  478. MYBOOL fOnlyIfUnused,
  479. PRM_STACK_RECORD pSR
  480. );
  481. VOID
  482. arpDeinitRemoteIp(
  483. PARPCB_REMOTE_IP pRemoteIp,
  484. PRM_STACK_RECORD pSR
  485. );
  486. VOID
  487. arpDeinitRemoteEth(
  488. PARPCB_REMOTE_ETH pRemoteEth,
  489. PRM_STACK_RECORD pSR
  490. );
  491. //=========================================================================
  492. // C O N N E C T I O N - O R I E N T E D H A N D L E R S
  493. //=========================================================================
  494. VOID
  495. ArpCoAfRegisterNotify(
  496. IN NDIS_HANDLE ProtocolBindingContext,
  497. IN PCO_ADDRESS_FAMILY pAddressFamily
  498. )
  499. /*++
  500. Routine Description:
  501. This routine is called by NDIS when a Call manager registers its support
  502. for an Address Family over an adapter. If this is the Address Family we
  503. are interested in (1394), then we create and initialize an IP interface for
  504. this adapter.
  505. Arguments:
  506. ProtocolBindingContext - our context passed in NdisOpenAdapter, which is
  507. a pointer to our Adapter structure.
  508. pAddressFamily - points to a structure describing the Address Family
  509. being registered by a Call Manager.
  510. --*/
  511. {
  512. ENTER("CoAfRegisterNotify", 0x51041947)
  513. PARP1394_ADAPTER pAdapter = (PARP1394_ADAPTER) ProtocolBindingContext;
  514. NDIS_STATUS Status;
  515. RM_DECLARE_STACK_RECORD(sr)
  516. do
  517. {
  518. PRM_TASK pTask;
  519. PARP1394_INTERFACE pIF;
  520. // Check if this AF is interesting to us.
  521. //
  522. if ((pAddressFamily->AddressFamily != CO_ADDRESS_FAMILY_1394) ||
  523. (pAddressFamily->MajorVersion != NIC1394_AF_CURRENT_MAJOR_VERSION) ||
  524. (pAddressFamily->MinorVersion != NIC1394_AF_CURRENT_MINOR_VERSION))
  525. {
  526. TR_INFO(
  527. ("Uninteresting AF %d or MajVer %d or MinVer %d\n",
  528. pAddressFamily->AddressFamily,
  529. pAddressFamily->MajorVersion,
  530. pAddressFamily->MinorVersion));
  531. break;
  532. }
  533. LOCKOBJ(pAdapter, &sr);
  534. // If we already have an interface active, we ignore this notification.
  535. //
  536. if (pAdapter->pIF != NULL)
  537. {
  538. UNLOCKOBJ (pAdapter, &sr);
  539. ASSERT (CHECK_POWER_STATE (pAdapter,ARPAD_POWER_LOW_POWER) == FALSE);
  540. TR_WARN(
  541. ("pAdapter 0x%p, IF already created!\n",
  542. pAdapter));
  543. ASSERTEX(FALSE, pAdapter);
  544. break;
  545. }
  546. // Create Interface
  547. //
  548. Status = arpCreateInterface(
  549. pAdapter,
  550. &pIF,
  551. &sr
  552. );
  553. if (FAIL(Status))
  554. {
  555. break;
  556. }
  557. //
  558. // Allocate and start task to complete the interface initialization...
  559. //
  560. Status = arpAllocateTask(
  561. &pIF->Hdr, // pParentObject
  562. arpTaskInitInterface, // pfnHandler
  563. 0, // Timeout
  564. "Task: InitInterface", // szDescription
  565. &pTask,
  566. &sr
  567. );
  568. if (FAIL(Status))
  569. {
  570. TR_WARN(("FATAL: couldn't alloc init intf task!\n"));
  571. arpDeleteInterface(pIF, &sr );
  572. break;
  573. }
  574. pAdapter->pIF = pIF;
  575. arpSetPrimaryIfTask(pIF, pTask, ARPIF_PS_INITING, &sr);
  576. UNLOCKOBJ(pAdapter, &sr);
  577. RM_ASSERT_NOLOCKS(&sr);
  578. (VOID)RmStartTask(
  579. pTask,
  580. 0, // UserParam (unused)
  581. &sr
  582. );
  583. //
  584. // The InitializeTask will do all required cleanup on failure, including
  585. // deallocating the interface.
  586. //
  587. } while (FALSE);
  588. RmUnlockAll(&sr);
  589. RM_ASSERT_CLEAR(&sr);
  590. EXIT()
  591. }
  592. VOID
  593. ArpCoOpenAfComplete(
  594. IN NDIS_STATUS Status,
  595. IN NDIS_HANDLE ProtocolAfContext,
  596. IN NDIS_HANDLE NdisAfHandle
  597. )
  598. /*++
  599. Routine Description:
  600. NDIS calls this function to indicate completion of a previous call to
  601. NdisClOpenAddressFamily.
  602. Arguments:
  603. Status - return status of the open address family call.
  604. ProtocolAfContext - actually a pointer to our interface control block.
  605. NdisAfHandle - the new Ndis AF handle for this adapter.
  606. --*/
  607. {
  608. ENTER("OpenAfComplete", 0x86a3c14d)
  609. PARP1394_INTERFACE pIF = (PARP1394_INTERFACE) ProtocolAfContext;
  610. PARP1394_ADAPTER pAdapter = (PARP1394_ADAPTER) RM_PARENT_OBJECT(pIF);
  611. RM_DECLARE_STACK_RECORD(sr)
  612. TIMESTAMP("==>OpenAfComplete");
  613. // We expect a nonzero task here (the pActDeactTask), which we unpend
  614. // after filling in the Ndis Af Handle.
  615. //
  616. {
  617. TR_INFO((
  618. "AfCtxt=0x%lx, status=0x%lx, NdisAfHandle=0x%lx",
  619. ProtocolAfContext,
  620. Status,
  621. NdisAfHandle
  622. ));
  623. // We don't pass on NdisAfHandle -- instead we place it in pIF.
  624. //
  625. if (Status == NDIS_STATUS_SUCCESS)
  626. {
  627. LOCKOBJ(pIF, &sr);
  628. ASSERTEX(pIF->ndis.AfHandle == NULL, pIF);
  629. DBG_ADDASSOC(
  630. &pIF->Hdr, // pObject
  631. NdisAfHandle, // Instance1
  632. NULL, // Instance2
  633. ARPASSOC_IF_OPENAF, // AssociationID
  634. " Open AF NdisHandle=%p\n",// szFormat
  635. &sr
  636. );
  637. pIF->ndis.AfHandle = NdisAfHandle;
  638. UNLOCKOBJ(pIF, &sr);
  639. }
  640. // This could have been caused by a resume or a bind.
  641. // In each case, resume the appropriate task
  642. //
  643. if (CHECK_POWER_STATE (pAdapter, ARPAD_POWER_LOW_POWER) == TRUE)
  644. {
  645. RmResumeTask (pIF->PoMgmt.pAfPendingTask, (UINT_PTR)Status , &sr);
  646. }
  647. else
  648. {
  649. // We expect a nonzero task here (UNbind task), which we unpend.
  650. // No need to grab locks or anything at this stage.
  651. //
  652. RmResumeTask(pIF->pActDeactTask, (UINT_PTR) Status, &sr);
  653. }
  654. }
  655. RM_ASSERT_CLEAR(&sr)
  656. TIMESTAMPX("<==OpenAfComplete");
  657. EXIT()
  658. }
  659. VOID
  660. ArpCoCloseAfComplete(
  661. IN NDIS_STATUS Status,
  662. IN NDIS_HANDLE ProtocolAfContext
  663. )
  664. /*++
  665. Routine Description:
  666. NDIS calls this function to indicate completion of a previous call to
  667. NdisClCloseAddressFamily.
  668. Arguments:
  669. Status - return status of the close address family call.
  670. ProtocolAfContext - actually a pointer to our interface control block.
  671. --*/
  672. {
  673. ENTER("CloseAfComplete", 0x0cc281db)
  674. PARP1394_INTERFACE pIF = (PARP1394_INTERFACE) ProtocolAfContext;
  675. PARP1394_ADAPTER pAdapter=(ARP1394_ADAPTER*)RM_PARENT_OBJECT(pIF);
  676. RM_DECLARE_STACK_RECORD(sr)
  677. TIMESTAMP("==>ArpCoCloseAfComlete");
  678. // This could happen because of a Set Power to a low power state.
  679. // of an actual unbind. In each case, resume the task that would
  680. // have been waiting for the CloseAf to complete.
  681. //
  682. if (CHECK_POWER_STATE (pAdapter, ARPAD_POWER_NORMAL) == TRUE ||
  683. pAdapter->PoMgmt.bFailedResume )
  684. {
  685. // We expect a nonzero task here (UNbind task), which we unpend.
  686. // No need to grab locks or anything at this stage.
  687. //
  688. RmResumeTask(pIF->pActDeactTask, (UINT_PTR) Status, &sr);
  689. }
  690. else
  691. {
  692. RmResumeTask (pIF->PoMgmt.pAfPendingTask, (UINT_PTR)Status , &sr);
  693. }
  694. RM_ASSERT_CLEAR(&sr)
  695. TIMESTAMP("<==ArpCoCloseAfComlete");
  696. EXIT()
  697. }
  698. VOID
  699. ArpCoSendComplete(
  700. IN NDIS_STATUS Status,
  701. IN NDIS_HANDLE ProtocolVcContext,
  702. IN PNDIS_PACKET pNdisPacket
  703. )
  704. /*++
  705. Routine Description:
  706. NDIS calls this function to indicate completion of a previous call to
  707. NdisCoSendPackets.
  708. Arguments:
  709. Status - return status of the send packet call.
  710. ProtocolVcContext - actually a pointer to our context for this VC. This
  711. is either a pointer to an ARPCB_DEST (if the VC is
  712. for a call to a remote FIFO address or channel),
  713. or to ARP1394_INTERFACE (if the VC is for a call to the
  714. single RECEIVE FIFO for this interface.)
  715. pNdisPacket - The packet that was sent.
  716. --*/
  717. {
  718. PARP_VC_HEADER pVcHdr = (PARP_VC_HEADER) ProtocolVcContext;
  719. //
  720. // We use the special status NDIS_STATUS_NOT_RESETTABLE to indicate
  721. // that the an encapsulation buffer hasn't been inserted into the IP packet.
  722. // (See 2/5/2000 notes.txt entry). So we want to make sure that the miniport
  723. // doesn't return this status.
  724. //
  725. ASSERT(Status != NDIS_STATUS_NOT_RESETTABLE);
  726. pVcHdr->pStaticInfo->CoSendCompleteHandler(
  727. Status,
  728. ProtocolVcContext,
  729. pNdisPacket
  730. );
  731. }
  732. VOID
  733. ArpCoStatus(
  734. IN NDIS_HANDLE ProtocolBindingContext,
  735. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  736. IN NDIS_STATUS GeneralStatus,
  737. IN PVOID pStatusBuffer,
  738. IN UINT StatusBufferSize
  739. )
  740. /*++
  741. Routine Description:
  742. This routine is called when the miniport indicates a status
  743. change, possibly on a VC.
  744. We ignore this.
  745. Arguments:
  746. <Ignored>
  747. --*/
  748. {
  749. PARP1394_ADAPTER pAdapter = (PARP1394_ADAPTER)ProtocolBindingContext;
  750. PNIC1394_STATUS_BUFFER p1394StatusBuffer = (PNIC1394_STATUS_BUFFER )pStatusBuffer;
  751. do
  752. {
  753. if (CHECK_AD_ACTIVE_STATE(pAdapter, ARPAD_AS_ACTIVATED)==FALSE)
  754. {
  755. break;
  756. }
  757. if (GeneralStatus != NDIS_STATUS_MEDIA_SPECIFIC_INDICATION)
  758. {
  759. break;
  760. }
  761. if ((p1394StatusBuffer->Signature == NIC1394_MEDIA_SPECIFIC) &&
  762. (p1394StatusBuffer->Event == NIC1394_EVENT_BUS_RESET ))
  763. {
  764. arpNdProcessBusReset(pAdapter);
  765. break;
  766. }
  767. }while (FALSE);
  768. }
  769. UINT
  770. ArpCoReceivePacket(
  771. IN NDIS_HANDLE ProtocolBindingContext,
  772. IN NDIS_HANDLE ProtocolVcContext,
  773. IN PNDIS_PACKET pNdisPacket
  774. )
  775. /*++
  776. HOT PATH
  777. Routine Description:
  778. This is routine is called when a packet is received on a VC owned
  779. by the arp module. If it is an ARP/MCAP-related packet, we consume it ourselves.
  780. Otherwise, we pass it up to IP.
  781. Arguments:
  782. ProtocolBindingContext - Actually a pointer to our Adapter structure
  783. ProtocolVcContext - Actually a pointer to our VC context, which is
  784. either ARP1394_INTERFACE (for the recv FIFO vc)
  785. or ARPCB_DEST (for vcs to remote destinations or
  786. to channels).
  787. pNdisPacket - NDIS packet being received.
  788. Return Value:
  789. 0 -- If we consume the packet ourselves (because we don't hold on to ARP/MCAP
  790. OR if we're calling the IP's IPRcvHandler (in which case we're ASSUMING IP
  791. doesn't hold on to the packet either).
  792. Set by IP -- if we're calling IP's IPRcvPktHandler
  793. --*/
  794. {
  795. PARP_VC_HEADER pVcHdr = (PARP_VC_HEADER) ProtocolVcContext;
  796. UINT Ret;
  797. ARP_INIT_REENTRANCY_COUNT()
  798. ARP_INC_REENTRANCY();
  799. Ret = pVcHdr->pStaticInfo->CoReceivePacketHandler(
  800. ProtocolBindingContext,
  801. ProtocolVcContext,
  802. pNdisPacket
  803. );
  804. ARP_DEC_REENTRANCY();
  805. return Ret;
  806. }
  807. NDIS_STATUS
  808. ArpCoCreateVc(
  809. IN NDIS_HANDLE ProtocolAfContext,
  810. IN NDIS_HANDLE NdisVcHandle,
  811. OUT PNDIS_HANDLE pProtocolVcContext
  812. )
  813. /*++
  814. Routine Description:
  815. Entry point called by NDIS when the Call Manager wants to create
  816. a new endpoint (VC). We don't expect this to be called, because all our calls
  817. are outgoing.
  818. Arguments:
  819. <ignored>
  820. Return Value:
  821. NDIS_STATUS_FAILURE
  822. --*/
  823. {
  824. // We don't expect this, because all our calls are outgoing.
  825. //
  826. ASSERT(!"Unexpected");
  827. return NDIS_STATUS_FAILURE;
  828. }
  829. NDIS_STATUS
  830. ArpCoDeleteVc(
  831. IN NDIS_HANDLE ProtocolVcContext
  832. )
  833. /*++
  834. Routine Description:
  835. Entry point called by NDIS when the Call Manager wants to delete a VC for
  836. an INCOMING call. We don't expect this to be called, because all our calls
  837. are outgoing.
  838. Arguments:
  839. <ignored>
  840. Return Value:
  841. NDIS_STATUS_FAILURE
  842. --*/
  843. {
  844. ASSERT(!"Unexpected");
  845. return 0;
  846. }
  847. NDIS_STATUS
  848. ArpCoIncomingCall(
  849. IN NDIS_HANDLE ProtocolSapContext,
  850. IN NDIS_HANDLE ProtocolVcContext,
  851. IN OUT PCO_CALL_PARAMETERS pCallParameters
  852. )
  853. /*++
  854. Routine Description:
  855. Entry point called by NDIS when the Call Manager wants to indicate an
  856. INCOMING call. We don't expect this to be called, because all our calls
  857. are outgoing.
  858. Arguments:
  859. <ignored>
  860. Return Value:
  861. NDIS_STATUS_FAILURE
  862. --*/
  863. {
  864. ASSERT(!"Unexpected");
  865. return NDIS_STATUS_FAILURE;
  866. }
  867. VOID
  868. ArpCoCallConnected(
  869. IN NDIS_HANDLE ProtocolVcContext
  870. )
  871. /*++
  872. Routine Description:
  873. Entry point called by NDIS when the Call Manager wants to indicate that an
  874. INCOMING call has reach the connected state. We don't expect this to be called,
  875. because all our calls are outgoing.
  876. Arguments:
  877. <ignored>
  878. --*/
  879. {
  880. ASSERT(!"Unexpected");
  881. }
  882. VOID
  883. ArpCoIncomingClose(
  884. IN NDIS_STATUS CloseStatus,
  885. IN NDIS_HANDLE ProtocolVcContext,
  886. IN PVOID pCloseData OPTIONAL,
  887. IN UINT Size OPTIONAL
  888. )
  889. /*++
  890. Routine Description:
  891. This handler is called by NDIS when a call is closed unsolicited,
  892. either by the network or by the remote peer. We need to unload all resources
  893. associated with this VC.
  894. Arguments:
  895. CloseStatus - Reason for the call clearing
  896. ProtocolVcContext - A pointer to the our context for this VC.
  897. pCloseData - (Ignored)
  898. Size - (Ignored)
  899. --*/
  900. {
  901. PARP_VC_HEADER pVcHdr = (PARP_VC_HEADER) ProtocolVcContext;
  902. pVcHdr->pStaticInfo->ClIncomingCloseCallHandler(
  903. CloseStatus,
  904. ProtocolVcContext,
  905. pCloseData,
  906. Size
  907. );
  908. }
  909. VOID
  910. ArpCoQosChange(
  911. IN NDIS_HANDLE ProtocolVcContext,
  912. IN PCO_CALL_PARAMETERS pCallParameters
  913. )
  914. /*++
  915. Routine Description:
  916. This handler is called by NDIS if the remote peer modifies call parameters
  917. "on the fly", i.e. after the call is established and running.
  918. We do not expect or support this.
  919. Arguments:
  920. ProtocolVcContext - Pointer to our context for this VC
  921. pCallParameters - updated call parameters.
  922. --*/
  923. {
  924. ASSERT(!"Unimplemented");
  925. }
  926. VOID
  927. ArpCoMakeCallComplete(
  928. IN NDIS_STATUS Status,
  929. IN NDIS_HANDLE ProtocolVcContext,
  930. IN NDIS_HANDLE NdisPartyHandle OPTIONAL,
  931. IN PCO_CALL_PARAMETERS pCallParameters
  932. )
  933. /*++
  934. Routine Description:
  935. This routine is called by NDIS when an outgoing call request (NdisClMakeCall)
  936. has completed. The "Status" parameter indicates whether the call was
  937. successful or not.
  938. Arguments:
  939. Status - Result of the NdisClMakeCall
  940. ProtocolVcContext - Pointer to our context for this VC.
  941. NdisPartyHandle - Not used (no point-to-multipoint calls)
  942. pCallParameters - Pointer to call parameters
  943. --*/
  944. {
  945. PRM_TASK pTask;
  946. PARP1394_INTERFACE pIF;
  947. PARP_VC_HEADER pVcHdr = (PARP_VC_HEADER) ProtocolVcContext;
  948. RM_DECLARE_STACK_RECORD(sr)
  949. if (pVcHdr->pStaticInfo->IsDestVc)
  950. {
  951. //
  952. // This is destination VC (either send FIFO or channel)
  953. //
  954. PARPCB_DEST pDest;
  955. pDest = CONTAINING_RECORD(pVcHdr, ARPCB_DEST, VcHdr);
  956. ASSERT_VALID_DEST(pDest);
  957. pIF = (PARP1394_INTERFACE) RM_PARENT_OBJECT(pDest);
  958. if (pVcHdr->pStaticInfo->VcType == ARPVCTYPE_SEND_FIFO)
  959. {
  960. DBGMARK(0x8a1c2e4d);
  961. if (Status == NDIS_STATUS_SUCCESS)
  962. {
  963. LOGSTATS_SuccessfulSendFifoMakeCalls(pIF);
  964. }
  965. else
  966. {
  967. LOGSTATS_FailedSendFifoMakeCalls(pIF);
  968. }
  969. }
  970. else
  971. {
  972. //
  973. // NOTE -- Ethernet is treated as "channel"
  974. //
  975. DBGMARK(0xb803909b);
  976. if (Status == NDIS_STATUS_SUCCESS)
  977. {
  978. LOGSTATS_SuccessfulChannelMakeCalls(pIF);
  979. }
  980. else
  981. {
  982. LOGSTATS_FailedChannelMakeCalls(pIF);
  983. }
  984. }
  985. }
  986. else
  987. {
  988. DBGMARK(0xd32d028c);
  989. ASSERT(pVcHdr->pStaticInfo->VcType == ARPVCTYPE_RECV_FIFO);
  990. pIF = CONTAINING_RECORD( pVcHdr, ARP1394_INTERFACE, recvinfo.VcHdr);
  991. ASSERT_VALID_INTERFACE(pIF);
  992. }
  993. pTask = pVcHdr->pMakeCallTask;
  994. ASSERT(pTask != NULL);
  995. RmResumeTask(pTask, (UINT_PTR) Status, &sr);
  996. RM_ASSERT_CLEAR(&sr)
  997. }
  998. VOID
  999. ArpCoCloseCallComplete(
  1000. IN NDIS_STATUS Status,
  1001. IN NDIS_HANDLE ProtocolVcContext,
  1002. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL
  1003. )
  1004. /*++
  1005. Routine Description:
  1006. This routine handles completion of a previous NdisClCloseCall.
  1007. We delete the VC on which the call was just closed, regardless of the value
  1008. of Status.
  1009. Arguments:
  1010. Status - Status of the Close Call.
  1011. ProtocolVcContext - Pointer to our contex for this VC.
  1012. ProtocolPartyContext - Not used.
  1013. --*/
  1014. {
  1015. PRM_TASK pTask;
  1016. PARP_VC_HEADER pVcHdr = (PARP_VC_HEADER) ProtocolVcContext;
  1017. RM_DECLARE_STACK_RECORD(sr)
  1018. DBGMARK(0x0ecb7bd5);
  1019. pTask = pVcHdr->pCleanupCallTask;
  1020. ASSERT(pTask != NULL);
  1021. RmResumeTask(pTask, (UINT_PTR) Status, &sr);
  1022. RM_ASSERT_CLEAR(&sr)
  1023. }
  1024. VOID
  1025. ArpCoModifyQosComplete(
  1026. IN NDIS_STATUS Status,
  1027. IN NDIS_HANDLE ProtocolVcContext,
  1028. IN PCO_CALL_PARAMETERS pCallParameters
  1029. )
  1030. /*++
  1031. Routine Description:
  1032. This routine is called by NDIS on completion of a previous call to
  1033. NdisClModifyCallQoS. Since we don't call this, this should never
  1034. get called.
  1035. Arguments:
  1036. <Don't care>
  1037. --*/
  1038. {
  1039. ASSERT(!"Unexpected");
  1040. }
  1041. NDIS_STATUS
  1042. ArpCoRequest(
  1043. IN NDIS_HANDLE ProtocolAfContext,
  1044. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  1045. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
  1046. IN OUT PNDIS_REQUEST pNdisRequest
  1047. )
  1048. /*++
  1049. Routine Description:
  1050. This routine is called by NDIS when our Call Manager sends us an
  1051. NDIS Request. NDIS Requests that are of significance to us are:
  1052. - OID_CO_AF_CLOSE
  1053. The Call Manager wants us to shut down this Interface.
  1054. We ignore all other OIDs.
  1055. Arguments:
  1056. ProtocolAfContext - Our context for the Address Family binding.
  1057. ProtocolVcContext - Our context for a VC.
  1058. ProtocolPartyContext - Our context for a Party. Since we don't do
  1059. PMP, this is ignored (must be NULL).
  1060. pNdisRequest - Pointer to the NDIS Request.
  1061. Return Value:
  1062. NDIS_STATUS_SUCCESS if we recognized the OID
  1063. NDIS_STATUS_NOT_RECOGNIZED if we didn't.
  1064. TODO: handle AF_CLOSE
  1065. --*/
  1066. {
  1067. NDIS_STATUS Status = NDIS_STATUS_NOT_RECOGNIZED;
  1068. ENTER("ArpCoRequest", 0x0d705cb5)
  1069. PARP1394_INTERFACE pIF = (PARP1394_INTERFACE) ProtocolAfContext;
  1070. RM_DECLARE_STACK_RECORD(sr)
  1071. if (pNdisRequest->RequestType == NdisRequestSetInformation)
  1072. {
  1073. switch (pNdisRequest->DATA.SET_INFORMATION.Oid)
  1074. {
  1075. case OID_CO_AF_CLOSE:
  1076. // TODO -- initiate shutdown of interface.
  1077. // But I don't think we will actually ever get this from
  1078. // NIC1394!
  1079. //
  1080. ASSERT(!"Unimplemented!");
  1081. Status = NDIS_STATUS_SUCCESS;
  1082. break;
  1083. default:
  1084. ASSERT(!"Unexpected OID from NIC1394!");
  1085. Status = NDIS_STATUS_FAILURE;
  1086. break;
  1087. }
  1088. }
  1089. TR_INFO((
  1090. "Called. pIF=0x%p. pReq=0x%p. Oid=0x%lu. Return status=0x%lx\n",
  1091. pIF,
  1092. pNdisRequest->RequestType,
  1093. pNdisRequest->DATA.SET_INFORMATION.Oid,
  1094. Status
  1095. ));
  1096. RM_ASSERT_CLEAR(&sr);
  1097. EXIT()
  1098. return (Status);
  1099. }
  1100. VOID
  1101. ArpCoRequestComplete(
  1102. IN NDIS_STATUS Status,
  1103. IN NDIS_HANDLE ProtocolAfContext,
  1104. IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
  1105. IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
  1106. IN PNDIS_REQUEST pNdisRequest
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. This routine is called by NDIS when a previous call to NdisCoRequest
  1111. that had pended, is complete. We handle this based on the request
  1112. we had sent, which has to be one of:
  1113. - OID_NIC1394_LOCAL_NODE_INFO
  1114. Get NIC1394 adapter information.
  1115. - OID_NIC1394_VC_INFO
  1116. Get updated NIC1394 information about this VC.
  1117. Arguments:
  1118. Status - Status of the Request.
  1119. ProtocolAfContext - Our context for the Address Family binding.
  1120. ProtocolVcContext - Our context for a VC.
  1121. ProtocolPartyContext - Our context for a Party. Since we don't do
  1122. PMP, this is ignored (must be NULL).
  1123. pNdisRequest - Pointer to the NDIS Request.
  1124. --*/
  1125. {
  1126. //
  1127. // TODO: unimplemented.
  1128. //
  1129. }
  1130. //=========================================================================
  1131. // P R I V A T E F U N C T I O N S
  1132. //
  1133. //=========================================================================
  1134. NDIS_STATUS
  1135. arpTaskInitInterface(
  1136. IN struct _RM_TASK * pTask,
  1137. IN RM_TASK_OPERATION Code,
  1138. IN UINT_PTR UserParam,
  1139. IN PRM_STACK_RECORD pSR
  1140. )
  1141. /*++
  1142. Routine Description:
  1143. Task handler responsible for loading a newly-created IP interface.
  1144. This is a primary task for the interface object.
  1145. Arguments:
  1146. UserParam for (Code == RM_TASKOP_START) : unused
  1147. --*/
  1148. {
  1149. NDIS_STATUS Status;
  1150. PARP1394_INTERFACE pIF;
  1151. ENTER("TaskInitInterface", 0x4d42506c)
  1152. // Following are the list of pending states for this task.
  1153. //
  1154. enum
  1155. {
  1156. PEND_InitAdapterComplete,
  1157. PEND_ActivateIfComplete,
  1158. PEND_DeinitIfOnFailureComplete
  1159. };
  1160. Status = NDIS_STATUS_FAILURE;
  1161. pIF = (PARP1394_INTERFACE) RM_PARENT_OBJECT(pTask);
  1162. switch(Code)
  1163. {
  1164. case RM_TASKOP_START:
  1165. {
  1166. CO_ADDRESS_FAMILY AddressFamily;
  1167. //
  1168. // We expect to ALREADY be the active primary task.
  1169. // No need to get the IF lock to do this check...
  1170. //
  1171. if (pIF->pPrimaryTask != pTask)
  1172. {
  1173. ASSERT(!"start: we are not the active primary task!");
  1174. Status = NDIS_STATUS_FAILURE;
  1175. break;
  1176. }
  1177. //
  1178. // Determine if adapter initialization is ongoing. If it is, we need
  1179. // to wait for it to complete.
  1180. //
  1181. {
  1182. PARP1394_ADAPTER pAdapter;
  1183. PRM_TASK pAdapterInitTask;
  1184. // No need to lock pIF to get pAdapter...
  1185. //
  1186. pAdapter = (PARP1394_ADAPTER) RM_PARENT_OBJECT(pIF);
  1187. LOCKOBJ(pAdapter, pSR);
  1188. if (CHECK_AD_PRIMARY_STATE(pAdapter, ARPAD_PS_INITING))
  1189. {
  1190. pAdapterInitTask = pAdapter->bind.pPrimaryTask;
  1191. ASSERT(pAdapterInitTask->pfnHandler
  1192. == arpTaskInitializeAdapter);
  1193. RmTmpReferenceObject(&pAdapterInitTask->Hdr, pSR);
  1194. OBJLOG0(
  1195. pIF,
  1196. "Waiting for adapter init to complere.\n"
  1197. );
  1198. Status = NDIS_STATUS_PENDING;
  1199. }
  1200. else
  1201. {
  1202. pAdapterInitTask = NULL;
  1203. if (CHECK_AD_PRIMARY_STATE(pAdapter, ARPAD_PS_INITED))
  1204. {
  1205. Status = NDIS_STATUS_SUCCESS;
  1206. }
  1207. else
  1208. {
  1209. OBJLOG1(
  1210. pIF,
  1211. "Failing init because adapter state(0x%x) is not INITED.\n",
  1212. GET_AD_PRIMARY_STATE(pAdapter)
  1213. );
  1214. Status = NDIS_STATUS_FAILURE;
  1215. }
  1216. }
  1217. UNLOCKOBJ(pAdapter, pSR);
  1218. RM_ASSERT_NOLOCKS(pSR);
  1219. if (pAdapterInitTask != NULL)
  1220. {
  1221. RmPendTaskOnOtherTask(
  1222. pTask,
  1223. PEND_InitAdapterComplete,
  1224. pAdapterInitTask,
  1225. pSR
  1226. );
  1227. RmTmpDereferenceObject(&pAdapterInitTask->Hdr, pSR);
  1228. }
  1229. }
  1230. if (!PEND(Status) && !FAIL(Status))
  1231. {
  1232. //
  1233. // Activate the interface...
  1234. //
  1235. arpActivateIf(pIF, pTask, PEND_ActivateIfComplete, pSR);
  1236. Status = NDIS_STATUS_PENDING;
  1237. }
  1238. }
  1239. break;
  1240. case RM_TASKOP_PENDCOMPLETE:
  1241. {
  1242. Status = (NDIS_STATUS) UserParam;
  1243. switch(RM_PEND_CODE(pTask))
  1244. {
  1245. case PEND_InitAdapterComplete:
  1246. {
  1247. //
  1248. // Activate the interface...
  1249. //
  1250. //
  1251. if (!FAIL(Status))
  1252. {
  1253. arpActivateIf(pIF, pTask, PEND_ActivateIfComplete, pSR);
  1254. Status = NDIS_STATUS_PENDING;
  1255. }
  1256. }
  1257. break;
  1258. case PEND_ActivateIfComplete:
  1259. {
  1260. LOCKOBJ(pIF, pSR);
  1261. if (FAIL(Status))
  1262. {
  1263. arpClearPrimaryIfTask(pIF, pTask, ARPIF_PS_FAILEDINIT, pSR);
  1264. UNLOCKOBJ(pIF, pSR);
  1265. arpDeinitIf(
  1266. pIF,
  1267. pTask, // pCallingTask
  1268. PEND_DeinitIfOnFailureComplete,
  1269. pSR
  1270. );
  1271. Status = NDIS_STATUS_PENDING;
  1272. }
  1273. else
  1274. {
  1275. //
  1276. // Successful activation. Clear the primary task
  1277. // and set the primary state appropriately.
  1278. //
  1279. arpClearPrimaryIfTask(pIF, pTask, ARPIF_PS_INITED, pSR);
  1280. UNLOCKOBJ(pIF, pSR);
  1281. }
  1282. } // end case PEND_ActivateIfComplete
  1283. break;
  1284. case PEND_DeinitIfOnFailureComplete:
  1285. {
  1286. // We expect pIF to be deallocated...
  1287. //
  1288. ASSERT(RM_IS_ZOMBIE(pIF));
  1289. //
  1290. // We ignore the return status of shutdown inteface.
  1291. // and set Status to failure, because it is
  1292. // the init interface task that is failing.
  1293. //
  1294. Status = NDIS_STATUS_FAILURE;
  1295. }
  1296. break;
  1297. default:
  1298. {
  1299. ASSERTEX(!"Unknown pend op", pTask);
  1300. }
  1301. break;
  1302. } // end switch(RM_PEND_CODE(pTask))
  1303. } // case RM_TASKOP_PENDCOMPLETE
  1304. break;
  1305. case RM_TASKOP_END:
  1306. {
  1307. //
  1308. // Nothing to do here. (Debug) Do some checking.
  1309. //
  1310. #if (DBG)
  1311. Status = (NDIS_STATUS) UserParam;
  1312. if (FAIL(Status))
  1313. {
  1314. ASSERT(RM_IS_ZOMBIE(pIF));
  1315. }
  1316. ASSERT(pIF->pPrimaryTask != pTask);
  1317. #endif // DBG
  1318. }
  1319. break;
  1320. default:
  1321. {
  1322. ASSERTEX(!"Unexpected task op", pTask);
  1323. }
  1324. break;
  1325. } // switch (Code)
  1326. RM_ASSERT_NOLOCKS(pSR);
  1327. EXIT()
  1328. return Status;
  1329. }
  1330. NDIS_STATUS
  1331. arpTaskActivateInterface(
  1332. IN struct _RM_TASK * pTask,
  1333. IN RM_TASK_OPERATION Code,
  1334. IN UINT_PTR UserParam,
  1335. IN PRM_STACK_RECORD pSR
  1336. )
  1337. /*++
  1338. Routine Description:
  1339. Task handler responsible for activating an already initialized IP interface.
  1340. Activating consists of:
  1341. - Reading configuration information
  1342. - Opening the address family
  1343. - Initiating the recv FIFO call
  1344. Arguments:
  1345. UserParam for (Code == RM_TASKOP_START) : unused
  1346. --*/
  1347. {
  1348. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1349. PARP1394_INTERFACE pIF = (PARP1394_INTERFACE) RM_PARENT_OBJECT(pTask);
  1350. PARP1394_ADAPTER pAdapter;
  1351. ENTER("TaskActivateInterface", 0x950cb22e)
  1352. // Following are the list of pending states for this task.
  1353. //
  1354. enum
  1355. {
  1356. PEND_OpenAF,
  1357. PEND_SetupBroadcastChannel,
  1358. PEND_SetupReceiveVc,
  1359. PEND_SetupMultiChannel,
  1360. PEND_SetupEthernetVc
  1361. };
  1362. // No need to lock pIF to get pAdapter...
  1363. //
  1364. pAdapter = (PARP1394_ADAPTER) RM_PARENT_OBJECT(pIF);
  1365. switch(Code)
  1366. {
  1367. case RM_TASKOP_START:
  1368. {
  1369. CO_ADDRESS_FAMILY AddressFamily;
  1370. TIMESTAMP("===ActivateIF: Starting");
  1371. // Fail initialization if the adapter is not INITED.
  1372. //
  1373. {
  1374. LOCKOBJ(pAdapter, pSR);
  1375. if (!CHECK_AD_PRIMARY_STATE(pAdapter, ARPAD_PS_INITED))
  1376. {
  1377. OBJLOG1(
  1378. pIF,
  1379. "Failing init because adapter state(0x%x) is not INITED.\n",
  1380. GET_AD_PRIMARY_STATE(pAdapter)
  1381. );
  1382. Status = NDIS_STATUS_FAILURE;
  1383. UNLOCKOBJ(pAdapter, pSR);
  1384. break;
  1385. }
  1386. UNLOCKOBJ(pAdapter, pSR);
  1387. }
  1388. LOCKOBJ(pIF, pSR);
  1389. if (pIF->pActDeactTask != NULL)
  1390. {
  1391. // This should never happen, because the Activate task is
  1392. // always started by an active primary task, and at most one primary
  1393. // task is active at any point of time.
  1394. //
  1395. ASSERTEX(!"start: activate/deactivate task exists!", pIF);
  1396. Status = NDIS_STATUS_FAILURE;
  1397. UNLOCKOBJ(pIF, pSR);
  1398. break;
  1399. }
  1400. arpSetSecondaryIfTask(pIF, pTask, ARPIF_AS_ACTIVATING, pSR);
  1401. // FIRST, we have to re-enable all the groups in the
  1402. // IF structure, which may be disabled if this activation
  1403. // is happening after a deactivation...
  1404. //
  1405. RmEnableGroup(&pIF->LocalIpGroup, pSR);
  1406. RmEnableGroup(&pIF->RemoteIpGroup, pSR);
  1407. if (ARP_BRIDGE_ENABLED(pAdapter))
  1408. {
  1409. RmEnableGroup(&pIF->RemoteEthGroup, pSR);
  1410. RmEnableGroup (&pIF->EthDhcpGroup, pSR);
  1411. }
  1412. RmEnableGroup(&pIF->DestinationGroup, pSR);
  1413. UNLOCKOBJ(pIF, pSR);
  1414. // Pick up configuration info for this interface.
  1415. //
  1416. Status = arpCfgGetInterfaceConfiguration(
  1417. pIF,
  1418. pSR
  1419. );
  1420. if (FAIL(Status))
  1421. {
  1422. OBJLOG1(pIF, "Cannot open IF configuration. Status=0x%lx\n", Status);
  1423. break;
  1424. }
  1425. //
  1426. // Suspend task and call NdisClOpenAddressFamily...
  1427. //
  1428. NdisZeroMemory(&AddressFamily, sizeof(AddressFamily));
  1429. AddressFamily.AddressFamily = CO_ADDRESS_FAMILY_1394;
  1430. AddressFamily.MajorVersion = NIC1394_AF_CURRENT_MAJOR_VERSION;
  1431. AddressFamily.MinorVersion = NIC1394_AF_CURRENT_MINOR_VERSION;
  1432. RmSuspendTask(pTask, PEND_OpenAF, pSR);
  1433. RM_ASSERT_NOLOCKS(pSR);
  1434. TIMESTAMP("===ActivateIF: Calling NdisClOpenAddressFamily");
  1435. Status = NdisClOpenAddressFamily(
  1436. pIF->ndis.AdapterHandle,
  1437. &AddressFamily,
  1438. (NDIS_HANDLE)pIF,
  1439. &ArpGlobals.ndis.CC,
  1440. sizeof(ArpGlobals.ndis.CC),
  1441. &(pIF->ndis.AfHandle)
  1442. );
  1443. if (Status != NDIS_STATUS_PENDING)
  1444. {
  1445. ArpCoOpenAfComplete(
  1446. Status,
  1447. (NDIS_HANDLE)pIF,
  1448. pIF->ndis.AfHandle
  1449. );
  1450. }
  1451. Status = NDIS_STATUS_PENDING;
  1452. }
  1453. break;
  1454. case RM_TASKOP_PENDCOMPLETE:
  1455. {
  1456. Status = (NDIS_STATUS) UserParam;
  1457. switch(RM_PEND_CODE(pTask))
  1458. {
  1459. case PEND_OpenAF:
  1460. {
  1461. PARPCB_DEST pBroadcastDest;
  1462. if (FAIL(Status))
  1463. {
  1464. //
  1465. // OpenAF failed...
  1466. //
  1467. break;
  1468. }
  1469. // Check if the adapter state is inited and fail if not.
  1470. // We keep coming down this path if we're waiting for
  1471. // the adapter to switch to the "connected" status -- so
  1472. // in the mean time, if we're shutting down the adapter,
  1473. // we want to bail out.
  1474. //
  1475. if (!CHECK_AD_PRIMARY_STATE(pAdapter, ARPAD_PS_INITED))
  1476. {
  1477. TR_WARN((
  1478. "Failing init because adapter state(0x%x) is not INITED.\n",
  1479. GET_AD_PRIMARY_STATE(pAdapter)
  1480. ));
  1481. TIMESTAMP("===ActivateIF: Failing Init because adapter state is not inited");
  1482. Status = NDIS_STATUS_FAILURE;
  1483. break;
  1484. }
  1485. else
  1486. {
  1487. ASSERT(sizeof(TASK_ACTIVATE_IF)<=sizeof(ARP1394_TASK));
  1488. //
  1489. // If we're not at passive, we need to switch to
  1490. // passive before we can call arpIsAdapterConnected().
  1491. //
  1492. if (!ARP_ATPASSIVE())
  1493. {
  1494. // NOTE: we specify completion code PEND_OpenAF
  1495. // because we want to get back here (except
  1496. // we'll be at passive).
  1497. //
  1498. RmSuspendTask(pTask, PEND_OpenAF, pSR);
  1499. RmResumeTaskAsync(
  1500. pTask,
  1501. NDIS_STATUS_SUCCESS,
  1502. &((TASK_ACTIVATE_IF*)pTask)->WorkItem,
  1503. pSR
  1504. );
  1505. Status = NDIS_STATUS_PENDING;
  1506. break;
  1507. }
  1508. if (!arpIsAdapterConnected(pAdapter, pSR))
  1509. {
  1510. //
  1511. // Let's wait awhile and try again.
  1512. //
  1513. TR_INFO((
  1514. "Delaying IF init until adapter goes"
  1515. " to connect state.\n"
  1516. ));
  1517. RmSuspendTask(pTask, PEND_OpenAF, pSR);
  1518. RmResumeTaskDelayed(
  1519. pTask,
  1520. NDIS_STATUS_SUCCESS,
  1521. ARP1394_WAIT_FOR_CONNECT_STATUS_TIMEOUT,
  1522. &((TASK_ACTIVATE_IF*)pTask)->Timer,
  1523. pSR
  1524. );
  1525. Status = NDIS_STATUS_PENDING;
  1526. break;
  1527. }
  1528. }
  1529. //
  1530. // Successfully opened the address family and waited for
  1531. // connect status.
  1532. // Now setup the broadcast channel VC.
  1533. //
  1534. //
  1535. TR_INFO(("Interface: 0x%p, Got NdisAfHandle: 0x%p\n",
  1536. pIF, pIF->ndis.AfHandle));
  1537. //
  1538. // Let's create a destination object representing the
  1539. // broadcast channel, and make a call to it.
  1540. //
  1541. Status = arpSetupSpecialDest(
  1542. pIF,
  1543. NIC1394AddressType_Channel, // This means bcast channel.
  1544. pTask, // pParentTask
  1545. PEND_SetupBroadcastChannel, // PendCode
  1546. &pBroadcastDest,
  1547. pSR
  1548. );
  1549. // Should either fail or pend -- never return success.
  1550. //
  1551. ASSERT(Status != NDIS_STATUS_SUCCESS);
  1552. if (!PEND(Status))
  1553. {
  1554. OBJLOG0( pIF, "FATAL: Couldn't create BC dest entry.\n");
  1555. }
  1556. else
  1557. {
  1558. //
  1559. }
  1560. }
  1561. break;
  1562. case PEND_SetupBroadcastChannel:
  1563. {
  1564. PRM_TASK pMakeCallTask;
  1565. if (FAIL(Status))
  1566. {
  1567. //
  1568. // Couldn't setup the broadcast channel...
  1569. //
  1570. break;
  1571. }
  1572. //
  1573. // Successfully opened the address family.
  1574. // Now setup the receive FIFO VC.
  1575. //
  1576. //
  1577. // TR_INFO(("Interface: 0x%p, Got NdisAfHandle: 0x%p\n",
  1578. // pIF, pIF->ndis.AfHandle));
  1579. //
  1580. // Let's start a MakeCall task and pend on it.
  1581. //
  1582. Status = arpAllocateTask(
  1583. &pIF->Hdr, // pParentObject
  1584. arpTaskMakeRecvFifoCall, // pfnHandler
  1585. 0, // Timeout
  1586. "Task: MakeRecvFifoCall", // szDescription
  1587. &pMakeCallTask,
  1588. pSR
  1589. );
  1590. if (FAIL(Status))
  1591. {
  1592. // Couldn't allocate task. Let's do a fake completion of
  1593. // this stage...
  1594. //
  1595. RmSuspendTask(pTask, PEND_SetupReceiveVc, pSR);
  1596. RmResumeTask(pTask, (UINT_PTR) Status, pSR);
  1597. Status = NDIS_STATUS_PENDING;
  1598. break;
  1599. }
  1600. else
  1601. {
  1602. RmPendTaskOnOtherTask(
  1603. pTask,
  1604. PEND_SetupReceiveVc,
  1605. pMakeCallTask,
  1606. pSR
  1607. );
  1608. (VOID)RmStartTask(
  1609. pMakeCallTask,
  1610. 0, // UserParam (unused)
  1611. pSR
  1612. );
  1613. Status = NDIS_STATUS_PENDING;
  1614. }
  1615. }
  1616. break;
  1617. case PEND_SetupReceiveVc:
  1618. {
  1619. PARPCB_DEST pMultiChannelDest;
  1620. if (FAIL(Status))
  1621. {
  1622. TR_WARN(("FATAL: COULDN'T SETUP RECEIVE FIFO VC!\n"));
  1623. break;
  1624. }
  1625. //
  1626. // Let's create a destination object representing the
  1627. // multichannel vc, and make a call to it.
  1628. //
  1629. Status = arpSetupSpecialDest(
  1630. pIF,
  1631. NIC1394AddressType_MultiChannel,
  1632. pTask, // pParentTask
  1633. PEND_SetupMultiChannel, // PendCode
  1634. &pMultiChannelDest,
  1635. pSR
  1636. );
  1637. // Should either fail or pend -- never return success.
  1638. //
  1639. ASSERT(Status != NDIS_STATUS_SUCCESS);
  1640. if (!PEND(Status))
  1641. {
  1642. OBJLOG0( pIF, "FATAL: Couldn't create BC dest entry.\n");
  1643. }
  1644. else
  1645. {
  1646. //
  1647. // On pending, pMultiChannelDest contains a valid
  1648. // pDest which has been tmpref'd.
  1649. // Keep a pointer to the broadcast dest in the IF.
  1650. // and link the broadcast dest to the IF.
  1651. //
  1652. {
  1653. #if RM_EXTRA_CHECKING
  1654. RmLinkObjectsEx(
  1655. &pIF->Hdr,
  1656. &pMultiChannelDest->Hdr,
  1657. 0x34639a4c,
  1658. ARPASSOC_LINK_IF_OF_MCDEST,
  1659. " IF of MultiChannel Dest 0x%p (%s)\n",
  1660. ARPASSOC_LINK_MCDEST_OF_IF,
  1661. " MultiChannel Dest of IF 0x%p (%s)\n",
  1662. pSR
  1663. );
  1664. #else // !RM_EXTRA_CHECKING
  1665. RmLinkObjects(&pIF->Hdr, &pMultiChannelDest->Hdr,pSR);
  1666. #endif // !RM_EXTRA_CHECKING
  1667. LOCKOBJ(pIF, pSR);
  1668. ASSERT(pIF->pMultiChannelDest == NULL);
  1669. pIF->pMultiChannelDest = pMultiChannelDest;
  1670. UNLOCKOBJ(pIF, pSR);
  1671. // arpSetupSpecialDest ref'd pBroadcastDest.
  1672. //
  1673. RmTmpDereferenceObject(&pMultiChannelDest->Hdr, pSR);
  1674. }
  1675. }
  1676. }
  1677. break;
  1678. case PEND_SetupMultiChannel:
  1679. {
  1680. PARPCB_DEST pEthernetDest;
  1681. if (FAIL(Status))
  1682. {
  1683. // Ignore the failure.
  1684. TR_WARN(("COULDN'T SETUP MULTI-CHANNEL VC (IGNORING FAILURE)!\n"));
  1685. }
  1686. //
  1687. // Let's create a destination object representing the
  1688. // ethernet, and make a call to it.
  1689. //
  1690. Status = arpSetupSpecialDest(
  1691. pIF,
  1692. NIC1394AddressType_Ethernet,
  1693. pTask, // pParentTask
  1694. PEND_SetupEthernetVc, // PendCode
  1695. &pEthernetDest,
  1696. pSR
  1697. );
  1698. // Should either fail or pend -- never return success.
  1699. //
  1700. ASSERT(Status != NDIS_STATUS_SUCCESS);
  1701. if (!PEND(Status))
  1702. {
  1703. OBJLOG0( pIF, "FATAL: Couldn't create BC dest entry.\n");
  1704. }
  1705. else
  1706. {
  1707. //
  1708. // On pending, pEthernetDest contains a valid
  1709. // pDest which has been tmpref'd.
  1710. // Keep a pointer to the broadcast dest in the IF.
  1711. // and link the broadcast dest to the IF.
  1712. //
  1713. {
  1714. #if RM_EXTRA_CHECKING
  1715. RmLinkObjectsEx(
  1716. &pIF->Hdr,
  1717. &pEthernetDest->Hdr,
  1718. 0xcea46d67,
  1719. ARPASSOC_LINK_IF_OF_ETHDEST,
  1720. " IF of Ethernet Dest 0x%p (%s)\n",
  1721. ARPASSOC_LINK_ETHDEST_OF_IF,
  1722. " Ethernet Dest of IF 0x%p (%s)\n",
  1723. pSR
  1724. );
  1725. #else // !RM_EXTRA_CHECKING
  1726. RmLinkObjects(&pIF->Hdr, &pEthernetDest->Hdr,pSR);
  1727. #endif // !RM_EXTRA_CHECKING
  1728. LOCKOBJ(pIF, pSR);
  1729. ASSERT(pIF->pEthernetDest == NULL);
  1730. pIF->pEthernetDest = pEthernetDest;
  1731. UNLOCKOBJ(pIF, pSR);
  1732. // arpSetupSpecialDest ref'd pBroadcastDest.
  1733. //
  1734. RmTmpDereferenceObject(&pEthernetDest->Hdr, pSR);
  1735. }
  1736. }
  1737. }
  1738. break;
  1739. case PEND_SetupEthernetVc:
  1740. {
  1741. if (FAIL(Status))
  1742. {
  1743. TR_WARN(("COULDN'T SETUP ETHERNET VC (IGNORING FAILURE)!\n"));
  1744. Status = NDIS_STATUS_SUCCESS;
  1745. }
  1746. if (!ARP_ATPASSIVE())
  1747. {
  1748. ASSERT(sizeof(TASK_ACTIVATE_IF)<=sizeof(ARP1394_TASK));
  1749. // We're not at passive level, but we need to be when we
  1750. // call IP's add interface. So we switch to passive...
  1751. // NOTE: we specify completion code PEND_SetupReceiveVc
  1752. // because we want to get back here (except
  1753. // we'll be at passive).
  1754. //
  1755. RmSuspendTask(pTask, PEND_SetupEthernetVc, pSR);
  1756. RmResumeTaskAsync(
  1757. pTask,
  1758. Status,
  1759. &((TASK_ACTIVATE_IF*)pTask)->WorkItem,
  1760. pSR
  1761. );
  1762. Status = NDIS_STATUS_PENDING;
  1763. break;
  1764. }
  1765. ASSERT(Status == NDIS_STATUS_SUCCESS);
  1766. //
  1767. // Successfully opened the address family and setup
  1768. // the recv VC.
  1769. // Announce this new interface to IP
  1770. //
  1771. TR_INFO(("Interface: 0x%p, Setup recv VC 0x%p\n",
  1772. pIF, pIF->recvinfo.VcHdr.NdisVcHandle));
  1773. if (!ARP_BRIDGE_ENABLED(pAdapter))
  1774. {
  1775. Status = arpCallIpAddInterface(
  1776. pIF,
  1777. pSR
  1778. );
  1779. // We don't expect a pending return here.
  1780. //
  1781. ASSERT(Status != NDIS_STATUS_PENDING);
  1782. if (!FAIL(Status))
  1783. {
  1784. LOCKOBJ(pIF, pSR);
  1785. // Add any static arp intries
  1786. //
  1787. arpAddStaticArpEntries(pIF, pSR);
  1788. UNLOCKOBJ(pIF, pSR);
  1789. }
  1790. }
  1791. if (!FAIL(Status))
  1792. {
  1793. //
  1794. // Start the maintenance task on this IF.
  1795. //
  1796. arpStartIfMaintenanceTask(pIF, pSR);
  1797. }
  1798. } // end case PEND_SetupEthernetVc
  1799. break;
  1800. default:
  1801. {
  1802. ASSERTEX(!"Unknown pend op", pTask);
  1803. }
  1804. break;
  1805. } // end switch(RM_PEND_CODE(pTask))
  1806. } // case RM_TASKOP_PENDCOMPLETE
  1807. break;
  1808. case RM_TASKOP_END:
  1809. {
  1810. Status = (NDIS_STATUS) UserParam;
  1811. LOCKOBJ(pIF, pSR);
  1812. //
  1813. // Was this task able to update the Interface' state
  1814. //
  1815. if (GET_IF_ACTIVE_STATE(pIF) == ARPIF_AS_ACTIVATING)
  1816. {
  1817. //
  1818. // If so, then set the new state
  1819. //
  1820. ASSERT (pIF->pActDeactTask == pTask)
  1821. if (FAIL(Status))
  1822. {
  1823. //
  1824. // Failure. Whoever was responsible for starting this task
  1825. // is also responsible for cleaning up after a failed
  1826. // activation.
  1827. //
  1828. arpClearSecondaryIfTask(pIF, pTask, ARPIF_AS_FAILEDACTIVATE, pSR);
  1829. }
  1830. else
  1831. {
  1832. //
  1833. // Success
  1834. //
  1835. arpClearSecondaryIfTask(pIF, pTask, ARPIF_AS_ACTIVATED, pSR);
  1836. }
  1837. }
  1838. else
  1839. {
  1840. //
  1841. // Only an early failure should get us here.
  1842. // Set the flag for informational purposes
  1843. //
  1844. ASSERT (FAIL(Status) == TRUE);
  1845. ASSERT (pIF->pActDeactTask == NULL);
  1846. ASSERT (!CHECK_AD_PRIMARY_STATE(pAdapter, ARPAD_PS_INITED));
  1847. SET_IF_ACTIVE_STATE(pIF, ARPIF_AS_FAILEDACTIVATE);
  1848. }
  1849. UNLOCKOBJ(pIF, pSR);
  1850. }
  1851. break;
  1852. default:
  1853. {
  1854. ASSERTEX(!"Unexpected task op", pTask);
  1855. }
  1856. break;
  1857. } // switch (Code)
  1858. RM_ASSERT_NOLOCKS(pSR);
  1859. EXIT()
  1860. return Status;
  1861. }
  1862. NDIS_STATUS
  1863. arpCallIpAddInterface(
  1864. IN ARP1394_INTERFACE * pIF, // NOLOCKIN NOLOCKOUT
  1865. IN PRM_STACK_RECORD pSR
  1866. )
  1867. /*++
  1868. Routine Description:
  1869. Call's IP's AddInterfaceRtn (ArpGlobals.ip.pAddInterfaceRtn), passing it
  1870. a structure continging pointers to our IP handlers and related information.
  1871. --*/
  1872. {
  1873. ENTER("CallIpAddInterface", 0xe47fc4d4)
  1874. struct LLIPBindInfo BindInfo;
  1875. ARP1394_ADAPTER * pAdapter = (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pIF);
  1876. NDIS_STATUS Status;
  1877. NdisZeroMemory(&BindInfo, sizeof(BindInfo));
  1878. RM_ASSERT_NOLOCKS(pSR);
  1879. #if ENABLE_OFFLOAD
  1880. #error "Unimplemented"
  1881. //
  1882. // Query and set NIC offload capabilities.
  1883. //
  1884. BindInfo.lip_OffloadFlags = pAdapter->Offload.Flags;
  1885. BindInfo.lip_MaxOffLoadSize = pAdapter->Offload.MaxOffLoadSize;
  1886. BindInfo.lip_MaxSegments = pAdapter->Offload.MinSegmentCount;
  1887. #endif // ENABLE_OFFLOAD
  1888. BindInfo.lip_context = (PVOID)pIF;
  1889. BindInfo.lip_transmit = ArpIpMultiTransmit;
  1890. BindInfo.lip_transfer = ArpIpTransfer;
  1891. BindInfo.lip_close = ArpIpClose;
  1892. BindInfo.lip_addaddr = ArpIpAddAddress;
  1893. BindInfo.lip_deladdr = ArpIpDelAddress;
  1894. BindInfo.lip_invalidate = ArpIpInvalidate;
  1895. BindInfo.lip_open = ArpIpOpen;
  1896. BindInfo.lip_qinfo = ArpIpQueryInfo;
  1897. BindInfo.lip_setinfo = ArpIpSetInfo;
  1898. BindInfo.lip_getelist = ArpIpGetEList;
  1899. BindInfo.lip_arpresolveip = ArpSendARPApi;
  1900. BindInfo.lip_mss = pIF->ip.MTU;
  1901. BindInfo.lip_speed = pAdapter->info.Speed;
  1902. //
  1903. // Set LIP_COPY_FLAG to avoid having TransferData
  1904. // called all the time.
  1905. //
  1906. BindInfo.lip_flags = LIP_COPY_FLAG;
  1907. #if MILLEN
  1908. #if (ARP1394_IP_PHYSADDR_LEN > 7)
  1909. #error "Win98 doesn't like addrlen to be > 7"
  1910. #endif
  1911. #endif // MILLEN
  1912. BindInfo.lip_addrlen = ARP1394_IP_PHYSADDR_LEN;
  1913. BindInfo.lip_addr = (PUCHAR) &pAdapter->info.EthernetMacAddress;
  1914. {
  1915. ENetAddr *pMacAddr = (ENetAddr *)BindInfo.lip_addr;
  1916. TR_INFO (("ARP1394 INTERFACE ADDRESS %x %x %x %x %x %x\n",
  1917. pMacAddr->addr[0],pMacAddr->addr[1],pMacAddr->addr[2],pMacAddr->addr[3],pMacAddr->addr[4],pMacAddr->addr[5]));
  1918. TR_INFO (("UNIQUE ID Address %I64x \n",pAdapter->info.LocalUniqueID));
  1919. }
  1920. BindInfo.lip_pnpcomplete = ArpIpPnPComplete;
  1921. Status = ArpGlobals.ip.pAddInterfaceRtn(
  1922. &pAdapter->bind.DeviceName,
  1923. NULL, // IfName (unused) -- See 10/14/1998 entry
  1924. // in atmarpc.sys, notes.txt
  1925. &pIF->ip.ConfigString,
  1926. pAdapter->bind.IpConfigHandle,
  1927. (PVOID)pIF,
  1928. ArpIpDynRegister,
  1929. &BindInfo
  1930. ,0, // RequestedIndex (unused) -- See 10/14/1998 entry
  1931. // in notes.txt
  1932. // IF_TYPE_IPOVER_ATM, // TODO: change to 1394
  1933. IF_TYPE_IEEE1394,
  1934. IF_ACCESS_BROADCAST,
  1935. IF_CONNECTION_DEDICATED
  1936. );
  1937. if (Status == IP_SUCCESS)
  1938. {
  1939. Status = NDIS_STATUS_SUCCESS;
  1940. }
  1941. else
  1942. {
  1943. //
  1944. // Sometimes IP can fail AddInterface synchronously. At that time, there
  1945. // may be an Resolve Local IP address Task going on. Keep the AddAddrCmplRtn
  1946. // function pointer.
  1947. //
  1948. IPAddAddrCmpltRtn AddAddrCmplRtn = pIF->ip.AddAddrCmplRtn;
  1949. ARP_ZEROSTRUCT(&(pIF->ip));
  1950. pIF->ip.AddAddrCmplRtn = AddAddrCmplRtn;
  1951. TR_WARN(("IPAddInterface ret 0x%p\n", Status));
  1952. Status = NDIS_STATUS_FAILURE;
  1953. }
  1954. RM_ASSERT_NOLOCKS(pSR);
  1955. EXIT()
  1956. return Status;
  1957. }
  1958. ULONG
  1959. arpIpAddressHash(
  1960. PVOID pKey
  1961. )
  1962. /*++
  1963. Routine Description:
  1964. Hash function responsible for returning a hash of pKey, which
  1965. we expect to be an Ip address (literally, not ptr to one).
  1966. Return Value:
  1967. ULONG-sized hash of the IP address.
  1968. --*/
  1969. {
  1970. ULONG u = (ULONG) (ULONG_PTR) pKey; // win64 safe (ip addr is 4 bytes)
  1971. char *pc = (char *) &u;
  1972. //
  1973. // The ip address is in network order, but we would like the 1st byte
  1974. // to contain the most variable information (to maximize the hashing benefit),
  1975. // while still keeping most of the information in the hash (so that the quick
  1976. // compare based on the hash key will be more effective). We could reversse
  1977. // the byte order of the entire address, but instead we simply xor in the 4th
  1978. // byte into the 1st byte position (fewer instructions, for whatever that's
  1979. // worth.)
  1980. //
  1981. return u ^ pc[3];
  1982. }
  1983. ULONG
  1984. arpRemoteDestHash(
  1985. PVOID pKey
  1986. )
  1987. /*++
  1988. Routine Description:
  1989. Hash function responsible for returning a hash of pKey, which
  1990. we expect to be an Ip address (literally, not ptr to one).
  1991. Return Value:
  1992. ULONG-sized hash of the IP address.
  1993. --*/
  1994. {
  1995. ULONG u = 0;
  1996. char *pc = NULL;
  1997. u = *((PULONG)pKey); // win64 safe (ip addr is 4 bytes)
  1998. pc = (char *) &u;
  1999. //
  2000. // The ip address is in network order, but we would like the 1st byte
  2001. // to contain the most variable information (to maximize the hashing benefit),
  2002. // while still keeping most of the information in the hash (so that the quick
  2003. // compare based on the hash key will be more effective). We could reversse
  2004. // the byte order of the entire address, but instead we simply xor in the 4th
  2005. // byte into the 1st byte position (fewer instructions, for whatever that's
  2006. // worth.)
  2007. //
  2008. return u ^ pc[3];
  2009. }
  2010. BOOLEAN
  2011. arpLocalIpCompareKey(
  2012. PVOID pKey,
  2013. PRM_HASH_LINK pItem
  2014. )
  2015. /*++
  2016. Routine Description:
  2017. Hash comparison function for ARPCB_LOCAL_IP.
  2018. Arguments:
  2019. pKey - Actually the IP address (not ptr to IP address) in network-byte
  2020. order.
  2021. pItem - Points to ARPCB_LOCAL_IP.Hdr.HashLink.
  2022. Return Value:
  2023. TRUE IFF the key (IP address) exactly matches the key of the specified
  2024. LocalIp object.
  2025. --*/
  2026. {
  2027. ARPCB_LOCAL_IP *pLIP =
  2028. CONTAINING_RECORD(pItem, ARPCB_LOCAL_IP, Hdr.HashLink);
  2029. if (pLIP->IpAddress == (ULONG) (ULONG_PTR) pKey)
  2030. {
  2031. return TRUE;
  2032. }
  2033. else
  2034. {
  2035. return FALSE;
  2036. }
  2037. }
  2038. BOOLEAN
  2039. arpRemoteDestCompareKey(
  2040. PVOID pKey,
  2041. PRM_HASH_LINK pItem
  2042. )
  2043. /*++
  2044. Routine Description:
  2045. Hash comparison function for ARPCB_REMOTE_IP.
  2046. Arguments:
  2047. pKey - Actually the IP address (not ptr to IP address) in network-byte
  2048. order.
  2049. pItem - Points to ARPCB_REMOTE_IP.Hdr.HashLink.
  2050. Return Value:
  2051. TRUE IFF the key (IP address) exactly matches the key of the specified
  2052. RemoteIp object.
  2053. --*/
  2054. {
  2055. ENTER ("arpRemoteDestCompareKey", 0x62b9d9ae)
  2056. PREMOTE_DEST_KEY pRemoteDestKey = (PREMOTE_DEST_KEY)pKey;
  2057. ARPCB_REMOTE_IP *pRIP =
  2058. CONTAINING_RECORD(pItem, ARPCB_REMOTE_IP, Hdr.HashLink);
  2059. BOOLEAN fCompare = FALSE;
  2060. if ((pRIP->Key.u.u32 == pRemoteDestKey->u.u32) &&
  2061. (pRIP->Key.u.u16 == pRemoteDestKey->u.u16))
  2062. {
  2063. fCompare = TRUE;
  2064. }
  2065. TR_INFO( ("Comparision %d Key %x %x %x %x %x %x pRemoteIP %x %x %x %x %x %x\n",
  2066. fCompare,
  2067. pRemoteDestKey->ENetAddress.addr[0],
  2068. pRemoteDestKey->ENetAddress.addr[1],
  2069. pRemoteDestKey->ENetAddress.addr[2],
  2070. pRemoteDestKey->ENetAddress.addr[3],
  2071. pRemoteDestKey->ENetAddress.addr[4],
  2072. pRemoteDestKey->ENetAddress.addr[5],
  2073. pRIP->Key.ENetAddress.addr[0],
  2074. pRIP->Key.ENetAddress.addr[1],
  2075. pRIP->Key.ENetAddress.addr[2],
  2076. pRIP->Key.ENetAddress.addr[3],
  2077. pRIP->Key.ENetAddress.addr[4],
  2078. pRIP->Key.ENetAddress.addr[5]));
  2079. EXIT();
  2080. return fCompare; // success
  2081. }
  2082. BOOLEAN
  2083. arpRemoteIpCompareKey(
  2084. PVOID pKey,
  2085. PRM_HASH_LINK pItem
  2086. )
  2087. /*++
  2088. Routine Description:
  2089. Hash comparison function for ARPCB_REMOTE_IP.
  2090. Arguments:
  2091. pKey - Actually the IP address
  2092. pItem - Points to ARPCB_REMOTE_IP.Hdr.HashLink.
  2093. Return Value:
  2094. TRUE IFF the key (IP address) exactly matches the key of the specified
  2095. RemoteIp object.
  2096. --*/
  2097. {
  2098. ARPCB_REMOTE_IP *pRIP =
  2099. CONTAINING_RECORD(pItem, ARPCB_REMOTE_IP, Hdr.HashLink);
  2100. if (pRIP->IpAddress == (ULONG) (ULONG_PTR) pKey)
  2101. {
  2102. return TRUE;
  2103. }
  2104. else
  2105. {
  2106. return FALSE;
  2107. }
  2108. }
  2109. BOOLEAN
  2110. arpRemoteEthCompareKey(
  2111. PVOID pKey,
  2112. PRM_HASH_LINK pItem
  2113. )
  2114. /*++
  2115. Routine Description:
  2116. Hash comparison function for ARPCB_REMOTE_ETH.
  2117. Arguments:
  2118. pKey - Actually the IP address (not ptr to IP address) in network-byte
  2119. order.
  2120. pItem - Points to ARPCB_REMOTE_ETH.Hdr.HashLink.
  2121. Return Value:
  2122. TRUE IFF the key (IP address) exactly matches the key of the specified
  2123. RemoteEth object.
  2124. --*/
  2125. {
  2126. ARPCB_REMOTE_ETH *pRE =
  2127. CONTAINING_RECORD(pItem, ARPCB_REMOTE_ETH, Hdr.HashLink);
  2128. if (pRE->IpAddress == (ULONG) (ULONG_PTR) pKey)
  2129. {
  2130. return TRUE;
  2131. }
  2132. else
  2133. {
  2134. return FALSE;
  2135. }
  2136. }
  2137. BOOLEAN
  2138. arpDestinationCompareKey(
  2139. PVOID pKey,
  2140. PRM_HASH_LINK pItem
  2141. )
  2142. /*++
  2143. Routine Description:
  2144. Hash comparison function for ARPCB_DEST.
  2145. Arguments:
  2146. pKey - Actually a pointer to a ARP_DEST_PARAMS structure.
  2147. pItem - Points to ARPCB_DEST.Hdr.HashLink.
  2148. Return Value:
  2149. TRUE IFF the key (HW address) exactly matches the key of the specified
  2150. Dest object.
  2151. --*/
  2152. {
  2153. ARPCB_DEST *pD = CONTAINING_RECORD(pItem, ARPCB_DEST, Hdr.HashLink);
  2154. PARP_DEST_PARAMS pDestParams = (PARP_DEST_PARAMS) pKey;
  2155. NIC1394_DESTINATION *pKeyHwAddr = &pDestParams->HwAddr;
  2156. NIC1394_ADDRESS_TYPE AddressType = pKeyHwAddr->AddressType;
  2157. if (pD->Params.HwAddr.AddressType == AddressType)
  2158. {
  2159. if (AddressType == NIC1394AddressType_FIFO)
  2160. {
  2161. if (pKeyHwAddr->FifoAddress.UniqueID == pD->Params.HwAddr.FifoAddress.UniqueID
  2162. && pKeyHwAddr->FifoAddress.Off_Low == pD->Params.HwAddr.FifoAddress.Off_Low
  2163. && pKeyHwAddr->FifoAddress.Off_High == pD->Params.HwAddr.FifoAddress.Off_High)
  2164. {
  2165. return TRUE;
  2166. }
  2167. }
  2168. else if (AddressType == NIC1394AddressType_Channel)
  2169. {
  2170. if (pKeyHwAddr->Channel == pD->Params.HwAddr.Channel)
  2171. {
  2172. if (pDestParams->ReceiveOnly == pD->Params.ReceiveOnly)
  2173. {
  2174. return TRUE;
  2175. }
  2176. }
  2177. }
  2178. else if (AddressType == NIC1394AddressType_MultiChannel)
  2179. {
  2180. return TRUE;
  2181. }
  2182. else if (AddressType == NIC1394AddressType_Ethernet)
  2183. {
  2184. return TRUE;
  2185. }
  2186. }
  2187. return FALSE;
  2188. }
  2189. ULONG
  2190. arpDestinationHash(
  2191. PVOID pKey
  2192. )
  2193. /*++
  2194. Routine Description:
  2195. Hash function responsible for returning a hash of pKey, which
  2196. we expect to be pointer to a NIC1394_DESTINATION HW address.
  2197. IMPORTANT: Since that address is a union of channel or Fifo (different sizes),
  2198. we expect that the structure was first zero'd out (no uninitialized bits).
  2199. We expect this pointer to be quadword aligned.
  2200. Arguments:
  2201. pKey - Actually a pointer to a ARP_DEST_KEY structure.
  2202. Return Value:
  2203. ULONG-sized hash of pKey.
  2204. --*/
  2205. {
  2206. ULONG *pu = (ULONG*) pKey;
  2207. // We expect both channel and fifo are at the beginning of the structure,
  2208. // and the structure is atleast 2 dwords.
  2209. // NOTE: we only look at the HwAddr field of ARP_DEST_PARAMS, so both
  2210. // send and receive destinations will hash to the same value. Big deal.
  2211. //
  2212. ASSERT(
  2213. FIELD_OFFSET(ARP_DEST_PARAMS, HwAddr) == 0 &&
  2214. FIELD_OFFSET(NIC1394_DESTINATION, FifoAddress) == 0 &&
  2215. FIELD_OFFSET(NIC1394_DESTINATION, Channel) == 0 &&
  2216. sizeof(NIC1394_DESTINATION) >= 2*sizeof(*pu));
  2217. // Return 1st DWORD xor 2nd DWORD
  2218. //
  2219. return pu[0] ^ pu[1];
  2220. }
  2221. BOOLEAN
  2222. arpDhcpTableCompareKey(
  2223. PVOID pKey,
  2224. PRM_HASH_LINK pItem
  2225. )
  2226. /*++
  2227. Routine Description:
  2228. Hash comparison function for ARPCB_DEST.
  2229. Arguments:
  2230. pKey - Actually a pointer to the xid .
  2231. pItem - Points to ARPCB_DEST.Hdr.HashLink.
  2232. Return Value:
  2233. TRUE IFF the key (HW address) exactly matches the key of the specified
  2234. Dest object.
  2235. --*/
  2236. {
  2237. ARP1394_ETH_DHCP_ENTRY *pEntry =
  2238. CONTAINING_RECORD(pItem, ARP1394_ETH_DHCP_ENTRY , Hdr.HashLink);
  2239. if (pEntry->xid== (*(PULONG)pKey))
  2240. {
  2241. return TRUE;
  2242. }
  2243. else
  2244. {
  2245. return FALSE;
  2246. }
  2247. }
  2248. ULONG
  2249. arpDhcpTableHash (
  2250. PVOID pKey
  2251. )
  2252. /*++
  2253. Routine Description:
  2254. Arguments:
  2255. pKey - Actually a pointer to a Xid of a dhcp transaction .
  2256. Return Value:
  2257. ULONG-sized hash of pKey.
  2258. --*/
  2259. {
  2260. ULONG *pu = (ULONG*) pKey;
  2261. return (*pu);
  2262. }
  2263. // arpLocalIp_HashInfo contains information required maintain a hashtable
  2264. // of ARPCB_LOCAL_IP objects.
  2265. //
  2266. RM_HASH_INFO
  2267. arpLocalIp_HashInfo =
  2268. {
  2269. NULL, // pfnTableAllocator
  2270. NULL, // pfnTableDeallocator
  2271. arpLocalIpCompareKey, // fnCompare
  2272. // Function to generate a ULONG-sized hash.
  2273. //
  2274. arpIpAddressHash // pfnHash
  2275. };
  2276. // arpRemoteIp_HashInfo contains information required maintain a hashtable
  2277. // of ARPCB_REMOTE_IP objects.
  2278. //
  2279. RM_HASH_INFO
  2280. arpRemoteIp_HashInfo =
  2281. {
  2282. NULL, // pfnTableAllocator
  2283. NULL, // pfnTableDeallocator
  2284. arpRemoteIpCompareKey, // fnCompare
  2285. // Function to generate a ULONG-sized hash.
  2286. //
  2287. arpIpAddressHash // pfnHash
  2288. };
  2289. // arpRemoteIp_HashInfo contains information required maintain a hashtable
  2290. // of ARPCB_REMOTE_IP objects.
  2291. //
  2292. RM_HASH_INFO
  2293. arpRemoteEth_HashInfo =
  2294. {
  2295. NULL, // pfnTableAllocator
  2296. NULL, // pfnTableDeallocator
  2297. arpRemoteEthCompareKey, // fnCompare
  2298. // Function to generate a ULONG-sized hash.
  2299. //
  2300. arpIpAddressHash // pfnHash
  2301. };
  2302. // arpDestination_HashInfo contains information required maintain a hashtable
  2303. // of ARPCB_DEST objects.
  2304. //
  2305. RM_HASH_INFO
  2306. arpDestination_HashInfo =
  2307. {
  2308. NULL, // pfnTableAllocator
  2309. NULL, // pfnTableDeallocator
  2310. arpDestinationCompareKey, // fnCompare
  2311. // Function to generate a ULONG-sized hash.
  2312. //
  2313. arpDestinationHash // pfnHash
  2314. };
  2315. // arpRemoteDest_HashInfo contains information required maintain a hashtable
  2316. // of ARPCB_REMOTE_IP objects.
  2317. //
  2318. RM_HASH_INFO
  2319. arpRemoteDest_HashInfo =
  2320. {
  2321. NULL, // pfnTableAllocator
  2322. NULL, // pfnTableDeallocator
  2323. arpRemoteDestCompareKey, // fnCompare
  2324. // Function to generate a ULONG-sized hash.
  2325. //
  2326. arpRemoteDestHash // pfnHash
  2327. };
  2328. // arpRemoteDest_HashInfo contains information required maintain a hashtable
  2329. // of ARPCB_REMOTE_IP objects.
  2330. //
  2331. RM_HASH_INFO
  2332. arpDhcpTable_HashInfo =
  2333. {
  2334. NULL, // pfnTableAllocator
  2335. NULL, // pfnTableDeallocator
  2336. arpDhcpTableCompareKey, // fnCompare
  2337. // Function to generate a ULONG-sized hash.
  2338. //
  2339. arpDhcpTableHash // pfnHash
  2340. };
  2341. // ArpGlobal_LocalIpStaticInfo contains static information about
  2342. // objects of type ARPCB_LOCAL_IP.
  2343. //
  2344. RM_STATIC_OBJECT_INFO
  2345. ArpGlobal_LocalIpStaticInfo =
  2346. {
  2347. 0, // TypeUID
  2348. 0, // TypeFlags
  2349. "LocalIp", // TypeName
  2350. 0, // Timeout
  2351. arpLocalIpCreate, // pfnCreate
  2352. arpLocalIpDelete, // pfnDelete
  2353. NULL, // pfnVerifyLock
  2354. 0, // Size of resource table
  2355. NULL, // ResourceTable
  2356. &arpLocalIp_HashInfo
  2357. };
  2358. // ArpGlobal_RemoteIpStaticInfo contains static information about
  2359. // objects of type ARPCB_REMOTE_IP.
  2360. //
  2361. RM_STATIC_OBJECT_INFO
  2362. ArpGlobal_RemoteIpStaticInfo =
  2363. {
  2364. 0, // TypeUID
  2365. 0, // TypeFlags
  2366. "RemoteIp", // TypeName
  2367. 0, // Timeout
  2368. arpRemoteDestCreate, // pfnCreate
  2369. arpRemoteIpDelete, // pfnDelete
  2370. NULL, // pfnVerifyLock
  2371. 0, // Size of resource table
  2372. NULL, // ResourceTable
  2373. &arpRemoteDest_HashInfo
  2374. };
  2375. // ArpGlobal_RemoteEthStaticInfo contains static information about
  2376. // objects of type ARPCB_REMOTE_ETH.
  2377. //
  2378. RM_STATIC_OBJECT_INFO
  2379. ArpGlobal_RemoteEthStaticInfo =
  2380. {
  2381. 0, // TypeUID
  2382. 0, // TypeFlags
  2383. "RemoteEth", // TypeName
  2384. 0, // Timeout
  2385. arpRemoteEthCreate, // pfnCreate
  2386. arpRemoteEthDelete, // pfnDelete
  2387. NULL, // pfnVerifyLock
  2388. 0, // Size of resource table
  2389. NULL, // ResourceTable
  2390. &arpRemoteEth_HashInfo
  2391. };
  2392. // ArpGlobal_DestinationStaticInfo contains static information about
  2393. // objects of type ARPCB_DEST.
  2394. //
  2395. RM_STATIC_OBJECT_INFO
  2396. ArpGlobal_DestinationStaticInfo =
  2397. {
  2398. 0, // TypeUID
  2399. 0, // TypeFlags
  2400. "Destination", // TypeName
  2401. 0, // Timeout
  2402. arpDestinationCreate, // pfnCreate
  2403. arpDestinationDelete, // pfnDelete
  2404. NULL, // pfnVerifyLock
  2405. 0, // Size of resource table
  2406. NULL, // ResourceTable
  2407. &arpDestination_HashInfo
  2408. };
  2409. RM_STATIC_OBJECT_INFO
  2410. ArpGlobal_RemoteDestStaticInfo =
  2411. {
  2412. 0, // TypeUID
  2413. 0, // TypeFlags
  2414. "RemoteIp", // TypeName
  2415. 0, // Timeout
  2416. arpRemoteDestCreate, // pfnCreate
  2417. arpRemoteDestDelete, // pfnDelete
  2418. NULL, // pfnVerifyLock
  2419. 0, // Size of resource table
  2420. NULL, // ResourceTable
  2421. &arpRemoteDest_HashInfo
  2422. };
  2423. RM_STATIC_OBJECT_INFO
  2424. ArpGlobal_DhcpTableStaticInfo =
  2425. {
  2426. 0, // TypeUID
  2427. 0, // TypeFlags
  2428. "DhcpTableEntry", // TypeName
  2429. 0, // Timeout
  2430. arpDhcpTableEntryCreate, // pfnCreate
  2431. arpDhcpTableEntryDelete, // pfnDelete
  2432. NULL, // pfnVerifyLock
  2433. 0, // Size of resource table
  2434. NULL, // ResourceTable
  2435. &arpDhcpTable_HashInfo
  2436. };
  2437. NDIS_STATUS
  2438. arpTaskDeactivateInterface(
  2439. IN struct _RM_TASK * pTask,
  2440. IN RM_TASK_OPERATION Code,
  2441. IN UINT_PTR UserParam,
  2442. IN PRM_STACK_RECORD pSR
  2443. )
  2444. /*++
  2445. Routine Description:
  2446. Task handler responsible for deactivating an IP interface (but leaving
  2447. it allocated and linked to the adapter).
  2448. Arguments:
  2449. UserParam for (Code == RM_TASKOP_START) : unused
  2450. --*/
  2451. {
  2452. NDIS_STATUS Status;
  2453. PARP1394_INTERFACE pIF;
  2454. PTASK_DEACTIVATE_IF pShutdownTask;
  2455. UINT Stage;
  2456. PARP1394_ADAPTER pAdapter;
  2457. enum
  2458. {
  2459. STAGE_Start,
  2460. STAGE_StopMaintenanceTask,
  2461. STAGE_CleanupVcComplete,
  2462. STAGE_CloseLocalIpGroup,
  2463. STAGE_CloseRemoteIpGroup,
  2464. STAGE_CloseRemoteEthGroup,
  2465. STAGE_CloseRemoteDhcpGroup,
  2466. STAGE_CloseDestinationGroup,
  2467. STAGE_SwitchedToPassive,
  2468. STAGE_CloseAF,
  2469. STAGE_CloseIp,
  2470. STAGE_End
  2471. };
  2472. ENTER("TaskDeactivateInterface", 0x1a34699e)
  2473. Status = NDIS_STATUS_FAILURE;
  2474. pIF = (ARP1394_INTERFACE*) RM_PARENT_OBJECT(pTask);
  2475. pShutdownTask = (PTASK_DEACTIVATE_IF) pTask;
  2476. pAdapter = (PARP1394_ADAPTER) RM_PARENT_OBJECT(pIF);
  2477. //
  2478. // Message normalizing code
  2479. //
  2480. switch(Code)
  2481. {
  2482. case RM_TASKOP_START:
  2483. Stage = STAGE_Start;
  2484. break;
  2485. case RM_TASKOP_PENDCOMPLETE:
  2486. Status = (NDIS_STATUS) UserParam;
  2487. ASSERT(!PEND(Status));
  2488. Stage = RM_PEND_CODE(pTask);
  2489. break;
  2490. case RM_TASKOP_END:
  2491. Status = (NDIS_STATUS) UserParam;
  2492. Stage= STAGE_End;
  2493. break;
  2494. default:
  2495. ASSERT(FALSE);
  2496. return NDIS_STATUS_FAILURE; // ** EARLY RETURN **
  2497. }
  2498. switch(Stage)
  2499. {
  2500. case STAGE_Start:
  2501. {
  2502. // There should NOT be another activate/deactivate task running
  2503. // on this interface. Why? Because an activate/deactivate task is ONLY
  2504. // started in the context of the active primary task, and there can be
  2505. // ONLY one active primary task on this IF at any one time.
  2506. //
  2507. TIMESTAMP("===DeinitIF:Starting");
  2508. LOCKOBJ(pIF, pSR);
  2509. if (pIF->pActDeactTask != NULL)
  2510. {
  2511. ASSERT(!"pIF->pActDeactTask != NULL");
  2512. UNLOCKOBJ(pIF, pSR);
  2513. Status = NDIS_STATUS_FAILURE;
  2514. break;
  2515. }
  2516. arpSetSecondaryIfTask(pIF, pTask, ARPIF_AS_DEACTIVATING, pSR);
  2517. UNLOCKOBJ(pIF, pSR);
  2518. //
  2519. // Stop the IF maintenance task if it's running.
  2520. //
  2521. Status = arpTryStopIfMaintenanceTask(
  2522. pIF,
  2523. pTask,
  2524. STAGE_StopMaintenanceTask,
  2525. pSR
  2526. );
  2527. }
  2528. if (PEND(Status)) break;
  2529. // FALL THROUGH
  2530. case STAGE_StopMaintenanceTask:
  2531. {
  2532. LOCKOBJ(pIF, pSR);
  2533. TIMESTAMP("===DeinitIF:MaintenanceTask stopped");
  2534. // Unlink the explicit reference of the broadcast channel destination
  2535. // from the interface.
  2536. //
  2537. if (pIF->pBroadcastDest != NULL)
  2538. {
  2539. PARPCB_DEST pBroadcastDest = pIF->pBroadcastDest;
  2540. pIF->pBroadcastDest = NULL;
  2541. // NOTE: We're unlinking the two with the IF lock (which is
  2542. // is the same as the pBroadcastDest's lock) held.
  2543. // This is OK to do.
  2544. //
  2545. #if RM_EXTRA_CHECKING
  2546. RmUnlinkObjectsEx(
  2547. &pIF->Hdr,
  2548. &pBroadcastDest->Hdr,
  2549. 0x66bda49b,
  2550. ARPASSOC_LINK_IF_OF_BCDEST,
  2551. ARPASSOC_LINK_BCDEST_OF_IF,
  2552. pSR
  2553. );
  2554. #else // !RM_EXTRA_CHECKING
  2555. RmUnlinkObjects(&pIF->Hdr, &pBroadcastDest->Hdr, pSR);
  2556. #endif // !RM_EXTRA_CHECKING
  2557. }
  2558. //
  2559. // If the VC state needs cleaning up, we need to get a task
  2560. // going to clean it up. Other wise we fake the completion of this
  2561. // stage so that we move on to the next...
  2562. //
  2563. if (pIF->recvinfo.VcHdr.NdisVcHandle == NULL)
  2564. {
  2565. UNLOCKOBJ(pIF, pSR);
  2566. Status = NDIS_STATUS_SUCCESS;
  2567. }
  2568. else
  2569. {
  2570. PRM_TASK pCleanupCallTask = pIF->recvinfo.VcHdr.pCleanupCallTask;
  2571. // If there is already an official cleanup-vc task, we pend on it.
  2572. // Other wise we allocate our own, pend on it, and start it.
  2573. //
  2574. if (pCleanupCallTask != NULL)
  2575. {
  2576. TR_WARN((
  2577. "IF %p Cleanup-vc task %p exists; pending on it.\n",
  2578. pIF,
  2579. pCleanupCallTask));
  2580. RmTmpReferenceObject(&pCleanupCallTask->Hdr, pSR);
  2581. UNLOCKOBJ(pIF, pSR);
  2582. RmPendTaskOnOtherTask(
  2583. pTask,
  2584. STAGE_CleanupVcComplete,
  2585. pCleanupCallTask,
  2586. pSR
  2587. );
  2588. RmTmpDereferenceObject(&pCleanupCallTask->Hdr, pSR);
  2589. Status = NDIS_STATUS_PENDING;
  2590. }
  2591. else
  2592. {
  2593. //
  2594. // Start the call cleanup task and pend on int.
  2595. //
  2596. UNLOCKOBJ(pIF, pSR);
  2597. Status = arpAllocateTask(
  2598. &pIF->Hdr, // pParentObject,
  2599. arpTaskCleanupRecvFifoCall, // pfnHandler,
  2600. 0, // Timeout,
  2601. "Task: CleanupRecvFifo on shutdown IF", // szDescrip.
  2602. &pCleanupCallTask,
  2603. pSR
  2604. );
  2605. if (FAIL(Status))
  2606. {
  2607. // Couldn't allocate task.
  2608. //
  2609. TR_WARN(("FATAL: couldn't alloc cleanup call task!\n"));
  2610. }
  2611. else
  2612. {
  2613. Status = RmPendTaskOnOtherTask(
  2614. pTask,
  2615. STAGE_CleanupVcComplete,
  2616. pCleanupCallTask,
  2617. pSR
  2618. );
  2619. ASSERT(!FAIL(Status));
  2620. // RmStartTask uses up the tmpref on the task
  2621. // which was added by arpAllocateTask.
  2622. //
  2623. Status = RmStartTask(
  2624. pCleanupCallTask,
  2625. 0, // UserParam (unused)
  2626. pSR
  2627. );
  2628. // We rely on pending status to decide whether
  2629. // or not to fall through to the next stage.
  2630. //
  2631. Status = NDIS_STATUS_PENDING;
  2632. }
  2633. }
  2634. }
  2635. }
  2636. if (PEND(Status)) break;
  2637. // FALL THROUGH
  2638. case STAGE_CleanupVcComplete:
  2639. {
  2640. TIMESTAMP("===DeinitIF:RecvFifo cleanup complete");
  2641. // Initiate unload of all the items in the LocalIpGroup.
  2642. //
  2643. OBJLOG1(pTask, " Unloading LocalIpGroup 0x%p\n",
  2644. &pIF->LocalIpGroup);
  2645. RmUnloadAllObjectsInGroup(
  2646. &pIF->LocalIpGroup,
  2647. arpAllocateTask,
  2648. arpTaskUnloadLocalIp,
  2649. NULL, // userParam
  2650. pTask, // pTask to unpend when the unload completes.
  2651. STAGE_CloseLocalIpGroup, // uTaskPendCode
  2652. pSR
  2653. );
  2654. Status = NDIS_STATUS_PENDING;
  2655. }
  2656. break;
  2657. case STAGE_CloseLocalIpGroup:
  2658. {
  2659. // Initiate unload of all the items in the RemoteIpGroup.
  2660. //
  2661. TIMESTAMP("===DeinitIF:LocalIp objects cleaned up.");
  2662. OBJLOG1(
  2663. pTask,
  2664. " Unloading RemoteIpGroup 0x%p\n",
  2665. &pIF->RemoteIpGroup
  2666. );
  2667. RmUnloadAllObjectsInGroup(
  2668. &pIF->RemoteIpGroup,
  2669. arpAllocateTask,
  2670. arpTaskUnloadRemoteIp,
  2671. NULL, // userParam
  2672. pTask, // pTask to unpend when the unload is complete.
  2673. STAGE_CloseRemoteIpGroup, // uTaskPendCode
  2674. pSR
  2675. );
  2676. Status = NDIS_STATUS_PENDING;
  2677. }
  2678. break;
  2679. case STAGE_CloseRemoteIpGroup:
  2680. {
  2681. if (ARP_BRIDGE_ENABLED(pAdapter))
  2682. {
  2683. // Initiate unload of all the items in the RemoteEthGroup.
  2684. //
  2685. TIMESTAMP("===DeinitIF:RemoteIp objects cleaned up.");
  2686. OBJLOG1(
  2687. pTask,
  2688. " Unloading RemoteEthGroup 0x%p\n",
  2689. &pIF->RemoteEthGroup
  2690. );
  2691. RmUnloadAllObjectsInGroup(
  2692. &pIF->RemoteEthGroup,
  2693. arpAllocateTask,
  2694. arpTaskUnloadRemoteEth,
  2695. NULL, // userParam
  2696. pTask, // pTask to unpend when the unload is complete.
  2697. STAGE_CloseRemoteEthGroup, // uTaskPendCode
  2698. pSR
  2699. );
  2700. Status = NDIS_STATUS_PENDING;
  2701. break;
  2702. }
  2703. else
  2704. {
  2705. // Bridging not enabled ...
  2706. // FALL THROUGH....
  2707. }
  2708. }
  2709. case STAGE_CloseRemoteEthGroup:
  2710. {
  2711. // Initiate unload of all the items in the DestinationGroup.
  2712. //
  2713. if (ARP_BRIDGE_ENABLED(pAdapter))
  2714. {
  2715. TIMESTAMP("===DeinitIF:RemoteEth Dhcp objects cleaned up.");
  2716. OBJLOG1(pTask, " Unloading EthDhcpGroup 0x%p\n",
  2717. &pIF->EthDhcpGroup);
  2718. RmUnloadAllObjectsInGroup(
  2719. &pIF->EthDhcpGroup,
  2720. arpAllocateTask,
  2721. arpTaskUnloadEthDhcpEntry,
  2722. NULL, // userParam
  2723. pTask, // pTask to unpend when the unload is complete.
  2724. STAGE_CloseRemoteDhcpGroup, // uTaskPendCode
  2725. pSR
  2726. );
  2727. Status = NDIS_STATUS_PENDING;
  2728. break;
  2729. }
  2730. else
  2731. {
  2732. // Bridging not enabled ...
  2733. // FALL THROUGH....
  2734. }
  2735. }
  2736. case STAGE_CloseRemoteDhcpGroup:
  2737. {
  2738. // Initiate unload of all the items in the DestinationGroup.
  2739. //
  2740. TIMESTAMP("===DeinitIF:RemoteIp objects cleaned up.");
  2741. OBJLOG1(pTask, " Unloading DestinationGroup 0x%p\n",
  2742. &pIF->DestinationGroup);
  2743. RmUnloadAllObjectsInGroup(
  2744. &pIF->DestinationGroup,
  2745. arpAllocateTask,
  2746. arpTaskUnloadDestination,
  2747. NULL, // userParam
  2748. pTask, // pTask to unpend when the unload is complete.
  2749. STAGE_CloseDestinationGroup, // uTaskPendCode
  2750. pSR
  2751. );
  2752. Status = NDIS_STATUS_PENDING;
  2753. }
  2754. break;
  2755. case STAGE_CloseDestinationGroup:
  2756. {
  2757. //
  2758. // Unlink the special "destination VCs"
  2759. //
  2760. LOCKOBJ(pIF, pSR);
  2761. TIMESTAMP("===DeinitIF:Destination objects cleaned up.");
  2762. if (pIF->pMultiChannelDest != NULL)
  2763. {
  2764. PARPCB_DEST pMultiChannelDest = pIF->pMultiChannelDest;
  2765. pIF->pMultiChannelDest = NULL;
  2766. // NOTE: We're unlinking the two with the IF lock (which is
  2767. // is the same as the pBroadcastDest's lock) held.
  2768. // This is OK to do.
  2769. //
  2770. #if RM_EXTRA_CHECKING
  2771. RmUnlinkObjectsEx(
  2772. &pIF->Hdr,
  2773. &pMultiChannelDest->Hdr,
  2774. 0xf28090bd,
  2775. ARPASSOC_LINK_IF_OF_MCDEST,
  2776. ARPASSOC_LINK_MCDEST_OF_IF,
  2777. pSR
  2778. );
  2779. #else // !RM_EXTRA_CHECKING
  2780. RmUnlinkObjects(&pIF->Hdr, &pMultiChannelDest->Hdr, pSR);
  2781. #endif // !RM_EXTRA_CHECKING
  2782. }
  2783. if (pIF->pEthernetDest != NULL)
  2784. {
  2785. PARPCB_DEST pEthernetDest = pIF->pEthernetDest;
  2786. pIF->pEthernetDest = NULL;
  2787. // NOTE: We're unlinking the two with the IF lock (which is
  2788. // is the same as the pBroadcastDest's lock) held.
  2789. // This is OK to do.
  2790. //
  2791. #if RM_EXTRA_CHECKING
  2792. RmUnlinkObjectsEx(
  2793. &pIF->Hdr,
  2794. &pEthernetDest->Hdr,
  2795. 0xf8eedcd1,
  2796. ARPASSOC_LINK_IF_OF_ETHDEST,
  2797. ARPASSOC_LINK_ETHDEST_OF_IF,
  2798. pSR
  2799. );
  2800. #else // !RM_EXTRA_CHECKING
  2801. RmUnlinkObjects(&pIF->Hdr, &pEthernetDest->Hdr, pSR);
  2802. #endif // !RM_EXTRA_CHECKING
  2803. }
  2804. UNLOCKOBJ(pIF, pSR);
  2805. // If required, switch to passive. This check should obviously be done
  2806. // without any locks held!
  2807. if (!ARP_ATPASSIVE())
  2808. {
  2809. // We're not at passive level, but we need to be when we
  2810. // call IP's del interface. So we switch to passive...
  2811. //
  2812. RmSuspendTask(pTask, STAGE_SwitchedToPassive, pSR);
  2813. RmResumeTaskAsync(pTask, 0, &pShutdownTask->WorkItem, pSR);
  2814. Status = NDIS_STATUS_PENDING;
  2815. }
  2816. else
  2817. {
  2818. Status = NDIS_STATUS_SUCCESS;
  2819. }
  2820. }
  2821. if (PEND(Status)) break;
  2822. // FALL THROUGH
  2823. case STAGE_SwitchedToPassive:
  2824. {
  2825. PVOID IpContext;
  2826. TIMESTAMP("===DeinitIF:Switched to Passive(if we aren't already).");
  2827. // We're now switched to passive
  2828. //
  2829. ASSERT(ARP_ATPASSIVE());
  2830. // If required, del the IP interface.
  2831. //
  2832. LOCKOBJ(pIF, pSR);
  2833. IpContext = pIF->ip.Context;
  2834. if (IpContext == NULL)
  2835. {
  2836. // Pretend that we're waiting on IpClose because
  2837. // we fall through below.
  2838. //
  2839. pShutdownTask->fPendingOnIpClose = TRUE;
  2840. UNLOCKOBJ(pIF, pSR);
  2841. Status = NDIS_STATUS_SUCCESS;
  2842. }
  2843. else
  2844. {
  2845. ASSERT(!ARP_BRIDGE_ENABLED(pAdapter));
  2846. pIF->ip.Context = NULL;
  2847. ASSERT(!pShutdownTask->fPendingOnIpClose);
  2848. // Note: a task's lock is it's parent's lock, and this task's
  2849. // parent is pIF...
  2850. //
  2851. pShutdownTask->fPendingOnIpClose = TRUE;
  2852. UNLOCKOBJ(pIF, pSR);
  2853. // We'll suspend this task, waiting for our ArpIpClose routine to
  2854. // be called...
  2855. //
  2856. RmSuspendTask(pTask, STAGE_CloseIp, pSR);
  2857. TIMESTAMP("===DeinitIF:Calling IP's DellInterface Rtn");
  2858. ArpGlobals.ip.pDelInterfaceRtn(
  2859. IpContext
  2860. ,TRUE // DeleteIndex (unused)
  2861. );
  2862. Status = NDIS_STATUS_PENDING;
  2863. }
  2864. }
  2865. if (PEND(Status)) break;
  2866. // FALL THROUGH
  2867. case STAGE_CloseIp:
  2868. {
  2869. NDIS_HANDLE NdisAfHandle;
  2870. TIMESTAMP("===DeinitIF:Done with deleting IP interface (if there was one)");
  2871. //
  2872. // IP has called our arpIpClose function (if we'd bound to IP)
  2873. // NOTE: Task's locks actually are their parent's locks,
  2874. // which in this case is pIF;
  2875. //
  2876. // We're done with all VCs, etc. Time to close the AF, if it's open.
  2877. //
  2878. LOCKOBJ(pTask, pSR);
  2879. ASSERT(pShutdownTask->fPendingOnIpClose);
  2880. pShutdownTask->fPendingOnIpClose = FALSE;
  2881. NdisAfHandle = pIF->ndis.AfHandle;
  2882. pIF->ndis.AfHandle = NULL;
  2883. UNLOCKOBJ(pTask, pSR);
  2884. if (NdisAfHandle == NULL)
  2885. {
  2886. Status = NDIS_STATUS_SUCCESS;
  2887. }
  2888. else
  2889. {
  2890. //
  2891. // (Debug) Delete the association we added when the
  2892. // address family was opened.
  2893. //
  2894. DBG_DELASSOC(
  2895. &pIF->Hdr, // pObject
  2896. NdisAfHandle, // Instance1
  2897. NULL, // Instance2
  2898. ARPASSOC_IF_OPENAF, // AssociationID
  2899. pSR
  2900. );
  2901. //
  2902. // Suspend task and call NdisCloseAdapter...
  2903. //
  2904. RmSuspendTask(pTask, STAGE_CloseAF, pSR);
  2905. RM_ASSERT_NOLOCKS(pSR);
  2906. TIMESTAMP("===DeinitIF: Calling NdisClCloseAddressFamily");
  2907. Status = NdisClCloseAddressFamily(
  2908. NdisAfHandle
  2909. );
  2910. if (Status != NDIS_STATUS_PENDING)
  2911. {
  2912. ArpCoCloseAfComplete(
  2913. Status,
  2914. (NDIS_HANDLE)pIF
  2915. );
  2916. Status = NDIS_STATUS_PENDING;
  2917. }
  2918. }
  2919. }
  2920. if (PEND(Status)) break;
  2921. // FALL THROUGH
  2922. case STAGE_CloseAF:
  2923. {
  2924. //
  2925. // The close AF operation is complete.
  2926. // We've not got anything else to do.
  2927. //
  2928. TIMESTAMP("===DeinitIF: Done with CloseAF");
  2929. // Recover the last status ...
  2930. //
  2931. Status = (NDIS_STATUS) UserParam;
  2932. // Status of the completed operation can't itself be pending!
  2933. //
  2934. ASSERT(Status != NDIS_STATUS_PENDING);
  2935. //
  2936. // By returning Status != pending, we implicitly complete
  2937. // this task.
  2938. //
  2939. }
  2940. break;
  2941. case STAGE_End:
  2942. {
  2943. //
  2944. // We are done with all async aspects of shutting down the interface.
  2945. // Nothing to do besides clearing the actdeact task.
  2946. //
  2947. LOCKOBJ(pIF, pSR);
  2948. arpClearSecondaryIfTask(pIF, pTask, ARPIF_AS_FAILEDACTIVATE, pSR);
  2949. UNLOCKOBJ(pIF, pSR);
  2950. TIMESTAMP("===DeinitIF: All done!");
  2951. // Force status to be success
  2952. //
  2953. Status = NDIS_STATUS_SUCCESS;
  2954. }
  2955. break;
  2956. default:
  2957. {
  2958. ASSERTEX(!"Unknown task op", pTask);
  2959. }
  2960. break;
  2961. } // switch (Stage)
  2962. RM_ASSERT_NOLOCKS(pSR);
  2963. EXIT()
  2964. return Status;
  2965. }
  2966. NDIS_STATUS
  2967. arpTaskDeinitInterface(
  2968. IN struct _RM_TASK * pTask,
  2969. IN RM_TASK_OPERATION Code,
  2970. IN UINT_PTR UserParam,
  2971. IN PRM_STACK_RECORD pSR
  2972. )
  2973. /*++
  2974. Routine Description:
  2975. Task handler responsible for deinitializing and deleting an interface.
  2976. Arguments:
  2977. UserParam for (Code == RM_TASKOP_START) : unused
  2978. --*/
  2979. {
  2980. NDIS_STATUS Status;
  2981. PARP1394_INTERFACE pIF;
  2982. MYBOOL fTryInitiateUnload;
  2983. enum
  2984. {
  2985. PEND_ExistingPrimaryTaskComplete,
  2986. PEND_DeactivateIfComplete
  2987. };
  2988. ENTER("TaskDeinitInterface", 0xf059b63b)
  2989. Status = NDIS_STATUS_FAILURE;
  2990. pIF = (PARP1394_INTERFACE) RM_PARENT_OBJECT(pTask);
  2991. fTryInitiateUnload = FALSE;
  2992. switch(Code)
  2993. {
  2994. case RM_TASKOP_START:
  2995. {
  2996. fTryInitiateUnload = TRUE;
  2997. }
  2998. break;
  2999. case RM_TASKOP_PENDCOMPLETE:
  3000. {
  3001. switch(RM_PEND_CODE(pTask))
  3002. {
  3003. case PEND_ExistingPrimaryTaskComplete:
  3004. {
  3005. fTryInitiateUnload = TRUE;
  3006. }
  3007. break;
  3008. case PEND_DeactivateIfComplete:
  3009. {
  3010. ASSERT(pIF->pPrimaryTask == pTask);
  3011. // We're done deactivating the IF. We actually delete the IF
  3012. // in the context of the END handler...
  3013. //
  3014. Status = NDIS_STATUS_SUCCESS;
  3015. }
  3016. break;
  3017. }
  3018. }
  3019. break;
  3020. case RM_TASKOP_END:
  3021. {
  3022. //
  3023. // We are done with all async aspects of unloading the interface.
  3024. // Now on to synchronous cleanup and deallocation...
  3025. //
  3026. ARP1394_ADAPTER * pAdapter;
  3027. // Nothing to do if we're not the active primary task.
  3028. //
  3029. if (pIF->pPrimaryTask != pTask)
  3030. {
  3031. // We should only get here if pIF was unloaded by someone else....
  3032. //
  3033. ASSERT(RM_IS_ZOMBIE(pIF));
  3034. Status = NDIS_STATUS_SUCCESS;
  3035. break;
  3036. }
  3037. pAdapter = (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pIF);
  3038. LOCKOBJ(pAdapter, pSR);
  3039. // Remove linkage to adapter. Note: pIF lock is the adapter lock.
  3040. //
  3041. pAdapter = (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pIF);
  3042. ASSERT(pIF->Hdr.pLock == pAdapter->Hdr.pLock);
  3043. ASSERT(pAdapter->pIF == pIF);
  3044. pAdapter->pIF = NULL;
  3045. // Clear ourselves as the primary task of the interface object.
  3046. //
  3047. arpClearPrimaryIfTask(pIF, pTask, ARPIF_PS_DEINITED, pSR);
  3048. // Deallocate the IF (adapter lock must be held when calling this)
  3049. //
  3050. arpDeleteInterface(pIF, pSR);
  3051. UNLOCKOBJ(pAdapter, pSR);
  3052. // Force status to be success
  3053. //
  3054. Status = NDIS_STATUS_SUCCESS;
  3055. }
  3056. break;
  3057. default:
  3058. {
  3059. ASSERTEX(!"Unknown task op", pTask);
  3060. }
  3061. break;
  3062. } // switch (Code)
  3063. if (fTryInitiateUnload)
  3064. {
  3065. LOCKOBJ(pIF, pSR);
  3066. if (pIF->pPrimaryTask!=NULL)
  3067. {
  3068. //
  3069. // There is an existing primary task -- we wait for it to complete.
  3070. //
  3071. PRM_TASK pPrimaryTask = pIF->pPrimaryTask;
  3072. RmTmpReferenceObject(&pPrimaryTask->Hdr, pSR);
  3073. UNLOCKOBJ(pIF,pSR);
  3074. RmPendTaskOnOtherTask(
  3075. pTask,
  3076. PEND_ExistingPrimaryTaskComplete,
  3077. pPrimaryTask,
  3078. pSR
  3079. );
  3080. arpTryAbortPrimaryIfTask(pIF, pSR);
  3081. RmTmpDereferenceObject(&pPrimaryTask->Hdr, pSR);
  3082. Status = NDIS_STATUS_PENDING;
  3083. }
  3084. else if (!RM_IS_ZOMBIE(pIF))
  3085. {
  3086. //
  3087. // There is no primary task currently, and the IF is not already
  3088. // been unloaded -- make pTask the primary task,
  3089. // and initiate deactivation of the IF. When it's done, we'll actually
  3090. // delete the IF.
  3091. //
  3092. arpSetPrimaryIfTask(pIF, pTask, ARPIF_PS_DEINITING, pSR);
  3093. UNLOCKOBJ(pIF,pSR);
  3094. arpDeactivateIf(pIF, pTask, PEND_DeactivateIfComplete, pSR);
  3095. Status = NDIS_STATUS_PENDING;
  3096. }
  3097. else
  3098. {
  3099. // pIF is already unloaded....
  3100. //
  3101. UNLOCKOBJ(pIF, pSR);
  3102. Status = NDIS_STATUS_SUCCESS;
  3103. }
  3104. }
  3105. RM_ASSERT_NOLOCKS(pSR);
  3106. EXIT()
  3107. return Status;
  3108. }
  3109. NDIS_STATUS
  3110. arpTaskReinitInterface(
  3111. IN struct _RM_TASK * pTask,
  3112. IN RM_TASK_OPERATION Code,
  3113. IN UINT_PTR UserParam,
  3114. IN PRM_STACK_RECORD pSR
  3115. )
  3116. /*++
  3117. Routine Description:
  3118. Task handler responsible for reiniting (deactivating, then activating)
  3119. an interface.
  3120. This is a primary interface task.
  3121. Arguments:
  3122. UserParam for (Code == RM_TASKOP_START) : unused
  3123. --*/
  3124. {
  3125. NDIS_STATUS Status;
  3126. PARP1394_INTERFACE pIF;
  3127. MYBOOL fTryInitiateReinit;
  3128. enum
  3129. {
  3130. PEND_ExistingPrimaryTaskComplete,
  3131. PEND_DeactivateIfComplete,
  3132. PEND_ActivateIfComplete,
  3133. PEND_DeinitInterfaceOnFailureComplete
  3134. };
  3135. ENTER("TaskReinitInterface", 0x8b670f05)
  3136. Status = NDIS_STATUS_FAILURE;
  3137. pIF = (PARP1394_INTERFACE) RM_PARENT_OBJECT(pTask);
  3138. fTryInitiateReinit = FALSE;
  3139. switch(Code)
  3140. {
  3141. case RM_TASKOP_START:
  3142. {
  3143. fTryInitiateReinit = TRUE;
  3144. }
  3145. break;
  3146. case RM_TASKOP_PENDCOMPLETE:
  3147. {
  3148. Status = (NDIS_STATUS) UserParam;
  3149. switch(RM_PEND_CODE(pTask))
  3150. {
  3151. case PEND_ExistingPrimaryTaskComplete:
  3152. {
  3153. fTryInitiateReinit = TRUE;
  3154. }
  3155. break;
  3156. case PEND_DeactivateIfComplete:
  3157. {
  3158. //
  3159. // We're done deactivating the IF. We now
  3160. // activate the IF.
  3161. //
  3162. arpActivateIf(pIF, pTask, PEND_ActivateIfComplete, pSR);
  3163. Status = NDIS_STATUS_PENDING;
  3164. }
  3165. break;
  3166. case PEND_ActivateIfComplete:
  3167. {
  3168. // We're done activating the IF.
  3169. //
  3170. LOCKOBJ(pIF, pSR);
  3171. if (FAIL(Status))
  3172. {
  3173. arpClearPrimaryIfTask(pIF, pTask, ARPIF_PS_FAILEDINIT, pSR);
  3174. UNLOCKOBJ(pIF, pSR);
  3175. arpDeinitIf(
  3176. pIF,
  3177. pTask, // pCallingTask
  3178. PEND_DeinitInterfaceOnFailureComplete,
  3179. pSR
  3180. );
  3181. Status = NDIS_STATUS_PENDING;
  3182. }
  3183. else
  3184. {
  3185. //
  3186. // Successful activation. Clear the primary task
  3187. // and set the primary state appropriately.
  3188. //
  3189. arpClearPrimaryIfTask(pIF, pTask, ARPIF_PS_INITED, pSR);
  3190. UNLOCKOBJ(pIF, pSR);
  3191. }
  3192. } // end case PEND_ActivateIfComplete
  3193. break;
  3194. case PEND_DeinitInterfaceOnFailureComplete:
  3195. {
  3196. // We expect pIF to be deallocated...
  3197. //
  3198. ASSERT(RM_IS_ZOMBIE(pIF));
  3199. //
  3200. // We ignore the return status of deinit inteface.
  3201. // and set Status to failure, because it is
  3202. // the reinit interface task that is failing.
  3203. //
  3204. Status = NDIS_STATUS_FAILURE;
  3205. }
  3206. break;
  3207. }
  3208. }
  3209. break;
  3210. case RM_TASKOP_END:
  3211. {
  3212. PARP1394_ADAPTER pAdapter;
  3213. PTASK_REINIT_IF pReinitTask;
  3214. pAdapter = (PARP1394_ADAPTER) RM_PARENT_OBJECT(pIF);
  3215. pReinitTask = (PTASK_REINIT_IF) pTask;
  3216. Status = (NDIS_STATUS) UserParam;
  3217. if (FAIL(Status))
  3218. {
  3219. ASSERT(RM_IS_ZOMBIE(pIF));
  3220. }
  3221. ASSERT(pIF->pPrimaryTask != pTask);
  3222. //
  3223. // IF the reconfig event is non NULL, signal completion of the net pnp
  3224. // event that started this
  3225. // reconfig task. No need to claim any locks here -- the fields
  3226. // referenced below are not going to change...
  3227. //
  3228. if (pReinitTask->pNetPnPEvent != NULL)
  3229. {
  3230. NdisCompletePnPEvent(
  3231. Status,
  3232. pAdapter->bind.AdapterHandle,
  3233. pReinitTask->pNetPnPEvent
  3234. );
  3235. }
  3236. }
  3237. break;
  3238. default:
  3239. {
  3240. ASSERTEX(!"Unknown task op", pTask);
  3241. }
  3242. break;
  3243. } // switch (Code)
  3244. if (fTryInitiateReinit)
  3245. {
  3246. LOCKOBJ(pIF, pSR);
  3247. if (pIF->pPrimaryTask!=NULL)
  3248. {
  3249. //
  3250. // There is an existing primary task -- we wait for it to complete.
  3251. //
  3252. PRM_TASK pPrimaryTask = pIF->pPrimaryTask;
  3253. RmTmpReferenceObject(&pIF->pPrimaryTask->Hdr, pSR);
  3254. UNLOCKOBJ(pIF,pSR);
  3255. RmPendTaskOnOtherTask(
  3256. pTask,
  3257. PEND_ExistingPrimaryTaskComplete,
  3258. pPrimaryTask,
  3259. pSR
  3260. );
  3261. RmTmpDereferenceObject(&pIF->pPrimaryTask->Hdr, pSR);
  3262. Status = NDIS_STATUS_PENDING;
  3263. }
  3264. else
  3265. {
  3266. //
  3267. // There is no primary task currently -- make pTask the primary task,
  3268. // and initiate deactivation of the IF. When it's done, we'll
  3269. // reactivate the IF.
  3270. //
  3271. arpSetPrimaryIfTask(pIF, pTask, ARPIF_PS_REINITING, pSR);
  3272. UNLOCKOBJ(pIF,pSR);
  3273. arpDeactivateIf(pIF, pTask, PEND_DeactivateIfComplete, pSR);
  3274. Status = NDIS_STATUS_PENDING;
  3275. }
  3276. }
  3277. RM_ASSERT_NOLOCKS(pSR);
  3278. EXIT()
  3279. return Status;
  3280. }
  3281. NDIS_STATUS
  3282. arpTaskUnloadLocalIp(
  3283. IN struct _RM_TASK * pTask,
  3284. IN RM_TASK_OPERATION Code,
  3285. IN UINT_PTR UserParam, // Unused
  3286. IN PRM_STACK_RECORD pSR
  3287. )
  3288. /*++
  3289. Routine Description:
  3290. Task handler responsible for shutting down an IP interface.
  3291. 3/26/1999 JosephJ TODO -- this being one of the earlier-written tasks,
  3292. is ripe for a re-write!
  3293. Arguments:
  3294. UserParam for (Code == RM_TASKOP_START) : unused
  3295. --*/
  3296. {
  3297. ENTER("TaskUnloadLocalIp", 0xf42aaa68)
  3298. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  3299. ARPCB_LOCAL_IP* pLocalIp = (ARPCB_LOCAL_IP*) RM_PARENT_OBJECT(pTask);
  3300. ARP1394_INTERFACE *pIF = (ARP1394_INTERFACE*) RM_PARENT_OBJECT(pLocalIp);
  3301. // Following are the list of pending states for this task.
  3302. //
  3303. enum
  3304. {
  3305. PEND_OtherUnloadComplete,
  3306. PEND_AddressRegistrationComplete
  3307. };
  3308. switch(Code)
  3309. {
  3310. case RM_TASKOP_START:
  3311. {
  3312. LOCKOBJ(pLocalIp, pSR);
  3313. // First check if pLocalIp is still allocated, if not we go away.
  3314. //
  3315. if (RM_IS_ZOMBIE(pLocalIp))
  3316. {
  3317. Status = NDIS_STATUS_SUCCESS;
  3318. break;
  3319. }
  3320. //
  3321. // pLocalIp is allocated. Now check if there is already a
  3322. // shutdown task attached to pLocalIp.
  3323. //
  3324. if (pLocalIp->pUnloadTask != NULL)
  3325. {
  3326. //
  3327. // There is a shutdown task. We pend on it.
  3328. //
  3329. PRM_TASK pOtherTask = pLocalIp->pUnloadTask;
  3330. TR_WARN(("Unload task %p exists; pending on it.\n", pOtherTask));
  3331. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  3332. UNLOCKOBJ(pLocalIp, pSR);
  3333. RmPendTaskOnOtherTask(
  3334. pTask,
  3335. PEND_OtherUnloadComplete,
  3336. pOtherTask,
  3337. pSR
  3338. );
  3339. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  3340. Status = NDIS_STATUS_PENDING;
  3341. break;
  3342. }
  3343. //
  3344. // There is no unload task going on. Let's
  3345. // make this task THE unload task.
  3346. //
  3347. pLocalIp->pUnloadTask = pTask;
  3348. //
  3349. // Since we're THE unload task, add an association to pLocalIp,
  3350. // which will only get cleared when the pLocalIp->pUnloadTask field
  3351. // above is cleared.
  3352. //
  3353. DBG_ADDASSOC(
  3354. &pLocalIp->Hdr, // pObject
  3355. pTask, // Instance1
  3356. pTask->Hdr.szDescription, // Instance2
  3357. ARPASSOC_LOCALIP_UNLOAD_TASK, // AssociationID
  3358. " Official unload task 0x%p (%s)\n", // szFormat
  3359. pSR
  3360. );
  3361. //
  3362. // If there is a registration task going, we cancel it and
  3363. // wait for it to complete.
  3364. //
  3365. if (pLocalIp->pRegistrationTask != NULL)
  3366. {
  3367. PRM_TASK pOtherTask = pLocalIp->pRegistrationTask;
  3368. TR_WARN(("Registration task %p exists; pending on it.\n", pOtherTask));
  3369. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  3370. UNLOCKOBJ(pLocalIp, pSR);
  3371. RmPendTaskOnOtherTask(
  3372. pTask,
  3373. PEND_AddressRegistrationComplete,
  3374. pOtherTask,
  3375. pSR
  3376. );
  3377. //
  3378. // TODO Cancel Registration task (we haven't implemented cancel
  3379. // yet!)
  3380. //
  3381. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  3382. Status = NDIS_STATUS_PENDING;
  3383. break;
  3384. }
  3385. //
  3386. // We're here because there is no async unload work to be done.
  3387. // We simply return and finish synchronous cleanup in the END
  3388. // handler for this task.
  3389. //
  3390. Status = NDIS_STATUS_SUCCESS;
  3391. } // START
  3392. break;
  3393. case RM_TASKOP_PENDCOMPLETE:
  3394. {
  3395. switch(RM_PEND_CODE(pTask))
  3396. {
  3397. case PEND_OtherUnloadComplete:
  3398. {
  3399. //
  3400. // There was another unload task going when we started, and
  3401. // it's now complete. Nothing for us to do...
  3402. //
  3403. // TODO need standard way to propagate the error code.
  3404. //
  3405. Status = (NDIS_STATUS) UserParam;
  3406. }
  3407. break;
  3408. case PEND_AddressRegistrationComplete:
  3409. {
  3410. //
  3411. // There was address-registration going on, but how it's
  3412. // complete. We should be able to synchronously clean up
  3413. // this task now
  3414. //
  3415. //
  3416. // If we're here, that means we're THE official unload
  3417. // task. Let's assert that fact.
  3418. // (no need to get the lock on the object).
  3419. //
  3420. ASSERTEX(pLocalIp->pUnloadTask == pTask, pLocalIp);
  3421. Status = NDIS_STATUS_SUCCESS;
  3422. }
  3423. break;
  3424. default:
  3425. {
  3426. ASSERTEX(!"Unknown pend op", pTask);
  3427. }
  3428. break;
  3429. } // end switch(RM_PEND_CODE(pTask))
  3430. } // case RM_TASKOP_PENDCOMPLETE
  3431. break;
  3432. case RM_TASKOP_END:
  3433. {
  3434. LOCKOBJ(pLocalIp, pSR);
  3435. //
  3436. // We're done. There should be no async activities left to do.
  3437. //
  3438. ASSERTEX(pLocalIp->pRegistrationTask == NULL, pLocalIp);
  3439. //
  3440. // If we're THE unload task, we go on and deallocate the object.
  3441. //
  3442. if (pLocalIp->pUnloadTask == pTask)
  3443. {
  3444. PARPCB_DEST pDest = pLocalIp->pDest;
  3445. //
  3446. // pLocalIp had better not be in a zombie state -- THIS task
  3447. // is the one responsible for deallocating the object!
  3448. //
  3449. ASSERTEX(!RM_IS_ZOMBIE(pLocalIp), pLocalIp);
  3450. if (pDest != NULL)
  3451. {
  3452. RmTmpReferenceObject(&pDest->Hdr, pSR);
  3453. arpUnlinkLocalIpFromDest(pLocalIp, pSR);
  3454. }
  3455. pLocalIp->pUnloadTask = NULL;
  3456. // Delete the association we added when we set
  3457. // pLocalIp->pUnloadTask to pTask.
  3458. //
  3459. DBG_DELASSOC(
  3460. &pLocalIp->Hdr, // pObject
  3461. pTask, // Instance1
  3462. pTask->Hdr.szDescription, // Instance2
  3463. ARPASSOC_LOCALIP_UNLOAD_TASK, // AssociationID
  3464. pSR
  3465. );
  3466. RmFreeObjectInGroup(
  3467. &pIF->LocalIpGroup,
  3468. &(pLocalIp->Hdr),
  3469. NULL, // NULL pTask == synchronous.
  3470. pSR
  3471. );
  3472. ASSERTEX(RM_IS_ZOMBIE(pLocalIp), pLocalIp);
  3473. UNLOCKOBJ(pLocalIp, pSR);
  3474. //
  3475. // If we were linked to a pDest, we unload it if it's
  3476. // no longer used by anyone else.
  3477. //
  3478. if (pDest != NULL)
  3479. {
  3480. arpDeinitDestination(pDest, TRUE, pSR); // TRUE==only if
  3481. // unused.
  3482. RmTmpDereferenceObject(&pDest->Hdr, pSR);
  3483. }
  3484. }
  3485. else
  3486. {
  3487. //
  3488. // We weren't THE unload task, nothing left to do.
  3489. // The object had better be in the zombie state..
  3490. //
  3491. ASSERTEX(
  3492. pLocalIp->pUnloadTask == NULL && RM_IS_ZOMBIE(pLocalIp),
  3493. pLocalIp
  3494. );
  3495. Status = NDIS_STATUS_SUCCESS;
  3496. }
  3497. Status = (NDIS_STATUS) UserParam;
  3498. }
  3499. break; // RM_TASKOP_END:
  3500. default:
  3501. {
  3502. ASSERTEX(!"Unexpected task op", pTask);
  3503. }
  3504. break;
  3505. } // switch (Code)
  3506. RmUnlockAll(pSR);
  3507. EXIT()
  3508. return Status;
  3509. }
  3510. NDIS_STATUS
  3511. arpTaskUnloadRemoteIp(
  3512. IN struct _RM_TASK * pTask,
  3513. IN RM_TASK_OPERATION Code,
  3514. IN UINT_PTR UserParam,
  3515. IN PRM_STACK_RECORD pSR
  3516. )
  3517. /*++
  3518. This task is responsible for shuttingdown and eventually deleting a remote IP
  3519. object.
  3520. It goes through the following stages:
  3521. - Cancel any ongoing address resolution and wait for that to complete.
  3522. - Unlink itself from a Destination object, if it's linked to one.
  3523. - Remove itself from the interface's LocalIpGroup (and thereby deallocate
  3524. itself).
  3525. UserParam for (Code == RM_TASKOP_START) : unused
  3526. --*/
  3527. {
  3528. ENTER("TaskUnloadRemoteIp", 0xf42aaa68)
  3529. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  3530. ARPCB_REMOTE_IP* pRemoteIp = (ARPCB_REMOTE_IP*) RM_PARENT_OBJECT(pTask);
  3531. ARP1394_INTERFACE *pIF = (ARP1394_INTERFACE*) RM_PARENT_OBJECT(pRemoteIp);
  3532. // Following are the list of pending states for this task.
  3533. //
  3534. enum
  3535. {
  3536. PEND_AtPassiveLevel,
  3537. PEND_OtherUnloadComplete,
  3538. PEND_SendPktsComplete,
  3539. PEND_ResolutionComplete
  3540. };
  3541. switch(Code)
  3542. {
  3543. case RM_TASKOP_START:
  3544. {
  3545. LOCKOBJ(pRemoteIp, pSR);
  3546. // First check if pRemoteIp is still allocated, if not we go away.
  3547. //
  3548. if (RM_IS_ZOMBIE(pRemoteIp))
  3549. {
  3550. Status = NDIS_STATUS_SUCCESS;
  3551. break;
  3552. }
  3553. //
  3554. // pRemoteIp is allocated. Now check if there is already a
  3555. // shutdown task attached to pRemoteIp.
  3556. //
  3557. if (pRemoteIp->pUnloadTask != NULL)
  3558. {
  3559. //
  3560. // There is a shutdown task. We pend on it.
  3561. //
  3562. PRM_TASK pOtherTask = pRemoteIp->pUnloadTask;
  3563. TR_WARN(("Unload task %p exists; pending on it.\n", pOtherTask));
  3564. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  3565. UNLOCKOBJ(pRemoteIp, pSR);
  3566. RmPendTaskOnOtherTask(
  3567. pTask,
  3568. PEND_OtherUnloadComplete,
  3569. pOtherTask,
  3570. pSR
  3571. );
  3572. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  3573. Status = NDIS_STATUS_PENDING;
  3574. break;
  3575. }
  3576. //
  3577. // There is no unload task going on. Let's
  3578. // make this task THE unload task.
  3579. //
  3580. pRemoteIp->pUnloadTask = pTask;
  3581. //
  3582. // Since we're THE unload task, add an association to pRemoteIp,
  3583. // which will only get cleared when the pRemoteIp->pUnloadTask field
  3584. // above is cleared.
  3585. //
  3586. DBG_ADDASSOC(
  3587. &pRemoteIp->Hdr, // pObject
  3588. pTask, // Instance1
  3589. pTask->Hdr.szDescription, // Instance2
  3590. ARPASSOC_REMOTEIP_UNLOAD_TASK, // AssociationID
  3591. " Official unload task 0x%p (%s)\n", // szFormat
  3592. pSR
  3593. );
  3594. //
  3595. // if we are at dpc level then resume at passive
  3596. //
  3597. RmSuspendTask(pTask, PEND_AtPassiveLevel, pSR);
  3598. UNLOCKOBJ(pRemoteIp,pSR);
  3599. Status = NDIS_STATUS_PENDING;
  3600. if (!ARP_ATPASSIVE())
  3601. {
  3602. // We're not at passive level, . So we switch to passive...
  3603. //
  3604. RmResumeTaskAsync(
  3605. pTask,
  3606. Status,
  3607. &((TASK_UNLOAD_REMOTE*)pTask)->WorkItem,
  3608. pSR
  3609. );
  3610. }
  3611. else
  3612. {
  3613. // We resume right away if we are already at passive
  3614. RmResumeTask(pTask,PEND_AtPassiveLevel,pSR);
  3615. }
  3616. } // START
  3617. break;
  3618. case RM_TASKOP_PENDCOMPLETE:
  3619. {
  3620. switch(RM_PEND_CODE(pTask))
  3621. {
  3622. case PEND_AtPassiveLevel:
  3623. {
  3624. LOCKOBJ (pRemoteIp, pSR);
  3625. //
  3626. // If there is a SendPkts task going, we cancel it and
  3627. // wait for it to complete.
  3628. // WARNING: We only do this check and wait ONCE. So we RELY
  3629. // on the fact that once there is a NONNULL pRemoteIp->pUnloadTask,
  3630. // NO NEW pSendPktsTasks will bind itself to pRemoteIP. If you
  3631. // look at the code for arpTaskSendPktsOnRemoteIp, you will
  3632. // see that it does not bind itself if pRemoteIp->pUnloadTask is nonnull
  3633. //
  3634. if (pRemoteIp->pSendPktsTask != NULL)
  3635. {
  3636. PRM_TASK pOtherTask = pRemoteIp->pSendPktsTask;
  3637. TR_WARN(("SendPkts task %p exists; pending on it.\n", pOtherTask));
  3638. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  3639. UNLOCKOBJ(pRemoteIp, pSR);
  3640. RmPendTaskOnOtherTask(
  3641. pTask,
  3642. PEND_SendPktsComplete,
  3643. pOtherTask,
  3644. pSR
  3645. );
  3646. //
  3647. // TODO Cancel SendPks task (we haven't implemented cancel
  3648. // yet!)
  3649. //
  3650. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  3651. Status = NDIS_STATUS_PENDING;
  3652. break;
  3653. }
  3654. //
  3655. // We're here because there is no async unload work to be done.
  3656. // We simply return and finish synchronous cleanup in the END
  3657. // handler for this task.
  3658. //
  3659. if (pRemoteIp->pResolutionTask != NULL)
  3660. {
  3661. PRM_TASK pOtherTask = pRemoteIp->pResolutionTask ;
  3662. TR_WARN(("Resolution task %p exists; pending on it.\n", pOtherTask));
  3663. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  3664. UNLOCKOBJ(pRemoteIp, pSR);
  3665. RmPendTaskOnOtherTask(
  3666. pTask,
  3667. PEND_ResolutionComplete,
  3668. pOtherTask,
  3669. pSR
  3670. );
  3671. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  3672. Status = NDIS_STATUS_PENDING;
  3673. break;
  3674. }
  3675. //
  3676. // If there were no tasks pending then we have completed our task.
  3677. //
  3678. Status = NDIS_STATUS_SUCCESS;
  3679. }
  3680. break;
  3681. case PEND_OtherUnloadComplete:
  3682. {
  3683. //
  3684. // There was another unload task going when we started, and
  3685. // it's now complete. Nothing for us to do...
  3686. //
  3687. // TODO need standard way to propagate the error code.
  3688. //
  3689. Status = (NDIS_STATUS) UserParam;
  3690. }
  3691. break;
  3692. case PEND_SendPktsComplete:
  3693. {
  3694. //
  3695. // There was a SendPktsTask going on, but how it's
  3696. // complete. We should be able to synchronously clean up
  3697. // this task now
  3698. //
  3699. //
  3700. // If we're here, that means we're THE official unload
  3701. // task. Let's assert that fact.
  3702. // (no need to get the lock on the object).
  3703. //
  3704. ASSERT(pRemoteIp->pUnloadTask == pTask);
  3705. Status = NDIS_STATUS_SUCCESS;
  3706. }
  3707. break;
  3708. case PEND_ResolutionComplete:
  3709. {
  3710. //
  3711. // There was a resolution Task going on, but how it's
  3712. // complete. We should be able to synchronously clean up
  3713. // this task now
  3714. //
  3715. //
  3716. // If we're here, that means we're THE official unload
  3717. // task. Let's assert that fact.
  3718. // (no need to get the lock on the object).
  3719. //
  3720. ASSERT(pRemoteIp->pUnloadTask == pTask);
  3721. Status = NDIS_STATUS_SUCCESS;
  3722. }
  3723. break;
  3724. default:
  3725. {
  3726. ASSERTEX(!"Unknown pend op", pTask);
  3727. }
  3728. break;
  3729. } // end switch(RM_PEND_CODE(pTask))
  3730. } // case RM_TASKOP_PENDCOMPLETE
  3731. break;
  3732. case RM_TASKOP_END:
  3733. {
  3734. LOCKOBJ(pRemoteIp, pSR);
  3735. //
  3736. // We're done. There should be no async activities left to do.
  3737. //
  3738. ASSERTEX(pRemoteIp->pResolutionTask == NULL, pRemoteIp);
  3739. ASSERTEX(pRemoteIp->pSendPktsTask == NULL, pRemoteIp);
  3740. //
  3741. // If we're THE unload task, we go on and deallocate the object.
  3742. //
  3743. if (pRemoteIp->pUnloadTask == pTask)
  3744. {
  3745. PARPCB_DEST pDest = pRemoteIp->pDest;
  3746. //
  3747. // pRemoteIp had better not be in a zombie state -- THIS task
  3748. // is the one responsible for deallocating the object!
  3749. //
  3750. ASSERTEX(!RM_IS_ZOMBIE(pRemoteIp), pRemoteIp);
  3751. if (pDest != NULL)
  3752. {
  3753. RmTmpReferenceObject(&pDest->Hdr, pSR);
  3754. arpUnlinkRemoteIpFromDest(pRemoteIp, pSR);
  3755. }
  3756. pRemoteIp->pUnloadTask = NULL;
  3757. // Del the association between pRCE and pRemoteIp...
  3758. //
  3759. ARP_WRITELOCK_IF_SEND_LOCK(pIF, pSR);
  3760. arpDelRceList(pRemoteIp, pSR);
  3761. ARP_UNLOCK_IF_SEND_LOCK(pIF, pSR);
  3762. RmFreeObjectInGroup(
  3763. &pIF->RemoteIpGroup,
  3764. &(pRemoteIp->Hdr),
  3765. NULL, // NULL pTask == synchronous.
  3766. pSR
  3767. );
  3768. ASSERTEX(RM_IS_ZOMBIE(pRemoteIp), pRemoteIp);
  3769. // Delete the association we added when we set
  3770. // pRemoteIp->pUnloadTask to pTask.
  3771. //
  3772. DBG_DELASSOC(
  3773. &pRemoteIp->Hdr, // pObject
  3774. pTask, // Instance1
  3775. pTask->Hdr.szDescription, // Instance2
  3776. ARPASSOC_REMOTEIP_UNLOAD_TASK, // AssociationID
  3777. pSR
  3778. );
  3779. UNLOCKOBJ(pRemoteIp, pSR);
  3780. //
  3781. // If we were linked to a pDest, we unload it if it's
  3782. // no longer used by anyone else.
  3783. //
  3784. if (pDest != NULL)
  3785. {
  3786. arpDeinitDestination(pDest, TRUE, pSR); // TRUE==only if
  3787. // unused.
  3788. RmTmpDereferenceObject(&pDest->Hdr, pSR);
  3789. }
  3790. }
  3791. else
  3792. {
  3793. //
  3794. // We weren't THE unload task, nothing left to do.
  3795. // The object had better be in the zombie state..
  3796. //
  3797. ASSERTEX(
  3798. pRemoteIp->pUnloadTask == NULL && RM_IS_ZOMBIE(pRemoteIp),
  3799. pRemoteIp
  3800. );
  3801. Status = NDIS_STATUS_SUCCESS;
  3802. }
  3803. Status = (NDIS_STATUS) UserParam;
  3804. }
  3805. break; // RM_TASKOP_END:
  3806. default:
  3807. {
  3808. ASSERTEX(!"Unexpected task op", pTask);
  3809. }
  3810. break;
  3811. } // switch (Code)
  3812. RmUnlockAll(pSR);
  3813. EXIT()
  3814. return Status;
  3815. }
  3816. NDIS_STATUS
  3817. arpTaskUnloadRemoteEth(
  3818. IN struct _RM_TASK * pTask,
  3819. IN RM_TASK_OPERATION Code,
  3820. IN UINT_PTR UserParam,
  3821. IN PRM_STACK_RECORD pSR
  3822. )
  3823. /*++
  3824. This task is responsible for shuttingdown and eventually deleting a remote IP
  3825. object.
  3826. It goes through the following stages:
  3827. - Cancel any ongoing address resolution and wait for that to complete.
  3828. - Unlink itself from a Destination object, if it's linked to one.
  3829. - Remove itself from the interface's LocalIpGroup (and thereby deallocate
  3830. itself).
  3831. UserParam for (Code == RM_TASKOP_START) : unused
  3832. --*/
  3833. {
  3834. ENTER("TaskUnloadRemoteEth", 0xf42aaa68)
  3835. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  3836. ARPCB_REMOTE_ETH* pRemoteEth = (ARPCB_REMOTE_ETH*) RM_PARENT_OBJECT(pTask);
  3837. ARP1394_INTERFACE *pIF = (ARP1394_INTERFACE*) RM_PARENT_OBJECT(pRemoteEth);
  3838. // Following are the list of pending states for this task.
  3839. //
  3840. enum
  3841. {
  3842. PEND_AtPassiveLevel,
  3843. PEND_OtherUnloadComplete
  3844. };
  3845. switch(Code)
  3846. {
  3847. case RM_TASKOP_START:
  3848. {
  3849. LOCKOBJ(pRemoteEth, pSR);
  3850. // First check if pRemoteEth is still allocated, if not we go away.
  3851. //
  3852. if (RM_IS_ZOMBIE(pRemoteEth))
  3853. {
  3854. Status = NDIS_STATUS_SUCCESS;
  3855. break;
  3856. }
  3857. //
  3858. // pRemoteEth is allocated. Now check if there is already a
  3859. // shutdown task attached to pRemoteEth.
  3860. //
  3861. if (pRemoteEth->pUnloadTask != NULL)
  3862. {
  3863. //
  3864. // There is a shutdown task. We pend on it.
  3865. //
  3866. PRM_TASK pOtherTask = pRemoteEth->pUnloadTask;
  3867. TR_WARN(("Unload task %p exists; pending on it.\n", pOtherTask));
  3868. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  3869. UNLOCKOBJ(pRemoteEth, pSR);
  3870. RmPendTaskOnOtherTask(
  3871. pTask,
  3872. PEND_OtherUnloadComplete,
  3873. pOtherTask,
  3874. pSR
  3875. );
  3876. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  3877. Status = NDIS_STATUS_PENDING;
  3878. break;
  3879. }
  3880. //
  3881. // There is no unload task going on. Let's
  3882. // make this task THE unload task.
  3883. //
  3884. pRemoteEth->pUnloadTask = pTask;
  3885. //
  3886. // Since we're THE unload task, add an association to pRemoteEth,
  3887. // which will only get cleared when the pRemoteEth->pUnloadTask field
  3888. // above is cleared.
  3889. //
  3890. DBG_ADDASSOC(
  3891. &pRemoteEth->Hdr, // pObject
  3892. pTask, // Instance1
  3893. pTask->Hdr.szDescription, // Instance2
  3894. ARPASSOC_REMOTEETH_UNLOAD_TASK, // AssociationID
  3895. " Official unload task 0x%p (%s)\n", // szFormat
  3896. pSR
  3897. );
  3898. //
  3899. // We're here because there is no async unload work to be done.
  3900. //
  3901. // if we are at dpc level then resume at passive
  3902. //
  3903. RmSuspendTask(pTask, PEND_AtPassiveLevel, pSR);
  3904. UNLOCKOBJ(pRemoteEth,pSR);
  3905. Status = NDIS_STATUS_PENDING;
  3906. if (!ARP_ATPASSIVE())
  3907. {
  3908. // We're not at passive level, . So we switch to passive...
  3909. //
  3910. RmResumeTaskAsync(
  3911. pTask,
  3912. Status,
  3913. &((TASK_UNLOAD_REMOTE*)pTask)->WorkItem,
  3914. pSR
  3915. );
  3916. }
  3917. else
  3918. {
  3919. // We resume right away if we are already at passive
  3920. RmResumeTask(pTask,PEND_AtPassiveLevel,pSR);
  3921. }
  3922. } // START
  3923. break;
  3924. case RM_TASKOP_PENDCOMPLETE:
  3925. {
  3926. switch(RM_PEND_CODE(pTask))
  3927. {
  3928. case PEND_AtPassiveLevel:
  3929. {
  3930. //
  3931. Status = NDIS_STATUS_SUCCESS;
  3932. }
  3933. break;
  3934. case PEND_OtherUnloadComplete:
  3935. {
  3936. //
  3937. // There was another unload task going when we started, and
  3938. // it's now complete. Nothing for us to do...
  3939. //
  3940. // TODO need standard way to propagate the error code.
  3941. //
  3942. Status = (NDIS_STATUS) UserParam;
  3943. }
  3944. break;
  3945. default:
  3946. {
  3947. ASSERTEX(!"Unknown pend op", pTask);
  3948. }
  3949. break;
  3950. } // end switch(RM_PEND_CODE(pTask))
  3951. } // case RM_TASKOP_PENDCOMPLETE
  3952. break;
  3953. case RM_TASKOP_END:
  3954. {
  3955. LOCKOBJ(pRemoteEth, pSR);
  3956. //
  3957. // We're done. There should be no async activities left to do.
  3958. //
  3959. //
  3960. // If we're THE unload task, we go on and deallocate the object.
  3961. //
  3962. if (pRemoteEth->pUnloadTask == pTask)
  3963. {
  3964. //
  3965. // pRemoteEth had better not be in a zombie state -- THIS task
  3966. // is the one responsible for deallocating the object!
  3967. //
  3968. ASSERTEX(!RM_IS_ZOMBIE(pRemoteEth), pRemoteEth);
  3969. pRemoteEth->pUnloadTask = NULL;
  3970. RmFreeObjectInGroup(
  3971. &pIF->RemoteEthGroup,
  3972. &(pRemoteEth->Hdr),
  3973. NULL, // NULL pTask == synchronous.
  3974. pSR
  3975. );
  3976. ASSERTEX(RM_IS_ZOMBIE(pRemoteEth), pRemoteEth);
  3977. // Delete the association we added when we set
  3978. // pRemoteEth->pUnloadTask to pTask.
  3979. //
  3980. DBG_DELASSOC(
  3981. &pRemoteEth->Hdr, // pObject
  3982. pTask, // Instance1
  3983. pTask->Hdr.szDescription, // Instance2
  3984. ARPASSOC_REMOTEETH_UNLOAD_TASK, // AssociationID
  3985. pSR
  3986. );
  3987. UNLOCKOBJ(pRemoteEth, pSR);
  3988. }
  3989. else
  3990. {
  3991. //
  3992. // We weren't THE unload task, nothing left to do.
  3993. // The object had better be in the zombie state..
  3994. //
  3995. ASSERTEX(
  3996. pRemoteEth->pUnloadTask == NULL && RM_IS_ZOMBIE(pRemoteEth),
  3997. pRemoteEth
  3998. );
  3999. Status = NDIS_STATUS_SUCCESS;
  4000. }
  4001. Status = (NDIS_STATUS) UserParam;
  4002. }
  4003. break; // RM_TASKOP_END:
  4004. default:
  4005. {
  4006. ASSERTEX(!"Unexpected task op", pTask);
  4007. }
  4008. break;
  4009. } // switch (Code)
  4010. RmUnlockAll(pSR);
  4011. EXIT()
  4012. return Status;
  4013. }
  4014. NDIS_STATUS
  4015. arpTaskUnloadDestination(
  4016. IN struct _RM_TASK * pTask,
  4017. IN RM_TASK_OPERATION Code,
  4018. IN UINT_PTR UserParam,
  4019. IN PRM_STACK_RECORD pSR
  4020. )
  4021. /*++
  4022. Routine Description:
  4023. Task handler responsible for unloading a destination.
  4024. Arguments:
  4025. UserParam for (Code == RM_TASKOP_START) : unused
  4026. --*/
  4027. {
  4028. ENTER("TaskUnloadDestination", 0x93f66831)
  4029. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  4030. ARPCB_DEST* pDest = (ARPCB_DEST*) RM_PARENT_OBJECT(pTask);
  4031. ARP1394_INTERFACE *pIF = (ARP1394_INTERFACE*) RM_PARENT_OBJECT(pDest);
  4032. // Following are the list of pending states for this task.
  4033. //
  4034. enum
  4035. {
  4036. PEND_OtherUnloadComplete,
  4037. PEND_CleanupVcComplete
  4038. };
  4039. switch(Code)
  4040. {
  4041. case RM_TASKOP_START:
  4042. {
  4043. LOCKOBJ(pDest, pSR);
  4044. // First check if pDest is still allocated, if not we go away.
  4045. //
  4046. if (RM_IS_ZOMBIE(pDest))
  4047. {
  4048. Status = NDIS_STATUS_SUCCESS;
  4049. break;
  4050. }
  4051. //
  4052. // pDest is allocated. Now check if there is already a
  4053. // shutdown task attached to pDest.
  4054. //
  4055. if (pDest->pUnloadTask != NULL)
  4056. {
  4057. //
  4058. // There is a shutdown task. We pend on it.
  4059. //
  4060. PRM_TASK pOtherTask = pDest->pUnloadTask;
  4061. TR_WARN(("Unload task %p exists; pending on it.\n", pOtherTask));
  4062. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  4063. UNLOCKOBJ(pDest, pSR);
  4064. RmPendTaskOnOtherTask(
  4065. pTask,
  4066. PEND_OtherUnloadComplete,
  4067. pOtherTask,
  4068. pSR
  4069. );
  4070. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  4071. Status = NDIS_STATUS_PENDING;
  4072. break;
  4073. }
  4074. //
  4075. // There is no unload task going on. Let's
  4076. // make this task THE unload task.
  4077. //
  4078. pDest->pUnloadTask = pTask;
  4079. //
  4080. // Since we're THE unload task, add an association to pDest,
  4081. // which will only get cleared when the pDest->pUnloadTask field
  4082. // above is cleared.
  4083. //
  4084. DBG_ADDASSOC(
  4085. &pDest->Hdr, // pObject
  4086. pTask, // Instance1
  4087. pTask->Hdr.szDescription, // Instance2
  4088. ARPASSOC_DEST_UNLOAD_TASK, // AssociationID
  4089. " Official unload task 0x%p (%s)\n", // szFormat
  4090. pSR
  4091. );
  4092. //
  4093. // If the VC state needs cleaning up, we need to get a task
  4094. // going to clean it up.
  4095. //
  4096. if (arpNeedToCleanupDestVc(pDest))
  4097. {
  4098. PRM_TASK pCleanupCallTask = pDest->VcHdr.pCleanupCallTask;
  4099. // If there is already an official cleanup-vc task, we pend on it.
  4100. // Other wise we allocate our own, pend on it, and start it.
  4101. //
  4102. if (pCleanupCallTask != NULL)
  4103. {
  4104. TR_WARN((
  4105. "Cleanup-vc task %p exists; pending on it.\n",
  4106. pCleanupCallTask));
  4107. RmTmpReferenceObject(&pCleanupCallTask->Hdr, pSR);
  4108. UNLOCKOBJ(pDest, pSR);
  4109. RmPendTaskOnOtherTask(
  4110. pTask,
  4111. PEND_CleanupVcComplete,
  4112. pCleanupCallTask,
  4113. pSR
  4114. );
  4115. RmTmpDereferenceObject(&pCleanupCallTask->Hdr, pSR);
  4116. Status = NDIS_STATUS_PENDING;
  4117. break;
  4118. }
  4119. else
  4120. {
  4121. //
  4122. // Start the call cleanup task and pend on int.
  4123. //
  4124. UNLOCKOBJ(pDest, pSR);
  4125. RM_ASSERT_NOLOCKS(pSR);
  4126. Status = arpAllocateTask(
  4127. &pDest->Hdr, // pParentObject,
  4128. arpTaskCleanupCallToDest, // pfnHandler,
  4129. 0, // Timeout,
  4130. "Task: CleanupCall on UnloadDest", // szDescription
  4131. &pCleanupCallTask,
  4132. pSR
  4133. );
  4134. if (FAIL(Status))
  4135. {
  4136. TR_WARN(("FATAL: couldn't alloc cleanup call task!\n"));
  4137. }
  4138. else
  4139. {
  4140. RmPendTaskOnOtherTask(
  4141. pTask,
  4142. PEND_CleanupVcComplete,
  4143. pCleanupCallTask, // task to pend on
  4144. pSR
  4145. );
  4146. // RmStartTask uses up the tmpref on the task
  4147. // which was added by arpAllocateTask.
  4148. //
  4149. Status = RmStartTask(
  4150. pCleanupCallTask,
  4151. 0, // UserParam (unused)
  4152. pSR
  4153. );
  4154. }
  4155. break;
  4156. }
  4157. }
  4158. //
  4159. // We're here because there is no async unload work to be done.
  4160. // We simply return and finish synchronous cleanup in the END
  4161. // handler for this task.
  4162. //
  4163. Status = NDIS_STATUS_SUCCESS;
  4164. } // START
  4165. break;
  4166. case RM_TASKOP_PENDCOMPLETE:
  4167. {
  4168. switch(RM_PEND_CODE(pTask))
  4169. {
  4170. case PEND_OtherUnloadComplete:
  4171. {
  4172. //
  4173. // There was another unload task going when we started, and
  4174. // it's now complete. Nothing for us to do...
  4175. //
  4176. // TODO need standard way to propagate the error code.
  4177. //
  4178. Status = (NDIS_STATUS) UserParam;
  4179. }
  4180. break;
  4181. case PEND_CleanupVcComplete:
  4182. {
  4183. //
  4184. // There was vc-cleanup to be done, but how it's
  4185. // complete. We should be able to synchronously clean up
  4186. // this task now
  4187. //
  4188. #if DBG
  4189. LOCKOBJ(pDest, pSR);
  4190. ASSERTEX(!arpNeedToCleanupDestVc(pDest), pDest);
  4191. //
  4192. // If we're here, that means we're THE official unload
  4193. // task. Let's assert that fact.
  4194. //
  4195. ASSERT(pDest->pUnloadTask == pTask);
  4196. UNLOCKOBJ(pDest, pSR);
  4197. #endif DBG
  4198. Status = NDIS_STATUS_SUCCESS;
  4199. }
  4200. break;
  4201. default:
  4202. {
  4203. ASSERTEX(!"Unknown pend op", pTask);
  4204. }
  4205. break;
  4206. } // end switch(RM_PEND_CODE(pTask))
  4207. } // case RM_TASKOP_PENDCOMPLETE
  4208. break;
  4209. case RM_TASKOP_END:
  4210. {
  4211. LOCKOBJ(pDest, pSR);
  4212. //
  4213. // We're done. There should be no async activities left to do.
  4214. //
  4215. ASSERTEX(!arpNeedToCleanupDestVc(pDest), pDest);
  4216. //
  4217. // If we're THE unload task, we go on and deallocate the object.
  4218. //
  4219. if (pDest->pUnloadTask == pTask)
  4220. {
  4221. //
  4222. // pDest had better not be in a zombie state -- THIS task
  4223. // is the one responsible for deallocating the object!
  4224. //
  4225. ASSERTEX(!RM_IS_ZOMBIE(pDest), pDest);
  4226. arpUnlinkAllRemoteIpsFromDest(pDest, pSR);
  4227. RmFreeObjectInGroup(
  4228. &pIF->DestinationGroup,
  4229. &(pDest->Hdr),
  4230. NULL, // NULL pTask == synchronous.
  4231. pSR
  4232. );
  4233. ASSERTEX(RM_IS_ZOMBIE(pDest), pDest);
  4234. pDest->pUnloadTask = NULL;
  4235. // Delete the association we added when we set
  4236. // pDest->pUnloadTask to pTask.
  4237. //
  4238. DBG_DELASSOC(
  4239. &pDest->Hdr, // pObject
  4240. pTask, // Instance1
  4241. pTask->Hdr.szDescription, // Instance2
  4242. ARPASSOC_DEST_UNLOAD_TASK, // AssociationID
  4243. pSR
  4244. );
  4245. }
  4246. else
  4247. {
  4248. //
  4249. // We weren't THE unload task, nothing left to do.
  4250. // The object had better be in the zombie state..
  4251. //
  4252. ASSERTEX(
  4253. pDest->pUnloadTask == NULL && RM_IS_ZOMBIE(pDest),
  4254. pDest
  4255. );
  4256. Status = NDIS_STATUS_SUCCESS;
  4257. }
  4258. Status = (NDIS_STATUS) UserParam;
  4259. }
  4260. break; // RM_TASKOP_END:
  4261. default:
  4262. {
  4263. ASSERTEX(!"Unexpected task op", pTask);
  4264. }
  4265. break;
  4266. } // switch (Code)
  4267. RmUnlockAll(pSR);
  4268. EXIT()
  4269. return Status;
  4270. }
  4271. // The following structure is to define a set of hard-coded arp entries...
  4272. //
  4273. typedef struct
  4274. {
  4275. IP_ADDRESS IpAddress;
  4276. NIC1394_FIFO_ADDRESS DestFifoAddr;
  4277. } UNICAST_REMOTE_IP_INFO;
  4278. // FakeDestinationsInfo contains information to setup a set of hard-coded
  4279. // arp entries..
  4280. //
  4281. UNICAST_REMOTE_IP_INFO
  4282. FakeDestinationsInfo[] =
  4283. {
  4284. //
  4285. //{IpAddr, {UniqueID, OffLow, OffHi}}
  4286. //
  4287. #if 0
  4288. {0x0100000a, {0, 0, 0x100}}, // 10.0.0.1 -> (0, 0, 0x100)
  4289. {0x0200000a, {0, 0, 0x100}}, // 10.0.0.2
  4290. {0x0300000a, {0, 0, 0x100}}, // 10.0.0.3
  4291. {0x0400000a, {0, 0, 0x100}}, // 10.0.0.4
  4292. {0x020000e0, {0, 0, 0x100}}, // 224.0.0.2 (mcast port)
  4293. {0xff00000a, {0, 0, 0x100}}, // 10.0.0.-1 (local bcast)
  4294. {0xffffffff, {0, 0, 0x100}}, // -1.-1.-1.-1 (bcast)
  4295. #endif //0
  4296. {0, {0, 0, 0}}, // Must be last -- Indicates end.
  4297. };
  4298. VOID
  4299. arpAddStaticArpEntries(
  4300. IN ARP1394_INTERFACE *pIF, // LOCKING LOCKOUT
  4301. IN PRM_STACK_RECORD pSR
  4302. )
  4303. /*++
  4304. Routine Description:
  4305. Add static items into the RemoteIp group (the arp cache).
  4306. TODO: we currently put in some fake entries.
  4307. --*/
  4308. {
  4309. UNICAST_REMOTE_IP_INFO *pRemoteIpInfo;
  4310. RM_DBG_ASSERT_LOCKED(&pIF->Hdr, pSR);
  4311. for(
  4312. pRemoteIpInfo = FakeDestinationsInfo;
  4313. pRemoteIpInfo->IpAddress != 0;
  4314. pRemoteIpInfo++)
  4315. {
  4316. NDIS_STATUS Status;
  4317. Status = arpAddOneStaticArpEntry(
  4318. pIF,
  4319. pRemoteIpInfo->IpAddress,
  4320. &pRemoteIpInfo->DestFifoAddr,
  4321. pSR
  4322. );
  4323. if (FAIL(Status))
  4324. {
  4325. break;
  4326. }
  4327. }
  4328. }
  4329. VOID
  4330. arpLinkRemoteIpToDest(
  4331. ARPCB_REMOTE_IP *pRemoteIp, // LOCKIN LOCKOUT
  4332. ARPCB_DEST *pDest, // LOCKIN LOCKOUT
  4333. PRM_STACK_RECORD pSR
  4334. )
  4335. /*++
  4336. Routine Description:
  4337. Link a remote IP entry (pRemoteIp) to the specified destination HW entry
  4338. (pDest). Update the pRemoteIp's state to indicate that this
  4339. is resolved.
  4340. --*/
  4341. {
  4342. ENTER("arpLinkRemoteIpToDest", 0x3be06bc6)
  4343. ARP_DUMP_MAPPING(
  4344. pRemoteIp->IpAddress,
  4345. (pDest==NULL)? NULL : &pDest->Params.HwAddr,
  4346. "Linking Remote IP");
  4347. TR_INFO(("Linking IP 0x%08lx to Dest addr 0x%08lx\n",
  4348. pRemoteIp->IpAddress,
  4349. (UINT) pDest->Params.HwAddr.FifoAddress.UniqueID // Truncation
  4350. ));
  4351. RM_DBG_ASSERT_LOCKED(&pRemoteIp->Hdr, pSR);
  4352. RM_DBG_ASSERT_LOCKED(&pDest->Hdr, pSR);
  4353. if (pRemoteIp->pDest != NULL)
  4354. {
  4355. ASSERT(!"pRemoteIp->pDest != NULL");
  4356. }
  4357. else
  4358. {
  4359. pRemoteIp->pDest = pDest;
  4360. InsertHeadList(&pDest->listIpToThisDest, &pRemoteIp->linkSameDest);
  4361. #if RM_EXTRA_CHECKING
  4362. RmLinkObjectsEx(
  4363. &pRemoteIp->Hdr,
  4364. &pDest->Hdr,
  4365. 0x597d0495,
  4366. ARPASSOC_LINK_IPADDR_OF_DEST,
  4367. " REMOTE_IP of 0x%p (%s)\n",
  4368. ARPASSOC_LINK_DEST_OF_IPADDR,
  4369. " DEST of 0x%p (%s)\n",
  4370. pSR
  4371. );
  4372. #else // !RM_EXTRA_CHECKING
  4373. RmLinkObjects(&pRemoteIp->Hdr, &pDest->Hdr, pSR);
  4374. #endif // !RM_EXTRA_CHECKING
  4375. // Now set the pRemoteIp state to reflect that it RESOLVED.
  4376. //
  4377. SET_REMOTEIP_RESOLVE_STATE(pRemoteIp, ARPREMOTEIP_RESOLVED);
  4378. }
  4379. EXIT()
  4380. }
  4381. VOID
  4382. arpUnlinkRemoteIpFromDest(
  4383. ARPCB_REMOTE_IP *pRemoteIp, // LOCKIN LOCKOUT
  4384. PRM_STACK_RECORD pSR
  4385. )
  4386. /*++
  4387. Routine Description:
  4388. Unlink the remote IP entry (pRemoteIp) from the destination HW entry its
  4389. linked to. Clear pRemoteIp's resolved flag.
  4390. --*/
  4391. {
  4392. ENTER("arpUnlinkRemoteIpFromDest", 0xc5809147)
  4393. ARPCB_DEST *pDest = pRemoteIp->pDest;
  4394. ARP_DUMP_MAPPING(
  4395. pRemoteIp->Key.IpAddress,
  4396. (pDest==NULL)? NULL : &pDest->Params.HwAddr,
  4397. "Unlink Remote IP");
  4398. TR_INFO(("Unlinking IP 0x%p (Addr 0x%08lx) from Dest 0x%p (addr 0x%08lx)\n",
  4399. pRemoteIp,
  4400. pRemoteIp->Key.IpAddress,
  4401. pDest,
  4402. (pDest==NULL)
  4403. ? 0
  4404. :((UINT) pDest->Params.HwAddr.FifoAddress.UniqueID) // Truncation
  4405. ));
  4406. if (pDest == NULL)
  4407. {
  4408. ASSERT(!"pRemoteIp->pDest == NULL");
  4409. }
  4410. else
  4411. {
  4412. //
  4413. // We assume that both objects share the same lock.
  4414. //
  4415. ASSERT(pRemoteIp->Hdr.pLock == pDest->Hdr.pLock);
  4416. RM_DBG_ASSERT_LOCKED(&pRemoteIp->Hdr, pSR);
  4417. RemoveEntryList(&pRemoteIp->linkSameDest);
  4418. pRemoteIp->pDest = NULL;
  4419. // Now set the pRemoteIp state to reflect that it UNRESOLVED.
  4420. //
  4421. SET_REMOTEIP_RESOLVE_STATE(pRemoteIp, ARPREMOTEIP_UNRESOLVED);
  4422. #if RM_EXTRA_CHECKING
  4423. RmUnlinkObjectsEx(
  4424. &pRemoteIp->Hdr,
  4425. &pDest->Hdr,
  4426. 0x5ad067aa,
  4427. ARPASSOC_LINK_IPADDR_OF_DEST,
  4428. ARPASSOC_LINK_DEST_OF_IPADDR,
  4429. pSR
  4430. );
  4431. #else // !RM_EXTRA_CHECKING
  4432. RmUnlinkObjects(&pRemoteIp->Hdr, &pDest->Hdr, pSR);
  4433. #endif // !RM_EXTRA_CHECKING
  4434. }
  4435. EXIT()
  4436. }
  4437. VOID
  4438. arpUnlinkAllRemoteIpsFromDest(
  4439. ARPCB_DEST *pDest, // LOCKIN LOCKOUT
  4440. PRM_STACK_RECORD pSR
  4441. )
  4442. /*++
  4443. Routine Description:
  4444. Unlink all RemoteIps (if any) from destination pDest.
  4445. --*/
  4446. {
  4447. ENTER("arpUnlinkAllRemoteIpsFromDest", 0x35120630)
  4448. TR_INFO(("Unlinking All RemoteIps from Dest 0x%p (addr 0x%08lx)\n",
  4449. pDest,
  4450. ((UINT) pDest->Params.HwAddr.FifoAddress.UniqueID) // Truncation
  4451. ));
  4452. RM_DBG_ASSERT_LOCKED(&pDest->Hdr, pSR);
  4453. while (!IsListEmpty(&pDest->listIpToThisDest))
  4454. {
  4455. LIST_ENTRY *pLink;
  4456. ARPCB_REMOTE_IP *pRemoteIp;
  4457. pLink = RemoveHeadList(&pDest->listIpToThisDest);
  4458. pRemoteIp = CONTAINING_RECORD(
  4459. pLink,
  4460. ARPCB_REMOTE_IP,
  4461. linkSameDest
  4462. );
  4463. arpUnlinkRemoteIpFromDest(pRemoteIp, pSR);
  4464. }
  4465. EXIT()
  4466. }
  4467. VOID
  4468. arpLinkLocalIpToDest(
  4469. ARPCB_LOCAL_IP *pLocalIp, // LOCKIN LOCKOUT
  4470. ARPCB_DEST *pDest, // LOCKIN LOCKOUT
  4471. PRM_STACK_RECORD pSR
  4472. )
  4473. /*++
  4474. Routine Description:
  4475. Link a remote IP entry (pLocalIp) to the specified destination HW entry
  4476. (pDest). Update the pLocalIp's state to indicate that this
  4477. is resolved.
  4478. --*/
  4479. {
  4480. ENTER("arpLinkLocalIpToDest", 0x3be06bc6)
  4481. ARP_DUMP_MAPPING(pLocalIp->IpAddress, &pDest->Params.HwAddr, "Linking Local IP");
  4482. #if 0
  4483. TR_INFO(("Linking Local IP 0x%08lx to Dest addr 0x%08lx\n",
  4484. pLocalIp->IpAddress,
  4485. (UINT) pDest->Params.HwAddr.FifoAddress.UniqueID // Truncation
  4486. ));
  4487. #endif // 0
  4488. RM_DBG_ASSERT_LOCKED(&pLocalIp->Hdr, pSR);
  4489. RM_DBG_ASSERT_LOCKED(&pDest->Hdr, pSR);
  4490. if (pLocalIp->pDest != NULL)
  4491. {
  4492. ASSERT(!"pLocalIp->pDest != NULL");
  4493. }
  4494. else
  4495. {
  4496. //
  4497. // LocalIps may only be linked to pDests of type
  4498. // ReceiveOnly.
  4499. //
  4500. ASSERT(pDest->Params.ReceiveOnly);
  4501. pLocalIp->pDest = pDest;
  4502. InsertHeadList(&pDest->listLocalIp, &pLocalIp->linkSameDest);
  4503. #if RM_EXTRA_CHECKING
  4504. RmLinkObjectsEx(
  4505. &pLocalIp->Hdr,
  4506. &pDest->Hdr,
  4507. 0x597d0495,
  4508. ARPASSOC_LINK_IPADDR_OF_DEST,
  4509. " LOCAL_IP of 0x%p (%s)\n",
  4510. ARPASSOC_LINK_DEST_OF_IPADDR,
  4511. " DEST of Local 0x%p (%s)\n",
  4512. pSR
  4513. );
  4514. #else // !RM_EXTRA_CHECKING
  4515. RmLinkObjects(&pLocalIp->Hdr, &pDest->Hdr, pSR);
  4516. #endif // !RM_EXTRA_CHECKING
  4517. }
  4518. EXIT()
  4519. }
  4520. VOID
  4521. arpUnlinkLocalIpFromDest(
  4522. ARPCB_LOCAL_IP *pLocalIp, // LOCKIN LOCKOUT
  4523. PRM_STACK_RECORD pSR
  4524. )
  4525. /*++
  4526. Routine Description:
  4527. Unlink the local IP entry (pLocalIp) from the destination HW entry its
  4528. linked to.
  4529. --*/
  4530. {
  4531. ENTER("arpUnlinkLocalIpFromDest", 0xc5809147)
  4532. ARPCB_DEST *pDest = pLocalIp->pDest;
  4533. ARP_DUMP_MAPPING(
  4534. pLocalIp->IpAddress,
  4535. (pDest==NULL)? NULL : &pDest->Params.HwAddr,
  4536. "Unlink Local IP");
  4537. TR_INFO(("Unlinking Local IP 0x%p (Addr 0x%08lx) from Dest 0x%p (addr 0x%08lx)\n",
  4538. pLocalIp,
  4539. pLocalIp->IpAddress,
  4540. pDest,
  4541. (pDest==NULL)
  4542. ? 0
  4543. :((UINT) pDest->Params.HwAddr.FifoAddress.UniqueID) // Truncation
  4544. ));
  4545. if (pDest == NULL)
  4546. {
  4547. ASSERT(!"pLocalIp->pDest == NULL");
  4548. }
  4549. else
  4550. {
  4551. //
  4552. // We assume that both objects share the same lock.
  4553. //
  4554. ASSERT(pLocalIp->Hdr.pLock == pDest->Hdr.pLock);
  4555. RM_DBG_ASSERT_LOCKED(&pLocalIp->Hdr, pSR);
  4556. //
  4557. // LocalIps may only be unlinked from pDests of type
  4558. // ReceiveOnly.
  4559. //
  4560. ASSERT(pDest->Params.ReceiveOnly);
  4561. RemoveEntryList(&pLocalIp->linkSameDest);
  4562. #if RM_EXTRA_CHECKING
  4563. RmUnlinkObjectsEx(
  4564. &pLocalIp->Hdr,
  4565. &pDest->Hdr,
  4566. 0x5ad067aa,
  4567. ARPASSOC_LINK_IPADDR_OF_DEST,
  4568. ARPASSOC_LINK_DEST_OF_IPADDR,
  4569. pSR
  4570. );
  4571. #else // !RM_EXTRA_CHECKING
  4572. RmUnlinkObjects(&pLocalIp->Hdr, &pDest->Hdr, pSR);
  4573. #endif // !RM_EXTRA_CHECKING
  4574. pLocalIp->pDest = NULL;
  4575. }
  4576. EXIT()
  4577. }
  4578. VOID
  4579. arpUnlinkAllLocalIpsFromDest(
  4580. ARPCB_DEST *pDest, // LOCKIN LOCKOUT
  4581. PRM_STACK_RECORD pSR
  4582. )
  4583. /*++
  4584. Routine Description:
  4585. Unlink all Localif any) from destination pDest.
  4586. --*/
  4587. {
  4588. ENTER("arpUnlinkAllLocalIpsFromDest", 0x35120630)
  4589. TR_INFO(("Unlinking All LocalIps from Dest 0x%p (addr 0x%08lx)\n",
  4590. pDest,
  4591. ((UINT) pDest->Params.HwAddr.FifoAddress.UniqueID) // Truncation
  4592. ));
  4593. RM_DBG_ASSERT_LOCKED(&pDest->Hdr, pSR);
  4594. //
  4595. // LocalIps may only be unlinked from pDests of type
  4596. // ReceiveOnly.
  4597. //
  4598. ASSERT(pDest->Params.ReceiveOnly);
  4599. while (!IsListEmpty(&pDest->listLocalIp))
  4600. {
  4601. LIST_ENTRY *pLink;
  4602. ARPCB_LOCAL_IP *pLocalIp;
  4603. pLink = RemoveHeadList(&pDest->listLocalIp);
  4604. pLocalIp = CONTAINING_RECORD(
  4605. pLink,
  4606. ARPCB_LOCAL_IP,
  4607. linkSameDest
  4608. );
  4609. arpUnlinkLocalIpFromDest(pLocalIp, pSR);
  4610. }
  4611. EXIT()
  4612. }
  4613. MYBOOL
  4614. arpNeedToCleanupDestVc(
  4615. ARPCB_DEST *pDest // LOCKING LOCKOUT
  4616. )
  4617. /*++
  4618. Routine Description:
  4619. Deterinine if we need to do any cleanup work on destination pDest.
  4620. "Cleanup work" includes if there is any ongoing asynchronous activity
  4621. involving pDest, such as a make call or close call in progress.
  4622. Return Value:
  4623. TRUE iff there is cleanup work to be done.
  4624. FALSE otherwise.
  4625. --*/
  4626. {
  4627. // Note -- return true if pDest->VcHdr.pCleanupCallTask is non-NULL, even if there
  4628. // is nothing else to be done -- we do have to wait for this pCleanupCallTask
  4629. // to complete.
  4630. if ( pDest->VcHdr.pMakeCallTask != NULL
  4631. || pDest->VcHdr.pCleanupCallTask!=NULL
  4632. || pDest->VcHdr.NdisVcHandle!=NULL)
  4633. {
  4634. return TRUE;
  4635. }
  4636. else
  4637. {
  4638. return FALSE;
  4639. }
  4640. }
  4641. PRM_OBJECT_HEADER
  4642. arpLocalIpCreate(
  4643. PRM_OBJECT_HEADER pParentObject,
  4644. PVOID pCreateParams,
  4645. PRM_STACK_RECORD pSR
  4646. )
  4647. /*++
  4648. Routine Description:
  4649. Allocate and initialize an object of type ARPCB_LOCAL_IP.
  4650. Arguments:
  4651. pParentObject - Actually a pointer to the interface (ARP1394_INTERFACE)
  4652. pCreateParams - Actually the IP address (not a pointer to the IP address)
  4653. to associate with this local IP.
  4654. Return Value:
  4655. Pointer to the allocated and initialized object on success.
  4656. NULL otherwise.
  4657. --*/
  4658. {
  4659. ARPCB_LOCAL_IP *pLocalIp;
  4660. PRM_OBJECT_HEADER pHdr;
  4661. NDIS_STATUS Status;
  4662. Status = ARP_ALLOCSTRUCT(pLocalIp, MTAG_LOCAL_IP);
  4663. if (Status != NDIS_STATUS_SUCCESS || pLocalIp== NULL)
  4664. {
  4665. return NULL;
  4666. }
  4667. ARP_ZEROSTRUCT(pLocalIp);
  4668. pHdr = (PRM_OBJECT_HEADER) pLocalIp;
  4669. ASSERT(pHdr == &pLocalIp->Hdr);
  4670. // We expect the parent object to be the IF object!
  4671. //
  4672. ASSERT(pParentObject->Sig == MTAG_INTERFACE);
  4673. if (pHdr)
  4674. {
  4675. RmInitializeHeader(
  4676. pParentObject,
  4677. pHdr,
  4678. MTAG_LOCAL_IP,
  4679. pParentObject->pLock,
  4680. &ArpGlobal_LocalIpStaticInfo,
  4681. NULL, // szDescription
  4682. pSR
  4683. );
  4684. pLocalIp->IpAddress = (IP_ADDRESS) (UINT_PTR) pCreateParams;
  4685. }
  4686. return pHdr;
  4687. }
  4688. VOID
  4689. arpLocalIpDelete(
  4690. PRM_OBJECT_HEADER pHdr,
  4691. PRM_STACK_RECORD pSR
  4692. )
  4693. /*++
  4694. Routine Description:
  4695. Free an object of type ARPCB_LOCAL_IP.
  4696. Arguments:
  4697. pHdr - Actually a pointer to the local ip object to be freed.
  4698. --*/
  4699. {
  4700. ARPCB_LOCAL_IP *pLocalIp = (ARPCB_LOCAL_IP *) pHdr;
  4701. ASSERT(pLocalIp->Hdr.Sig == MTAG_LOCAL_IP);
  4702. pLocalIp->Hdr.Sig = MTAG_FREED;
  4703. ARP_FREE(pHdr);
  4704. }
  4705. PRM_OBJECT_HEADER
  4706. arpRemoteIpCreate(
  4707. PRM_OBJECT_HEADER pParentObject,
  4708. PVOID pCreateParams,
  4709. PRM_STACK_RECORD pSR
  4710. )
  4711. /*++
  4712. Routine Description:
  4713. Allocate and initialize an object of type ARPCB_REMOTE_IP.
  4714. Arguments:
  4715. pParentObject - Actually a pointer to the interface (ARP1394_INTERFACE)
  4716. pCreateParams - Actually the IP address (not a pointer to the IP address)
  4717. to associate with this remote IP object.
  4718. Return Value:
  4719. Pointer to the allocated and initialized object on success.
  4720. NULL otherwise.
  4721. --*/
  4722. {
  4723. ARPCB_REMOTE_IP *pRemoteIp;
  4724. PRM_OBJECT_HEADER pHdr;
  4725. NDIS_STATUS Status;
  4726. Status = ARP_ALLOCSTRUCT(pRemoteIp, MTAG_REMOTE_IP);
  4727. if (Status != NDIS_STATUS_SUCCESS || pRemoteIp == NULL)
  4728. {
  4729. return NULL;
  4730. }
  4731. ARP_ZEROSTRUCT(pRemoteIp);
  4732. pHdr = (PRM_OBJECT_HEADER) pRemoteIp;
  4733. ASSERT(pHdr == &pRemoteIp->Hdr);
  4734. // We expect the parent object to be the IF object!
  4735. //
  4736. ASSERT(pParentObject->Sig == MTAG_INTERFACE);
  4737. if (pHdr)
  4738. {
  4739. RmInitializeHeader(
  4740. pParentObject,
  4741. pHdr,
  4742. MTAG_REMOTE_IP,
  4743. pParentObject->pLock,
  4744. &ArpGlobal_RemoteIpStaticInfo,
  4745. NULL, // szDescription
  4746. pSR
  4747. );
  4748. pRemoteIp->IpAddress = (IP_ADDRESS) (UINT_PTR) pCreateParams;
  4749. // Initialize various other stuff...
  4750. InitializeListHead(&pRemoteIp->sendinfo.listSendPkts);
  4751. if (arpCanTryMcap(pRemoteIp->IpAddress))
  4752. {
  4753. SET_REMOTEIP_MCAP(pRemoteIp, ARPREMOTEIP_MCAP_CAPABLE);
  4754. }
  4755. }
  4756. return pHdr;
  4757. }
  4758. PRM_OBJECT_HEADER
  4759. arpRemoteEthCreate(
  4760. PRM_OBJECT_HEADER pParentObject,
  4761. PVOID pCreateParams,
  4762. PRM_STACK_RECORD pSR
  4763. )
  4764. /*++
  4765. Routine Description:
  4766. Allocate and initialize an object of type ARPCB_REMOTE_ETH.
  4767. Arguments:
  4768. pParentObject - Actually a pointer to the interface (ARP1394_INTERFACE)
  4769. pCreateParams - Points to a ARP_REMOTE_ETH_PARAMS structure
  4770. to associate with this remote IP object.
  4771. Return Value:
  4772. Pointer to the allocated and initialized object on success.
  4773. NULL otherwise.
  4774. --*/
  4775. {
  4776. ARPCB_REMOTE_ETH *pRemoteEth;
  4777. PARP_REMOTE_ETH_PARAMS pMyParams = (PARP_REMOTE_ETH_PARAMS) pCreateParams;
  4778. PRM_OBJECT_HEADER pHdr;
  4779. NDIS_STATUS Status;
  4780. Status = ARP_ALLOCSTRUCT(pRemoteEth, MTAG_REMOTE_ETH);
  4781. if (Status != NDIS_STATUS_SUCCESS || pRemoteEth == NULL)
  4782. {
  4783. return NULL;
  4784. }
  4785. ARP_ZEROSTRUCT(pRemoteEth);
  4786. pHdr = (PRM_OBJECT_HEADER) pRemoteEth;
  4787. ASSERT(pHdr == &pRemoteEth->Hdr);
  4788. // We expect the parent object to be the IF object!
  4789. //
  4790. ASSERT(pParentObject->Sig == MTAG_INTERFACE);
  4791. if (pHdr)
  4792. {
  4793. RmInitializeHeader(
  4794. pParentObject,
  4795. pHdr,
  4796. MTAG_REMOTE_ETH,
  4797. pParentObject->pLock,
  4798. &ArpGlobal_RemoteEthStaticInfo,
  4799. NULL, // szDescription
  4800. pSR
  4801. );
  4802. pRemoteEth->IpAddress = pMyParams->IpAddress;
  4803. pRemoteEth->EthAddress = pMyParams->EthAddress;
  4804. }
  4805. return pHdr;
  4806. }
  4807. VOID
  4808. arpRemoteIpDelete(
  4809. PRM_OBJECT_HEADER pHdr,
  4810. PRM_STACK_RECORD pSR
  4811. )
  4812. /*++
  4813. Routine Description:
  4814. Free an object of type ARPCB_REMOTE_IP.
  4815. Arguments:
  4816. pHdr - Actually a pointer to the remote ip object to be freed.
  4817. --*/
  4818. {
  4819. ARPCB_REMOTE_IP *pRemoteIp = (ARPCB_REMOTE_IP *) pHdr;
  4820. ASSERT(pRemoteIp->Hdr.Sig == MTAG_REMOTE_IP);
  4821. pRemoteIp->Hdr.Sig = MTAG_FREED;
  4822. ARP_FREE(pHdr);
  4823. }
  4824. VOID
  4825. arpRemoteEthDelete(
  4826. PRM_OBJECT_HEADER pHdr,
  4827. PRM_STACK_RECORD pSR
  4828. )
  4829. /*++
  4830. Routine Description:
  4831. Free an object of type ARPCB_REMOTE_IP.
  4832. Arguments:
  4833. pHdr - Actually a pointer to the remote ip object to be freed.
  4834. --*/
  4835. {
  4836. ARPCB_REMOTE_ETH *pRemoteEth = (ARPCB_REMOTE_ETH *) pHdr;
  4837. ASSERT(pRemoteEth->Hdr.Sig == MTAG_REMOTE_ETH);
  4838. pRemoteEth->Hdr.Sig = MTAG_FREED;
  4839. ARP_FREE(pHdr);
  4840. }
  4841. PRM_OBJECT_HEADER
  4842. arpDestinationCreate(
  4843. PRM_OBJECT_HEADER pParentObject,
  4844. PVOID pCreateParams,
  4845. PRM_STACK_RECORD pSR
  4846. )
  4847. /*++
  4848. Routine Description:
  4849. Allocate and initialize an object of type ARPCB_DEST.
  4850. Arguments:
  4851. pParentObject - Actually a pointer to the interface (ARP1394_INTERFACE)
  4852. pCreateParams - Actually a pointer to a ARP_DEST_KEY containing
  4853. the hw addresses to associate with this object.
  4854. Return Value:
  4855. Pointer to the allocated and initialized object on success.
  4856. NULL otherwise.
  4857. --*/
  4858. {
  4859. ARPCB_DEST *pDest;
  4860. PRM_OBJECT_HEADER pHdr;
  4861. NDIS_STATUS Status;
  4862. Status = ARP_ALLOCSTRUCT(pDest, MTAG_DEST);
  4863. if (Status != NDIS_STATUS_SUCCESS || pDest == NULL)
  4864. {
  4865. return NULL;
  4866. }
  4867. ARP_ZEROSTRUCT(pDest);
  4868. pHdr = (PRM_OBJECT_HEADER) pDest;
  4869. ASSERT(pHdr == &pDest->Hdr);
  4870. // We expect the parent object to be the IF object!
  4871. //
  4872. ASSERT(pParentObject->Sig == MTAG_INTERFACE);
  4873. if (pHdr)
  4874. {
  4875. RmInitializeHeader(
  4876. pParentObject,
  4877. pHdr,
  4878. MTAG_DEST,
  4879. pParentObject->pLock,
  4880. &ArpGlobal_DestinationStaticInfo,
  4881. NULL, // szDescription
  4882. pSR
  4883. );
  4884. pDest->Params = *((PARP_DEST_PARAMS) pCreateParams);
  4885. InitializeListHead(&pDest->listIpToThisDest);
  4886. InitializeListHead(&pDest->listLocalIp);
  4887. }
  4888. return pHdr;
  4889. }
  4890. VOID
  4891. arpDestinationDelete(
  4892. PRM_OBJECT_HEADER pHdr,
  4893. PRM_STACK_RECORD pSR
  4894. )
  4895. /*++
  4896. Routine Description:
  4897. Free an object of type ARPCB_DEST.
  4898. Arguments:
  4899. pHdr - Actually a pointer to the destination object to be freed.
  4900. --*/
  4901. {
  4902. ARPCB_DEST *pDest = (ARPCB_DEST *) pHdr;
  4903. ASSERT(pDest->Hdr.Sig == MTAG_DEST);
  4904. pDest->Hdr.Sig = MTAG_FREED;
  4905. ARP_FREE(pHdr);
  4906. }
  4907. PRM_OBJECT_HEADER
  4908. arpDhcpTableEntryCreate(
  4909. PRM_OBJECT_HEADER pParentObject,
  4910. PVOID pCreateParams,
  4911. PRM_STACK_RECORD pSR
  4912. )
  4913. /*++
  4914. Routine Description:
  4915. Allocate and initialize an object of type ARPCB_REMOTE_IP.
  4916. Arguments:
  4917. pParentObject - Actually a pointer to the interface (ARP1394_INTERFACE)
  4918. pCreateParams - Actually the IP address (not a pointer to the IP address)
  4919. to associate with this remote IP object.
  4920. Return Value:
  4921. Pointer to the allocated and initialized object on success.
  4922. NULL otherwise.
  4923. --*/
  4924. {
  4925. ENTER ("arpRemoteDestCreate", 0xa896311a)
  4926. ARP1394_ETH_DHCP_ENTRY *pEntry = NULL;
  4927. ULONG xid = *(PULONG)pCreateParams;
  4928. PRM_OBJECT_HEADER pHdr;
  4929. NDIS_STATUS Status;
  4930. Status = ARP_ALLOCSTRUCT(pEntry, MTAG_ARP_GENERIC);
  4931. if (Status != NDIS_STATUS_SUCCESS || pEntry == NULL)
  4932. {
  4933. return NULL;
  4934. }
  4935. ARP_ZEROSTRUCT(pEntry);
  4936. pHdr = (PRM_OBJECT_HEADER) pEntry;
  4937. ASSERT(pHdr == &pEntry->Hdr);
  4938. // We expect the parent object to be the IF object!
  4939. //
  4940. ASSERT(pParentObject->Sig == MTAG_INTERFACE);
  4941. if (pHdr)
  4942. {
  4943. RmInitializeHeader(
  4944. pParentObject,
  4945. pHdr,
  4946. MTAG_ARP_GENERIC,
  4947. pParentObject->pLock,
  4948. &ArpGlobal_DhcpTableStaticInfo ,
  4949. NULL, // szDescription
  4950. pSR
  4951. );
  4952. TR_INFO( ("New XID %x \n", xid));
  4953. // set up the key
  4954. pEntry->xid = xid;
  4955. }
  4956. EXIT()
  4957. return pHdr;
  4958. }
  4959. VOID
  4960. arpDhcpTableEntryDelete(
  4961. PRM_OBJECT_HEADER pHdr,
  4962. PRM_STACK_RECORD pSR
  4963. )
  4964. /*++
  4965. Routine Description:
  4966. Free an object of type ARPCB_REMOTE_IP.
  4967. Arguments:
  4968. pHdr - Actually a pointer to the remote ip object to be freed.
  4969. --*/
  4970. {
  4971. ARP1394_ETH_DHCP_ENTRY *pEntry = (ARP1394_ETH_DHCP_ENTRY*) pHdr;
  4972. ASSERT(pEntry->Hdr.Sig == MTAG_ARP_GENERIC);
  4973. pEntry->Hdr.Sig = MTAG_FREED;
  4974. ARP_FREE(pHdr);
  4975. }
  4976. NDIS_STATUS
  4977. arpTaskMakeCallToDest(
  4978. IN struct _RM_TASK * pTask,
  4979. IN RM_TASK_OPERATION Code,
  4980. IN UINT_PTR UserParam,
  4981. IN PRM_STACK_RECORD pSR
  4982. )
  4983. /*++
  4984. This task is responsible for making a call to a destination
  4985. (either send-FIFO or send/recv-CHANNEL).
  4986. Arguments:
  4987. UserParam for (Code == RM_TASKOP_START) : unused
  4988. --*/
  4989. {
  4990. ENTER("TaskMakeCallToDest", 0x25108eaa)
  4991. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  4992. ARPCB_DEST * pDest = (ARPCB_DEST*) RM_PARENT_OBJECT(pTask);
  4993. ARP1394_INTERFACE * pIF = (ARP1394_INTERFACE*) RM_PARENT_OBJECT(pDest);
  4994. TASK_MAKECALL * pMakeCallTask = (TASK_MAKECALL*) pTask;
  4995. // Following are the list of pending states for this task.
  4996. //
  4997. enum
  4998. {
  4999. PEND_OtherMakeCallTaskComplete,
  5000. PEND_MakeCallComplete
  5001. };
  5002. ASSERT(sizeof(ARP1394_TASK) >= sizeof(*pMakeCallTask));
  5003. switch(Code)
  5004. {
  5005. case RM_TASKOP_START:
  5006. {
  5007. BOOLEAN IsFifo;
  5008. PARP_STATIC_VC_INFO pVcStaticInfo;
  5009. LOCKOBJ(pDest, pSR);
  5010. DBGMARK(0x7a74bf2a);
  5011. // First check if pDest is still allocated, if not we go away.
  5012. //
  5013. if (RM_IS_ZOMBIE(pDest))
  5014. {
  5015. Status = NDIS_STATUS_FAILURE;
  5016. break;
  5017. }
  5018. // If there is a call cleanup task in progress, we fail right away...
  5019. //
  5020. if (pDest->VcHdr.pCleanupCallTask != NULL)
  5021. {
  5022. OBJLOG2(
  5023. pDest,
  5024. "Failing MakeCall task %p because Cleanup task %p exists.\n",
  5025. pTask,
  5026. pDest->VcHdr.pCleanupCallTask
  5027. );
  5028. Status = NDIS_STATUS_FAILURE;
  5029. break;
  5030. }
  5031. //
  5032. // pDest is allocated. Now check if there is already a
  5033. // MakeCall task attached to pDest.
  5034. //
  5035. if (pDest->VcHdr.pMakeCallTask != NULL)
  5036. {
  5037. //
  5038. // There is a make-call task. We pend on it.
  5039. //
  5040. PRM_TASK pOtherTask = pDest->VcHdr.pMakeCallTask;
  5041. OBJLOG1(
  5042. pTask,
  5043. "MakeCall task %p exists; pending on it.\n",
  5044. pOtherTask);
  5045. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  5046. UNLOCKOBJ(pDest, pSR);
  5047. RmPendTaskOnOtherTask(
  5048. pTask,
  5049. PEND_OtherMakeCallTaskComplete,
  5050. pOtherTask,
  5051. pSR
  5052. );
  5053. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  5054. Status = NDIS_STATUS_PENDING;
  5055. break;
  5056. }
  5057. //
  5058. // Grab the IF send lock and make sure we're in the position to make a
  5059. // call -- there should be no VC handle.
  5060. // We must do this BEFORE we become the official task, so that we don't
  5061. // wipe out the connection as part of our cleanup.
  5062. //
  5063. ARP_WRITELOCK_IF_SEND_LOCK(pIF, pSR);
  5064. if (pDest->VcHdr.NdisVcHandle != NULL)
  5065. {
  5066. OBJLOG1(
  5067. pTask,
  5068. "VcHandle 0x%p already exists!, failing make call attempt.\n",
  5069. pDest->VcHdr.NdisVcHandle);
  5070. Status = NDIS_STATUS_FAILURE;
  5071. break;
  5072. }
  5073. ASSERT(pDest->sendinfo.OkToSend == FALSE);
  5074. ASSERT(pDest->sendinfo.NumOutstandingSends == 0);
  5075. //
  5076. // There is no MakeCall task going on, and there's no VC handle. Let's
  5077. // make this task THE MakeCall task.
  5078. //
  5079. pDest->VcHdr.pMakeCallTask = pTask;
  5080. //
  5081. // Since we're THE MakeCall task, add an association to pDest,
  5082. // which will only get cleared when the pDest->VcHdr.pMakeCallTask field
  5083. // above is cleared.
  5084. //
  5085. DBG_ADDASSOC(
  5086. &pDest->Hdr, // pObject
  5087. pTask, // Instance1
  5088. pTask->Hdr.szDescription, // Instance2
  5089. ARPASSOC_DEST_MAKECALL_TASK, // AssociationID
  5090. " Official makecall task 0x%p (%s)\n", // szFormat
  5091. pSR
  5092. );
  5093. // Setup call params.
  5094. //
  5095. {
  5096. PNIC1394_MEDIA_PARAMETERS p1394Params =
  5097. (PNIC1394_MEDIA_PARAMETERS)
  5098. &pMakeCallTask->MediaParams.Parameters;
  5099. PNIC1394_DESTINATION pDestAddr = &pDest->Params.HwAddr;
  5100. //No need: ARP_ZEROSTRUCT(&pMakeCallTask->CallParams);
  5101. //No need: ARP_ZEROSTRUCT(&pMakeCallTask->MediaParams);
  5102. pMakeCallTask->CallParams.MediaParameters =
  5103. (PCO_MEDIA_PARAMETERS) &pMakeCallTask->MediaParams;
  5104. pMakeCallTask->MediaParams.ParamType = NIC1394_MEDIA_SPECIFIC;
  5105. IsFifo = FALSE;
  5106. switch(pDestAddr->AddressType)
  5107. {
  5108. case NIC1394AddressType_Channel:
  5109. pMakeCallTask->MediaParams.Flags = TRANSMIT_VC | RECEIVE_VC;
  5110. pVcStaticInfo = &g_ArpBroadcastChannelVcStaticInfo;
  5111. break;
  5112. case NIC1394AddressType_FIFO:
  5113. pMakeCallTask->MediaParams.Flags = TRANSMIT_VC;
  5114. pVcStaticInfo = &g_ArpSendFifoVcStaticInfo;
  5115. IsFifo = TRUE;
  5116. break;
  5117. case NIC1394AddressType_MultiChannel:
  5118. pMakeCallTask->MediaParams.Flags = RECEIVE_VC;
  5119. pVcStaticInfo = &g_ArpMultiChannelVcStaticInfo;
  5120. break;
  5121. case NIC1394AddressType_Ethernet:
  5122. pMakeCallTask->MediaParams.Flags = TRANSMIT_VC | RECEIVE_VC;
  5123. pVcStaticInfo = &g_ArpEthernetVcStaticInfo;
  5124. break;
  5125. default:
  5126. ASSERT(FALSE);
  5127. break;
  5128. }
  5129. TR_INFO(("Our Parameters offset = 0x%lx; Official offset = 0x%lx\n",
  5130. FIELD_OFFSET(ARP1394_CO_MEDIA_PARAMETERS, Parameters),
  5131. FIELD_OFFSET(CO_MEDIA_PARAMETERS, MediaSpecific.Parameters)));
  5132. ASSERT(FIELD_OFFSET(ARP1394_CO_MEDIA_PARAMETERS, Parameters)
  5133. == FIELD_OFFSET(CO_MEDIA_PARAMETERS, MediaSpecific.Parameters));
  5134. p1394Params->Destination = *pDestAddr; // struct copy.
  5135. p1394Params->Flags = NIC1394_VCFLAG_FRAMED;
  5136. p1394Params->MaxSendBlockSize = -1; // (nic should pick)
  5137. p1394Params->MaxSendSpeed = -1; // (nic should pick)
  5138. p1394Params->MTU = ARP1394_ADAPTER_MTU;
  5139. // TODO -- make above based on
  5140. // config.
  5141. }
  5142. // Now create a vc and make the call...
  5143. //
  5144. {
  5145. RmUnlockAll(pSR);
  5146. Status = arpInitializeVc(
  5147. pIF,
  5148. pVcStaticInfo,
  5149. &pDest->Hdr,
  5150. &pDest->VcHdr,
  5151. pSR
  5152. );
  5153. if (FAIL(Status))
  5154. {
  5155. break;
  5156. }
  5157. // Save away the fields within sendinfo...
  5158. //
  5159. ARP_WRITELOCK_IF_SEND_LOCK(pIF, pSR);
  5160. pDest->sendinfo.OkToSend = FALSE;
  5161. pDest->sendinfo.IsFifo = IsFifo;
  5162. ARP_UNLOCK_IF_SEND_LOCK(pIF, pSR);
  5163. RmSuspendTask(pTask, PEND_MakeCallComplete, pSR);
  5164. DBGMARK(0xef9d8be3);
  5165. //
  5166. // Make the Call now
  5167. //
  5168. if (IsFifo)
  5169. {
  5170. LOGSTATS_TotalSendFifoMakeCalls(pIF);
  5171. }
  5172. else
  5173. {
  5174. LOGSTATS_TotalChannelMakeCalls(pIF);
  5175. }
  5176. RM_ASSERT_NOLOCKS(pSR);
  5177. #if ARPDBG_FAKE_CALLS
  5178. Status = arpDbgFakeNdisClMakeCall(
  5179. pDest->VcHdr.NdisVcHandle,
  5180. &pMakeCallTask->CallParams,
  5181. NULL, // ProtocolPartyContext
  5182. NULL, // NdisPartyHandle
  5183. &pDest->Hdr,
  5184. &pDest->VcHdr,
  5185. pSR
  5186. );
  5187. #else // !ARPDBG_FAKE_CALLS
  5188. Status = NdisClMakeCall(
  5189. pDest->VcHdr.NdisVcHandle,
  5190. &pMakeCallTask->CallParams,
  5191. NULL, // ProtocolPartyContext
  5192. NULL // NdisPartyHandle
  5193. );
  5194. #endif // !ARPDBG_FAKE_CALLS
  5195. if (!PEND(Status))
  5196. {
  5197. ArpCoMakeCallComplete(
  5198. Status,
  5199. (NDIS_HANDLE) (&pDest->VcHdr),
  5200. NULL,
  5201. &pMakeCallTask->CallParams
  5202. );
  5203. Status = NDIS_STATUS_PENDING;
  5204. }
  5205. }
  5206. } // START
  5207. break;
  5208. case RM_TASKOP_PENDCOMPLETE:
  5209. {
  5210. switch(RM_PEND_CODE(pTask))
  5211. {
  5212. case PEND_OtherMakeCallTaskComplete:
  5213. {
  5214. //
  5215. // There was another makecall task going when we started, and
  5216. // it's now complete. Nothing for us to do...
  5217. //
  5218. Status = (NDIS_STATUS) UserParam;
  5219. }
  5220. break;
  5221. case PEND_MakeCallComplete:
  5222. {
  5223. //
  5224. // The make call is complete. We're done...
  5225. //
  5226. Status = (NDIS_STATUS) UserParam;
  5227. #if ARPDBG_FAKE_CALLS
  5228. //
  5229. // In the fake case, we give the "user" the opportunity to change
  5230. // the status to Success for the special VC (BROADCAST
  5231. // MCAP, ETHERNET) make call fails,
  5232. // because otherwise the adapter bind itself is going to fail.
  5233. //
  5234. // We do this even in the retail build (if ARPDBG_FAKE_CALLS is
  5235. // enabled).
  5236. //
  5237. if ((1 || FAIL(Status)) && !pDest->sendinfo.IsFifo)
  5238. {
  5239. // To try the failure path of the BC make call, enable
  5240. // the if 0 code. Currently we change status to success
  5241. // so that stress tests which include loading/unloading
  5242. // of the driver will run without breaking here everytime.
  5243. //
  5244. #if 1
  5245. DbgPrint(
  5246. "A13: Fake %s failed. &Status=%p.\n",
  5247. pDest->VcHdr.pStaticInfo->Description,
  5248. &Status
  5249. );
  5250. DbgBreakPoint();
  5251. #else
  5252. Status = NDIS_STATUS_SUCCESS;
  5253. #endif
  5254. }
  5255. #endif // ARPDBG_FAKE_CALLS
  5256. LOCKOBJ(pDest, pSR);
  5257. ASSERT (pDest->VcHdr.pMakeCallTask == pTask);
  5258. ASSERT(pDest->VcHdr.NdisVcHandle != NULL);
  5259. ARP_WRITELOCK_IF_SEND_LOCK(pIF, pSR);
  5260. DBGMARK(0xd50a6864);
  5261. if (FAIL(Status))
  5262. {
  5263. pDest->sendinfo.OkToSend = FALSE;
  5264. }
  5265. else
  5266. {
  5267. //
  5268. // Success! Packets can now be sent over this VC without
  5269. // further ado.
  5270. //
  5271. pDest->sendinfo.OkToSend = TRUE;
  5272. }
  5273. RmUnlockAll(pSR);
  5274. }
  5275. break;
  5276. default:
  5277. {
  5278. ASSERTEX(!"Unknown pend op", pTask);
  5279. }
  5280. break;
  5281. } // end switch(RM_PEND_CODE(pTask))
  5282. } // case RM_TASKOP_PENDCOMPLETE
  5283. break;
  5284. case RM_TASKOP_END:
  5285. {
  5286. Status = (NDIS_STATUS) UserParam;
  5287. LOCKOBJ(pDest, pSR);
  5288. if (pDest->VcHdr.pMakeCallTask == pTask)
  5289. {
  5290. //
  5291. // We're the official pMakeCallTask
  5292. //
  5293. // Delete the association we added when we set
  5294. // pDest->VcHdr.pMakeCallTask to pTask.
  5295. //
  5296. DBG_DELASSOC(
  5297. &pDest->Hdr, // pObject
  5298. pTask, // Instance1
  5299. pTask->Hdr.szDescription, // Instance2
  5300. ARPASSOC_DEST_MAKECALL_TASK, // AssociationID
  5301. pSR
  5302. );
  5303. // Remove reference to us in pDest.
  5304. //
  5305. pDest->VcHdr.pMakeCallTask = NULL;
  5306. if (FAIL(Status) && pDest->VcHdr.NdisVcHandle != NULL)
  5307. {
  5308. UNLOCKOBJ(pDest, pSR);
  5309. // WARNING: the above completely nukes out pDest.VcHdr.
  5310. //
  5311. arpDeinitializeVc(pIF, &pDest->VcHdr, &pDest->Hdr, pSR);
  5312. }
  5313. }
  5314. }
  5315. break;
  5316. default:
  5317. {
  5318. ASSERTEX(!"Unexpected task op", pTask);
  5319. }
  5320. break;
  5321. } // switch (Code)
  5322. RmUnlockAll(pSR);
  5323. EXIT()
  5324. return Status;
  5325. }
  5326. NDIS_STATUS
  5327. arpTaskCleanupCallToDest(
  5328. IN struct _RM_TASK * pTask,
  5329. IN RM_TASK_OPERATION Code,
  5330. IN UINT_PTR UserParam,
  5331. IN PRM_STACK_RECORD pSR
  5332. )
  5333. /*++
  5334. This task is responsible for cleaning up a previously-made call to a
  5335. destination.
  5336. Arguments:
  5337. UserParam for (Code == RM_TASKOP_START) : unused
  5338. --*/
  5339. {
  5340. ENTER("TaskCleanupCallToDest", 0xc89dfb47)
  5341. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  5342. ARPCB_DEST * pDest = (ARPCB_DEST*) RM_PARENT_OBJECT(pTask);
  5343. ARP1394_INTERFACE * pIF = (ARP1394_INTERFACE*) RM_PARENT_OBJECT(pDest);
  5344. MYBOOL fCloseCall = FALSE;
  5345. NDIS_HANDLE NdisVcHandle = NULL;
  5346. // Following are the list of pending states for this task.
  5347. //
  5348. enum
  5349. {
  5350. PEND_OtherCleanupTaskComplete,
  5351. PEND_OutstandingSendsComplete,
  5352. PEND_CloseCallComplete
  5353. };
  5354. DBGMARK(0x6198198e);
  5355. switch(Code)
  5356. {
  5357. case RM_TASKOP_START:
  5358. {
  5359. LOCKOBJ(pDest, pSR);
  5360. // First check if pDest is still allocated, if not we go away.
  5361. //
  5362. if (RM_IS_ZOMBIE(pDest))
  5363. {
  5364. Status = NDIS_STATUS_SUCCESS;
  5365. break;
  5366. }
  5367. //
  5368. // pDest is allocated. Now check if there is already a
  5369. // CleanupCall task attached to pDest.
  5370. //
  5371. if (pDest->VcHdr.pCleanupCallTask != NULL)
  5372. {
  5373. //
  5374. // There is an existing CleanupCall task. We pend on it.
  5375. //
  5376. PRM_TASK pOtherTask = pDest->VcHdr.pCleanupCallTask;
  5377. OBJLOG1(
  5378. pTask,
  5379. "CleanupVc task %p exists; pending on it.\n",
  5380. pOtherTask
  5381. );
  5382. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  5383. UNLOCKOBJ(pDest, pSR);
  5384. RmPendTaskOnOtherTask(
  5385. pTask,
  5386. PEND_OtherCleanupTaskComplete,
  5387. pOtherTask,
  5388. pSR
  5389. );
  5390. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  5391. Status = NDIS_STATUS_PENDING;
  5392. break;
  5393. }
  5394. //
  5395. // There is no CleanupCall task going on. Let's
  5396. // make this task THE CleanupCall task.
  5397. //
  5398. pDest->VcHdr.pCleanupCallTask = pTask;
  5399. //
  5400. // Since we're THE CleanupCall task, add an association to pDest,
  5401. // which will only get cleared when the pDest->VcHdr.pCleanupCallTask field
  5402. // above is cleared.
  5403. //
  5404. DBG_ADDASSOC(
  5405. &pDest->Hdr, // pObject
  5406. pTask, // Instance1
  5407. pTask->Hdr.szDescription, // Instance2
  5408. ARPASSOC_DEST_CLEANUPCALL_TASK, // AssociationID
  5409. " Official CleanupCall task 0x%p (%s)\n", // szFormat
  5410. pSR
  5411. );
  5412. //
  5413. // Grab the IF send lock and disable further sends on this vc;
  5414. // Also if there are pending sends, we'll need to suspend ourselves
  5415. // until all the sends are done.
  5416. //
  5417. ARP_WRITELOCK_IF_SEND_LOCK(pIF, pSR);
  5418. pDest->sendinfo.OkToSend = FALSE;
  5419. // There should be no other task waiting for outstanding sends to
  5420. // complete -- only the OFFICIAL CleanupTask (that's us) explicitly
  5421. // waits for sends to complete.
  5422. //
  5423. ASSERTEX(pDest->sendinfo.pSuspendedCleanupCallTask == NULL,
  5424. pDest->sendinfo.pSuspendedCleanupCallTask);
  5425. if (pDest->sendinfo.NumOutstandingSends != 0)
  5426. {
  5427. DBGMARK(0xea3987f0);
  5428. //
  5429. // Outstanding sends, we need to suspend ourselves until
  5430. // the count goes to zero...
  5431. //
  5432. pDest->sendinfo.pSuspendedCleanupCallTask = pTask;
  5433. // Following association will be cleared when we are resumed
  5434. // after the outstanding sends goes to zero.
  5435. //
  5436. DBG_ADDASSOC(
  5437. &pDest->Hdr, // pObject
  5438. pTask, // Instance1
  5439. pTask->Hdr.szDescription, // Instance2
  5440. ARPASSOC_DEST_CLEANUPCALLTASK_WAITING_ON_SENDS,// AssociationID
  5441. " Vc tasks 0x%p (%s) waiting on outstanding sends\n",
  5442. pSR
  5443. );
  5444. RmSuspendTask(pTask, PEND_OutstandingSendsComplete, pSR);
  5445. Status = NDIS_STATUS_PENDING;
  5446. }
  5447. else
  5448. {
  5449. DBGMARK(0x306bc5c3);
  5450. //
  5451. // If we're here, we're free to go on and close the call.
  5452. //
  5453. fCloseCall = TRUE;
  5454. NdisVcHandle = pDest->VcHdr.NdisVcHandle;
  5455. }
  5456. } // START
  5457. break;
  5458. case RM_TASKOP_PENDCOMPLETE:
  5459. {
  5460. switch(RM_PEND_CODE(pTask))
  5461. {
  5462. case PEND_OtherCleanupTaskComplete:
  5463. {
  5464. //
  5465. // There was another cleanup-vc task going when we started, and
  5466. // it's now complete. Nothing for us to do...
  5467. //
  5468. Status = NDIS_STATUS_SUCCESS;
  5469. }
  5470. break;
  5471. case PEND_OutstandingSendsComplete:
  5472. {
  5473. // We were waiting for outstanding sends to complete, and
  5474. // the last one to complete has resumed us (after setting
  5475. // pDest->sendinfo.pSuspendedCleanupCallTask to NULL).
  5476. //
  5477. ARP_WRITELOCK_IF_SEND_LOCK(pIF, pSR);
  5478. ASSERT(pDest->sendinfo.pSuspendedCleanupCallTask == NULL);
  5479. ASSERT(!ARP_CAN_SEND_ON_DEST(pDest));
  5480. ASSERT(pDest->sendinfo.NumOutstandingSends==0);
  5481. NdisVcHandle = pDest->VcHdr.NdisVcHandle;
  5482. ARP_UNLOCK_IF_SEND_LOCK(pIF, pSR);
  5483. // There were outstanding sends, but how there are none.
  5484. // We should be able to close the call now.
  5485. //
  5486. fCloseCall = TRUE;
  5487. DBGMARK(0xf3b10866);
  5488. Status = NDIS_STATUS_SUCCESS;
  5489. break;
  5490. }
  5491. break;
  5492. case PEND_CloseCallComplete:
  5493. {
  5494. //
  5495. // The close call is complete...
  5496. //
  5497. LOCKOBJ(pDest, pSR);
  5498. ASSERT(pDest->VcHdr.pCleanupCallTask == pTask);
  5499. // Delete the association we added when we set
  5500. // pDest->VcHdr.pCleanupCallTask to pTask.
  5501. //
  5502. DBG_DELASSOC(
  5503. &pDest->Hdr, // pObject
  5504. pTask, // Instance1
  5505. pTask->Hdr.szDescription, // Instance2
  5506. ARPASSOC_DEST_CLEANUPCALL_TASK, // AssociationID
  5507. pSR
  5508. );
  5509. pDest->VcHdr.pCleanupCallTask = NULL;
  5510. RmUnlockAll(pSR);
  5511. DBGMARK(0xa590bb4f);
  5512. arpDeinitializeVc(pIF, &pDest->VcHdr, &pDest->Hdr, pSR);
  5513. Status = NDIS_STATUS_SUCCESS;
  5514. }
  5515. break;
  5516. default:
  5517. {
  5518. ASSERTEX(!"Unknown pend op", pTask);
  5519. }
  5520. break;
  5521. } // end switch(RM_PEND_CODE(pTask))
  5522. } // case RM_TASKOP_PENDCOMPLETE
  5523. break;
  5524. case RM_TASKOP_END:
  5525. {
  5526. LOCKOBJ(pDest, pSR);
  5527. DBGMARK(0xcfc9dbaf);
  5528. //
  5529. // We're done. There should be no async activities left to do.
  5530. //
  5531. #if DBG
  5532. ARP_READLOCK_IF_SEND_LOCK(pIF, pSR);
  5533. ASSERTEX(pDest->VcHdr.NdisVcHandle == NULL, pDest);
  5534. ASSERTEX(!ARP_CAN_SEND_ON_DEST(pDest), pDest);
  5535. ASSERTEX(pDest->sendinfo.NumOutstandingSends==0, pDest);
  5536. ARP_UNLOCK_IF_SEND_LOCK(pIF, pSR);
  5537. #endif DBG
  5538. Status = NDIS_STATUS_SUCCESS;
  5539. }
  5540. break; // RM_TASKOP_END:
  5541. default:
  5542. {
  5543. ASSERTEX(!"Unexpected task op", pTask);
  5544. }
  5545. break;
  5546. } // switch (Code)
  5547. RmUnlockAll(pSR);
  5548. if (fCloseCall)
  5549. {
  5550. DBGMARK(0x653b1cc3);
  5551. RmSuspendTask(pTask, PEND_CloseCallComplete, pSR);
  5552. #if ARPDBG_FAKE_CALLS
  5553. Status = arpDbgFakeNdisClCloseCall(
  5554. NdisVcHandle,
  5555. NULL, // No party handle
  5556. NULL, // No Buffer
  5557. 0, // Size of above
  5558. &pDest->Hdr,
  5559. &pDest->VcHdr,
  5560. pSR
  5561. );
  5562. #else // !ARPDBG_FAKE_CALLS
  5563. Status = NdisClCloseCall(
  5564. NdisVcHandle,
  5565. NULL, // No party handle
  5566. NULL, // No Buffer
  5567. 0 // Size of above
  5568. );
  5569. #endif // !ARPDBG_FAKE_CALLS
  5570. if (Status != NDIS_STATUS_PENDING)
  5571. {
  5572. ArpCoCloseCallComplete(
  5573. Status,
  5574. (NDIS_HANDLE) &pDest->VcHdr,
  5575. (NDIS_HANDLE)NULL
  5576. );
  5577. Status = NDIS_STATUS_PENDING;
  5578. }
  5579. }
  5580. EXIT()
  5581. return Status;
  5582. }
  5583. NDIS_STATUS
  5584. arpTaskMakeRecvFifoCall(
  5585. IN PRM_TASK pTask,
  5586. IN RM_TASK_OPERATION Code,
  5587. IN UINT_PTR UserParam, // Unused
  5588. IN PRM_STACK_RECORD pSR
  5589. )
  5590. /*++
  5591. Routine Description:
  5592. This task is responsible for making a call to the interface's single
  5593. receive FIFO.
  5594. Arguments:
  5595. UserParam for (Code == RM_TASKOP_START) : unused
  5596. --*/
  5597. {
  5598. ENTER("TaskMakeRecvFifoCall", 0x25108eaa)
  5599. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  5600. ARP1394_INTERFACE * pIF = (ARP1394_INTERFACE*) RM_PARENT_OBJECT(pTask);
  5601. TASK_MAKECALL * pMakeCallTask = (TASK_MAKECALL*) pTask;
  5602. // Following are the list of pending states for this task.
  5603. //
  5604. enum
  5605. {
  5606. PEND_OtherMakeCallTaskComplete,
  5607. PEND_MakeCallComplete
  5608. };
  5609. ASSERT(sizeof(ARP1394_TASK) >= sizeof(*pMakeCallTask));
  5610. switch(Code)
  5611. {
  5612. case RM_TASKOP_START:
  5613. {
  5614. LOCKOBJ(pIF, pSR);
  5615. DBGMARK(0x6d7d9959);
  5616. // If there is a call cleanup task in progress, we fail right away...
  5617. //
  5618. if (pIF->recvinfo.VcHdr.pCleanupCallTask != NULL)
  5619. {
  5620. OBJLOG2(
  5621. pIF,
  5622. "Failing MakeCall task %p because Cleanup task %p exists.\n",
  5623. pIF,
  5624. pIF->recvinfo.VcHdr.pCleanupCallTask
  5625. );
  5626. Status = NDIS_STATUS_FAILURE;
  5627. break;
  5628. }
  5629. //
  5630. // Now check if there is already a
  5631. // MakeCall task attached to pIF.
  5632. //
  5633. if (pIF->recvinfo.VcHdr.pMakeCallTask != NULL)
  5634. {
  5635. //
  5636. // There is a make-call task. We pend on it.
  5637. //
  5638. PRM_TASK pOtherTask = pIF->recvinfo.VcHdr.pMakeCallTask;
  5639. OBJLOG1(
  5640. pTask,
  5641. "MakeCall task %p exists; pending on it.\n",
  5642. pOtherTask);
  5643. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  5644. UNLOCKOBJ(pIF, pSR);
  5645. RmPendTaskOnOtherTask(
  5646. pTask,
  5647. PEND_OtherMakeCallTaskComplete,
  5648. pOtherTask,
  5649. pSR
  5650. );
  5651. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  5652. Status = NDIS_STATUS_PENDING;
  5653. break;
  5654. }
  5655. //
  5656. // There is no MakeCall task going on. Let's
  5657. // make this task THE MakeCall task.
  5658. //
  5659. pIF->recvinfo.VcHdr.pMakeCallTask = pTask;
  5660. //
  5661. // Since we're THE MakeCall task, add an association to pIF,
  5662. // which will only get cleared when the pIF->pMakeCallTask field
  5663. // above is cleared.
  5664. //
  5665. DBG_ADDASSOC(
  5666. &pIF->Hdr, // pObject
  5667. pTask, // Instance1
  5668. pTask->Hdr.szDescription, // Instance2
  5669. ARPASSOC_IF_MAKECALL_TASK, // AssociationID
  5670. " Official makecall task 0x%p (%s)\n", // szFormat
  5671. pSR
  5672. );
  5673. //
  5674. // Make sure we're in the position to make a
  5675. // call -- there should be no VC handle.
  5676. //
  5677. if (pIF->recvinfo.VcHdr.NdisVcHandle != NULL)
  5678. {
  5679. OBJLOG1(
  5680. pTask,
  5681. "VcHandle 0x%p already exists!, failing make call attempt.\n",
  5682. pIF->recvinfo.VcHdr.NdisVcHandle);
  5683. Status = NDIS_STATUS_FAILURE;
  5684. break;
  5685. }
  5686. // Setup call params.
  5687. //
  5688. {
  5689. PNIC1394_MEDIA_PARAMETERS p1394Params =
  5690. (PNIC1394_MEDIA_PARAMETERS)
  5691. &pMakeCallTask->MediaParams.Parameters;
  5692. NIC1394_DESTINATION DestAddr;
  5693. PNIC1394_DESTINATION pDestAddr;
  5694. ARP_ZEROSTRUCT(&DestAddr);
  5695. // TODO: put real values....
  5696. //
  5697. DestAddr.FifoAddress.UniqueID = 0;
  5698. DestAddr.FifoAddress.Off_Low = 0;
  5699. DestAddr.FifoAddress.Off_High = 0x100;
  5700. DestAddr.AddressType = NIC1394AddressType_FIFO;
  5701. pDestAddr = &DestAddr;
  5702. //No need: ARP_ZEROSTRUCT(&pMakeCallTask->CallParams);
  5703. //No need: ARP_ZEROSTRUCT(&pMakeCallTask->MediaParams);
  5704. pMakeCallTask->CallParams.MediaParameters =
  5705. (PCO_MEDIA_PARAMETERS) &pMakeCallTask->MediaParams;
  5706. pMakeCallTask->MediaParams.Flags = RECEIVE_VC;
  5707. pMakeCallTask->MediaParams.ParamType = NIC1394_MEDIA_SPECIFIC;
  5708. ASSERT(FIELD_OFFSET(ARP1394_CO_MEDIA_PARAMETERS, Parameters)
  5709. == FIELD_OFFSET(CO_MEDIA_PARAMETERS, MediaSpecific.Parameters));
  5710. p1394Params->Destination = *pDestAddr; // struct copy.
  5711. p1394Params->Flags = NIC1394_VCFLAG_FRAMED;
  5712. p1394Params->MaxSendBlockSize = -1; // (nic should pick)
  5713. p1394Params->MaxSendSpeed = -1; // (nic should pick)
  5714. p1394Params->MTU = ARP1394_ADAPTER_MTU;
  5715. // TODO -- make above based on
  5716. // config.
  5717. }
  5718. // Now create a vc and make the call...
  5719. //
  5720. {
  5721. NDIS_HANDLE NdisVcHandle;
  5722. RmUnlockAll(pSR);
  5723. Status = arpInitializeVc(
  5724. pIF,
  5725. &g_ArpRecvFifoVcStaticInfo,
  5726. &pIF->Hdr,
  5727. &pIF->recvinfo.VcHdr,
  5728. pSR
  5729. );
  5730. if (FAIL(Status))
  5731. {
  5732. break;
  5733. }
  5734. NdisVcHandle = pIF->recvinfo.VcHdr.NdisVcHandle;
  5735. RmSuspendTask(pTask, PEND_MakeCallComplete, pSR);
  5736. DBGMARK(0xf313a276);
  5737. //
  5738. // Make the Call now
  5739. //
  5740. RM_ASSERT_NOLOCKS(pSR);
  5741. #if ARPDBG_FAKE_CALLS
  5742. Status = arpDbgFakeNdisClMakeCall(
  5743. NdisVcHandle,
  5744. &pMakeCallTask->CallParams,
  5745. NULL, // ProtocolPartyContext
  5746. NULL, // NdisPartyHandle
  5747. &pIF->Hdr,
  5748. &pIF->recvinfo.VcHdr,
  5749. pSR
  5750. );
  5751. #else // !ARPDBG_FAKE_CALLS
  5752. Status = NdisClMakeCall(
  5753. NdisVcHandle,
  5754. &pMakeCallTask->CallParams,
  5755. NULL, // ProtocolPartyContext
  5756. NULL // NdisPartyHandle
  5757. );
  5758. #endif // !ARPDBG_FAKE_CALLS
  5759. if (!PEND(Status))
  5760. {
  5761. ArpCoMakeCallComplete(
  5762. Status,
  5763. (NDIS_HANDLE) &pIF->recvinfo.VcHdr,
  5764. NULL,
  5765. &pMakeCallTask->CallParams
  5766. );
  5767. Status = NDIS_STATUS_PENDING;
  5768. }
  5769. }
  5770. } // START
  5771. break;
  5772. case RM_TASKOP_PENDCOMPLETE:
  5773. {
  5774. switch(RM_PEND_CODE(pTask))
  5775. {
  5776. case PEND_OtherMakeCallTaskComplete:
  5777. {
  5778. //
  5779. // There was another makecall task going when we started, and
  5780. // it's now complete. Nothing for us to do...
  5781. //
  5782. Status = (NDIS_STATUS) UserParam;
  5783. }
  5784. break;
  5785. case PEND_MakeCallComplete:
  5786. {
  5787. //
  5788. // The make call is complete. We're done...
  5789. //
  5790. Status = (NDIS_STATUS) UserParam;
  5791. #if ARPDBG_FAKE_CALLS
  5792. //
  5793. // In the fake case, we give the "user" the opportunity to change
  5794. // the status to Success if the recv FIFO make call fails,
  5795. // because otherwise the adapter bind itself is going to fail.
  5796. //
  5797. // We do this even in the retail build (if ARPDBG_FAKE_CALLS is
  5798. // enabled).
  5799. //
  5800. if (FAIL(Status))
  5801. {
  5802. // To try the failure path of the recv fifo make call, enable
  5803. // the if 0 code. Currently we change status to success
  5804. // so that stress tests which include loading/unloading
  5805. // of the driver will run without breaking here everytime.
  5806. //
  5807. #if 0
  5808. DbgPrint(
  5809. "A13: FakeRecvMakeCall failed. &Status=%p.\n",
  5810. &Status
  5811. );
  5812. DbgBreakPoint();
  5813. #else
  5814. Status = NDIS_STATUS_SUCCESS;
  5815. #endif
  5816. }
  5817. #endif // ARPDBG_FAKE_CALLS
  5818. LOCKOBJ(pIF, pSR);
  5819. ASSERT (pIF->recvinfo.VcHdr.pMakeCallTask == pTask);
  5820. ASSERT(pIF->recvinfo.VcHdr.NdisVcHandle != NULL);
  5821. // On success, update pIF->recvinfo.offset.
  5822. //
  5823. if (!FAIL(Status))
  5824. {
  5825. PNIC1394_MEDIA_PARAMETERS p1394Params =
  5826. (PNIC1394_MEDIA_PARAMETERS)
  5827. &pMakeCallTask->MediaParams.Parameters;
  5828. pIF->recvinfo.offset.Off_Low =
  5829. p1394Params->Destination.FifoAddress.Off_Low;
  5830. pIF->recvinfo.offset.Off_High =
  5831. p1394Params->Destination.FifoAddress.Off_High;
  5832. }
  5833. DBGMARK(0xa3b591b7);
  5834. RmUnlockAll(pSR);
  5835. }
  5836. break;
  5837. default:
  5838. {
  5839. ASSERTEX(!"Unknown pend op", pTask);
  5840. }
  5841. break;
  5842. } // end switch(RM_PEND_CODE(pTask))
  5843. } // case RM_TASKOP_PENDCOMPLETE
  5844. break;
  5845. case RM_TASKOP_END:
  5846. {
  5847. Status = (NDIS_STATUS) UserParam;
  5848. LOCKOBJ(pIF, pSR);
  5849. if (pIF->recvinfo.VcHdr.pMakeCallTask == pTask)
  5850. {
  5851. //
  5852. // We're the official pMakeCallTask
  5853. //
  5854. // Delete the association we added when we set
  5855. // pIF->recvinfo.VcHdr.pMakeCallTask to pTask.
  5856. //
  5857. DBG_DELASSOC(
  5858. &pIF->Hdr, // pObject
  5859. pTask, // Instance1
  5860. pTask->Hdr.szDescription, // Instance2
  5861. ARPASSOC_IF_MAKECALL_TASK, // AssociationID
  5862. pSR
  5863. );
  5864. // Remove reference to us in pIF.
  5865. //
  5866. pIF->recvinfo.VcHdr.pMakeCallTask = NULL;
  5867. if (FAIL(Status) && pIF->recvinfo.VcHdr.NdisVcHandle != NULL)
  5868. {
  5869. UNLOCKOBJ(pIF, pSR);
  5870. // WARNING: the above completely nukes out VcHdr.
  5871. //
  5872. arpDeinitializeVc(pIF, &pIF->recvinfo.VcHdr, &pIF->Hdr, pSR);
  5873. }
  5874. }
  5875. }
  5876. break;
  5877. default:
  5878. {
  5879. ASSERTEX(!"Unexpected task op", pTask);
  5880. }
  5881. break;
  5882. } // switch (Code)
  5883. RmUnlockAll(pSR);
  5884. EXIT()
  5885. return Status;
  5886. }
  5887. NDIS_STATUS
  5888. arpTaskCleanupRecvFifoCall(
  5889. IN PRM_TASK pTask,
  5890. IN RM_TASK_OPERATION Code,
  5891. IN UINT_PTR UserParam, // Unused
  5892. IN PRM_STACK_RECORD pSR
  5893. )
  5894. /*++
  5895. Routine Description:
  5896. This task is responsible for cleaning up a previously-made call to the
  5897. IF's single recvFIFO VC.
  5898. Arguments:
  5899. UserParam for (Code == RM_TASKOP_START) : unused
  5900. --*/
  5901. {
  5902. ENTER("TaskCleanupRecvFifoCall", 0x6e9581f7)
  5903. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  5904. ARP1394_INTERFACE * pIF = (ARP1394_INTERFACE*) RM_PARENT_OBJECT(pTask);
  5905. MYBOOL fCloseCall = FALSE;
  5906. NDIS_HANDLE NdisVcHandle = NULL;
  5907. // Following are the list of pending states for this task.
  5908. //
  5909. enum
  5910. {
  5911. PEND_MakeCallTaskComplete,
  5912. PEND_OtherCleanupTaskComplete,
  5913. PEND_CloseCallComplete
  5914. };
  5915. DBGMARK(0xa651415b);
  5916. switch(Code)
  5917. {
  5918. case RM_TASKOP_START:
  5919. {
  5920. LOCKOBJ(pIF, pSR);
  5921. // First check if pIF is still allocated, if not we go away.
  5922. //
  5923. if (RM_IS_ZOMBIE(pIF))
  5924. {
  5925. Status = NDIS_STATUS_SUCCESS;
  5926. break;
  5927. }
  5928. //
  5929. // pIF is allocated. Now check if there is already a
  5930. // CleanupCall task attached to pIF.
  5931. //
  5932. if (pIF->recvinfo.VcHdr.pCleanupCallTask != NULL)
  5933. {
  5934. //
  5935. // There is an existing CleanupCall task. We pend on it.
  5936. //
  5937. PRM_TASK pOtherTask = pIF->recvinfo.VcHdr.pCleanupCallTask;
  5938. OBJLOG1(
  5939. pTask,
  5940. "CleanupVc task %p exists; pending on it.\n",
  5941. pOtherTask
  5942. );
  5943. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  5944. UNLOCKOBJ(pIF, pSR);
  5945. RmPendTaskOnOtherTask(
  5946. pTask,
  5947. PEND_OtherCleanupTaskComplete,
  5948. pOtherTask,
  5949. pSR
  5950. );
  5951. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  5952. Status = NDIS_STATUS_PENDING;
  5953. break;
  5954. }
  5955. //
  5956. // There is no CleanupCall task going on. Let's
  5957. // make this task THE CleanupCall task.
  5958. //
  5959. pIF->recvinfo.VcHdr.pCleanupCallTask = pTask;
  5960. //
  5961. // Since we're THE CleanupCall task, add an association to pIF,
  5962. // which will only get cleared when the pIF->recvinfo.VcHdr.pCleanupCallTask
  5963. // field above is cleared.
  5964. //
  5965. DBG_ADDASSOC(
  5966. &pIF->Hdr, // pObject
  5967. pTask, // Instance1
  5968. pTask->Hdr.szDescription, // Instance2
  5969. ARPASSOC_IF_CLEANUPCALL_TASK, // AssociationID
  5970. " Official CleanupCall task 0x%p (%s)\n", // szFormat
  5971. pSR
  5972. );
  5973. if (pIF->recvinfo.VcHdr.pMakeCallTask != NULL)
  5974. {
  5975. // Oops, there is a make call task ongoing.
  5976. // TODO: abort the makecall task.
  5977. // For now, we just wait until it's complete.
  5978. //
  5979. PRM_TASK pOtherTask = pIF->recvinfo.VcHdr.pMakeCallTask;
  5980. OBJLOG1(
  5981. pTask,
  5982. "MakeCall task %p exists; pending on it.\n",
  5983. pOtherTask
  5984. );
  5985. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  5986. UNLOCKOBJ(pIF, pSR);
  5987. RmPendTaskOnOtherTask(
  5988. pTask,
  5989. PEND_MakeCallTaskComplete,
  5990. pOtherTask,
  5991. pSR
  5992. );
  5993. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  5994. Status = NDIS_STATUS_PENDING;
  5995. break;
  5996. }
  5997. else
  5998. {
  5999. NdisVcHandle = pIF->recvinfo.VcHdr.NdisVcHandle;
  6000. if (NdisVcHandle != NULL)
  6001. {
  6002. fCloseCall = TRUE;
  6003. }
  6004. else
  6005. {
  6006. // Nothing to do.
  6007. Status = NDIS_STATUS_SUCCESS;
  6008. }
  6009. }
  6010. } // START
  6011. break;
  6012. case RM_TASKOP_PENDCOMPLETE:
  6013. {
  6014. switch(RM_PEND_CODE(pTask))
  6015. {
  6016. case PEND_OtherCleanupTaskComplete:
  6017. {
  6018. //
  6019. // There was another cleanup-vc task going when we started, and
  6020. // it's now complete. Nothing for us to do...
  6021. //
  6022. Status = NDIS_STATUS_SUCCESS;
  6023. }
  6024. break;
  6025. case PEND_MakeCallTaskComplete:
  6026. {
  6027. //
  6028. // There was a makecall task going when we started, and
  6029. // it's now complete. We go on to cleanup the call.
  6030. // There cannot be another makecall task now, because a
  6031. // makecall task doesn't start if there is an active
  6032. // cleanupcall task.
  6033. //
  6034. ASSERT(pIF->recvinfo.VcHdr.pMakeCallTask == NULL);
  6035. NdisVcHandle = pIF->recvinfo.VcHdr.NdisVcHandle;
  6036. if (NdisVcHandle != NULL)
  6037. {
  6038. fCloseCall = TRUE;
  6039. }
  6040. else
  6041. {
  6042. // Nothing to do.
  6043. Status = NDIS_STATUS_SUCCESS;
  6044. }
  6045. }
  6046. break;
  6047. case PEND_CloseCallComplete:
  6048. {
  6049. //
  6050. // The close call is complete...
  6051. //
  6052. LOCKOBJ(pIF, pSR);
  6053. ASSERT(pIF->recvinfo.VcHdr.pCleanupCallTask == pTask);
  6054. // Delete the association we added when we set
  6055. // pIF->recvinfo.VcHdr.pCleanupCallTask to pTask.
  6056. //
  6057. DBG_DELASSOC(
  6058. &pIF->Hdr, // pObject
  6059. pTask, // Instance1
  6060. pTask->Hdr.szDescription, // Instance2
  6061. ARPASSOC_IF_CLEANUPCALL_TASK, // AssociationID
  6062. pSR
  6063. );
  6064. pIF->recvinfo.VcHdr.pCleanupCallTask = NULL;
  6065. // Delete the VC...
  6066. //
  6067. ASSERT(pIF->recvinfo.VcHdr.NdisVcHandle != NULL);
  6068. UNLOCKOBJ(pIF, pSR);
  6069. DBGMARK(0xc6b52f21);
  6070. arpDeinitializeVc(pIF, &pIF->recvinfo.VcHdr, &pIF->Hdr, pSR);
  6071. Status = NDIS_STATUS_SUCCESS;
  6072. }
  6073. break;
  6074. default:
  6075. {
  6076. ASSERTEX(!"Unknown pend op", pTask);
  6077. }
  6078. break;
  6079. } // end switch(RM_PEND_CODE(pTask))
  6080. } // case RM_TASKOP_PENDCOMPLETE
  6081. break;
  6082. case RM_TASKOP_END:
  6083. {
  6084. LOCKOBJ(pIF, pSR);
  6085. DBGMARK(0xc65b2f08);
  6086. //
  6087. // We're done. There should be no async activities left to do.
  6088. //
  6089. ASSERTEX(pIF->recvinfo.VcHdr.NdisVcHandle == NULL, pIF);
  6090. Status = NDIS_STATUS_SUCCESS;
  6091. }
  6092. break; // RM_TASKOP_END:
  6093. default:
  6094. {
  6095. ASSERTEX(!"Unexpected task op", pTask);
  6096. }
  6097. break;
  6098. } // switch (Code)
  6099. RmUnlockAll(pSR);
  6100. if (fCloseCall)
  6101. {
  6102. DBGMARK(0x04d5b2d9);
  6103. RmSuspendTask(pTask, PEND_CloseCallComplete, pSR);
  6104. #if ARPDBG_FAKE_CALLS
  6105. Status = arpDbgFakeNdisClCloseCall(
  6106. NdisVcHandle,
  6107. NULL, // No party handle
  6108. NULL, // No Buffer
  6109. 0, // Size of above
  6110. &pIF->Hdr,
  6111. &pIF->recvinfo.VcHdr,
  6112. pSR
  6113. );
  6114. #else // !ARPDBG_FAKE_CALLS
  6115. Status = NdisClCloseCall(
  6116. NdisVcHandle,
  6117. NULL, // No party handle
  6118. NULL, // No Buffer
  6119. 0 // Size of above
  6120. );
  6121. #endif // !ARPDBG_FAKE_CALLS
  6122. if (Status != NDIS_STATUS_PENDING)
  6123. {
  6124. ArpCoCloseCallComplete(
  6125. Status,
  6126. (NDIS_HANDLE) &pIF->recvinfo.VcHdr,
  6127. (NDIS_HANDLE)NULL
  6128. );
  6129. Status = NDIS_STATUS_PENDING;
  6130. }
  6131. }
  6132. EXIT()
  6133. return Status;
  6134. }
  6135. NDIS_STATUS
  6136. arpAddOneStaticArpEntry(
  6137. IN PARP1394_INTERFACE pIF, // LOCKIN LOCKOUT
  6138. IN IP_ADDRESS IpAddress,
  6139. IN PNIC1394_FIFO_ADDRESS pFifoAddr,
  6140. IN PRM_STACK_RECORD pSR
  6141. )
  6142. /*++
  6143. Routine Description:
  6144. Create a pRemoteIp and IP address IpAddress and (if not already existing)
  6145. create a pDest object with hw address pFifoAddr and link the two.
  6146. Return Value:
  6147. NDIS_STATUS_SUCCESS on success. Ndis failure code on failure (could be
  6148. because of a resource allocation failure or because there already exists
  6149. a pRemoteIp with the specified IP address).
  6150. --*/
  6151. {
  6152. INT fCreated = FALSE;
  6153. ARPCB_REMOTE_IP *pRemoteIp = NULL;
  6154. ARPCB_DEST *pDest = NULL;
  6155. NDIS_STATUS Status;
  6156. ARP_DEST_PARAMS DestParams;
  6157. REMOTE_DEST_KEY RemoteDestKey;
  6158. RM_DBG_ASSERT_LOCKED(&pIF->Hdr, pSR);
  6159. ARP_ZEROSTRUCT(&DestParams);
  6160. DestParams.HwAddr.AddressType = NIC1394AddressType_FIFO;
  6161. DestParams.HwAddr.FifoAddress = *pFifoAddr; // struct copy
  6162. REMOTE_DEST_KEY_INIT(&RemoteDestKey);
  6163. RemoteDestKey.IpAddress = IpAddress;
  6164. do
  6165. {
  6166. Status = RmLookupObjectInGroup(
  6167. &pIF->RemoteIpGroup,
  6168. RM_CREATE|RM_NEW,
  6169. (PVOID) (&RemoteDestKey),
  6170. (PVOID) (&RemoteDestKey), // pCreateParams
  6171. (RM_OBJECT_HEADER**) &pRemoteIp,
  6172. &fCreated, // pfCreated
  6173. pSR
  6174. );
  6175. if (FAIL(Status))
  6176. {
  6177. OBJLOG1(
  6178. pIF,
  6179. "Couldn't add fake static localIp entry with addr 0x%lx\n",
  6180. IpAddress
  6181. );
  6182. break;
  6183. }
  6184. // Now create a destination item for this structure.
  6185. //
  6186. Status = RmLookupObjectInGroup(
  6187. &pIF->DestinationGroup,
  6188. RM_CREATE, //NOT RM_NEW (could be existing)
  6189. &DestParams,
  6190. &DestParams, // pParams
  6191. (RM_OBJECT_HEADER**) &pDest,
  6192. &fCreated,
  6193. pSR
  6194. );
  6195. if (FAIL(Status))
  6196. {
  6197. OBJLOG1(
  6198. pIF,
  6199. "Couldn't add fake dest entry with hw addr 0x%lx\n",
  6200. (UINT) DestParams.HwAddr.FifoAddress.UniqueID // Truncation
  6201. );
  6202. #if 0
  6203. TR_WARN((
  6204. "Couldn't add fake dest entry with hw addr 0x%lx\n",
  6205. (UINT) DestParams.HwAddr.FifoAddress.UniqueID // Truncation
  6206. ));
  6207. #endif // 0
  6208. //
  6209. // We'll leave the RemoteIp entry around -- it will be cleaned up later.
  6210. // We do have to deref the tmpref added when looking it up.
  6211. //
  6212. RmTmpDereferenceObject(&pRemoteIp->Hdr, pSR);
  6213. break;
  6214. }
  6215. //
  6216. // We've created both RemoteIp and Destination entries. Now link them.
  6217. // (We still have the IF lock, which is the same as the RemoteIP and
  6218. // desination locks for now).
  6219. //
  6220. // TODO: will need to change this when pRemoteIp gets its own lock.
  6221. //
  6222. RM_ASSERT_SAME_LOCK_AS_PARENT(pRemoteIp);
  6223. RM_ASSERT_SAME_LOCK_AS_PARENT(pDest);
  6224. arpLinkRemoteIpToDest(
  6225. pRemoteIp,
  6226. pDest,
  6227. pSR
  6228. );
  6229. // Now set the pRemoteIp state to reflect that it is STATIC and FIFO
  6230. //
  6231. SET_REMOTEIP_SDTYPE(pRemoteIp, ARPREMOTEIP_STATIC);
  6232. SET_REMOTEIP_FCTYPE(pRemoteIp, ARPREMOTEIP_FIFO);
  6233. // Finally, remove the tmprefs added in the lookups.
  6234. //
  6235. RmTmpDereferenceObject(&pRemoteIp->Hdr, pSR);
  6236. RmTmpDereferenceObject(&pDest->Hdr, pSR);
  6237. } while (FALSE);
  6238. return Status;
  6239. }
  6240. VOID
  6241. arpActivateIf(
  6242. PARP1394_INTERFACE pIF,
  6243. PRM_TASK pCallingTask, // OPTIONAL
  6244. UINT SuspendCode, // OPTIONAL
  6245. PRM_STACK_RECORD pSR
  6246. )
  6247. /*++
  6248. Routine Description:
  6249. Initiate the asynchronous activation of pIF.
  6250. NO locks must be held on entrance and none are held on exit.
  6251. Arguments:
  6252. pIF - Interface to activate.
  6253. pCallingTask - Optional task to suspend and resume when activation completes
  6254. (possibly async).
  6255. SuspendCode - SuspendCode for the above task.
  6256. --*/
  6257. {
  6258. PRM_TASK pTask;
  6259. NDIS_STATUS Status;
  6260. RM_ASSERT_NOLOCKS(pSR);
  6261. Status = arpAllocateTask(
  6262. &pIF->Hdr, // pParentObject,
  6263. arpTaskActivateInterface, // pfnHandler,
  6264. 0, // Timeout,
  6265. "Task: Activate Interface", // szDescription
  6266. &pTask,
  6267. pSR
  6268. );
  6269. if (FAIL(Status))
  6270. {
  6271. OBJLOG0(pIF, ("FATAL: couldn't alloc Activate IF task!\n"));
  6272. ASSERT(FALSE);
  6273. if (pCallingTask != NULL)
  6274. {
  6275. RmSuspendTask(pCallingTask, SuspendCode, pSR);
  6276. RmResumeTask(pCallingTask, Status, pSR);
  6277. }
  6278. }
  6279. else
  6280. {
  6281. if (pCallingTask != NULL)
  6282. {
  6283. RmPendTaskOnOtherTask(
  6284. pCallingTask,
  6285. SuspendCode,
  6286. pTask,
  6287. pSR
  6288. );
  6289. }
  6290. (void)RmStartTask(pTask, 0, pSR);
  6291. }
  6292. }
  6293. VOID
  6294. arpDeinitIf(
  6295. PARP1394_INTERFACE pIF,
  6296. PRM_TASK pCallingTask, // OPTIONAL
  6297. UINT SuspendCode, // OPTIONAL
  6298. PRM_STACK_RECORD pSR
  6299. )
  6300. /*++
  6301. Routine Description:
  6302. Initiate the asynchronous unload of pIF. If pIF is currently being loaded
  6303. (initialized), abort the initializeation or wait for it to complete before
  6304. unloading it. If pIF is currently being unloaded and pCallingTask is
  6305. NULL, return right away, else (pCallingTask is not NULL),
  6306. suspend pCallingTask and make it pend until the unload completes.
  6307. NO locks must be held on entrance and none are held on exit.
  6308. Arguments:
  6309. pIF - Interface to unload.
  6310. pCallingTask - Optional task to suspend if unload is completing async.
  6311. SuspendCode - SuspendCode for the above task.
  6312. Return Value:
  6313. NDIS_STATUS_SUCCESS -- on synchronous success OR pCallingTask==NULL
  6314. NDIS_STATUS_PENDING -- if pCallingTask is made to pend until the operation
  6315. completes.
  6316. --*/
  6317. {
  6318. PRM_TASK pTask;
  6319. NDIS_STATUS Status;
  6320. //
  6321. // NOTE: We could check to see if pIF can be synchronously unloaded,
  6322. // and if so unload it right here. We don't bother because that's just
  6323. // more code, and with dubious perf benefit.
  6324. //
  6325. RM_ASSERT_NOLOCKS(pSR);
  6326. Status = arpAllocateTask(
  6327. &pIF->Hdr, // pParentObject,
  6328. arpTaskDeinitInterface, // pfnHandler,
  6329. 0, // Timeout,
  6330. "Task: Deinit Interface", // szDescription
  6331. &pTask,
  6332. pSR
  6333. );
  6334. if (FAIL(Status))
  6335. {
  6336. OBJLOG0(pIF, ("FATAL: couldn't alloc close IF task!\n"));
  6337. ASSERT(FALSE);
  6338. if (pCallingTask != NULL)
  6339. {
  6340. RmSuspendTask(pCallingTask, SuspendCode, pSR);
  6341. RmResumeTask(pCallingTask, Status, pSR);
  6342. }
  6343. }
  6344. else
  6345. {
  6346. if (pCallingTask != NULL)
  6347. {
  6348. RmPendTaskOnOtherTask(
  6349. pCallingTask,
  6350. SuspendCode,
  6351. pTask,
  6352. pSR
  6353. );
  6354. }
  6355. (void)RmStartTask(pTask, 0, pSR);
  6356. }
  6357. }
  6358. VOID
  6359. arpDeinitDestination(
  6360. PARPCB_DEST pDest, // NOLOCKIN NOLOCKOUT
  6361. MYBOOL fOnlyIfUnused,
  6362. PRM_STACK_RECORD pSR
  6363. )
  6364. /*++
  6365. Routine Description:
  6366. Initate the unload of destination pDest.
  6367. If fOnlyIfUnused is TRUE, then only do this if there are no
  6368. local or remote IPs pointing to it.
  6369. NOTE: it's possible that some pLocal/pRemoteIps may be linked to
  6370. pDest AFTER we've decided to deinit pDest. Tough luck -- in this
  6371. unlikely event, we'll unload this pDest, and the unlinked
  6372. pLocals/pRemotes will have to re-figure who to link to.
  6373. --*/
  6374. {
  6375. ENTER("DeinitDestination", 0xc61b8f82)
  6376. PRM_TASK pTask;
  6377. NDIS_STATUS Status;
  6378. RM_ASSERT_NOLOCKS(pSR);
  6379. if (fOnlyIfUnused)
  6380. {
  6381. //
  6382. // We don't deinit the destination if there are local or remote ip's
  6383. // linked to it, OR if it is the broadcast channel.
  6384. //
  6385. LOCKOBJ(pDest, pSR);
  6386. if ( !IsListEmpty(&pDest->listLocalIp)
  6387. || !IsListEmpty(&pDest->listIpToThisDest)
  6388. || pDest == ((PARP1394_INTERFACE) RM_PARENT_OBJECT(pDest))
  6389. ->pBroadcastDest)
  6390. {
  6391. UNLOCKOBJ(pDest, pSR);
  6392. return; // ********* EARLY RETURN **********
  6393. }
  6394. UNLOCKOBJ(pDest, pSR);
  6395. }
  6396. #if DBG
  6397. if (pDest->Params.HwAddr.AddressType == NIC1394AddressType_FIFO)
  6398. {
  6399. PUCHAR puc = (PUCHAR) &pDest->Params.HwAddr.FifoAddress;
  6400. TR_WARN(("Deiniting Destination: FIFO %02lx-%02lx-%02lx-%02lx-%02lx-%02lx-%02lx-%02lx.\n",
  6401. puc[0], puc[1], puc[2], puc[3],
  6402. puc[4], puc[5], puc[6], puc[7]));
  6403. }
  6404. else if (pDest->Params.HwAddr.AddressType == NIC1394AddressType_Channel)
  6405. {
  6406. TR_WARN(("Deiniting Destination: Channel %lu.\n",
  6407. pDest->Params.HwAddr.Channel));
  6408. }
  6409. #endif // DBG
  6410. Status = arpAllocateTask(
  6411. &pDest->Hdr, // pParentObject,
  6412. arpTaskUnloadDestination, // pfnHandler,
  6413. 0, // Timeout,
  6414. "Task: Unload Dest", // szDescription
  6415. &pTask,
  6416. pSR
  6417. );
  6418. if (FAIL(Status))
  6419. {
  6420. OBJLOG0(pDest, ("FATAL: couldn't alloc unload dest task!\n"));
  6421. }
  6422. else
  6423. {
  6424. (VOID) RmStartTask(
  6425. pTask,
  6426. 0, // UserParam (unused)
  6427. pSR
  6428. );
  6429. }
  6430. }
  6431. VOID
  6432. arpDeactivateIf(
  6433. PARP1394_INTERFACE pIF,
  6434. PRM_TASK pCallingTask, // OPTIONAL
  6435. UINT SuspendCode, // OPTIONAL
  6436. PRM_STACK_RECORD pSR
  6437. )
  6438. /*++
  6439. Routine Description:
  6440. Initiate the asynchronous deactivation of pIF.
  6441. "Deactivation" consists of tearing down any activity and handles associated
  6442. with this IF. The IF will remain allocated linked to the adapter.
  6443. NO locks must be held on entrance and none are held on exit.
  6444. Arguments:
  6445. pIF - Interface to unload.
  6446. pCallingTask - Optional task to suspend if deactivation is completing async.
  6447. SuspendCode - SuspendCode for the above task.
  6448. --*/
  6449. {
  6450. PRM_TASK pTask;
  6451. NDIS_STATUS Status;
  6452. //
  6453. // NOTE: We could check to see if pIF can be synchronously deactivated,
  6454. // and if so deactivate it right here. We don't bother because that's just
  6455. // more code, and with dubious perf benefit.
  6456. //
  6457. RM_ASSERT_NOLOCKS(pSR);
  6458. Status = arpAllocateTask(
  6459. &pIF->Hdr, // pParentObject,
  6460. arpTaskDeactivateInterface, // pfnHandler,
  6461. 0, // Timeout,
  6462. "Task: DeactivateInterface",// szDescription
  6463. &pTask,
  6464. pSR
  6465. );
  6466. if (FAIL(Status))
  6467. {
  6468. OBJLOG0(pIF, ("FATAL: couldn't alloc deactivate IF task!\n"));
  6469. ASSERT(FALSE);
  6470. if (pCallingTask != NULL)
  6471. {
  6472. RmSuspendTask(pCallingTask, SuspendCode, pSR);
  6473. RmResumeTask(pCallingTask, Status, pSR);
  6474. }
  6475. }
  6476. else
  6477. {
  6478. if (pCallingTask != NULL)
  6479. {
  6480. RmPendTaskOnOtherTask(
  6481. pCallingTask,
  6482. SuspendCode,
  6483. pTask,
  6484. pSR
  6485. );
  6486. }
  6487. (void)RmStartTask(pTask, 0, pSR);
  6488. }
  6489. }
  6490. NDIS_STATUS
  6491. arpCreateInterface(
  6492. IN PARP1394_ADAPTER pAdapter, // LOCKIN LOCKOUT
  6493. OUT PARP1394_INTERFACE *ppIF,
  6494. IN PRM_STACK_RECORD pSR
  6495. )
  6496. /*++
  6497. Routine Description:
  6498. Allocates and performs basic initialization of an interface object.
  6499. The interface object subsequently needs to be initialized by the starting
  6500. the initialization task before it is completely initialized.
  6501. *ppIF shares the same lock as it's parent, pAdapter.
  6502. Arguments:
  6503. pAdapter - Adapter that will own the interface.
  6504. ppIF - Place to store the allocated interface.
  6505. Return Value:
  6506. NDIS_STATUS_SUCCESS on successful allocation and initialization of the interface.
  6507. NDIS failure code on failure.
  6508. --*/
  6509. {
  6510. NDIS_STATUS Status;
  6511. ARP1394_INTERFACE *pIF;
  6512. ENTER("arpCreateInterface", 0x938c36ff)
  6513. RM_ASSERT_OBJLOCKED(&pAdapter->Hdr, pSR);
  6514. do
  6515. {
  6516. Status = ARP_ALLOCSTRUCT(pIF, MTAG_INTERFACE);
  6517. if (Status != NDIS_STATUS_SUCCESS || pIF == NULL)
  6518. {
  6519. Status = NDIS_STATUS_RESOURCES;
  6520. break;
  6521. }
  6522. ARP_ZEROSTRUCT(pIF);
  6523. RmInitializeHeader(
  6524. &(pAdapter->Hdr), // pParentObject
  6525. &pIF->Hdr,
  6526. MTAG_INTERFACE,
  6527. &pAdapter->Lock,
  6528. &ARP1394_INTERFACE_StaticInfo,
  6529. NULL, // szDescription
  6530. pSR
  6531. );
  6532. // Note arpInitializeIfPools expects pIF to be locked. We know it's locked
  6533. // because it shares the same lock as it's parent, and the parent is lozked.
  6534. //
  6535. Status = arpInitializeIfPools(pIF, pSR);
  6536. if (FAIL(Status))
  6537. {
  6538. RmDeallocateObject(
  6539. &(pIF->Hdr),
  6540. pSR
  6541. );
  6542. pIF = NULL;
  6543. break;
  6544. }
  6545. //
  6546. // Intialize the various groups in the interface...
  6547. //
  6548. RmInitializeGroup(
  6549. &pIF->Hdr, // pOwningObject
  6550. &ArpGlobal_LocalIpStaticInfo,
  6551. &(pIF->LocalIpGroup),
  6552. "LocalIp group", // szDescription
  6553. pSR
  6554. );
  6555. RmInitializeGroup(
  6556. &pIF->Hdr, // pOwningObject
  6557. &ArpGlobal_RemoteIpStaticInfo,
  6558. &(pIF->RemoteIpGroup),
  6559. "RemoteIp group", // szDescription
  6560. pSR
  6561. );
  6562. RmInitializeGroup(
  6563. &pIF->Hdr, // pOwningObject
  6564. &ArpGlobal_RemoteEthStaticInfo,
  6565. &(pIF->RemoteEthGroup),
  6566. "RemoteEth group", // szDescription
  6567. pSR
  6568. );
  6569. RmInitializeGroup(
  6570. &pIF->Hdr, // pOwningObject
  6571. &ArpGlobal_DhcpTableStaticInfo,
  6572. &(pIF->EthDhcpGroup),
  6573. "Eth Dhcp group", // szDescription
  6574. pSR
  6575. );
  6576. RmInitializeGroup(
  6577. &pIF->Hdr, // pOwningObject
  6578. &ArpGlobal_DestinationStaticInfo,
  6579. &(pIF->DestinationGroup),
  6580. "Destination group", // szDescription
  6581. pSR
  6582. );
  6583. //
  6584. // Cache the adapter handle.
  6585. //
  6586. pIF->ndis.AdapterHandle = pAdapter->bind.AdapterHandle;
  6587. // TODO -- put the real IP MTU (based on adapter info and config info)
  6588. //
  6589. pIF->ip.MTU = ARP1394_ADAPTER_MTU-16; // Bytes ('-16' accounts for
  6590. // the encapsulation header.
  6591. // 16 is overkill: 4 should
  6592. // be enough.)
  6593. // Init stuff in pIF->sendinfo (the const header pools were initialized
  6594. // earlier, because their initialization could fail).
  6595. //
  6596. RmInitializeLock(&pIF->sendinfo.Lock, LOCKLEVEL_IF_SEND);
  6597. InitializeListHead(&pIF->sendinfo.listPktsWaitingForHeaders);
  6598. arpResetIfStats(pIF, pSR);
  6599. pIF->ip.ATInstance = INVALID_ENTITY_INSTANCE;
  6600. pIF->ip.IFInstance = INVALID_ENTITY_INSTANCE;
  6601. pIF->ip.BroadcastAddress = 0xFFFFFFFF; // Defaults to all-1's.
  6602. //
  6603. // Do any other non-failure-prone initialization here.
  6604. //
  6605. } while (FALSE);
  6606. *ppIF = pIF;
  6607. EXIT()
  6608. return Status;
  6609. }
  6610. VOID
  6611. arpDeleteInterface(
  6612. IN PARP1394_INTERFACE pIF, // LOCKIN LOCKOUT (adapter lock)
  6613. IN PRM_STACK_RECORD pSR
  6614. )
  6615. {
  6616. ARP1394_ADAPTER * pAdapter =
  6617. (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pIF);
  6618. RM_ASSERT_OBJLOCKED(&pAdapter->Hdr, pSR);
  6619. // We expect that the adapter has already removed it's reference to pIF.
  6620. //
  6621. ASSERT(pAdapter->pIF != pIF);
  6622. // Deinitialize all the groups in the IF ...
  6623. //
  6624. RmDeinitializeGroup(&(pIF->LocalIpGroup), pSR);
  6625. RmDeinitializeGroup(&(pIF->RemoteIpGroup), pSR);
  6626. RmDeinitializeGroup(&(pIF->RemoteEthGroup), pSR);
  6627. RmDeinitializeGroup(&(pIF->DestinationGroup), pSR);
  6628. RmDeinitializeGroup(&(pIF->EthDhcpGroup),pSR);
  6629. // Deinit the various pools associated with pIF.
  6630. //
  6631. arpDeInitializeIfPools(pIF, pSR);
  6632. // Verify that everything is truly done...
  6633. //
  6634. ASSERTEX(pIF->pPrimaryTask == NULL, pIF);
  6635. ASSERTEX(pIF->pActDeactTask == NULL, pIF);
  6636. ASSERTEX(pIF->ip.Context == NULL, pIF);
  6637. ASSERTEX(pIF->ndis.AfHandle == NULL, pIF);
  6638. // Add any other checks you want here...
  6639. // Deallocate the IF
  6640. //
  6641. RmDeallocateObject(
  6642. &(pIF->Hdr),
  6643. pSR
  6644. );
  6645. }
  6646. VOID
  6647. arpResetIfStats(
  6648. IN PARP1394_INTERFACE pIF, // LOCKIN LOCKOUT
  6649. IN PRM_STACK_RECORD pSR
  6650. )
  6651. {
  6652. ENTER("arpResetIfStats", 0x3eb52cda)
  6653. RM_ASSERT_OBJLOCKED(&pIF->Hdr, pSR);
  6654. // Zero stats
  6655. //
  6656. //
  6657. ARP_ZEROSTRUCT(&(pIF->stats));
  6658. // Set the timestamp indicating start of stats collection.
  6659. //
  6660. NdisGetCurrentSystemTime(&(pIF->stats.StatsResetTime));
  6661. // Get the perf counter frequency (we don't need to do this each time, but
  6662. // why bother special casing.)
  6663. //
  6664. (VOID) KeQueryPerformanceCounter(&(pIF->stats.PerformanceFrequency));
  6665. EXIT()
  6666. }
  6667. NDIS_STATUS
  6668. arpInitializeVc(
  6669. PARP1394_INTERFACE pIF,
  6670. PARP_STATIC_VC_INFO pVcInfo,
  6671. PRM_OBJECT_HEADER pOwner,
  6672. PARP_VC_HEADER pVcHdr,
  6673. PRM_STACK_RECORD pSR
  6674. )
  6675. /*++
  6676. Routine Description:
  6677. Initialize the Vc Header; Allocate the NdisVcHandle;
  6678. Arguments:
  6679. pIF - Interface this applies to
  6680. pVcInfo - Static info about this VC
  6681. pOwner - Owning object (for referencing)
  6682. pVcHdr - Protocol Vc context to initialize
  6683. --*/
  6684. {
  6685. NDIS_STATUS Status;
  6686. NDIS_HANDLE NdisVcHandle;
  6687. ENTER("arpInitializeVc", 0x36fe9837)
  6688. // (DEBUG ONLY) Verify that all fields are already zero.
  6689. // TODO: We don't assert that pVcHdr->pMakeCallTask == NULL, because
  6690. // it's already set on entry -- we should clean up the semantics of
  6691. // arpInitializeVc.
  6692. //
  6693. ASSERT ( pVcHdr->pStaticInfo == NULL
  6694. && pVcHdr->NdisVcHandle == NULL
  6695. && pVcHdr->pCleanupCallTask == NULL );
  6696. NdisVcHandle = NULL;
  6697. // Try to create Ndis VC
  6698. //
  6699. Status = NdisCoCreateVc(
  6700. pIF->ndis.AdapterHandle,
  6701. pIF->ndis.AfHandle,
  6702. (NDIS_HANDLE) pVcHdr, // ProtocolVcContext,
  6703. &NdisVcHandle
  6704. );
  6705. if (FAIL(Status))
  6706. {
  6707. TR_WARN(("Couldn't create VC handle\n"));
  6708. pVcHdr->NdisVcHandle = NULL;
  6709. }
  6710. else
  6711. {
  6712. pVcHdr->pStaticInfo = pVcInfo;
  6713. pVcHdr->NdisVcHandle = NdisVcHandle;
  6714. // Link-to-external pOwningObject to the ndis-vc handle.
  6715. //
  6716. #if RM_EXTRA_CHECKING
  6717. #define szARPASSOC_EXTLINK_TO_NDISVCHANDLE " Linked to NdisVcHandle 0x%p\n"
  6718. RmLinkToExternalEx(
  6719. pOwner, // pHdr
  6720. 0xb57e657b, // LUID
  6721. (UINT_PTR) NdisVcHandle, // External entity
  6722. ARPASSOC_EXTLINK_TO_NDISVCHANDLE, // AssocID
  6723. szARPASSOC_EXTLINK_TO_NDISVCHANDLE,
  6724. pSR
  6725. );
  6726. #else // !RM_EXTRA_CHECKING
  6727. RmLinkToExternalFast(pOwner);
  6728. #endif // !RM_EXTRA_CHECKING
  6729. }
  6730. EXIT()
  6731. return Status;
  6732. }
  6733. VOID
  6734. arpDeinitializeVc(
  6735. PARP1394_INTERFACE pIF,
  6736. PARP_VC_HEADER pVcHdr,
  6737. PRM_OBJECT_HEADER pOwner, // NOLOCKIN NOLOCKOUT
  6738. PRM_STACK_RECORD pSR
  6739. )
  6740. /*++
  6741. Routine Description:
  6742. DeInitialize the Vc Header; Deallocate the NdisVcHandle;
  6743. Arguments:
  6744. pIF - Interface this applies to
  6745. pOwner - Owning object (for de-referencing)
  6746. pVcHdr - Protocol Vc context to de-initialize
  6747. --*/
  6748. {
  6749. ENTER("arpDeinitializeVc", 0x270b29ac)
  6750. NDIS_HANDLE NdisVcHandle;
  6751. RM_ASSERT_NOLOCKS(pSR);
  6752. LOCKHDR(pOwner, pSR);
  6753. // (DEBUG ONLY) Verify that there is no make-call or close-call task.
  6754. //
  6755. ASSERT( pVcHdr->pMakeCallTask == NULL && pVcHdr->pCleanupCallTask == NULL );
  6756. NdisVcHandle = pVcHdr->NdisVcHandle;
  6757. // Zero out the structure.
  6758. //
  6759. ARP_ZEROSTRUCT(pVcHdr);
  6760. UNLOCKHDR(pOwner, pSR);
  6761. RM_ASSERT_NOLOCKS(pSR);
  6762. // Delete the Link-to-external pOwningObject to the ndis-vc handle.
  6763. //
  6764. #if RM_EXTRA_CHECKING
  6765. RmUnlinkFromExternalEx(
  6766. pOwner, // pHdr
  6767. 0xee1b4fe3, // LUID
  6768. (UINT_PTR) NdisVcHandle, // External entity
  6769. ARPASSOC_EXTLINK_TO_NDISVCHANDLE, // AssocID
  6770. pSR
  6771. );
  6772. #else // !RM_EXTRA_CHECKING
  6773. RmUnlinkFromExternalFast(pOwner);
  6774. #endif // !RM_EXTRA_CHECKING
  6775. // Delete the ndis vc handle.
  6776. //
  6777. NdisCoDeleteVc(NdisVcHandle);
  6778. EXIT()
  6779. }
  6780. UINT
  6781. arpRecvFifoReceivePacket(
  6782. IN NDIS_HANDLE ProtocolBindingContext,
  6783. IN NDIS_HANDLE ProtocolVcContext,
  6784. IN PNDIS_PACKET pNdisPacket
  6785. )
  6786. /*++
  6787. HOT PATH
  6788. --*/
  6789. {
  6790. PARP_VC_HEADER pVcHdr;
  6791. PARP1394_INTERFACE pIF;
  6792. pVcHdr = (PARP_VC_HEADER) ProtocolVcContext;
  6793. pIF = CONTAINING_RECORD( pVcHdr, ARP1394_INTERFACE, recvinfo.VcHdr);
  6794. ASSERT_VALID_INTERFACE(pIF);
  6795. return arpProcessReceivedPacket(
  6796. pIF,
  6797. pNdisPacket,
  6798. FALSE // IsChannel
  6799. );
  6800. }
  6801. VOID
  6802. arpRecvFifoIncomingClose(
  6803. IN NDIS_STATUS CloseStatus,
  6804. IN NDIS_HANDLE ProtocolVcContext,
  6805. IN PVOID pCloseData OPTIONAL,
  6806. IN UINT Size OPTIONAL
  6807. )
  6808. {
  6809. PARP_VC_HEADER pVcHdr;
  6810. PARP1394_INTERFACE pIF;
  6811. RM_DECLARE_STACK_RECORD(sr)
  6812. pVcHdr = (PARP_VC_HEADER) ProtocolVcContext;
  6813. pIF = CONTAINING_RECORD( pVcHdr, ARP1394_INTERFACE, recvinfo.VcHdr);
  6814. ASSERT_VALID_INTERFACE(pIF);
  6815. //
  6816. // This is the IF receive FIFO VC. For now, geting an incoming close on
  6817. // the receive FIFO vc results in our initiating the deinit of pIF.
  6818. //
  6819. OBJLOG1(pIF,"Got incoming close on recv FIFO!. Status=0x%lx\n", CloseStatus);
  6820. (VOID) arpDeinitIf(
  6821. pIF,
  6822. NULL, // pCallingTask
  6823. 0, // SuspendCode
  6824. &sr
  6825. );
  6826. RM_ASSERT_CLEAR(&sr);
  6827. }
  6828. VOID
  6829. arpBroadcastChannelIncomingClose(
  6830. IN NDIS_STATUS CloseStatus,
  6831. IN NDIS_HANDLE ProtocolVcContext,
  6832. IN PVOID pCloseData OPTIONAL,
  6833. IN UINT Size OPTIONAL
  6834. )
  6835. {
  6836. PARP_VC_HEADER pVcHdr;
  6837. PARP1394_INTERFACE pIF;
  6838. ARPCB_DEST * pDest;
  6839. RM_DECLARE_STACK_RECORD(sr)
  6840. pVcHdr = (PARP_VC_HEADER) ProtocolVcContext;
  6841. pDest = CONTAINING_RECORD( pVcHdr, ARPCB_DEST, VcHdr);
  6842. ASSERT_VALID_DEST(pDest);
  6843. pIF = (ARP1394_INTERFACE*) RM_PARENT_OBJECT(pDest);
  6844. //
  6845. // Since all our calls are outgoing, getting an IncomingClose means that
  6846. // the call was in the active state. Anyway, what we need to do is update the
  6847. // call state and start the VcCleanupTask for this Vc.
  6848. //
  6849. //
  6850. // This is the broadcast channel VC.
  6851. // FOR NOW: we leave the IF alone, but deinit the dest-VC.
  6852. //
  6853. OBJLOG1(pDest,"Got incoming close! Status=0x%lx\n", CloseStatus);
  6854. LOGSTATS_IncomingClosesOnChannels(pIF);
  6855. (VOID) arpDeinitDestination(pDest, FALSE, &sr); // FALSE == force deinit
  6856. RM_ASSERT_CLEAR(&sr);
  6857. }
  6858. UINT
  6859. arpProcessReceivedPacket(
  6860. IN PARP1394_INTERFACE pIF,
  6861. IN PNDIS_PACKET pNdisPacket,
  6862. IN MYBOOL IsChannel
  6863. )
  6864. {
  6865. ENTER("arpProcessReceivedPacket", 0xe317990b)
  6866. UINT TotalLength; // Total bytes in packet
  6867. PNDIS_BUFFER pNdisBuffer; // Pointer to first buffer
  6868. UINT BufferLength;
  6869. UINT ReturnCount;
  6870. PVOID pvPktHeader;
  6871. PNIC1394_ENCAPSULATION_HEADER
  6872. pEncapHeader;
  6873. const UINT MacHeaderLength = sizeof(NIC1394_ENCAPSULATION_HEADER);
  6874. ARP1394_ADAPTER * pAdapter =
  6875. (ARP1394_ADAPTER*) RM_PARENT_OBJECT(pIF);
  6876. BOOLEAN fBridgeMode = ARP_BRIDGE_ENABLED(pAdapter);
  6877. DBGMARK(0x2361f585);
  6878. ReturnCount = 0;
  6879. NdisQueryPacket(
  6880. pNdisPacket,
  6881. NULL,
  6882. NULL,
  6883. &pNdisBuffer,
  6884. &TotalLength
  6885. );
  6886. if (TotalLength > 0)
  6887. {
  6888. NdisQueryBuffer(
  6889. pNdisBuffer,
  6890. (PVOID *)&pvPktHeader,
  6891. &BufferLength
  6892. );
  6893. }
  6894. else
  6895. {
  6896. pvPktHeader = NULL;
  6897. BufferLength = 0;
  6898. }
  6899. pEncapHeader = (PNIC1394_ENCAPSULATION_HEADER) pvPktHeader;
  6900. TR_INFO(
  6901. ("Rcv: NDISpkt 0x%x, NDISbuf 0x%x, Buflen %d, Totlen %d, Pkthdr 0x%x\n",
  6902. pNdisPacket,
  6903. pNdisBuffer,
  6904. BufferLength,
  6905. TotalLength,
  6906. pvPktHeader));
  6907. // TODO -- we include mcap/arp in InOctets below, is this the right thing?
  6908. //
  6909. ARP_IF_STAT_ADD(pIF, InOctets, TotalLength);
  6910. LOGSTATS_TotRecvs(pIF, pNdisPacket);
  6911. if (IsChannel)
  6912. {
  6913. LOGSTATS_RecvChannelCounts(pIF, pNdisPacket);
  6914. }
  6915. else
  6916. {
  6917. LOGSTATS_RecvFifoCounts(pIF, pNdisPacket);
  6918. }
  6919. if (BufferLength < MacHeaderLength || pvPktHeader == NULL)
  6920. {
  6921. // Packet is too small, discard.
  6922. //
  6923. ARP_IF_STAT_INCR(pIF, InDiscards);
  6924. return 0; // EARLY RETURN
  6925. }
  6926. if (fBridgeMode)
  6927. {
  6928. arpEthReceive1394Packet(
  6929. pIF,
  6930. pNdisPacket,
  6931. pvPktHeader,
  6932. BufferLength,
  6933. IsChannel
  6934. );
  6935. return 0; // ********* EARLY RETURN *******
  6936. }
  6937. //
  6938. // Discard the packet if the IP interface is not open
  6939. //
  6940. if (!CHECK_IF_IP_STATE(pIF, ARPIF_IPS_OPEN))
  6941. {
  6942. TR_INFO(("Discardning received pkt because pIF 0x%p IP IF is not open.\n", pIF));
  6943. return 0; // ********* EARLY RETURN *******
  6944. }
  6945. //
  6946. // At this point, pEncapHeader contains the IP/1394 unfragmented encapsulation
  6947. // header. We look at the ethertype to decide what to do with it.
  6948. //
  6949. if (pEncapHeader->EtherType == H2N_USHORT(NIC1394_ETHERTYPE_IP))
  6950. {
  6951. //
  6952. // The EtherType is IP, so we pass up this packet to the IP layer.
  6953. // (Also we indicate all packets we receive on the broadcast channel
  6954. // to the ethernet VC).
  6955. //
  6956. TR_INFO(
  6957. ("Rcv: pPkt 0x%x: EtherType is IP, passing up.\n", pNdisPacket));
  6958. if (IsChannel)
  6959. {
  6960. ARP_IF_STAT_INCR(pIF, InNonUnicastPkts);
  6961. }
  6962. else
  6963. {
  6964. ARP_IF_STAT_INCR(pIF, InUnicastPkts);
  6965. }
  6966. if (NDIS_GET_PACKET_STATUS(pNdisPacket) != NDIS_STATUS_RESOURCES)
  6967. {
  6968. UINT DataSize;
  6969. #define ARP_MIN_1ST_RECV_BUFSIZE 512
  6970. //
  6971. // Following are notes taken from atmarpc.sys sources...
  6972. //
  6973. // 2/8/1998 JosephJ
  6974. // We set DataSize to the total payload size,
  6975. // unless the first buffer is too small to
  6976. // hold the IP header. In the latter case,
  6977. // we set DataSize to be the size of the 1st buffer
  6978. // (minus the LLS/SNAP header size).
  6979. //
  6980. // This is to work around a bug in tcpip.
  6981. //
  6982. // 2/25/1998 JosephJ
  6983. // Unfortunately we have to back out YET AGAIN
  6984. // because large pings (eg ping -l 4000) doesn't
  6985. // work -- bug#297784
  6986. // Hence the "0" in "0 && DataSize" below.
  6987. // Take out the "0" to put back the per fix.
  6988. //
  6989. //
  6990. // Note: MacHeaderLength is the TOTAL size of the stuff before the
  6991. // start of the IP pkt. This includes the size of the encapsulation
  6992. // header plus (for channels only) the size of the GASP header.
  6993. //
  6994. DataSize = BufferLength - MacHeaderLength;
  6995. {
  6996. LOGSTATS_CopyRecvs(pIF, pNdisPacket);
  6997. }
  6998. pIF->ip.RcvPktHandler(
  6999. pIF->ip.Context,
  7000. (PVOID)((PUCHAR)pEncapHeader+sizeof(*pEncapHeader)), // start of data
  7001. DataSize,
  7002. TotalLength,
  7003. (NDIS_HANDLE)pNdisPacket,
  7004. MacHeaderLength,
  7005. IsChannel,
  7006. 0,
  7007. pNdisBuffer,
  7008. &ReturnCount,
  7009. NULL
  7010. );
  7011. }
  7012. else
  7013. {
  7014. LOGSTATS_ResourceRecvs(pIF, pNdisPacket);
  7015. pIF->ip.RcvHandler(
  7016. pIF->ip.Context,
  7017. (PVOID)((PUCHAR)pEncapHeader+sizeof(*pEncapHeader)),
  7018. BufferLength - MacHeaderLength,
  7019. TotalLength - MacHeaderLength,
  7020. (NDIS_HANDLE)pNdisPacket,
  7021. MacHeaderLength,
  7022. IsChannel,
  7023. NULL
  7024. );
  7025. }
  7026. }
  7027. else if (pEncapHeader->EtherType == H2N_USHORT(NIC1394_ETHERTYPE_ARP))
  7028. {
  7029. PIP1394_ARP_PKT pArpPkt = (PIP1394_ARP_PKT) pEncapHeader;
  7030. if (TotalLength != BufferLength)
  7031. {
  7032. ASSERT(!"Can't deal with TotalLength != BufferLength");
  7033. }
  7034. else
  7035. {
  7036. arpProcessArpPkt(
  7037. pIF,
  7038. pArpPkt,
  7039. BufferLength
  7040. );
  7041. }
  7042. }
  7043. else if (pEncapHeader->EtherType == H2N_USHORT(NIC1394_ETHERTYPE_MCAP))
  7044. {
  7045. PIP1394_MCAP_PKT pMcapPkt = (PIP1394_MCAP_PKT) pEncapHeader;
  7046. if (TotalLength != BufferLength)
  7047. {
  7048. ASSERT(!"Can't deal wiht TotalLength != BufferLength");
  7049. }
  7050. else
  7051. {
  7052. arpProcessMcapPkt(
  7053. pIF,
  7054. pMcapPkt,
  7055. BufferLength
  7056. );
  7057. }
  7058. }
  7059. else
  7060. {
  7061. //
  7062. // Discard packet -- unknown/bad EtherType
  7063. //
  7064. TR_INFO(("Encap hdr 0x%x, bad EtherType 0x%x\n",
  7065. pEncapHeader, pEncapHeader->EtherType));
  7066. ARP_IF_STAT_INCR(pIF, UnknownProtos);
  7067. }
  7068. EXIT()
  7069. return ReturnCount;
  7070. }
  7071. NDIS_STATUS
  7072. arpInitializeIfPools(
  7073. IN PARP1394_INTERFACE pIF,
  7074. IN PRM_STACK_RECORD pSR
  7075. )
  7076. /*++
  7077. Routine Description:
  7078. This routine is called in the context of creating an interface. It
  7079. allocate the various buffer and packet pools associated with the interface.
  7080. It cleans up all pools on failure.
  7081. Arguments:
  7082. pIF - Interface to initialize
  7083. Return Value:
  7084. NDIS_STATUS_SUCCESS on success
  7085. Ndis failure code otherwise.
  7086. --*/
  7087. {
  7088. ENTER("arpInitializeIfPools", 0x0a3b1b32)
  7089. MYBOOL fHeaderPoolInitialized = FALSE;
  7090. MYBOOL fPacketPoolInitialized = FALSE;
  7091. MYBOOL fEthernetPoolsInitialized = FALSE;
  7092. NDIS_STATUS Status;
  7093. do
  7094. {
  7095. // TODO: replace 10, 100, by constants, or perhaps global vars.
  7096. Status = arpInitializeConstBufferPool(
  7097. 10, //NumBuffersToCache,
  7098. 100, //MaxBuffers,
  7099. &Arp1394_IpEncapHeader, //pvMem,
  7100. sizeof(Arp1394_IpEncapHeader), //cbMem,
  7101. &pIF->Hdr,
  7102. &pIF->sendinfo.HeaderPool,
  7103. pSR
  7104. );
  7105. if (FAIL(Status))
  7106. {
  7107. OBJLOG1(
  7108. pIF,
  7109. "Couldn't initialize const header pool (Status=0x%lx)!\n",
  7110. Status
  7111. );
  7112. break;
  7113. }
  7114. fHeaderPoolInitialized = TRUE;
  7115. Status = arpAllocateControlPacketPool(
  7116. pIF,
  7117. ARP1394_MAX_PROTOCOL_PACKET_SIZE,
  7118. pSR
  7119. );
  7120. if (FAIL(Status))
  7121. {
  7122. TR_WARN((
  7123. "Couldn't allocate control packet pool (Status=0x%lx)!\n",
  7124. Status
  7125. ));
  7126. break;
  7127. }
  7128. fPacketPoolInitialized = TRUE;
  7129. Status = arpAllocateEthernetPools(
  7130. pIF,
  7131. pSR
  7132. );
  7133. if (FAIL(Status))
  7134. {
  7135. OBJLOG1(
  7136. pIF,
  7137. "Couldn't allocate ethernet packet pool (Status=0x%lx)!\n",
  7138. Status
  7139. );
  7140. break;
  7141. }
  7142. fEthernetPoolsInitialized = TRUE;
  7143. } while (FALSE);
  7144. if (FAIL(Status))
  7145. {
  7146. if (fHeaderPoolInitialized)
  7147. {
  7148. // Deinit the header const buffer pool.
  7149. //
  7150. arpDeinitializeConstBufferPool(&pIF->sendinfo.HeaderPool, pSR);
  7151. }
  7152. if (fPacketPoolInitialized)
  7153. {
  7154. // Deinit the control packet pool
  7155. //
  7156. arpFreeControlPacketPool( pIF,pSR);
  7157. }
  7158. if (fEthernetPoolsInitialized)
  7159. {
  7160. // Deinit the ethernet packet pool
  7161. //
  7162. arpFreeEthernetPools(pIF, pSR);
  7163. }
  7164. }
  7165. else
  7166. {
  7167. ASSERT(fHeaderPoolInitialized && fPacketPoolInitialized);
  7168. ASSERT(fEthernetPoolsInitialized);
  7169. }
  7170. return Status;
  7171. }
  7172. VOID
  7173. arpDeInitializeIfPools(
  7174. IN PARP1394_INTERFACE pIF, // LOCKIN LOCKOUT
  7175. IN PRM_STACK_RECORD pSR
  7176. )
  7177. /*++
  7178. Routine Description:
  7179. This routine is called in the context of deleting an interface. It
  7180. cleans up the various buffer and packet pools associated with the interface.
  7181. Should NOT be called with a partially-initialized pIF.
  7182. Arguments:
  7183. pIF - Interface to deinit pools
  7184. --*/
  7185. {
  7186. ENTER("arpDeInitializeIfPools", 0x1a54488d)
  7187. RM_ASSERT_OBJLOCKED(&pIF->Hdr, pSR);
  7188. // Deinit the header const buffer pool.
  7189. //
  7190. arpDeinitializeConstBufferPool(&pIF->sendinfo.HeaderPool, pSR);
  7191. // Deinit the control packet pool
  7192. //
  7193. arpFreeControlPacketPool(pIF,pSR);
  7194. // Deinit the ethernet packet and buffer pool
  7195. //
  7196. arpFreeEthernetPools(pIF,pSR);
  7197. }
  7198. MYBOOL
  7199. arpIsAdapterConnected(
  7200. IN PARP1394_ADAPTER pAdapter, // NOLOCKIN NOLOCKOUT
  7201. IN PRM_STACK_RECORD pSR
  7202. )
  7203. {
  7204. ENTER("arpIsAdapterConnected", 0x126b577a)
  7205. // static UINT u = 0;
  7206. MYBOOL fRet;
  7207. ARP_NDIS_REQUEST ArpNdisRequest;
  7208. NDIS_MEDIA_STATE ConnectStatus;
  7209. NDIS_STATUS Status;
  7210. RM_ASSERT_NOLOCKS(pSR);
  7211. #if 0
  7212. if (u==0)
  7213. {
  7214. fRet = FALSE;
  7215. u=1;
  7216. }
  7217. else
  7218. {
  7219. fRet = TRUE;
  7220. }
  7221. #else // !0
  7222. Status = arpPrepareAndSendNdisRequest(
  7223. pAdapter,
  7224. &ArpNdisRequest,
  7225. NULL, // pTask (NULL==BLOCK)
  7226. 0, // unused
  7227. OID_1394_IP1394_CONNECT_STATUS,
  7228. &ConnectStatus,
  7229. sizeof(ConnectStatus),
  7230. NdisRequestQueryInformation,
  7231. pSR
  7232. );
  7233. ASSERT(!PEND(Status));
  7234. fRet = FALSE;
  7235. if (!FAIL(Status))
  7236. {
  7237. if (ConnectStatus == NdisMediaStateConnected)
  7238. {
  7239. fRet = TRUE;
  7240. }
  7241. }
  7242. #endif // !0
  7243. RM_ASSERT_NOLOCKS(pSR);
  7244. EXIT()
  7245. return fRet;
  7246. }
  7247. NDIS_STATUS
  7248. arpSetupSpecialDest(
  7249. IN PARP1394_INTERFACE pIF,
  7250. IN NIC1394_ADDRESS_TYPE AddressType,
  7251. IN PRM_TASK pParentTask,
  7252. IN UINT PendCode,
  7253. OUT PARPCB_DEST * ppSpecialDest,
  7254. IN PRM_STACK_RECORD pSR
  7255. )
  7256. {
  7257. ENTER("SetupSpecialDest", 0x745a806d)
  7258. ARP_DEST_PARAMS DestParams;
  7259. PCHAR szDescription;
  7260. PARPCB_DEST pDest;
  7261. INT fCreated = FALSE;
  7262. PRM_TASK pMakeCallTask;
  7263. NDIS_STATUS Status;
  7264. MYBOOL fBroadcastDest = FALSE;
  7265. ULONG LookupFlags = 0;
  7266. PARP1394_ADAPTER pAdapter = (PARP1394_ADAPTER)RM_PARENT_OBJECT(pIF);
  7267. *ppSpecialDest = NULL;
  7268. //
  7269. // Let's create a destination object representing the
  7270. // multichannel, and make a call to it.
  7271. //
  7272. ARP_ZEROSTRUCT(&DestParams);
  7273. DestParams.HwAddr.AddressType = AddressType;
  7274. switch(AddressType)
  7275. {
  7276. case NIC1394AddressType_Channel:
  7277. DestParams.HwAddr.Channel = NIC1394_BROADCAST_CHANNEL;
  7278. fBroadcastDest = TRUE;
  7279. szDescription = "Task: Broadcast MakeCall";
  7280. break;
  7281. case NIC1394AddressType_MultiChannel:
  7282. szDescription = "Task: MultiChannel MakeCall";
  7283. break;
  7284. case NIC1394AddressType_Ethernet:
  7285. szDescription = "Task: Ethernet MakeCall";
  7286. break;
  7287. default:
  7288. ASSERT(FALSE);
  7289. return NDIS_STATUS_FAILURE; // ****** EARLY RETURN *****
  7290. }
  7291. #if RM_EXTRA_CHECKING
  7292. switch(AddressType)
  7293. {
  7294. case NIC1394AddressType_Channel:
  7295. szDescription = "Task: Broadcast MakeCall";
  7296. break;
  7297. case NIC1394AddressType_MultiChannel:
  7298. szDescription = "Task: MultiChannel MakeCall";
  7299. break;
  7300. case NIC1394AddressType_Ethernet:
  7301. szDescription = "Task: Ethernet MakeCall";
  7302. break;
  7303. default:
  7304. ASSERT(FALSE);
  7305. return NDIS_STATUS_FAILURE; // ****** EARLY RETURN *****
  7306. }
  7307. #endif // RM_EXTRA_CHECKING
  7308. // Now create a destination item for this structure.
  7309. //
  7310. if (CHECK_POWER_STATE(pAdapter,ARPAD_POWER_LOW_POWER) == TRUE)
  7311. {
  7312. // In the resume, the Destination structures are aleady there
  7313. // so don't create a new one.
  7314. LookupFlags = 0;
  7315. }
  7316. else
  7317. {
  7318. //
  7319. // We don't expect it to already exist in the non PM case
  7320. //
  7321. LookupFlags = RM_CREATE | RM_NEW;
  7322. }
  7323. Status = RmLookupObjectInGroup(
  7324. &pIF->DestinationGroup,
  7325. LookupFlags ,
  7326. &DestParams, // Key
  7327. &DestParams, // pParams
  7328. (RM_OBJECT_HEADER**) &pDest,
  7329. &fCreated,
  7330. pSR
  7331. );
  7332. if (FAIL(Status))
  7333. {
  7334. OBJLOG1( pIF, "FATAL: Couldn't create special dest type %d.\n", AddressType);
  7335. }
  7336. else
  7337. {
  7338. Status = arpAllocateTask(
  7339. &pDest->Hdr, // pParentObject
  7340. arpTaskMakeCallToDest, // pfnHandler
  7341. 0, // Timeout
  7342. szDescription,
  7343. &pMakeCallTask,
  7344. pSR
  7345. );
  7346. if (FAIL(Status))
  7347. {
  7348. RmTmpDereferenceObject(&pDest->Hdr, pSR);
  7349. // NOTE: Even on failure, we leave the newly-created
  7350. // special dest object. It will get cleaned up when
  7351. // the interface is unloaded.
  7352. //
  7353. }
  7354. else
  7355. {
  7356. *ppSpecialDest = pDest;
  7357. if (fBroadcastDest)
  7358. {
  7359. // pDest contains a valid
  7360. // pDest which has been tmpref'd.
  7361. // Keep a pointer to the broadcast dest in the IF.
  7362. // and link the broadcast dest to the IF.
  7363. //
  7364. #if RM_EXTRA_CHECKING
  7365. RmLinkObjectsEx(
  7366. &pIF->Hdr,
  7367. &pDest->Hdr,
  7368. 0xacc1dbe9,
  7369. ARPASSOC_LINK_IF_OF_BCDEST,
  7370. " IF of Broadcast Dest 0x%p (%s)\n",
  7371. ARPASSOC_LINK_BCDEST_OF_IF,
  7372. " Broadcast Dest of IF 0x%p (%s)\n",
  7373. pSR
  7374. );
  7375. #else // !RM_EXTRA_CHECKING
  7376. RmLinkObjects(&pIF->Hdr, &pDest->Hdr,pSR);
  7377. #endif // !RM_EXTRA_CHECKING
  7378. LOCKOBJ(pIF, pSR);
  7379. ASSERT(pIF->pBroadcastDest == NULL);
  7380. pIF->pBroadcastDest = pDest;
  7381. UNLOCKOBJ(pIF, pSR);
  7382. // arpSetupSpecialDest ref'd pDest.
  7383. //
  7384. RmTmpDereferenceObject(&pDest->Hdr, pSR);
  7385. }
  7386. RmPendTaskOnOtherTask(
  7387. pParentTask,
  7388. PendCode,
  7389. pMakeCallTask,
  7390. pSR
  7391. );
  7392. (VOID)RmStartTask(
  7393. pMakeCallTask,
  7394. 0, // UserParam (unused)
  7395. pSR
  7396. );
  7397. Status = NDIS_STATUS_PENDING;
  7398. }
  7399. }
  7400. return Status;
  7401. }
  7402. VOID
  7403. arpDestSendComplete(
  7404. IN NDIS_STATUS Status,
  7405. IN NDIS_HANDLE ProtocolVcContext,
  7406. IN PNDIS_PACKET pNdisPacket
  7407. )
  7408. {
  7409. PARP_VC_HEADER pVcHdr = (PARP_VC_HEADER) ProtocolVcContext;
  7410. PARPCB_DEST pDest = CONTAINING_RECORD(pVcHdr, ARPCB_DEST, VcHdr);
  7411. PARP1394_INTERFACE pIF = (PARP1394_INTERFACE) RM_PARENT_OBJECT(pDest);
  7412. ASSERT_VALID_DEST(pDest);
  7413. ASSERT_VALID_INTERFACE(pIF);
  7414. // The call to NdisCoSendPacket returns.
  7415. arpCompleteSentPkt(
  7416. Status,
  7417. pIF,
  7418. pDest,
  7419. pNdisPacket
  7420. );
  7421. }
  7422. UINT
  7423. arpDestReceivePacket(
  7424. IN NDIS_HANDLE ProtocolBindingContext,
  7425. IN NDIS_HANDLE ProtocolVcContext,
  7426. IN PNDIS_PACKET pNdisPacket
  7427. )
  7428. //
  7429. // Standard Recv Handler for most Vcs
  7430. //
  7431. {
  7432. PARP_VC_HEADER pVcHdr;
  7433. PARPCB_DEST pDest;
  7434. PARP1394_INTERFACE pIF;
  7435. PARP1394_ADAPTER pAdapter ;
  7436. BOOLEAN fBridgeMode ;
  7437. pVcHdr = (PARP_VC_HEADER) ProtocolVcContext;
  7438. pDest = CONTAINING_RECORD( pVcHdr, ARPCB_DEST, VcHdr);
  7439. ASSERT_VALID_DEST(pDest);
  7440. pIF = (ARP1394_INTERFACE*) RM_PARENT_OBJECT(pDest);
  7441. ASSERT_VALID_INTERFACE(pIF);
  7442. pAdapter = (PARP1394_ADAPTER)pIF->Hdr.pParentObject;
  7443. fBridgeMode = ARP_BRIDGE_ENABLED(pAdapter);
  7444. //
  7445. // if we are in bridge mode, then check to see if
  7446. // this is a loopback packet
  7447. //
  7448. if (fBridgeMode == TRUE)
  7449. {
  7450. PLOOPBACK_RSVD pLoopbackRsvd = (PLOOPBACK_RSVD) pNdisPacket->ProtocolReserved;
  7451. BOOLEAN fIsLoopbackPacket = (pLoopbackRsvd->LoopbackTag == NIC_LOOPBACK_TAG);
  7452. if (fIsLoopbackPacket == TRUE)
  7453. {
  7454. // drop the packet as it is a loopback packet
  7455. return 0;
  7456. }
  7457. // else it is a normal receive. continue to arpProcessReceivedPacket
  7458. }
  7459. //
  7460. // Process the receive packet
  7461. //
  7462. return arpProcessReceivedPacket(
  7463. pIF,
  7464. pNdisPacket,
  7465. TRUE // IsChannel
  7466. );
  7467. }
  7468. VOID
  7469. arpDestIncomingClose(
  7470. IN NDIS_STATUS CloseStatus,
  7471. IN NDIS_HANDLE ProtocolVcContext,
  7472. IN PVOID pCloseData OPTIONAL,
  7473. IN UINT Size OPTIONAL
  7474. )
  7475. {
  7476. PARP_VC_HEADER pVcHdr;
  7477. PARP1394_INTERFACE pIF;
  7478. ARPCB_DEST * pDest;
  7479. ENTER("arpDestIncomingClose",0x8727a7f1)
  7480. RM_DECLARE_STACK_RECORD(sr)
  7481. pVcHdr = (PARP_VC_HEADER) ProtocolVcContext;
  7482. pDest = CONTAINING_RECORD( pVcHdr, ARPCB_DEST, VcHdr);
  7483. ASSERT_VALID_DEST(pDest);
  7484. pIF = (ARP1394_INTERFACE*) RM_PARENT_OBJECT(pDest);
  7485. //
  7486. // Since all our calls are outgoing, getting an IncomingClose means that
  7487. // the call was in the active state. Anyway, what we need to do is update the
  7488. // call state and start the VcCleanupTask for this Vc.
  7489. //
  7490. //
  7491. // We leave the IF alone, but deinit the dest-VC.
  7492. //
  7493. OBJLOG1(pDest,"Got incoming close! Status=0x%lx\n", CloseStatus);
  7494. LOGSTATS_IncomingClosesOnChannels(pIF);
  7495. {
  7496. ARP1394_ADAPTER *pAdapter = (ARP1394_ADAPTER*)RM_PARENT_OBJECT(pIF);
  7497. BOOLEAN fBridgeMode = ARP_BRIDGE_ENABLED(pAdapter);
  7498. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  7499. //
  7500. // If the Bridge is enabled, then just close the call on the destination.
  7501. // In the normal case, we delete the destintation structure.
  7502. if (fBridgeMode == TRUE)
  7503. {
  7504. PRM_TASK pCleanupCallTask = NULL;
  7505. //
  7506. // In the Bridgecase we want to keep alive our knowledge
  7507. // about the 1394 network as we
  7508. // can only learn this knowledge from Ethernet arps
  7509. // which are outside our control.
  7510. //
  7511. //
  7512. // AN incoming close signifies that the Remote Node that this Dest
  7513. // represents has gone away. We want to keep the Dest structure alive
  7514. // in case the other node resumes from standby/ hibernate and
  7515. // does not send out any ARPs so we cannot learn its address.
  7516. //
  7517. //
  7518. Status = arpAllocateTask(
  7519. &pDest->Hdr, // pParentObject,
  7520. arpTaskCleanupCallToDest, // pfnHandler,
  7521. 0, // Timeout,
  7522. "Task: CleanupCall on UnloadDest", // szDescription
  7523. &pCleanupCallTask,
  7524. &sr
  7525. );
  7526. if (FAIL(Status))
  7527. {
  7528. TR_WARN(("FATAL: couldn't alloc cleanup call task!\n"));
  7529. }
  7530. else
  7531. {
  7532. // RmStartTask uses up the tmpref on the task
  7533. // which was added by arpAllocateTask.
  7534. //
  7535. Status = RmStartTask(
  7536. pCleanupCallTask,
  7537. 0, // UserParam (unused)
  7538. &sr
  7539. );
  7540. }
  7541. }
  7542. else
  7543. {
  7544. (VOID) arpDeinitDestination(pDest, FALSE, &sr); // FALSE == forced deinit
  7545. }
  7546. }
  7547. RM_ASSERT_CLEAR(&sr);
  7548. }
  7549. VOID
  7550. arpTryAbortPrimaryIfTask(
  7551. PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  7552. PRM_STACK_RECORD pSR
  7553. )
  7554. {
  7555. ENTER("arpTryAbortPrimaryIfTask", 0x39c51d16)
  7556. RM_ASSERT_NOLOCKS(pSR);
  7557. LOCKOBJ(pIF,pSR);
  7558. if (pIF->pActDeactTask!=NULL)
  7559. {
  7560. //
  7561. // Actually
  7562. // delayed.
  7563. //
  7564. PRM_TASK pTask = pIF->pActDeactTask;
  7565. RmTmpReferenceObject(&pTask->Hdr, pSR);
  7566. UNLOCKOBJ(pIF,pSR);
  7567. if (pTask->pfnHandler == arpTaskActivateInterface)
  7568. {
  7569. TASK_ACTIVATE_IF *pActivateIfTask = (TASK_ACTIVATE_IF *) pTask;
  7570. UINT TaskResumed;
  7571. TR_WARN(("Aborting ActivateIfTask %p\n", pTask));
  7572. RmResumeDelayedTaskNow(
  7573. &pActivateIfTask->TskHdr,
  7574. &pActivateIfTask->Timer,
  7575. &TaskResumed,
  7576. pSR
  7577. );
  7578. }
  7579. RmTmpDereferenceObject(&pTask->Hdr, pSR);
  7580. }
  7581. else
  7582. {
  7583. UNLOCKOBJ(pIF,pSR);
  7584. }
  7585. RM_ASSERT_NOLOCKS(pSR);
  7586. EXIT()
  7587. }
  7588. NDIS_STATUS
  7589. arpTaskIfMaintenance(
  7590. IN struct _RM_TASK * pTask,
  7591. IN RM_TASK_OPERATION Code,
  7592. IN UINT_PTR UserParam,
  7593. IN PRM_STACK_RECORD pSR
  7594. )
  7595. /*++
  7596. Routine Description:
  7597. Task handler responsible for periodic IF maintenance.
  7598. Arguments:
  7599. UserParam for (Code == RM_TASKOP_START) : unused
  7600. --*/
  7601. {
  7602. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  7603. ARP1394_INTERFACE * pIF = (ARP1394_INTERFACE*) RM_PARENT_OBJECT(pTask);
  7604. PTASK_IF_MAINTENANCE pIfTask;
  7605. enum
  7606. {
  7607. STAGE_Start,
  7608. STAGE_ResumeDelayed,
  7609. STAGE_End
  7610. } Stage;
  7611. ENTER("TaskIfMaintenance", 0x57e523ed)
  7612. pIfTask = (PTASK_IF_MAINTENANCE) pTask;
  7613. ASSERT(sizeof(TASK_IF_MAINTENANCE) <= sizeof(ARP1394_TASK));
  7614. //
  7615. // Message normalizing code
  7616. //
  7617. switch(Code)
  7618. {
  7619. case RM_TASKOP_START:
  7620. Stage = STAGE_Start;
  7621. break;
  7622. case RM_TASKOP_PENDCOMPLETE:
  7623. Status = (NDIS_STATUS) UserParam;
  7624. ASSERT(!PEND(Status));
  7625. Stage = RM_PEND_CODE(pTask);
  7626. break;
  7627. case RM_TASKOP_END:
  7628. Status = (NDIS_STATUS) UserParam;
  7629. Stage= STAGE_End;
  7630. break;
  7631. default:
  7632. ASSERT(FALSE);
  7633. return NDIS_STATUS_FAILURE; // ** EARLY RETURN **
  7634. }
  7635. ASSERTEX(!PEND(Status), pTask);
  7636. switch(Stage)
  7637. {
  7638. case STAGE_Start:
  7639. {
  7640. // If there is already a maintenance task, we exit immediately.
  7641. //
  7642. LOCKOBJ(pIF, pSR);
  7643. if (pIF->pMaintenanceTask == NULL)
  7644. {
  7645. pIF->pMaintenanceTask = pTask;
  7646. DBG_ADDASSOC(
  7647. &pIF->Hdr, // pObject
  7648. pTask, // Instance1
  7649. pTask->Hdr.szDescription, // Instance2
  7650. ARPASSOC_IF_MAINTENANCE_TASK, // AssociationID
  7651. " Official maintenance task 0x%p (%s)\n", // szFormat
  7652. pSR
  7653. );
  7654. }
  7655. else
  7656. {
  7657. // There already is a maintenance task. We're done.
  7658. //
  7659. UNLOCKOBJ(pIF, pSR);
  7660. Status = NDIS_STATUS_SUCCESS;
  7661. break;
  7662. }
  7663. UNLOCKOBJ(pIF, pSR);
  7664. //
  7665. // We're now the official maintenance task for this interface.
  7666. //
  7667. // We move on to the next stage, after a delay, and to get
  7668. // out of the current context.
  7669. //
  7670. pIfTask->Delay = 5; // Arbitrary initial delay (seconds)
  7671. RmSuspendTask(pTask, STAGE_ResumeDelayed, pSR);
  7672. RmResumeTaskDelayed(
  7673. pTask,
  7674. 0,
  7675. 1000 * pIfTask->Delay,
  7676. &pIfTask->Timer,
  7677. pSR
  7678. );
  7679. Status = NDIS_STATUS_PENDING;
  7680. }
  7681. break;
  7682. case STAGE_ResumeDelayed:
  7683. {
  7684. UINT Time;
  7685. UINT Delta;
  7686. MYBOOL fProcessed;
  7687. //
  7688. // If qe're quitting, we get out of here.
  7689. // Otherwise we'll send a packet either on the ethernet VC
  7690. // or via the miniport's connectionless ethernet interface.
  7691. //
  7692. if (pIfTask->Quit)
  7693. {
  7694. Status = NDIS_STATUS_SUCCESS;
  7695. break;
  7696. }
  7697. Time = arpGetSystemTime();
  7698. //
  7699. // Process the MCAP database
  7700. //
  7701. Delta = Time - pIfTask->McapDbMaintenanceTime;
  7702. arpDoMcapDbMaintenance(pIF, Time, Delta, &fProcessed, pSR);
  7703. if (fProcessed)
  7704. {
  7705. //
  7706. // Update the last "McapDbMaintenance" time.
  7707. //
  7708. pIfTask->McapDbMaintenanceTime = Time;
  7709. }
  7710. //
  7711. // Process Remote IPs
  7712. //
  7713. Delta = Time - pIfTask->RemoteIpMaintenanceTime;
  7714. arpDoRemoteIpMaintenance(pIF, Time, Delta, &fProcessed, pSR);
  7715. if (fProcessed)
  7716. {
  7717. //
  7718. // Update the last "RemoteIpMaintenance" time.
  7719. //
  7720. pIfTask->RemoteIpMaintenanceTime = Time;
  7721. }
  7722. //
  7723. // Process Remote Eths
  7724. //
  7725. Delta = Time - pIfTask->RemoteEthMaintenanceTime;
  7726. arpDoRemoteEthMaintenance(pIF, Time, Delta, &fProcessed, pSR);
  7727. if (fProcessed)
  7728. {
  7729. //
  7730. // Update the last "RemoteIpMaintenance" time.
  7731. //
  7732. pIfTask->RemoteEthMaintenanceTime = Time;
  7733. }
  7734. //
  7735. // Process Local IPs
  7736. //
  7737. Delta = Time - pIfTask->LocalIpMaintenanceTime;
  7738. arpDoLocalIpMaintenance(pIF, Time, Delta, &fProcessed, pSR);
  7739. if (fProcessed)
  7740. {
  7741. //
  7742. // Update the last "LocalIpMaintenance" time.
  7743. //
  7744. pIfTask->LocalIpMaintenanceTime = Time;
  7745. }
  7746. //
  7747. // Process DhcpTableEntries
  7748. //
  7749. Delta = Time - pIfTask->DhcpTableMaintainanceTime;;
  7750. arpDoDhcpTableMaintenance(pIF, Time, Delta, &fProcessed, pSR);
  7751. if (fProcessed)
  7752. {
  7753. //
  7754. // Update the last "LocalIpMaintenance" time.
  7755. //
  7756. pIfTask->DhcpTableMaintainanceTime= Time;
  7757. }
  7758. // Now we wait again...
  7759. //
  7760. RmSuspendTask(pTask, STAGE_ResumeDelayed, pSR);
  7761. RmResumeTaskDelayed(
  7762. pTask,
  7763. 0,
  7764. 1000 * pIfTask->Delay,
  7765. &pIfTask->Timer,
  7766. pSR
  7767. );
  7768. Status = NDIS_STATUS_PENDING;
  7769. }
  7770. break;
  7771. case STAGE_End:
  7772. {
  7773. NDIS_HANDLE BindContext;
  7774. LOCKOBJ(pIF, pSR);
  7775. if (pIF->pMaintenanceTask == pTask)
  7776. {
  7777. // We're the official ics test task, we clear ourselves from
  7778. // the interface object and do any initialization required.
  7779. //
  7780. DBG_DELASSOC(
  7781. &pIF->Hdr, // pObject
  7782. pTask, // Instance1
  7783. pTask->Hdr.szDescription, // Instance2
  7784. ARPASSOC_IF_MAINTENANCE_TASK, // AssociationID
  7785. pSR
  7786. );
  7787. pIF->pMaintenanceTask = NULL;
  7788. UNLOCKOBJ(pIF, pSR);
  7789. }
  7790. else
  7791. {
  7792. // We're not the official IF maintenance task.
  7793. // Nothing else to do.
  7794. //
  7795. UNLOCKOBJ(pIF, pSR);
  7796. break;
  7797. }
  7798. }
  7799. break;
  7800. default:
  7801. {
  7802. ASSERTEX(!"Unknown task op", pTask);
  7803. }
  7804. break;
  7805. } // switch (Code)
  7806. RM_ASSERT_NOLOCKS(pSR);
  7807. EXIT()
  7808. return Status;
  7809. }
  7810. VOID
  7811. arpStartIfMaintenanceTask(
  7812. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  7813. PRM_STACK_RECORD pSR
  7814. )
  7815. {
  7816. PRM_TASK pTask;
  7817. NDIS_STATUS Status;
  7818. ENTER("arpStartIfMaintenanceTask", 0xb987276b)
  7819. RM_ASSERT_NOLOCKS(pSR);
  7820. //
  7821. // Allocate and start an instance of the arpTaskIfMaintenance task.
  7822. //
  7823. Status = arpAllocateTask(
  7824. &pIF->Hdr, // pParentObject
  7825. arpTaskIfMaintenance, // pfnHandler
  7826. 0, // Timeout
  7827. "Task: IF Maintenance", // szDescription
  7828. &pTask,
  7829. pSR
  7830. );
  7831. if (FAIL(Status))
  7832. {
  7833. TR_WARN(("couldn't alloc IF maintenance task!\n"));
  7834. }
  7835. else
  7836. {
  7837. (VOID)RmStartTask(
  7838. pTask,
  7839. 0, // UserParam (unused)
  7840. pSR
  7841. );
  7842. }
  7843. EXIT()
  7844. }
  7845. NDIS_STATUS
  7846. arpTryStopIfMaintenanceTask(
  7847. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  7848. IN PRM_TASK pTask, // task to pend until M task completes
  7849. IN UINT PendCode, // Pend code to suspend task.
  7850. PRM_STACK_RECORD pSR
  7851. )
  7852. /*++
  7853. Status : PENDING means task has been suspended, non PENDING
  7854. means operation has completed synchronously.
  7855. --*/
  7856. {
  7857. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  7858. PTASK_IF_MAINTENANCE pIfTask;
  7859. ENTER("arpTryStopIfMaintenanceTask", 0xb987276b)
  7860. LOCKOBJ(pIF, pSR);
  7861. pIfTask = (PTASK_IF_MAINTENANCE) pIF->pMaintenanceTask;
  7862. if (pIfTask != NULL)
  7863. {
  7864. pIfTask->Quit = TRUE;
  7865. RmTmpReferenceObject(&pIfTask->TskHdr.Hdr, pSR);
  7866. }
  7867. UNLOCKOBJ(pIF, pSR);
  7868. //
  7869. // Resume the maintenance task if it's waiting -- it will then quit
  7870. // because we set the Quit field above.
  7871. //
  7872. if (pIfTask != NULL)
  7873. {
  7874. UINT TaskResumed;
  7875. Status = RmPendTaskOnOtherTask(
  7876. pTask,
  7877. PendCode,
  7878. &pIfTask->TskHdr,
  7879. pSR
  7880. );
  7881. if (Status == NDIS_STATUS_SUCCESS)
  7882. {
  7883. RmResumeDelayedTaskNow(
  7884. &pIfTask->TskHdr,
  7885. &pIfTask->Timer,
  7886. &TaskResumed,
  7887. pSR
  7888. );
  7889. Status = NDIS_STATUS_PENDING; // We've GOT to return pending!
  7890. }
  7891. else
  7892. {
  7893. ASSERT(FALSE);
  7894. Status = NDIS_STATUS_FAILURE;
  7895. }
  7896. RmTmpDereferenceObject(&pIfTask->TskHdr.Hdr, pSR);
  7897. }
  7898. RM_ASSERT_NOLOCKS(pSR)
  7899. EXIT()
  7900. return Status;
  7901. }
  7902. VOID
  7903. arpDoLocalIpMaintenance(
  7904. PARP1394_INTERFACE pIF,
  7905. UINT CurrentTime,
  7906. UINT SecondsSinceLastMaintenance,
  7907. MYBOOL *pfProcessed,
  7908. PRM_STACK_RECORD pSR
  7909. )
  7910. {
  7911. ENTER("LocalIpMaintenance", 0x1a39fc89)
  7912. if (SecondsSinceLastMaintenance < 10)
  7913. {
  7914. TR_INFO(("Skipping Local Ip maintenance (delay=%lu).\n",
  7915. SecondsSinceLastMaintenance
  7916. ));
  7917. *pfProcessed = FALSE;
  7918. return; // EARLY RETURN;
  7919. }
  7920. *pfProcessed = TRUE;
  7921. TR_INFO(("Actually doing Local Ip maintenance.\n"));
  7922. RmWeakEnumerateObjectsInGroup(
  7923. &pIF->LocalIpGroup,
  7924. arpMaintainOneLocalIp,
  7925. NULL, // Context
  7926. pSR
  7927. );
  7928. EXIT()
  7929. }
  7930. VOID
  7931. arpDoRemoteIpMaintenance(
  7932. PARP1394_INTERFACE pIF,
  7933. UINT CurrentTime,
  7934. UINT SecondsSinceLastMaintenance,
  7935. MYBOOL *pfProcessed,
  7936. PRM_STACK_RECORD pSR
  7937. )
  7938. {
  7939. ENTER("RemoteIpMaintenance", 0x1ae00035)
  7940. if (SecondsSinceLastMaintenance < 15)
  7941. {
  7942. TR_INFO(("Skipping Remote Ip maintenance (delay=%lu).\n",
  7943. SecondsSinceLastMaintenance
  7944. ));
  7945. *pfProcessed = FALSE;
  7946. return; // EARLY RETURN;
  7947. }
  7948. *pfProcessed = TRUE;
  7949. TR_INFO(("Actually doing Remote Ip maintenance.\n"));
  7950. RmWeakEnumerateObjectsInGroup(
  7951. &pIF->RemoteIpGroup,
  7952. arpMaintainArpCache,
  7953. NULL, // Context
  7954. pSR
  7955. );
  7956. EXIT()
  7957. }
  7958. VOID
  7959. arpDoRemoteEthMaintenance(
  7960. PARP1394_INTERFACE pIF,
  7961. UINT CurrentTime,
  7962. UINT SecondsSinceLastMaintenance,
  7963. MYBOOL *pfProcessed,
  7964. PRM_STACK_RECORD pSR
  7965. )
  7966. {
  7967. ENTER("RemoteEthMaintenance", 0x6c496b7f)
  7968. if (SecondsSinceLastMaintenance < 15)
  7969. {
  7970. TR_INFO(("Skipping Eth Ip maintenance (delay=%lu).\n",
  7971. SecondsSinceLastMaintenance
  7972. ));
  7973. *pfProcessed = FALSE;
  7974. return; // EARLY RETURN;
  7975. }
  7976. *pfProcessed = TRUE;
  7977. TR_INFO(("Actually doing Remote Eth maintenance.\n"));
  7978. RmWeakEnumerateObjectsInGroup(
  7979. &pIF->RemoteEthGroup,
  7980. arpMaintainOneRemoteEth,
  7981. NULL, // Context
  7982. pSR
  7983. );
  7984. EXIT()
  7985. }
  7986. VOID
  7987. arpDoDhcpTableMaintenance(
  7988. PARP1394_INTERFACE pIF,
  7989. UINT CurrentTime,
  7990. UINT SecondsSinceLastMaintenance,
  7991. MYBOOL *pfProcessed,
  7992. PRM_STACK_RECORD pSR
  7993. )
  7994. {
  7995. ENTER("DhcpMaintenance", 0x1a39fc89)
  7996. if (SecondsSinceLastMaintenance < 120)
  7997. {
  7998. TR_INFO(("Skipping Local Ip maintenance (delay=%lu).\n",
  7999. SecondsSinceLastMaintenance
  8000. ));
  8001. *pfProcessed = FALSE;
  8002. return; // EARLY RETURN;
  8003. }
  8004. *pfProcessed = TRUE;
  8005. TR_INFO(("Actually doing Dhcp maintenance.\n"));
  8006. RmWeakEnumerateObjectsInGroup(
  8007. &pIF->EthDhcpGroup,
  8008. arpMaintainOneDhcpEntry,
  8009. NULL, // Context
  8010. pSR
  8011. );
  8012. EXIT()
  8013. }
  8014. // Enum function
  8015. //
  8016. INT
  8017. arpMaintainOneDhcpEntry(
  8018. PRM_OBJECT_HEADER pHdr,
  8019. PVOID pvContext, // Unused
  8020. PRM_STACK_RECORD pSR
  8021. )
  8022. {
  8023. ENTER("arpMaintainOneDhcpEntry", 0xc7604372)
  8024. NDIS_STATUS Status;
  8025. ARP1394_ETH_DHCP_ENTRY *pEntry;
  8026. PARP1394_INTERFACE pIF;
  8027. pEntry = (ARP1394_ETH_DHCP_ENTRY *) pHdr;
  8028. pIF = (PARP1394_INTERFACE )RM_PARENT_OBJECT (pEntry);
  8029. RM_ASSERT_NOLOCKS(pSR);
  8030. do
  8031. {
  8032. UINT CurrentTime = arpGetSystemTime();
  8033. #define ARP_PURGE_DHCP_TABLE_TIME 90 // Arp entry timeout.
  8034. //
  8035. // NOTE: we don't bother to get the lock with dealing with
  8036. // sendinfo.TimeLastChecked -- this is ok.
  8037. //
  8038. if (pEntry->TimeLastChecked==0)
  8039. {
  8040. // Set this field to the current time. It will be cleared back to 0
  8041. // when the next packet is sent to this remote Eth.
  8042. //
  8043. pEntry->TimeLastChecked = CurrentTime;
  8044. }
  8045. else if ((CurrentTime - pEntry->TimeLastChecked)
  8046. >= ARP_PURGE_DHCP_TABLE_TIME )
  8047. {
  8048. //
  8049. // We should clean up this dhcp entry. this is the only code path
  8050. // from which an entry is ever deleted.
  8051. //
  8052. RmFreeObjectInGroup(
  8053. &pIF->EthDhcpGroup,
  8054. &(pEntry->Hdr),
  8055. NULL, // NULL pTask == synchronous.
  8056. pSR
  8057. );
  8058. break;
  8059. }
  8060. } while (FALSE);
  8061. RM_ASSERT_NOLOCKS(pSR)
  8062. return TRUE; // Continue to enumerate.
  8063. }
  8064. // Enum function
  8065. //
  8066. INT
  8067. arpMaintainOneLocalIp(
  8068. PRM_OBJECT_HEADER pHdr,
  8069. PVOID pvContext, // Unused
  8070. PRM_STACK_RECORD pSR
  8071. )
  8072. {
  8073. ENTER("MaintainOneLocalIp", 0x1ae00035)
  8074. PARPCB_LOCAL_IP pLocalIp;
  8075. IP_ADDRESS LocalAddr;
  8076. PARP1394_INTERFACE pIF;
  8077. UINT Channel;
  8078. pLocalIp = (PARPCB_LOCAL_IP) pHdr;
  8079. LocalAddr = pLocalIp->IpAddress;
  8080. pIF = IF_FROM_LOCALIP(pLocalIp);
  8081. RM_ASSERT_NOLOCKS(pSR);
  8082. do
  8083. {
  8084. ARPCB_DEST *pDest;
  8085. ARP_DEST_PARAMS DestParams;
  8086. // Skip if we can't do MCAP on this address.
  8087. //
  8088. LOCKOBJ(pLocalIp, pSR);
  8089. if (!CHECK_LOCALIP_MCAP(pLocalIp, ARPLOCALIP_MCAP_CAPABLE))
  8090. {
  8091. UNLOCKOBJ(pLocalIp, pSR);
  8092. break;
  8093. }
  8094. UNLOCKOBJ(pLocalIp, pSR);
  8095. //
  8096. // Find a channel mapping to this address, if any.
  8097. //
  8098. Channel = arpFindAssignedChannel(
  8099. pIF,
  8100. LocalAddr,
  8101. 0, // TODO -- pass in current time.
  8102. pSR
  8103. );
  8104. //
  8105. // NOTE: Special return value NIC1394_BROADCAST_CHANNEL is returned if
  8106. // this address is mapped to no specific channel.
  8107. //
  8108. ARP_ZEROSTRUCT(&DestParams);
  8109. DestParams.HwAddr.AddressType = NIC1394AddressType_Channel;
  8110. DestParams.HwAddr.Channel = Channel;
  8111. DestParams.ReceiveOnly = TRUE;
  8112. DestParams.AcquireChannel = FALSE;
  8113. arpUpdateLocalIpDest(pIF, pLocalIp, &DestParams, pSR);
  8114. } while (FALSE);
  8115. RM_ASSERT_NOLOCKS(pSR)
  8116. return TRUE; // Continue to enumerate.
  8117. }
  8118. // Enum function
  8119. //
  8120. INT
  8121. arpMaintainOneRemoteIp(
  8122. PRM_OBJECT_HEADER pHdr,
  8123. PVOID pvContext, // Unused
  8124. PRM_STACK_RECORD pSR
  8125. )
  8126. #if 0
  8127. for each RIP send VC
  8128. if !marked dirty
  8129. mark dirty
  8130. if linked to channel pdest
  8131. check if channel is still mapped to group
  8132. if not, unlink.
  8133. if required initiate link to new pdest (possibly channel)
  8134. else
  8135. //expired
  8136. unlink from pdest and get rid of it
  8137. #endif // 0
  8138. {
  8139. ENTER("MaintainOneRemoteIp", 0x1ae00035)
  8140. NDIS_STATUS Status;
  8141. PARPCB_REMOTE_IP pRemoteIp;
  8142. PARP1394_INTERFACE pIF;
  8143. pRemoteIp = (PARPCB_REMOTE_IP) pHdr;
  8144. pIF = IF_FROM_LOCALIP(pRemoteIp);
  8145. RM_ASSERT_NOLOCKS(pSR);
  8146. do
  8147. {
  8148. IP_ADDRESS IpAddr;
  8149. UINT Channel;
  8150. ARP_DEST_PARAMS DestParams;
  8151. ARPCB_DEST *pDest;
  8152. BOOLEAN AcquireChannel;
  8153. UINT CurrentTime = arpGetSystemTime();
  8154. IpAddr = pRemoteIp->Key.IpAddress;
  8155. #define ARP_PURGE_REMOTEIP_TIME 300 // Arp entry timeout.
  8156. //
  8157. // NOTE: we don't bother to get the lock with dealing with
  8158. // sendinfo.TimeLastChecked -- this is ok.
  8159. //
  8160. if (pRemoteIp->sendinfo.TimeLastChecked==0)
  8161. {
  8162. if (CHECK_REMOTEIP_SDTYPE(pRemoteIp, ARPREMOTEIP_DYNAMIC)
  8163. || CHECK_REMOTEIP_RESOLVE_STATE (pRemoteIp, ARPREMOTEIP_UNRESOLVED))
  8164. {
  8165. // Set this field to the current time. It will be cleared back to 0
  8166. // when the next packet is sent to this remote ip.
  8167. //
  8168. pRemoteIp->sendinfo.TimeLastChecked = CurrentTime;
  8169. }
  8170. }
  8171. else if ((CurrentTime - pRemoteIp->sendinfo.TimeLastChecked)
  8172. >= ARP_PURGE_REMOTEIP_TIME)
  8173. {
  8174. //
  8175. // We should clean up this remote ip.
  8176. //
  8177. arpDeinitRemoteIp(pRemoteIp, pSR);
  8178. break;
  8179. }
  8180. #if ARP_ENABLE_MCAP_SEND
  8181. //
  8182. // We'll now see if we need to re-set which destination this
  8183. // pRemoteIp points to.
  8184. //
  8185. // Skip if we can't do MCAP on this address.
  8186. //
  8187. LOCKOBJ(pRemoteIp, pSR);
  8188. if (!CHECK_REMOTEIP_MCAP(pRemoteIp, ARPREMOTEIP_MCAP_CAPABLE))
  8189. {
  8190. UNLOCKOBJ(pRemoteIp, pSR);
  8191. break;
  8192. }
  8193. UNLOCKOBJ(pRemoteIp, pSR);
  8194. //
  8195. // Find a channel mapping to this address, if any.
  8196. //
  8197. Channel = arpFindAssignedChannel(
  8198. pIF,
  8199. pRemoteIp->Key.IpAddress,
  8200. 0,
  8201. pSR
  8202. );
  8203. //
  8204. // NOTE: Special return value NIC1394_BROADCAST_CHANNEL is returned if
  8205. // this address is mapped to no specific channel.
  8206. //
  8207. AcquireChannel = FALSE;
  8208. #if 0 // Let's not enable this just yet -- instead
  8209. if (Channel == NIC1394_BROADCAST_CHANNEL)
  8210. {
  8211. //
  8212. // Hmm... let's get aggressive and try to grab a channel.
  8213. //
  8214. Channel = arpFindFreeChannel(pIF, pSR);
  8215. if (Channel != NIC1394_BROADCAST_CHANNEL)
  8216. {
  8217. //
  8218. // Got one!
  8219. //
  8220. AcquireChannel = TRUE;
  8221. }
  8222. }
  8223. else
  8224. {
  8225. //
  8226. // There is already a channel allocated by someone to be used
  8227. // for this ip address. Let's use it.
  8228. //
  8229. }
  8230. #endif // 0
  8231. ARP_ZEROSTRUCT(&DestParams);
  8232. DestParams.HwAddr.AddressType = NIC1394AddressType_Channel;
  8233. DestParams.HwAddr.Channel = Channel;
  8234. DestParams.AcquireChannel = AcquireChannel;
  8235. arpUpdateRemoteIpDest(pIF, pRemoteIp, &DestParams, pSR);
  8236. #endif // ARP_ENABLE_MCAP_SEND
  8237. } while (FALSE);
  8238. RM_ASSERT_NOLOCKS(pSR)
  8239. return TRUE; // Continue to enumerate.
  8240. }
  8241. // Enum function
  8242. //
  8243. INT
  8244. arpMaintainOneRemoteEth(
  8245. PRM_OBJECT_HEADER pHdr,
  8246. PVOID pvContext, // Unused
  8247. PRM_STACK_RECORD pSR
  8248. )
  8249. {
  8250. ENTER("MaintainOneRemoteEth", 0x21807796)
  8251. NDIS_STATUS Status;
  8252. PARPCB_REMOTE_ETH pRemoteEth;
  8253. PARP1394_INTERFACE pIF;
  8254. pRemoteEth = (PARPCB_REMOTE_ETH) pHdr;
  8255. pIF = IF_FROM_LOCALIP(pRemoteEth);
  8256. RM_ASSERT_NOLOCKS(pSR);
  8257. do
  8258. {
  8259. UINT CurrentTime = arpGetSystemTime();
  8260. #define ARP_PURGE_REMOTEETH_TIME 300 // Arp entry timeout.
  8261. //
  8262. // NOTE: we don't bother to get the lock with dealing with
  8263. // sendinfo.TimeLastChecked -- this is ok.
  8264. //
  8265. if (pRemoteEth->TimeLastChecked==0)
  8266. {
  8267. // Set this field to the current time. It will be cleared back to 0
  8268. // when the next packet is sent to this remote Eth.
  8269. //
  8270. pRemoteEth->TimeLastChecked = CurrentTime;
  8271. }
  8272. else if ((CurrentTime - pRemoteEth->TimeLastChecked)
  8273. >= ARP_PURGE_REMOTEETH_TIME)
  8274. {
  8275. //
  8276. // We should clean up this remote eth.
  8277. //
  8278. arpDeinitRemoteEth(pRemoteEth, pSR);
  8279. break;
  8280. }
  8281. } while (FALSE);
  8282. RM_ASSERT_NOLOCKS(pSR)
  8283. return TRUE; // Continue to enumerate.
  8284. }
  8285. UINT
  8286. arpFindAssignedChannel(
  8287. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  8288. IN IP_ADDRESS IpAddress,
  8289. IN UINT CurrentTime, // OPTIONAL
  8290. PRM_STACK_RECORD pSR
  8291. )
  8292. /*++
  8293. NOTE: Special return value NIC1394_BROADCAST_CHANNEL is returned if
  8294. this address is mapped to no specific channel.
  8295. --*/
  8296. {
  8297. ENTER("FindAssignedChannel", 0xd20a216b)
  8298. UINT Channel = NIC1394_BROADCAST_CHANNEL;
  8299. UINT u;
  8300. LOCKOBJ(pIF, pSR);
  8301. if (CurrentTime == 0)
  8302. {
  8303. CurrentTime = arpGetSystemTime();
  8304. }
  8305. //
  8306. // Run down the channel info array, looking for a matching IP address.
  8307. //
  8308. for (u = 0; u < ARP_NUM_CHANNELS; u++)
  8309. {
  8310. PMCAP_CHANNEL_INFO pMci;
  8311. pMci = &pIF->mcapinfo.rgChannelInfo[u];
  8312. if ( IpAddress == pMci->GroupAddress
  8313. && arpIsActiveMcapChannel(pMci, CurrentTime))
  8314. {
  8315. ASSERT(pMci->Channel == u);
  8316. Channel = u;
  8317. TR_WARN(("Found Matching channel %lu for ip address 0x%lu.\n",
  8318. Channel,
  8319. IpAddress
  8320. ));
  8321. break;
  8322. }
  8323. }
  8324. UNLOCKOBJ(pIF, pSR);
  8325. return Channel;
  8326. EXIT()
  8327. }
  8328. VOID
  8329. arpUpdateLocalIpDest(
  8330. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  8331. IN PARPCB_LOCAL_IP pLocalIp,
  8332. IN PARP_DEST_PARAMS pDestParams,
  8333. PRM_STACK_RECORD pSR
  8334. )
  8335. /*++
  8336. Make pLocalIp point to a des with params pDestParams.
  8337. Create a pDest if required.
  8338. If pLocalIp is pointing to some other pDest, cleanup that other pDest if
  8339. no one else is refering to it.
  8340. --*/
  8341. {
  8342. ENTER("UpdateLocalIpDest", 0x3f2dcaa7)
  8343. ARPCB_DEST *pOldDest = NULL;
  8344. RM_ASSERT_NOLOCKS(pSR);
  8345. // pLocalIp uses it's parent's (pIF's) lock.
  8346. //
  8347. RM_ASSERT_SAME_LOCK_AS_PARENT(pLocalIp);
  8348. do
  8349. {
  8350. PCHAR szDescription;
  8351. INT fCreated = FALSE;
  8352. PRM_TASK pMakeCallTask;
  8353. UINT Channel;
  8354. NDIS_STATUS Status;
  8355. ARPCB_DEST *pDest;
  8356. //
  8357. // Currently, only Channel Dests are supported.
  8358. //
  8359. if (pDestParams->HwAddr.AddressType != NIC1394AddressType_Channel)
  8360. {
  8361. ASSERT(FALSE);
  8362. break;
  8363. }
  8364. else
  8365. {
  8366. Channel = pDestParams->HwAddr.Channel;
  8367. }
  8368. LOCKOBJ(pIF, pSR);
  8369. RM_DBG_ASSERT_LOCKED(&pLocalIp->Hdr, pSR); // same lock as pIF;
  8370. pDest = pLocalIp->pDest;
  8371. if (pDest != NULL)
  8372. {
  8373. RM_DBG_ASSERT_LOCKED(&pDest->Hdr, pSR); // same lock as pIF;
  8374. if (pDest->Params.HwAddr.AddressType == NIC1394AddressType_Channel)
  8375. {
  8376. if (pDest->Params.HwAddr.Channel == Channel)
  8377. {
  8378. //
  8379. // We're already linked to this channel. Nothing more to do.
  8380. //
  8381. UNLOCKOBJ(pIF, pSR);
  8382. break;
  8383. }
  8384. }
  8385. else
  8386. {
  8387. //
  8388. // Shouldn't get here -- MCAP_CAPABLE addresses shouldn't be
  8389. // linked to non-channel destinations (for NOW anyway).
  8390. //
  8391. ASSERT(!"pLocalIp linked to non-channel pDest.");
  8392. UNLOCKOBJ(pIF, pSR);
  8393. break;
  8394. }
  8395. //
  8396. // We're linked to some other pDest currently. We'll have
  8397. // to unlink ourselves from pDest, and get rid of the other
  8398. // pDest if no one is using it.
  8399. //
  8400. RmTmpReferenceObject(&pDest->Hdr, pSR);
  8401. arpUnlinkLocalIpFromDest(pLocalIp, pSR);
  8402. }
  8403. pOldDest = pDest;
  8404. pDest = NULL;
  8405. ASSERT(pLocalIp->pDest == NULL);
  8406. //
  8407. // SPECIAL CASE: If the channel is the broadcast channel, we don't
  8408. // need to do anything more, because the broadcast channel is always
  8409. // active.
  8410. //
  8411. if (Channel == NIC1394_BROADCAST_CHANNEL)
  8412. {
  8413. UNLOCKOBJ(pIF, pSR);
  8414. break;
  8415. }
  8416. //
  8417. // Now link to a new dest and if required initiate a call on it.
  8418. //
  8419. // Now create a destination item for this structure.
  8420. //
  8421. Status = RmLookupObjectInGroup(
  8422. &pIF->DestinationGroup,
  8423. RM_CREATE, // Create if required
  8424. pDestParams, // Key
  8425. pDestParams, // pParams
  8426. (RM_OBJECT_HEADER**) &pDest,
  8427. &fCreated,
  8428. pSR
  8429. );
  8430. if (FAIL(Status))
  8431. {
  8432. UNLOCKOBJ(pIF, pSR);
  8433. OBJLOG1( pIF, "FATAL: Couldn't create local-ip dest type %d.\n",
  8434. pDestParams->HwAddr.AddressType);
  8435. break;
  8436. }
  8437. Status = arpAllocateTask(
  8438. &pDest->Hdr, // pParentObject
  8439. arpTaskMakeCallToDest, // pfnHandler
  8440. 0, // Timeout
  8441. "Task: MakeCallToDest (local ip)",
  8442. &pMakeCallTask,
  8443. pSR
  8444. );
  8445. if (FAIL(Status))
  8446. {
  8447. UNLOCKOBJ(pIF, pSR);
  8448. // NOTE: Even on failure, we leave the newly-created
  8449. // special dest object. It will get cleaned up when
  8450. // the interface is unloaded.
  8451. //
  8452. }
  8453. else
  8454. {
  8455. arpLinkLocalIpToDest(pLocalIp, pDest, pSR);
  8456. UNLOCKOBJ(pIF, pSR);
  8457. (VOID)RmStartTask(
  8458. pMakeCallTask,
  8459. 0, // UserParam (unused)
  8460. pSR
  8461. );
  8462. }
  8463. RmTmpDereferenceObject(&pDest->Hdr, pSR); // Added by RmLookupObjectIn..
  8464. } while (FALSE);
  8465. //
  8466. // If required, get rid of pOldDest.
  8467. //
  8468. if (pOldDest != NULL)
  8469. {
  8470. arpDeinitDestination(pOldDest, TRUE, pSR); // TRUE == only if unused.
  8471. RmTmpDereferenceObject(&pOldDest->Hdr, pSR);
  8472. }
  8473. RM_ASSERT_NOLOCKS(pSR);
  8474. }
  8475. UINT
  8476. arpFindFreeChannel(
  8477. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  8478. PRM_STACK_RECORD pSR
  8479. )
  8480. /*++
  8481. NOTE: Special return value NIC1394_BROADCAST_CHANNEL is returned if
  8482. we couldn't find a free channel.
  8483. Also there's no guarantee that this channel is really free.
  8484. --*/
  8485. {
  8486. ENTER("FindAssignedChannel", 0xd20a216b)
  8487. UINT Channel = NIC1394_BROADCAST_CHANNEL;
  8488. UINT u;
  8489. LOCKOBJ(pIF, pSR);
  8490. //
  8491. // Run down the channel info array, looking for an empty slot.
  8492. //
  8493. for (u = 0; u < ARP_NUM_CHANNELS; u++)
  8494. {
  8495. PMCAP_CHANNEL_INFO pMci;
  8496. pMci = &pIF->mcapinfo.rgChannelInfo[u];
  8497. if (pMci->GroupAddress == 0)
  8498. {
  8499. ASSERT(pMci->Channel == 0);
  8500. // pMci->Channel = u;
  8501. Channel = u;
  8502. TR_WARN(("Found Free channel %lu.\n",
  8503. Channel
  8504. ));
  8505. break;
  8506. }
  8507. }
  8508. UNLOCKOBJ(pIF, pSR);
  8509. return Channel;
  8510. EXIT()
  8511. }
  8512. VOID
  8513. arpUpdateRemoteIpDest(
  8514. IN PARP1394_INTERFACE pIF, // NOLOCKIN NOLOCKOUT
  8515. IN PARPCB_REMOTE_IP pRemoteIp,
  8516. IN PARP_DEST_PARAMS pDestParams,
  8517. PRM_STACK_RECORD pSR
  8518. )
  8519. {
  8520. ENTER("UpdateRemoteIpDest", 0x3f2dcaa7)
  8521. ARPCB_DEST *pOldDest = NULL;
  8522. RM_ASSERT_NOLOCKS(pSR);
  8523. // pRemoteIp uses it's parent's (pIF's) lock.
  8524. //
  8525. RM_ASSERT_SAME_LOCK_AS_PARENT(pRemoteIp);
  8526. do
  8527. {
  8528. PCHAR szDescription;
  8529. INT fCreated = FALSE;
  8530. PRM_TASK pMakeCallTask;
  8531. UINT Channel;
  8532. NDIS_STATUS Status;
  8533. ARPCB_DEST *pDest;
  8534. //
  8535. // Lookup/Create Remote Destination
  8536. // NOTE/WARNING: We'll create a new destination even if one exists for
  8537. // the same uniqueID but different FIFO-address -- this is by design.
  8538. // What should happen is that the old pDest should be eventually removed.
  8539. //
  8540. Status = RmLookupObjectInGroup(
  8541. &pIF->DestinationGroup,
  8542. RM_CREATE, //NOT RM_NEW (could be existing)
  8543. pDestParams,
  8544. pDestParams, // pParams
  8545. (RM_OBJECT_HEADER**) &pDest,
  8546. &fCreated,
  8547. pSR
  8548. );
  8549. if (FAIL(Status))
  8550. {
  8551. OBJLOG1(
  8552. pIF,
  8553. "Couldn't add dest entry with hw addr 0x%lx\n",
  8554. (UINT) pDestParams->HwAddr.FifoAddress.UniqueID // Truncation
  8555. );
  8556. //
  8557. // We'll leave the RemoteIp entry around -- it will be cleaned up later.
  8558. //
  8559. #if 0
  8560. // We do have to deref the tmpref added when looking it up.
  8561. //
  8562. RmTmpDereferenceObject(&pRemoteIp->Hdr, pSR);
  8563. #endif // 0
  8564. break;
  8565. }
  8566. LOCKOBJ(pIF, pSR);
  8567. if (pRemoteIp->pDest != pDest)
  8568. {
  8569. // If required, unlink any existing destination from pIP.
  8570. //
  8571. if (pRemoteIp->pDest != NULL)
  8572. {
  8573. pOldDest = pRemoteIp->pDest;
  8574. RmTmpReferenceObject(&pOldDest->Hdr, pSR);
  8575. arpUnlinkRemoteIpFromDest(
  8576. pRemoteIp, // LOCKIN LOCKOUT
  8577. pSR
  8578. );
  8579. ASSERT(pRemoteIp->pDest == NULL);
  8580. }
  8581. // Set the pRemoteIp state to reflect that it is FIFO/Channel
  8582. // and DYNAMIC.
  8583. //
  8584. {
  8585. // (Dbg only) Change lock scope from pIF to pLocalIp, because
  8586. // we're altering pLocalIp's state below...
  8587. //
  8588. RmDbgChangeLockScope(
  8589. &pIF->Hdr,
  8590. &pRemoteIp->Hdr,
  8591. 0x1385053b, // LocID
  8592. pSR
  8593. );
  8594. if (pDestParams->HwAddr.AddressType == NIC1394AddressType_FIFO)
  8595. {
  8596. SET_REMOTEIP_FCTYPE(pRemoteIp, ARPREMOTEIP_FIFO);
  8597. }
  8598. else
  8599. {
  8600. SET_REMOTEIP_FCTYPE(pRemoteIp, ARPREMOTEIP_CHANNEL);
  8601. }
  8602. SET_REMOTEIP_SDTYPE(pRemoteIp, ARPREMOTEIP_DYNAMIC);
  8603. // (Dbg only) Change lock scope back to pIF.
  8604. //
  8605. RmDbgChangeLockScope(
  8606. &pRemoteIp->Hdr,
  8607. &pIF->Hdr,
  8608. 0x315d28a1, // LocID
  8609. pSR
  8610. );
  8611. }
  8612. // Link pRemoteIp to pDest.
  8613. //
  8614. //
  8615. // We've created both RemoteIp and Destination entries. Now link them.
  8616. // (We still have the IF lock, which is the same as the RemoteIP and
  8617. // desination locks for now).
  8618. //
  8619. // TODO: will need to change this when pRemoteIp gets its own lock.
  8620. //
  8621. RM_ASSERT_SAME_LOCK_AS_PARENT(pRemoteIp);
  8622. RM_ASSERT_SAME_LOCK_AS_PARENT(pDest);
  8623. arpLinkRemoteIpToDest(
  8624. pRemoteIp,
  8625. pDest,
  8626. pSR
  8627. );
  8628. }
  8629. UNLOCKOBJ(pIF, pSR);
  8630. RmTmpDereferenceObject(&pDest->Hdr, pSR);
  8631. } while(FALSE);
  8632. //
  8633. // If required, get rid of pOldDest.
  8634. //
  8635. if (pOldDest != NULL)
  8636. {
  8637. arpDeinitDestination(pOldDest, TRUE, pSR); // TRUE == only if unused.
  8638. RmTmpDereferenceObject(&pOldDest->Hdr, pSR);
  8639. }
  8640. RM_ASSERT_NOLOCKS(pSR);
  8641. }
  8642. VOID
  8643. arpDeinitRemoteIp(
  8644. PARPCB_REMOTE_IP pRemoteIp,
  8645. PRM_STACK_RECORD pSR
  8646. )
  8647. /*++
  8648. Unload a remote ip.
  8649. --*/
  8650. {
  8651. ENTER("arpDeinitRemoteIp", 0xea0a2662)
  8652. PRM_TASK pTask;
  8653. NDIS_STATUS Status;
  8654. RM_ASSERT_NOLOCKS(pSR);
  8655. #if DBG
  8656. {
  8657. IP_ADDRESS IpAddress = pRemoteIp->Key.IpAddress;
  8658. TR_WARN(("Deiniting RemoteIp %d.%d.%d.%d\n",
  8659. ((PUCHAR)(&IpAddress))[0],
  8660. ((PUCHAR)(&IpAddress))[1],
  8661. ((PUCHAR)(&IpAddress))[2],
  8662. ((PUCHAR)(&IpAddress))[3]));
  8663. }
  8664. #endif // DBG
  8665. Status = arpAllocateTask(
  8666. &pRemoteIp->Hdr, // pParentObject,
  8667. arpTaskUnloadRemoteIp, // pfnHandler,
  8668. 0, // Timeout,
  8669. "Task: Unload Remote Ip", // szDescription
  8670. &pTask,
  8671. pSR
  8672. );
  8673. if (FAIL(Status))
  8674. {
  8675. OBJLOG0(pRemoteIp, ("FATAL: couldn't alloc unload pRemoteIp task!\n"));
  8676. }
  8677. else
  8678. {
  8679. (VOID) RmStartTask(
  8680. pTask,
  8681. 0, // UserParam (unused)
  8682. pSR
  8683. );
  8684. }
  8685. }
  8686. VOID
  8687. arpDeinitRemoteEth(
  8688. PARPCB_REMOTE_ETH pRemoteEth,
  8689. PRM_STACK_RECORD pSR
  8690. )
  8691. /*++
  8692. Unload a remote ip.
  8693. --*/
  8694. {
  8695. ENTER("arpDeinitRemoteEth", 0x72dd17e7)
  8696. PRM_TASK pTask;
  8697. NDIS_STATUS Status;
  8698. RM_ASSERT_NOLOCKS(pSR);
  8699. #if DBG
  8700. {
  8701. IP_ADDRESS IpAddress = pRemoteEth->IpAddress;
  8702. TR_WARN(("Deiniting RemoteEth %d.%d.%d.%d\n",
  8703. ((PUCHAR)(&IpAddress))[0],
  8704. ((PUCHAR)(&IpAddress))[1],
  8705. ((PUCHAR)(&IpAddress))[2],
  8706. ((PUCHAR)(&IpAddress))[3]));
  8707. }
  8708. #endif // DBG
  8709. Status = arpAllocateTask(
  8710. &pRemoteEth->Hdr, // pParentObject,
  8711. arpTaskUnloadRemoteEth, // pfnHandler,
  8712. 0, // Timeout,
  8713. "Task: Unload Remote Eth", // szDescription
  8714. &pTask,
  8715. pSR
  8716. );
  8717. if (FAIL(Status))
  8718. {
  8719. OBJLOG0(pRemoteEth, ("FATAL: couldn't alloc unload pRemoteIp task!\n"));
  8720. }
  8721. else
  8722. {
  8723. (VOID) RmStartTask(
  8724. pTask,
  8725. 0, // UserParam (unused)
  8726. pSR
  8727. );
  8728. }
  8729. }
  8730. VOID
  8731. arpDoMcapDbMaintenance(
  8732. PARP1394_INTERFACE pIF,
  8733. UINT CurrentTime,
  8734. UINT SecondsSinceLastMaintenance,
  8735. MYBOOL *pfProcessed,
  8736. PRM_STACK_RECORD pSR
  8737. )
  8738. /*++
  8739. Go through the mcap database, zeroing out all entries marked
  8740. "NotRecentlyUpdated", and marking all others "NotRecentlyUpdated."
  8741. Also send out an mcap advertisements for all channels we've locally allocated.
  8742. --*/
  8743. {
  8744. UINT u;
  8745. UINT NumLocallyAllocated =0;
  8746. PNDIS_PACKET pNdisPacket;
  8747. NDIS_STATUS Status;
  8748. ENTER("McapDbMaintenance", 0x1ae00035)
  8749. if (SecondsSinceLastMaintenance < 10)
  8750. {
  8751. TR_INFO(("Skipping McapDb maintenance (delay=%lu).\n",
  8752. SecondsSinceLastMaintenance
  8753. ));
  8754. *pfProcessed = FALSE;
  8755. return; // EARLY RETURN;
  8756. }
  8757. *pfProcessed = TRUE;
  8758. TR_INFO(("Actually doing Mcap Db maintenance.\n"));
  8759. LOCKOBJ(pIF, pSR);
  8760. //
  8761. // Run down the channel info array, looking for and zapping stale channel
  8762. // assignments.
  8763. //
  8764. for (u = 0; u < ARP_NUM_CHANNELS; u++)
  8765. {
  8766. PMCAP_CHANNEL_INFO pMci;
  8767. MYBOOL fOk;
  8768. pMci = &pIF->mcapinfo.rgChannelInfo[u];
  8769. if (pMci->GroupAddress == 0) continue; // An empty record.
  8770. fOk = arpIsActiveMcapChannel(pMci, CurrentTime);
  8771. if (!fOk)
  8772. {
  8773. TR_WARN(("McapDB: clearing stale channel %lu.\n",
  8774. pMci->Channel
  8775. ));
  8776. ASSERT(pMci->Channel == u);
  8777. ARP_ZEROSTRUCT(pMci);
  8778. continue;
  8779. }
  8780. if (pMci->Flags & MCAP_CHANNEL_FLAGS_LOCALLY_ALLOCATED)
  8781. {
  8782. NumLocallyAllocated++;
  8783. }
  8784. }
  8785. // If required, send an mcap advertisement packet.
  8786. //
  8787. do
  8788. {
  8789. IP1394_MCAP_PKT_INFO PktInfo;
  8790. PIP1394_MCAP_GD_INFO pGdi;
  8791. UINT cb = NumLocallyAllocated * sizeof(*pGdi);
  8792. UINT v;
  8793. if (NumLocallyAllocated==0) break;
  8794. ASSERT(FALSE);
  8795. if (cb <= sizeof(PktInfo.GdiSpace))
  8796. {
  8797. pGdi = PktInfo.GdiSpace;
  8798. }
  8799. else
  8800. {
  8801. NdisAllocateMemoryWithTag(&pGdi, cb, MTAG_MCAP_GD);
  8802. if (pGdi == NULL)
  8803. {
  8804. TR_WARN(("Allocation Failure"));
  8805. break;
  8806. }
  8807. }
  8808. PktInfo.pGdis = pGdi;
  8809. // Now go through the mcap list, picking up locally allocated
  8810. // channels.
  8811. //
  8812. for (u=0, v=0; u < ARP_NUM_CHANNELS; u++)
  8813. {
  8814. PMCAP_CHANNEL_INFO pMci;
  8815. pMci = &pIF->mcapinfo.rgChannelInfo[u];
  8816. if (pMci->Flags & MCAP_CHANNEL_FLAGS_LOCALLY_ALLOCATED)
  8817. {
  8818. if (v >= NumLocallyAllocated)
  8819. {
  8820. ASSERT(FALSE);
  8821. break;
  8822. }
  8823. if (pMci->ExpieryTime > CurrentTime)
  8824. {
  8825. pGdi->Expiration = pMci->ExpieryTime - CurrentTime;
  8826. }
  8827. else
  8828. {
  8829. pGdi->Expiration = 0;
  8830. }
  8831. pGdi->Channel = pMci->Channel;
  8832. pGdi->SpeedCode = pMci->SpeedCode;
  8833. pGdi->GroupAddress = pMci->GroupAddress;
  8834. v++; pGdi++;
  8835. }
  8836. }
  8837. UNLOCKOBJ(pIF, pSR);
  8838. PktInfo.NumGroups = v;
  8839. PktInfo.SenderNodeID = 0; // TODO
  8840. PktInfo.OpCode = IP1394_MCAP_OP_ADVERTISE;
  8841. //
  8842. // Now we must actually allocate and send the advertisement.
  8843. //
  8844. Status = arpCreateMcapPkt(
  8845. pIF,
  8846. &PktInfo,
  8847. &pNdisPacket,
  8848. pSR
  8849. );
  8850. if (FAIL(Status)) break;
  8851. TR_WARN(("Attempting to send MCAP ADVERTISE PKT."
  8852. "NumGoups=%lu Group0-1 == 0x%08lx->%lu 0x%08lx->%lu.\n",
  8853. PktInfo.NumGroups,
  8854. PktInfo.pGdis[0].GroupAddress,
  8855. PktInfo.pGdis[0].Channel,
  8856. PktInfo.pGdis[1].GroupAddress,
  8857. PktInfo.pGdis[1].Channel
  8858. ));
  8859. ARP_FASTREADLOCK_IF_SEND_LOCK(pIF);
  8860. // Actually send the packet (this will silently fail and free the pkt
  8861. // if we're not in a position to send the pkt.)
  8862. //
  8863. arpSendControlPkt(
  8864. pIF, // LOCKIN NOLOCKOUT (IF send lk)
  8865. pNdisPacket,
  8866. pIF->pBroadcastDest,
  8867. pSR
  8868. );
  8869. RM_ASSERT_NOLOCKS(pSR);
  8870. RmTmpDereferenceObject(&pIF->Hdr, pSR);
  8871. } while (FALSE);
  8872. UNLOCKOBJ(pIF, pSR);
  8873. EXIT()
  8874. }
  8875. #if DBG
  8876. VOID
  8877. arpDbgDisplayMapping(
  8878. IP_ADDRESS IpAddress,
  8879. PNIC1394_DESTINATION pHwAddr,
  8880. char * szPrefix
  8881. )
  8882. {
  8883. ENTER("MAP", 0x0)
  8884. if (pHwAddr == NULL)
  8885. {
  8886. TR_WARN(("%s %d.%d.%d.%d --> <no destination>\n",
  8887. szPrefix,
  8888. ((PUCHAR)(&IpAddress))[0],
  8889. ((PUCHAR)(&IpAddress))[1],
  8890. ((PUCHAR)(&IpAddress))[2],
  8891. ((PUCHAR)(&IpAddress))[3]));
  8892. }
  8893. else if (pHwAddr->AddressType == NIC1394AddressType_FIFO)
  8894. {
  8895. PUCHAR puc = (PUCHAR) &pHwAddr->FifoAddress;
  8896. TR_WARN(("%s %d.%d.%d.%d --> FIFO %02lx-%02lx-%02lx-%02lx-%02lx-%02lx-%02lx-%02lx.\n",
  8897. szPrefix,
  8898. ((PUCHAR)(&IpAddress))[0],
  8899. ((PUCHAR)(&IpAddress))[1],
  8900. ((PUCHAR)(&IpAddress))[2],
  8901. ((PUCHAR)(&IpAddress))[3],
  8902. puc[0], puc[1], puc[2], puc[3],
  8903. puc[4], puc[5], puc[6], puc[7]));
  8904. }
  8905. else if (pHwAddr->AddressType == NIC1394AddressType_Channel)
  8906. {
  8907. TR_WARN(("%s %d.%d.%d.%d --> CHANNEL %d.\n",
  8908. szPrefix,
  8909. ((PUCHAR)(&IpAddress))[0],
  8910. ((PUCHAR)(&IpAddress))[1],
  8911. ((PUCHAR)(&IpAddress))[2],
  8912. ((PUCHAR)(&IpAddress))[3],
  8913. pHwAddr->Channel));
  8914. }
  8915. else
  8916. {
  8917. TR_WARN(("%s %d.%d.%d.%d --> Special dest 0x%08lx.\n",
  8918. szPrefix,
  8919. ((PUCHAR)(&IpAddress))[0],
  8920. ((PUCHAR)(&IpAddress))[1],
  8921. ((PUCHAR)(&IpAddress))[2],
  8922. ((PUCHAR)(&IpAddress))[3],
  8923. pHwAddr->Channel));
  8924. }
  8925. EXIT()
  8926. }
  8927. #endif // DBG
  8928. PRM_OBJECT_HEADER
  8929. arpRemoteDestCreate(
  8930. PRM_OBJECT_HEADER pParentObject,
  8931. PVOID pCreateParams,
  8932. PRM_STACK_RECORD pSR
  8933. )
  8934. /*++
  8935. Routine Description:
  8936. Allocate and initialize an object of type ARPCB_REMOTE_IP.
  8937. Arguments:
  8938. pParentObject - Actually a pointer to the interface (ARP1394_INTERFACE)
  8939. pCreateParams - Actually the IP address (not a pointer to the IP address)
  8940. to associate with this remote IP object.
  8941. Return Value:
  8942. Pointer to the allocated and initialized object on success.
  8943. NULL otherwise.
  8944. --*/
  8945. {
  8946. ENTER ("arpRemoteDestCreate", 0xa896311a)
  8947. ARPCB_REMOTE_IP *pRemoteIp;
  8948. PRM_OBJECT_HEADER pHdr;
  8949. PREMOTE_DEST_KEY pKey = (PREMOTE_DEST_KEY)pCreateParams;
  8950. NDIS_STATUS Status;
  8951. Status = ARP_ALLOCSTRUCT(pRemoteIp, MTAG_REMOTE_IP);
  8952. if (Status != NDIS_STATUS_SUCCESS || pRemoteIp == NULL)
  8953. {
  8954. return NULL;
  8955. }
  8956. ARP_ZEROSTRUCT(pRemoteIp);
  8957. pHdr = (PRM_OBJECT_HEADER) pRemoteIp;
  8958. ASSERT(pHdr == &pRemoteIp->Hdr);
  8959. // We expect the parent object to be the IF object!
  8960. //
  8961. ASSERT(pParentObject->Sig == MTAG_INTERFACE);
  8962. if (pHdr)
  8963. {
  8964. RmInitializeHeader(
  8965. pParentObject,
  8966. pHdr,
  8967. MTAG_REMOTE_IP,
  8968. pParentObject->pLock,
  8969. &ArpGlobal_RemoteIpStaticInfo,
  8970. NULL, // szDescription
  8971. pSR
  8972. );
  8973. TR_INFO( ("New RemoteDest Key %x %x %x %x %x %x \n",
  8974. pKey->ENetAddress.addr[0],
  8975. pKey->ENetAddress.addr[1],
  8976. pKey->ENetAddress.addr[2],
  8977. pKey->ENetAddress.addr[3],
  8978. pKey->ENetAddress.addr[4],
  8979. pKey->ENetAddress.addr[5]));
  8980. // set up the remote key
  8981. REMOTE_DEST_KEY_INIT(&pRemoteIp->Key);
  8982. pRemoteIp->Key = *((PREMOTE_DEST_KEY) pCreateParams);
  8983. pRemoteIp->IpAddress = ((PREMOTE_DEST_KEY) pCreateParams)->IpAddress;
  8984. // Initialize various other stuff...
  8985. InitializeListHead(&pRemoteIp->sendinfo.listSendPkts);
  8986. if ((IS_REMOTE_DEST_IP_ADDRESS(&pRemoteIp->Key) == TRUE) &&
  8987. arpCanTryMcap(pRemoteIp->IpAddress))
  8988. {
  8989. SET_REMOTEIP_MCAP(pRemoteIp, ARPREMOTEIP_MCAP_CAPABLE);
  8990. }
  8991. }
  8992. //
  8993. // Add a backup task that could potentially be used to delete this Remote Ip
  8994. //
  8995. arpAddBackupTasks (&ArpGlobals, 1);
  8996. EXIT()
  8997. return pHdr;
  8998. }
  8999. VOID
  9000. arpRemoteDestDelete(
  9001. PRM_OBJECT_HEADER pHdr,
  9002. PRM_STACK_RECORD pSR
  9003. )
  9004. /*++
  9005. Routine Description:
  9006. Free an object of type ARPCB_REMOTE_IP.
  9007. Arguments:
  9008. pHdr - Actually a pointer to the remote ip object to be freed.
  9009. --*/
  9010. {
  9011. ARPCB_REMOTE_IP *pRemoteIp = (ARPCB_REMOTE_IP *) pHdr;
  9012. ASSERT(pRemoteIp->Hdr.Sig == MTAG_REMOTE_IP);
  9013. pRemoteIp->Hdr.Sig = MTAG_FREED;
  9014. ARP_FREE(pHdr);
  9015. //
  9016. // Remove a backup task that was added when RemoteIp was created
  9017. //
  9018. arpRemoveBackupTasks (&ArpGlobals, 1);
  9019. }
  9020. // Enum function
  9021. //
  9022. INT
  9023. arpMaintainArpCache(
  9024. PRM_OBJECT_HEADER pHdr,
  9025. PVOID pvContext, // Unused
  9026. PRM_STACK_RECORD pSR
  9027. )
  9028. #if 0
  9029. for each RIP send VC
  9030. if !marked dirty
  9031. mark dirty
  9032. if linked to channel pdest
  9033. check if channel is still mapped to group
  9034. if not, unlink.
  9035. if required initiate link to new pdest (possibly channel)
  9036. else
  9037. //expired
  9038. unlink from pdest and get rid of it
  9039. #endif // 0
  9040. {
  9041. ENTER("arpMaintainArpCache", 0xefc55765)
  9042. NDIS_STATUS Status;
  9043. PARPCB_REMOTE_IP pRemoteIp;
  9044. PARP1394_INTERFACE pIF;
  9045. pRemoteIp = (PARPCB_REMOTE_IP) pHdr;
  9046. pIF = IF_FROM_LOCALIP(pRemoteIp);
  9047. RM_ASSERT_NOLOCKS(pSR);
  9048. do
  9049. {
  9050. IP_ADDRESS IpAddr;
  9051. UINT Channel;
  9052. ARP_DEST_PARAMS DestParams;
  9053. ARPCB_DEST *pDest;
  9054. BOOLEAN AcquireChannel;
  9055. UINT CurrentTime = arpGetSystemTime();
  9056. UINT TimeSinceLastCheck;
  9057. IpAddr = pRemoteIp->Key.IpAddress;
  9058. #define ARP_PURGE_REMOTEIP_TIME 300 // Arp entry timeout.
  9059. #define ARP_REFRESH_REMOTEIP_TIME (ARP_PURGE_REMOTEIP_TIME - 60) // Arp Refresh time
  9060. TimeSinceLastCheck = CurrentTime - pRemoteIp->sendinfo.TimeLastChecked ;
  9061. //
  9062. // NOTE: we don't bother to get the lock with dealing with
  9063. // sendinfo.TimeLastChecked -- this is ok.
  9064. //
  9065. if (pRemoteIp->sendinfo.TimeLastChecked==0)
  9066. {
  9067. if (CHECK_REMOTEIP_SDTYPE(pRemoteIp, ARPREMOTEIP_DYNAMIC)
  9068. || CHECK_REMOTEIP_RESOLVE_STATE (pRemoteIp, ARPREMOTEIP_UNRESOLVED))
  9069. {
  9070. // Set this field to the current time. It will be cleared back to 0
  9071. // when the next packet is sent to this remote ip.
  9072. //
  9073. pRemoteIp->sendinfo.TimeLastChecked = CurrentTime;
  9074. }
  9075. }
  9076. else if (TimeSinceLastCheck >= ARP_REFRESH_REMOTEIP_TIME &&
  9077. TimeSinceLastCheck <= ARP_PURGE_REMOTEIP_TIME)
  9078. {
  9079. arpRefreshArpEntry(pRemoteIp, pSR);
  9080. }
  9081. else if (TimeSinceLastCheck >= ARP_PURGE_REMOTEIP_TIME)
  9082. {
  9083. //
  9084. // We should clean up this remote ip.
  9085. //
  9086. arpDeinitRemoteIp(pRemoteIp, pSR);
  9087. break;
  9088. }
  9089. #if ARP_ENABLE_MCAP_SEND
  9090. //
  9091. // We'll now see if we need to re-set which destination this
  9092. // pRemoteIp points to.
  9093. //
  9094. // Skip if we can't do MCAP on this address.
  9095. //
  9096. LOCKOBJ(pRemoteIp, pSR);
  9097. if (!CHECK_REMOTEIP_MCAP(pRemoteIp, ARPREMOTEIP_MCAP_CAPABLE))
  9098. {
  9099. UNLOCKOBJ(pRemoteIp, pSR);
  9100. break;
  9101. }
  9102. UNLOCKOBJ(pRemoteIp, pSR);
  9103. //
  9104. // Find a channel mapping to this address, if any.
  9105. //
  9106. Channel = arpFindAssignedChannel(
  9107. pIF,
  9108. pRemoteIp->Key.IpAddress,
  9109. 0,
  9110. pSR
  9111. );
  9112. //
  9113. // NOTE: Special return value NIC1394_BROADCAST_CHANNEL is returned if
  9114. // this address is mapped to no specific channel.
  9115. //
  9116. AcquireChannel = FALSE;
  9117. #if 0 // Let's not enable this just yet -- instead
  9118. if (Channel == NIC1394_BROADCAST_CHANNEL)
  9119. {
  9120. //
  9121. // Hmm... let's get aggressive and try to grab a channel.
  9122. //
  9123. Channel = arpFindFreeChannel(pIF, pSR);
  9124. if (Channel != NIC1394_BROADCAST_CHANNEL)
  9125. {
  9126. //
  9127. // Got one!
  9128. //
  9129. AcquireChannel = TRUE;
  9130. }
  9131. }
  9132. else
  9133. {
  9134. //
  9135. // There is already a channel allocated by someone to be used
  9136. // for this ip address. Let's use it.
  9137. //
  9138. }
  9139. #endif // 0
  9140. ARP_ZEROSTRUCT(&DestParams);
  9141. DestParams.HwAddr.AddressType = NIC1394AddressType_Channel;
  9142. DestParams.HwAddr.Channel = Channel;
  9143. DestParams.AcquireChannel = AcquireChannel;
  9144. arpUpdateRemoteIpDest(pIF, pRemoteIp, &DestParams, pSR);
  9145. #endif // ARP_ENABLE_MCAP_SEND
  9146. } while (FALSE);
  9147. RM_ASSERT_NOLOCKS(pSR)
  9148. return TRUE; // Continue to enumerate.
  9149. }
  9150. VOID
  9151. arpRefreshArpEntry(
  9152. PARPCB_REMOTE_IP pRemoteIp,
  9153. PRM_STACK_RECORD pSR
  9154. )
  9155. {
  9156. ENTER("arpRefreshArpEntry",0x2e19af0b)
  9157. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  9158. PRM_TASK pTask = NULL;
  9159. do
  9160. {
  9161. PUCHAR pIpAddress;
  9162. //
  9163. // We do not refresh Ip addresses ending in 0xff because they are broadcast
  9164. // packets and we are only concernetd with maintaining unicast destinations
  9165. //
  9166. pIpAddress = (PUCHAR)&pRemoteIp->IpAddress;
  9167. if (pIpAddress[3] == 0xff)
  9168. {
  9169. break;
  9170. }
  9171. //
  9172. // We do not need to hold the lock as we are gauranteed that only one instance
  9173. // of the original timer function is going to fire. By implication, all calls to
  9174. // this function are serialized
  9175. //
  9176. if (pRemoteIp->pResolutionTask != NULL)
  9177. {
  9178. // There is already another task trying to resolve this Ip Address
  9179. // so exit
  9180. break;
  9181. }
  9182. Status = arpAllocateTask(
  9183. &pRemoteIp->Hdr, // pParentObject,
  9184. arpTaskResolveIpAddress, // pfnHandler,
  9185. 0, // Timeout
  9186. "Task: ResolveIpAddress", // szDescription
  9187. &pTask,
  9188. pSR
  9189. );
  9190. if (FAIL(Status))
  9191. {
  9192. pTask = NULL;
  9193. break;
  9194. }
  9195. RmStartTask (pTask,0,pSR);
  9196. }while (FALSE);
  9197. EXIT()
  9198. }
  9199. NDIS_STATUS
  9200. arpTaskUnloadEthDhcpEntry(
  9201. IN struct _RM_TASK * pTask,
  9202. IN RM_TASK_OPERATION Code,
  9203. IN UINT_PTR UserParam,
  9204. IN PRM_STACK_RECORD pSR
  9205. )
  9206. /*++
  9207. This task is responsible for shuttingdown and eventually deleting a Dhcp Entry
  9208. It goes through the following stages:
  9209. simply calls RmFreeObject in Group as there is no asynchronous unload work to be done.
  9210. UserParam for (Code == RM_TASKOP_START) : unused
  9211. --*/
  9212. {
  9213. ENTER("TaskUnloadRemoteEth", 0xf42aaa68)
  9214. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  9215. ARP1394_ETH_DHCP_ENTRY * pDhcpEntry = (ARP1394_ETH_DHCP_ENTRY*) RM_PARENT_OBJECT(pTask);
  9216. ARP1394_INTERFACE *pIF = (ARP1394_INTERFACE*) RM_PARENT_OBJECT(pDhcpEntry );
  9217. // Following are the list of pending states for this task.
  9218. //
  9219. enum
  9220. {
  9221. PEND_OtherUnloadComplete
  9222. };
  9223. switch(Code)
  9224. {
  9225. case RM_TASKOP_START:
  9226. {
  9227. LOCKOBJ(pDhcpEntry, pSR);
  9228. // First check if pDhcpEntry is still allocated, if not we go away.
  9229. //
  9230. if (RM_IS_ZOMBIE(pDhcpEntry))
  9231. {
  9232. Status = NDIS_STATUS_SUCCESS;
  9233. break;
  9234. }
  9235. //
  9236. // pDhcpEntry is allocated. Now check if there is already a
  9237. // shutdown task attached to pDhcpEntry.
  9238. //
  9239. if (pDhcpEntry ->pUnloadTask != NULL)
  9240. {
  9241. //
  9242. // There is a shutdown task. We pend on it.
  9243. //
  9244. PRM_TASK pOtherTask = pDhcpEntry->pUnloadTask;
  9245. TR_WARN(("Unload task %p exists; pending on it.\n", pOtherTask));
  9246. RmTmpReferenceObject(&pOtherTask->Hdr, pSR);
  9247. UNLOCKOBJ(pDhcpEntry , pSR);
  9248. RmPendTaskOnOtherTask(
  9249. pTask,
  9250. PEND_OtherUnloadComplete,
  9251. pOtherTask,
  9252. pSR
  9253. );
  9254. RmTmpDereferenceObject(&pOtherTask->Hdr, pSR);
  9255. Status = NDIS_STATUS_PENDING;
  9256. break;
  9257. }
  9258. //
  9259. // There is no unload task going on. Let's
  9260. // make this task THE unload task.
  9261. //
  9262. pDhcpEntry->pUnloadTask = pTask;
  9263. //
  9264. // Since we're THE unload task, add an association to pDhcpEntry,
  9265. // which will only get cleared when the pDhcpEntry->pUnloadTask field
  9266. // above is cleared.
  9267. //
  9268. DBG_ADDASSOC(
  9269. &pDhcpEntry->Hdr, // pObject
  9270. pTask, // Instance1
  9271. pTask->Hdr.szDescription, // Instance2
  9272. ARPASSOC_ETHDHCP_UNLOAD_TASK, // AssociationID
  9273. " Official unload task 0x%p (%s)\n", // szFormat
  9274. pSR
  9275. );
  9276. //
  9277. // We're here because there is no async unload work to be done.
  9278. // We simply return and finish synchronous cleanup in the END
  9279. // handler for this task.
  9280. //
  9281. Status = NDIS_STATUS_SUCCESS;
  9282. } // START
  9283. break;
  9284. case RM_TASKOP_PENDCOMPLETE:
  9285. {
  9286. switch(RM_PEND_CODE(pTask))
  9287. {
  9288. case PEND_OtherUnloadComplete:
  9289. {
  9290. //
  9291. // There was another unload task going when we started, and
  9292. // it's now complete. Nothing for us to do...
  9293. //
  9294. // TODO need standard way to propagate the error code.
  9295. //
  9296. Status = (NDIS_STATUS) UserParam;
  9297. }
  9298. break;
  9299. default:
  9300. {
  9301. ASSERTEX(!"Unknown pend op", pTask);
  9302. }
  9303. break;
  9304. } // end switch(RM_PEND_CODE(pTask))
  9305. } // case RM_TASKOP_PENDCOMPLETE
  9306. break;
  9307. case RM_TASKOP_END:
  9308. {
  9309. LOCKOBJ(pDhcpEntry, pSR);
  9310. //
  9311. // We're done. There should be no async activities left to do.
  9312. //
  9313. //
  9314. // If we're THE unload task, we go on and deallocate the object.
  9315. //
  9316. if (pDhcpEntry ->pUnloadTask == pTask)
  9317. {
  9318. //
  9319. // pDhcpEntry had better not be in a zombie state -- THIS task
  9320. // is the one responsible for deallocating the object!
  9321. //
  9322. ASSERTEX(!RM_IS_ZOMBIE(pDhcpEntry ), pDhcpEntry );
  9323. pDhcpEntry ->pUnloadTask = NULL;
  9324. RmFreeObjectInGroup(
  9325. &pIF->EthDhcpGroup,
  9326. &(pDhcpEntry ->Hdr),
  9327. NULL, // NULL pTask == synchronous.
  9328. pSR
  9329. );
  9330. ASSERTEX(RM_IS_ZOMBIE(pDhcpEntry ), pDhcpEntry );
  9331. // Delete the association we added when we set
  9332. // pDhcpEntry->pUnloadTask to pTask.
  9333. //
  9334. DBG_DELASSOC(
  9335. &pDhcpEntry ->Hdr, // pObject
  9336. pTask, // Instance1
  9337. pTask->Hdr.szDescription, // Instance2
  9338. ARPASSOC_ETHDHCP_UNLOAD_TASK, // AssociationID
  9339. pSR
  9340. );
  9341. UNLOCKOBJ(pDhcpEntry, pSR);
  9342. }
  9343. else
  9344. {
  9345. //
  9346. // We weren't THE unload task, nothing left to do.
  9347. // The object had better be in the zombie state..
  9348. //
  9349. ASSERTEX(
  9350. pDhcpEntry->pUnloadTask == NULL && RM_IS_ZOMBIE(pDhcpEntry),
  9351. pDhcpEntry
  9352. );
  9353. Status = NDIS_STATUS_SUCCESS;
  9354. }
  9355. Status = (NDIS_STATUS) UserParam;
  9356. }
  9357. break; // RM_TASKOP_END:
  9358. default:
  9359. {
  9360. ASSERTEX(!"Unexpected task op", pTask);
  9361. }
  9362. break;
  9363. } // switch (Code)
  9364. RmUnlockAll(pSR);
  9365. EXIT()
  9366. return Status;
  9367. }