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

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