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

2823 lines
83 KiB

  1. //
  2. // Copyright (c) 1998-1999, Microsoft Corporation, all rights reserved
  3. //
  4. // bcm.c
  5. //
  6. // IEEE1394 mini-port/call-manager driver
  7. //
  8. // Bradcast Channel Manager
  9. //
  10. // 07/05/99 ADube - Created - Declaration for miniport routines
  11. //
  12. #include <precomp.h>
  13. #pragma hdrstop
  14. //
  15. // Local Prototypes
  16. //
  17. VOID
  18. nicUpdateLocalHostNodeAddress (
  19. IN PADAPTERCB
  20. );
  21. //
  22. // Local functions
  23. //
  24. VOID
  25. nicBCMReset (
  26. IN PADAPTERCB pAdapter
  27. )
  28. /*++
  29. Routine Description:
  30. Resets the Bus with the force root flag.
  31. Only if there are remote nodes present on the bus
  32. Arguments:
  33. pAdapter
  34. Return Value:
  35. --*/
  36. {
  37. BOOLEAN NoRemoteNodes = FALSE;
  38. TRACE( TL_T, TM_Bcm, ( "==> nicBCMReset " ) );
  39. ADAPTER_ACQUIRE_LOCK (pAdapter);
  40. NoRemoteNodes = IsListEmpty (&pAdapter->PDOList);
  41. ADAPTER_RELEASE_LOCK (pAdapter);
  42. //
  43. // Do not reset the bus if there are no remote nodes present
  44. //
  45. if (NoRemoteNodes == TRUE)
  46. {
  47. return;
  48. }
  49. //
  50. //Reset the bus
  51. //
  52. TRACE( TL_I, TM_Bcm, ( " RESETTING WITH FORCE ROOT") );
  53. nicBusReset( pAdapter , BUS_RESET_FLAGS_FORCE_ROOT);
  54. TRACE( TL_T, TM_Bcm, ( "<== nicBCMReset " ) );
  55. }
  56. VOID
  57. nicBCRAccessedCallback (
  58. IN PNOTIFICATION_INFO pNotificationInfo
  59. )
  60. // Function Description:
  61. // This is the callback function invoked whenever another node
  62. // tries to access the local host's BCR
  63. // The value of the BCR is set elsewhere. So this function simply returns
  64. //
  65. // Arguments
  66. // Adapter - this is passed to the workitem
  67. //
  68. //
  69. // Return Value:
  70. // Failure if allocation of workitem failed
  71. //
  72. {
  73. UNALIGNED NETWORK_CHANNELSR* pBCR = NULL;
  74. PADAPTERCB pAdapter = (PADAPTERCB) pNotificationInfo->Context;
  75. PBROADCAST_CHANNEL_DATA pBCRData = &pAdapter->BCRData;
  76. TRACE( TL_T, TM_Bcm, ( "==> nicBCRAccessedCallback NotificationInfo %x", pNotificationInfo) );
  77. TRACE( TL_V, TM_Bcm, ( " pMdl %x", pNotificationInfo->Mdl) );
  78. TRACE( TL_V, TM_Bcm, ( " SourceID %x", ((PASYNC_PACKET)pNotificationInfo->RequestPacket)->AP_Source_ID) );
  79. pBCR = (NETWORK_CHANNELSR*) NIC_GET_SYSTEM_ADDRESS_FOR_MDL(pNotificationInfo->Mdl);
  80. ASSERT (pNotificationInfo->Mdl == pAdapter->BCRData.AddressRangeContext.pMdl);
  81. switch (pNotificationInfo->fulNotificationOptions)
  82. {
  83. case NOTIFY_FLAGS_AFTER_READ:
  84. {
  85. TRACE( TL_V, TM_Bcm, ( " LocalHost's BCR is READ") );
  86. if ( pBCRData->Flags & BCR_ChannelAllocated)
  87. {
  88. TRACE( TL_V, TM_Bcm, ( " BCR_ChannelAllocated Flag Set ") );
  89. }
  90. else
  91. {
  92. TRACE( TL_V, TM_Bcm, ( " BCR_ChannelAllocated Flag Not Set ") );
  93. }
  94. ASSERT ( pAdapter->BCRData.LocalHostBCRBigEndian & BCR_IMPLEMENTED_BIG_ENDIAN);
  95. TRACE( TL_V, TM_Bcm, ( " pBCR %x", pBCR) );
  96. TRACE( TL_I, TM_Bcm, ( " BCR Accessed %x", *pBCR) );
  97. break;
  98. }
  99. case NOTIFY_FLAGS_AFTER_LOCK:
  100. {
  101. TRACE( TL_V, TM_Bcm, ( " LocalHost's BCR is being Locked to") );
  102. //
  103. // knowingly fall into AsyncWrite
  104. //
  105. }
  106. case NOTIFY_FLAGS_AFTER_WRITE:
  107. {
  108. ULONG LocalHostBCRLittleEndian;
  109. TRACE( TL_V, TM_Bcm, ( " LocalHost's BCR is being Written to") );
  110. //
  111. // Update local data structures.
  112. //
  113. LocalHostBCRLittleEndian = SWAPBYTES_ULONG (pAdapter->BCRData.LocalHostBCRBigEndian);
  114. pBCR = (NETWORK_CHANNELSR*)(&LocalHostBCRLittleEndian);
  115. TRACE( TL_V, TM_Bcm, ( " pBCR %x", pBCR) );
  116. TRACE( TL_V, TM_Bcm, ( " BCR %x", *pBCR) );
  117. if ( BCR_IS_VALID (pBCR) == TRUE)
  118. {
  119. ADAPTER_ACQUIRE_LOCK(pAdapter);
  120. pAdapter->BCRData.IRM_BCR.NC_One =1;
  121. pAdapter->BCRData.IRM_BCR.NC_Valid =1;
  122. pAdapter->BCRData.IRM_BCR.NC_Channel = pBCR->NC_Channel;
  123. BCR_SET_FLAG (pAdapter,BCR_LocalHostBCRUpdated);
  124. ADAPTER_RELEASE_LOCK(pAdapter);
  125. nicSetEventMakeCall(pAdapter);
  126. TRACE( TL_I, TM_Bcm, ( " IRM_BCR Accessed %x", pAdapter->BCRData.IRM_BCR) );
  127. }
  128. break;
  129. }
  130. default :
  131. {
  132. ASSERT (0);
  133. break;
  134. }
  135. }
  136. TRACE( TL_T, TM_Bcm, ( "<== nicBCRAccessedCallback NotificationInfo %x", pNotificationInfo) );
  137. }
  138. VOID
  139. nicBCMAddRemoteNode (
  140. IN PADAPTERCB pAdapter,
  141. IN BOOLEAN fIsOnlyRemoteNode
  142. )
  143. /*++
  144. Routine Description:
  145. This is the BCM algorithm - It finds out if the local host is the IRM and goes into the appropriate code path.
  146. Due to network conditions, this can quietly fail if all other remedies fail
  147. Arguments:
  148. pAdapter - Adapter
  149. Generation - Generation associated with this iteration of the algorithm
  150. Return Value:
  151. None -
  152. --*/
  153. {
  154. BOOLEAN fDoBcm = FALSE;
  155. ULONG Generation = 0;
  156. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  157. TRACE( TL_T, TM_Bcm, ( "==>nicBCMAddRemoteNode pAdapter %x, fIsOnlyRemoteNode %x ", pAdapter, fIsOnlyRemoteNode ) );
  158. NdisStatus = nicGetGenerationCount (pAdapter, &Generation);
  159. //
  160. // Do not schedule the BCM, if the have a valid BCR for the current generation
  161. //
  162. if (NdisStatus == NDIS_STATUS_SUCCESS &&
  163. (BCR_IS_VALID (&pAdapter->BCRData.IRM_BCR) == TRUE) &&
  164. Generation == pAdapter->Generation )
  165. {
  166. fDoBcm = FALSE;
  167. }
  168. else
  169. {
  170. fDoBcm = TRUE;
  171. }
  172. TRACE( TL_T, TM_Bcm, ( " nicBCMAddRemoteNode fDoBCM%x ", fDoBcm) );
  173. //
  174. // Set An Event so a waiting BCM thread (in FindIrmAmongRemoteNodes) can
  175. // be schduled to run
  176. //
  177. ADAPTER_ACQUIRE_LOCK (pAdapter);
  178. BCR_CLEAR_FLAG (pAdapter, BCR_LastNodeRemoved);
  179. if (fDoBcm == TRUE)
  180. {
  181. //
  182. // if the BCM is already in progress, mark it as dirty
  183. //
  184. BCR_SET_FLAG (pAdapter, BCR_NewNodeArrived);
  185. pAdapter->BCRData.BCRWaitForNewRemoteNode.EventCode = Nic1394EventCode_NewNodeArrived;
  186. NdisSetEvent( &pAdapter->BCRData.BCRWaitForNewRemoteNode.NdisEvent);
  187. }
  188. ADAPTER_RELEASE_LOCK (pAdapter);
  189. if (fDoBcm == TRUE)
  190. {
  191. TRACE( TL_A, TM_Bcm , ("Add RemoteNode- scheduling the BCM" ) );
  192. nicScheduleBCMWorkItem(pAdapter);
  193. }
  194. //
  195. // now do the media connectivity stuff
  196. //
  197. if (fIsOnlyRemoteNode == TRUE)
  198. {
  199. //
  200. // WE have media connectivity
  201. //
  202. pAdapter->MediaConnectStatus = NdisMediaStateConnected;
  203. nicMIndicateStatus( pAdapter, NDIS_STATUS_MEDIA_CONNECT, NULL, 0);
  204. }
  205. TRACE( TL_T, TM_Bcm, ( "<== nicBCMAddRemoteNode ") );
  206. }
  207. VOID
  208. nicBCMAlgorithm(
  209. PADAPTERCB pAdapter,
  210. ULONG BcmGeneration
  211. )
  212. /*++
  213. Routine Description:
  214. Execute the BCM algorithm.
  215. Finds out if the current host Is IRM
  216. If YES then inform remote nodes and exit
  217. if NO then find the remote node and read its BCR.
  218. Reasons for abort - New Node Arrival or Invalid Generation caused by a BusReset
  219. If no remote nodes are present and this node is the IRM it will allocate the b channel and exit
  220. Arguments:
  221. pAdapter - paDapter
  222. BCMGeneration - Generation at which the BCM was started
  223. Return Value:
  224. --*/
  225. {
  226. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  227. PREMOTE_NODE pRemoteNode= NULL;
  228. PREMOTE_NODE pIRMRemoteNode = NULL;
  229. PTOPOLOGY_MAP pTopologyMap = NULL;
  230. ULONG Length = DEFAULT_TOPOLOGY_MAP_LENGTH;
  231. PVOID pTopologyBuffer = NULL;
  232. NODE_ADDRESS LocalNodeAddress;
  233. BOOLEAN fIsLocalHostIrm = FALSE;
  234. ULONG TopologyGeneration = 0;
  235. PVOID pOldTopologyMap = NULL;
  236. STORE_CURRENT_IRQL;
  237. ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
  238. TRACE( TL_T, TM_Bcm, ( "==>nicBCMAlgorithm pAdapter %x, BcmGen %x", pAdapter, BcmGeneration ) );
  239. do
  240. {
  241. ASSERT (BCR_TEST_FLAG (pAdapter, BCR_BCMInProgress) == TRUE);
  242. //
  243. // find out if the local host is the IRM and update the generation count as well
  244. //
  245. NdisStatus = nicIsLocalHostTheIrm ( pAdapter,
  246. &fIsLocalHostIrm,
  247. &pTopologyMap,
  248. &LocalNodeAddress);
  249. if (NdisStatus != NDIS_STATUS_SUCCESS)
  250. {
  251. TRACE( TL_A, TM_Bcm, ( " nicBCMAlgorithm: nicIsLocalHostTheIrm FAILED ") );
  252. break;
  253. }
  254. //
  255. // Update the adapter structure
  256. //
  257. TopologyGeneration = pTopologyMap->TOP_Generation;
  258. ADAPTER_ACQUIRE_LOCK (pAdapter);
  259. if (TopologyGeneration != BcmGeneration)
  260. {
  261. ADAPTER_SET_FLAG(pAdapter, fADAPTER_InvalidGenerationCount);
  262. ADAPTER_RELEASE_LOCK(pAdapter);
  263. FREE_NONPAGED (pTopologyMap);
  264. pTopologyMap = NULL;
  265. TRACE( TL_A, TM_Bcm, ( " TopologyGeneration %x, BcmGeneration %x", TopologyGeneration, BcmGeneration) );
  266. break;
  267. }
  268. //
  269. // extract information from the topology map and store it in the adapter structure
  270. //
  271. ASSERT (pAdapter->Generation == pTopologyMap->TOP_Generation);
  272. pAdapter->BCRData.LocalNodeAddress = LocalNodeAddress;
  273. pOldTopologyMap = pAdapter->BCRData.pTopologyMap;
  274. pAdapter->BCRData.pTopologyMap = pTopologyMap;
  275. pAdapter->BCRData.LocalNodeNumber = LocalNodeAddress.NA_Node_Number;
  276. pAdapter->NodeAddress = LocalNodeAddress;
  277. pAdapter->Generation = pTopologyMap->TOP_Generation;
  278. BcmGeneration = pTopologyMap->TOP_Generation;
  279. ADAPTER_RELEASE_LOCK (pAdapter);
  280. //
  281. // Free the Old Topology Map
  282. //
  283. if (pOldTopologyMap != NULL)
  284. {
  285. FREE_NONPAGED(pOldTopologyMap);
  286. }
  287. //
  288. // Now Start the BCM algorithm
  289. //
  290. if (fIsLocalHostIrm == TRUE)
  291. {
  292. pAdapter->BCRData.Flags |= BCR_LocalHostIsIRM;
  293. ASSERT (pTopologyMap->TOP_Node_Count-1 == LocalNodeAddress.NA_Node_Number);
  294. TRACE( TL_V, TM_Bcm, ( " LOCAL HOST IS IRM ") );
  295. NdisStatus = nicLocalHostIsIrm (pAdapter);
  296. }
  297. else
  298. {
  299. TRACE( TL_V, TM_Bcm, ( " LOCAL HOST IS NOT IRM ") );
  300. NdisStatus = nicLocalHostIsNotIrm( pAdapter,
  301. BcmGeneration );
  302. }
  303. if (NdisStatus != NDIS_STATUS_SUCCESS)
  304. {
  305. TRACE( TL_V, TM_Bcm, ( " nicBCMAlogrithm: nicLocalHostIsNotIrm or nicLocalHostIsIrm FAILED") );
  306. break;
  307. }
  308. //
  309. // Marks the end of the BCM algorithm . Do the clean up work.
  310. // Check for the last node going away. , Release any pending make calls
  311. // and set up the Gasp Header
  312. //
  313. nicMakeGaspHeader (pAdapter, &pAdapter->GaspHeader);
  314. nicSetEventMakeCall (pAdapter);
  315. } while (FALSE);
  316. if (NdisStatus != NDIS_STATUS_SUCCESS)
  317. {
  318. NIC1394_LOG_PKT(pAdapter,
  319. NIC1394_LOGFLAGS_BCM_FAILED,
  320. pAdapter->Generation,
  321. fIsLocalHostIrm ,
  322. &NdisStatus,
  323. sizeof (NDIS_STATUS));
  324. BCR_SET_FLAG (pAdapter, BCR_BCMFailed);
  325. }
  326. TRACE( TL_T, TM_Bcm, ( "<==nicBCMAlgorithm %x ", NdisStatus ) );
  327. MATCH_IRQL;
  328. }
  329. VOID
  330. nicBCMAlgorithmWorkItem(
  331. PNDIS_WORK_ITEM pWorkItem,
  332. PVOID pContext
  333. )
  334. /*++
  335. Routine Description:
  336. The function kicks of the BCM algorithm.
  337. Restarts the BCM if a reset occurred during the BCM algorithm.
  338. Arguments:
  339. Adapter - localhost
  340. Return Value:
  341. --*/
  342. {
  343. PADAPTERCB pAdapter = (PADAPTERCB)pContext;
  344. ULONG BcmGeneration = pAdapter->Generation;
  345. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  346. ULONG Generation;
  347. BOOLEAN fRestartBCM = FALSE;
  348. BOOLEAN fFreeBCR = FALSE;
  349. BOOLEAN fFlagSetByThisThread = FALSE;
  350. STORE_CURRENT_IRQL;
  351. TRACE( TL_T, TM_Bcm, ( "==>nicBCMAlgorithmWorkItem pAdapter %x, Generation %x", pAdapter, BcmGeneration ) );
  352. //
  353. // Ensure that only one thread gets into the BCM algorithm and
  354. // all other threads are returned immediately
  355. //
  356. ADAPTER_ACQUIRE_LOCK (pAdapter);
  357. //
  358. // If the BCR is being freed, then don't touch it
  359. //
  360. if (BCR_TEST_FLAGS (pAdapter, (BCR_Freed |BCR_BCRNeedsToBeFreed ) )== TRUE)
  361. {
  362. // Do Nothing, this thread will simply exit
  363. //
  364. }
  365. else
  366. {
  367. //
  368. // The BCR is active,
  369. // If there is no other thread running the BCM algorithm, then this thread should set
  370. // the BCMInProgress flag
  371. //
  372. if (BCR_TEST_FLAG (pAdapter, BCR_BCMInProgress ) == FALSE )
  373. {
  374. BCR_SET_FLAG (pAdapter, BCR_BCMInProgress );
  375. fFlagSetByThisThread = TRUE;
  376. }
  377. }
  378. ADAPTER_RELEASE_LOCK (pAdapter);
  379. do
  380. {
  381. //
  382. // First check to see if we have a valid reason to stop
  383. //
  384. if (fFlagSetByThisThread == FALSE)
  385. {
  386. break;
  387. }
  388. ADAPTER_ACQUIRE_LOCK (pAdapter);
  389. //
  390. // If there are no remote nodes then mark the BCR as so
  391. //
  392. if (IsListEmpty (&pAdapter->PDOList) == TRUE )
  393. {
  394. TRACE (TL_V, TM_Bcm, ("No Nodes present" ) );
  395. BCR_SET_FLAG (pAdapter, BCR_NoNodesPresent);
  396. }
  397. else
  398. {
  399. BCR_CLEAR_FLAG (pAdapter, BCR_NoNodesPresent);
  400. }
  401. //
  402. // Clear the two flags which cause us to restart the BCM
  403. //
  404. ADAPTER_CLEAR_FLAG (pAdapter, fADAPTER_InvalidGenerationCount) ;
  405. BCR_CLEAR_FLAG (pAdapter, BCR_NewNodeArrived );
  406. ADAPTER_RELEASE_LOCK (pAdapter);
  407. do
  408. {
  409. NdisStatus = nicGetGenerationCount (pAdapter, &Generation) ;
  410. if (NdisStatus != NDIS_STATUS_SUCCESS)
  411. {
  412. TRACE( TL_T, TM_Bcm, ( " nicGetGenerationCount , Generation %x", pAdapter, BcmGeneration ) );
  413. break;
  414. }
  415. //
  416. // If the BCM is freed then exit
  417. //
  418. if ((BCR_TEST_FLAGS (pAdapter, BCR_Freed | BCR_BCRNeedsToBeFreed )== TRUE) )
  419. {
  420. break;
  421. }
  422. //
  423. // Update the generation count
  424. //
  425. BcmGeneration = Generation;
  426. pAdapter->Generation = Generation;
  427. //
  428. // Update the remote nodes table
  429. //
  430. nicUpdateRemoteNodeTable (pAdapter);
  431. nicUpdateLocalHostNodeAddress (pAdapter);
  432. if ( ADAPTER_TEST_FLAG (pAdapter, fADAPTER_InvalidGenerationCount) == TRUE)
  433. {
  434. //
  435. // The local host has been reset since the start of the loop. Break
  436. // out and restart
  437. //
  438. break;
  439. }
  440. //
  441. // Now start the BCM
  442. //
  443. if (BCR_TEST_FLAG (pAdapter, BCR_LocalHostBCRUpdated ) == FALSE)
  444. {
  445. //
  446. // We need to go and do the BCM because our registers have not been updated
  447. //
  448. nicBCMAlgorithm(pAdapter, BcmGeneration);
  449. }
  450. else
  451. {
  452. //
  453. // Our BCR was written to
  454. //
  455. ULONG LocalHostBCRLittleEndian ;
  456. NETWORK_CHANNELSR* pBCR;
  457. ASSERT (BCR_TEST_FLAG (pAdapter, BCR_LocalHostBCRUpdated ) == TRUE);
  458. //
  459. // Update the IRM_BCR so we have a record of the new BCM
  460. //
  461. ADAPTER_ACQUIRE_LOCK (pAdapter);
  462. NdisZeroMemory (&pAdapter->BCRData.IRM_BCR, sizeof (NETWORK_CHANNELSR) );
  463. LocalHostBCRLittleEndian = SWAPBYTES_ULONG (pAdapter->BCRData.LocalHostBCRBigEndian);
  464. ASSERT ((LocalHostBCRLittleEndian & BCR_VALID_LITTLE_ENDIAN) == BCR_VALID_LITTLE_ENDIAN);
  465. pBCR = (NETWORK_CHANNELSR*)(&LocalHostBCRLittleEndian);
  466. pAdapter->BCRData.IRM_BCR.NC_Channel = pBCR->NC_Channel ; // bits 0-5
  467. pAdapter->BCRData.IRM_BCR.NC_Valid = pBCR->NC_Valid ; // bit 30
  468. pAdapter->BCRData.IRM_BCR.NC_One = pBCR->NC_One ;
  469. ADAPTER_RELEASE_LOCK (pAdapter);
  470. }
  471. } while (FALSE);
  472. //
  473. // Check to see if another Bus Reset has come in.
  474. // if so we need to restart the BCM
  475. //
  476. ADAPTER_ACQUIRE_LOCK (pAdapter);
  477. BCR_CLEAR_FLAG (pAdapter, BCR_BCMInProgress);
  478. //
  479. // if the generation is bad the BCR is not being freed initialzed then restart the BCM
  480. //
  481. TRACE( TL_V, TM_Bcm, ( "pAdapter Flags %x, BCM flags %x, BCM %x", pAdapter->ulFlags, pAdapter->BCRData.Flags, pAdapter->BCRData.IRM_BCR) );
  482. //
  483. // If the BCR is getting freed , set the flag and break, then we cannot loop back, we must exit
  484. //
  485. if (BCR_TEST_FLAGS (pAdapter, (BCR_Freed |BCR_BCRNeedsToBeFreed ) )== TRUE)
  486. {
  487. //
  488. // As the BCM is about to be freed, this run of the BCM should terminate
  489. // and free the BCR
  490. //
  491. fRestartBCM = FALSE;
  492. fFreeBCR = TRUE;
  493. ADAPTER_RELEASE_LOCK (pAdapter);
  494. break;
  495. }
  496. //
  497. // We need to do the bcm again, if a reset has occurred or a new node has arrived
  498. //
  499. if ((ADAPTER_TEST_FLAG (pAdapter, fADAPTER_InvalidGenerationCount) == TRUE) ||
  500. (BCR_TEST_FLAG (pAdapter, BCR_NewNodeArrived)== TRUE) )
  501. {
  502. //
  503. // Invalidate the BCR and restart
  504. //
  505. pAdapter->BCRData.IRM_BCR.NC_Valid = 0;
  506. //
  507. // We are going to try again. Update the flags
  508. //
  509. BCR_CLEAR_FLAG (pAdapter, BCR_BCMFailed | BCR_LocalHostBCRUpdated | BCR_LocalHostIsIRM | BCR_NewNodeArrived );
  510. //
  511. // As this thread is going ot retry thr BCM, it must block all new entrants again
  512. //
  513. BCR_SET_FLAG (pAdapter, BCR_BCMInProgress);
  514. fRestartBCM = TRUE;
  515. TRACE( TL_V, TM_Bcm, ( "Restart BCM TRUE ") );
  516. }
  517. else
  518. {
  519. //
  520. // We do not retart the BCM has completed
  521. //
  522. TRACE( TL_V, TM_Bcm, ( "Restart BCM FALSE") );
  523. fRestartBCM = FALSE;
  524. }
  525. ADAPTER_RELEASE_LOCK (pAdapter);
  526. if ((fRestartBCM == TRUE) &&
  527. (BCR_TEST_FLAGS (pAdapter, BCR_ChannelAllocated) == TRUE))
  528. {
  529. TRACE (TL_V, TM_Bcm, ("Free Channel %x", pAdapter->BCRData.LocallyAllocatedChannel ));
  530. nicFreeChannel (pAdapter, pAdapter->BCRData.LocallyAllocatedChannel );
  531. }
  532. //
  533. // fSimply Exit is also false, and will allow this thread to execute again
  534. //
  535. }while (fRestartBCM == TRUE) ;
  536. if (fFlagSetByThisThread == TRUE)
  537. {
  538. if ( BCR_TEST_FLAG (pAdapter, BCR_BCRNeedsToBeFreed) == FALSE)
  539. {
  540. //
  541. // If we are not freeing the BCR, then the adapter is still valid.
  542. // Update the local Host Node Address, so that we have the latest information
  543. // from the bus.
  544. //
  545. nicUpdateLocalHostNodeAddress (pAdapter);
  546. nicUpdateRemoteNodeTable (pAdapter);
  547. }
  548. }
  549. //
  550. // Does the BCR need to be freed by this thread. Only threads that have been
  551. // given a chance to execute the bcm, should be able to free the BCR
  552. //
  553. if (fFreeBCR == TRUE)
  554. {
  555. nicFreeBroadcastChannelRegister (pAdapter);
  556. }
  557. //
  558. // Dereference the adapter . reference was added for the work item
  559. //
  560. nicDereferenceAdapter (pAdapter, "nicBCMAlgorithmWorkItem ");
  561. FREE_NONPAGED (pWorkItem);
  562. TRACE( TL_T, TM_Bcm, ( "<==nicBCMAlgorithmWorkItem fRestartBCM %x", fRestartBCM) );
  563. MATCH_IRQL;
  564. }
  565. VOID
  566. nicBCMAbort (
  567. IN PADAPTERCB pAdapter,
  568. IN PREMOTE_NODE pRemoteNode
  569. )
  570. // Function Description:
  571. // This function is called when the BCM aborts. It should release the allocated channel
  572. //
  573. // Arguments
  574. // pAdapter - Current local Host
  575. //
  576. // Return Value:
  577. //
  578. {
  579. BOOLEAN fNeedToFreeChannel = FALSE;
  580. PBROADCAST_CHANNEL_DATA pBCRData = &pAdapter->BCRData;
  581. TRACE( TL_T, TM_Bcm, ( "==>nicBCMAbort pAdapter %x", pAdapter) );
  582. ADAPTER_ACQUIRE_LOCK (pAdapter);
  583. if ( BCR_TEST_FLAG (pAdapter, BCR_InformingRemoteNodes) == TRUE)
  584. {
  585. fNeedToFreeChannel = TRUE;
  586. BCR_CLEAR_FLAG (pAdapter, BCR_ChannelAllocated);
  587. BCR_CLEAR_FLAG (pAdapter, BCR_InformingRemoteNodes);
  588. }
  589. else
  590. {
  591. fNeedToFreeChannel = FALSE;
  592. }
  593. ADAPTER_RELEASE_LOCK (pAdapter);
  594. if (fNeedToFreeChannel == TRUE)
  595. {
  596. nicFreeChannel ( pAdapter,
  597. pBCRData->LocallyAllocatedChannel);
  598. }
  599. pBCRData->LocallyAllocatedChannel = INVALID_CHANNEL;
  600. TRACE( TL_T, TM_Bcm, ( "<==nicBCMAbort " ) );
  601. }
  602. NDIS_STATUS
  603. nicFindIrmAmongRemoteNodes (
  604. IN PADAPTERCB pAdapter,
  605. IN ULONG BCMGeneration,
  606. OUT PPREMOTE_NODE ppIrmRemoteNode
  607. )
  608. // Function Description:
  609. // This function goes through all the remote nodes
  610. // and attempts to get their address to verify which one is
  611. // the IRM
  612. //
  613. //
  614. // Arguments
  615. // pADpater - Local host
  616. // BCMGeneration - the Gerneration at which the BCMStarted
  617. // ppIrmRemoteNode - output value - IRM
  618. //
  619. // Return Value:
  620. // Success - if an IRM is found
  621. //
  622. {
  623. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  624. PLIST_ENTRY pPdoListEntry = NULL;
  625. PREMOTE_NODE pRemoteNode = NULL;
  626. PREMOTE_NODE pIrmRemoteNode = NULL;
  627. NODE_ADDRESS RemoteNodeAddress;
  628. ULONG HighestNode;
  629. ULONG Generation;
  630. ULONG NumRetry =0;
  631. PNIC1394_EVENT pBCRWaitForNewRemoteNode = &pAdapter->BCRData.BCRWaitForNewRemoteNode;
  632. ULONG BackOffWait = ONE_MINUTE>>4;
  633. TRACE( TL_T, TM_Bcm, ( "==>nicFindIrmAmongRemoteNodes pAdapter %x, ppIrmRemoteNode %x",
  634. pAdapter, ppIrmRemoteNode) );
  635. ASSERT (pAdapter->BCRData.pTopologyMap != NULL);
  636. HighestNode = pAdapter->BCRData.pTopologyMap->TOP_Node_Count-1;
  637. //
  638. // Set up a loop, so that we continue until we succeed, timeout, or have a good reason to break
  639. // One of two things will cause the break:
  640. // 1. the bus has been reset - break out
  641. // 2. Irm has been found
  642. //
  643. do
  644. {
  645. //
  646. // Reset the event here - This is so that when the newly arrived node is not the IRM
  647. // and we will need to wait another time
  648. //
  649. pBCRWaitForNewRemoteNode->EventCode = Nic1394EventCode_InvalidEventCode;
  650. NdisResetEvent (&pBCRWaitForNewRemoteNode->NdisEvent);
  651. //
  652. // First see if we already have this remote node in our table
  653. //
  654. ADAPTER_ACQUIRE_LOCK (pAdapter);
  655. if (pAdapter->NodeTable.RemoteNode[HighestNode] != NULL)
  656. {
  657. //
  658. // we found the IRM. Lets break out.
  659. //
  660. *ppIrmRemoteNode = pAdapter->NodeTable.RemoteNode[HighestNode] ;
  661. //
  662. // Reference the IRM. This will be dereferenced after the BCM is finished. (ie) at the end of nicLocalHostisNotIrm
  663. //
  664. nicReferenceRemoteNode (*ppIrmRemoteNode, FindIrmAmongRemoteNodes);
  665. ADAPTER_RELEASE_LOCK (pAdapter);
  666. NdisStatus = NDIS_STATUS_SUCCESS;
  667. //
  668. // Break out if the IRM is found
  669. //
  670. break;
  671. }
  672. else
  673. {
  674. //
  675. // If the IRM is not in adapter's data structures, the thread needs to wait for it to arrive
  676. //
  677. BOOLEAN bWaitSuccessful;
  678. ADAPTER_RELEASE_LOCK (pAdapter);
  679. //
  680. // Sleep and try again
  681. //
  682. TRACE (TL_V, TM_Bcm, ( " About to Wait 15 sec. for Remote Node") );
  683. bWaitSuccessful = NdisWaitEvent (&pBCRWaitForNewRemoteNode->NdisEvent, BackOffWait );
  684. TRACE (TL_V, TM_Bcm, ( " pBCRWaitForNewRemoteNode signalled Event Code = %x, bWaitSuccessful %x",
  685. pBCRWaitForNewRemoteNode->EventCode, bWaitSuccessful) );
  686. BackOffWait = BackOffWait << 1;
  687. //
  688. // It has been seen that the Remote Node's address might get updated
  689. // after a small delay. Refresh our NodeTable here
  690. //
  691. nicUpdateRemoteNodeTable(pAdapter);
  692. if (bWaitSuccessful == TRUE)
  693. {
  694. //
  695. // Check for invalid conditions
  696. //
  697. if (pBCRWaitForNewRemoteNode->EventCode == nic1394EventCode_BusReset ||
  698. pBCRWaitForNewRemoteNode->EventCode == nic1394EventCode_FreedAddressRange)
  699. {
  700. TRACE( TL_V, TM_Bcm, ( " Bus Has been reset,or addresss range freed aborting BCM") );
  701. //
  702. // Break out if the Bus Has been reset
  703. //
  704. break;
  705. }
  706. TRACE( TL_V, TM_Bcm, ( " New Node has arrived check its node address") );
  707. ASSERT (pBCRWaitForNewRemoteNode->EventCode == Nic1394EventCode_NewNodeArrived);
  708. //
  709. // Hit the while (TRUE) condition loop back and verify if the new node is the IRM
  710. //
  711. }
  712. else
  713. {
  714. //
  715. // Wait has timed out
  716. //
  717. if (ADAPTER_TEST_FLAG (pAdapter, fADAPTER_InvalidGenerationCount) == TRUE)
  718. {
  719. //
  720. // If the generation is invalid then break out and abort the BCM
  721. //
  722. NdisStatus = NIC1394_STATUS_INVALID_GENERATION;
  723. break;
  724. }
  725. NumRetry ++;
  726. if (NumRetry == 5 )// arbtrary constant
  727. {
  728. break;
  729. }
  730. }
  731. }
  732. } while (TRUE);
  733. if (NdisStatus != NDIS_STATUS_SUCCESS)
  734. {
  735. //
  736. // Log this failuire
  737. //
  738. NIC1394_LOG_PKT(pAdapter,
  739. NIC1394_LOGFLAGS_BCM_IRM_NOT_FOUND,
  740. pAdapter->Generation,
  741. HighestNode,
  742. &pAdapter->NodeTable,
  743. 5 * sizeof (PVOID)); // arbitrarily number - copies 5 entries
  744. }
  745. TRACE( TL_T, TM_Bcm, ( "<==nicFindIrmAmongRemoteNodes Status %x pIrm %x", NdisStatus, *ppIrmRemoteNode ) );
  746. return NdisStatus;
  747. }
  748. VOID
  749. nicFreeBroadcastChannelRegister(
  750. IN PADAPTERCB pAdapter
  751. )
  752. // Function Description:
  753. // Free the boradcast channed reigster. Only called
  754. // from the Init failure or halt code path
  755. //
  756. // Arguments
  757. // pAdapter
  758. //
  759. // Return Value:
  760. //
  761. // None
  762. //
  763. {
  764. ADDRESS_RANGE_CONTEXT BCRAddressRange;
  765. TIMESTAMP_ENTRY ("==>Free BCR");
  766. TRACE( TL_T, TM_Bcm, ( "==> nicFreeBroadcastChannelRegister pAdapter %x", pAdapter ) );
  767. do
  768. {
  769. ADAPTER_ACQUIRE_LOCK (pAdapter);
  770. //
  771. // Mark the BCR so that so the adapter knows that the BCR is about to be freed
  772. //
  773. BCR_SET_FLAG (pAdapter, BCR_BCRNeedsToBeFreed);
  774. //
  775. // If a Make Call is pending, then set the Event so that the make call can complete.
  776. //
  777. if (BCR_TEST_FLAG (pAdapter,BCR_MakeCallPending)== TRUE)
  778. {
  779. pAdapter->BCRData.MakeCallWaitEvent.EventCode = nic1394EventCode_FreedAddressRange;
  780. NdisSetEvent (&pAdapter->BCRData.MakeCallWaitEvent.NdisEvent);
  781. }
  782. //
  783. // If the BCM is in progress, let the BCM thread free the BCR instead
  784. //
  785. if (BCR_TEST_FLAG (pAdapter, BCR_BCMInProgress) == TRUE)
  786. {
  787. ADAPTER_RELEASE_LOCK (pAdapter);
  788. //
  789. // Wake up any pending threads - This wakes up an existing BCM thread that could
  790. // be waiting for a new remote node
  791. //
  792. pAdapter->BCRData.BCRWaitForNewRemoteNode.EventCode = nic1394EventCode_FreedAddressRange;
  793. NdisSetEvent (&pAdapter->BCRData.BCRWaitForNewRemoteNode.NdisEvent);
  794. TRACE( TL_N, TM_Bcm, ( " nicFreeBroadcastChannelRegister BCM in progress or already freed, breaking out", pAdapter ) );
  795. break;
  796. }
  797. //
  798. // if the BCR is already freed, then simply exit. The event that the caller will wait
  799. // on BCRData.BCRFreeAddressRange.NdisEvent has already been set
  800. //
  801. if (BCR_TEST_FLAG (pAdapter, BCR_Freed) == TRUE)
  802. {
  803. ADAPTER_RELEASE_LOCK (pAdapter);
  804. break;
  805. }
  806. //
  807. // sanity check
  808. //
  809. ASSERT (BCR_TEST_FLAG (pAdapter, BCR_BCRNeedsToBeFreed) == TRUE);
  810. //
  811. // Now update the flags
  812. //
  813. BCR_CLEAR_FLAG (pAdapter, BCR_Initialized | BCR_ChannelAllocated | BCR_BCRNeedsToBeFreed);
  814. //
  815. // clear all the BCR Valid bits
  816. //
  817. pAdapter->BCRData.IRM_BCR.NC_Valid = 0;
  818. pAdapter->BCRData.LocalHostBCRBigEndian = BCR_IMPLEMENTED_LITTLE_ENDIAN; //0x80000000
  819. if (pAdapter->BCRData.pAsyncWriteBCRMdl != NULL)
  820. {
  821. nicFreeMdl (pAdapter->BCRData.pAsyncWriteBCRMdl );
  822. pAdapter->BCRData.pAsyncWriteBCRMdl = NULL;
  823. }
  824. if (pAdapter->BCRData.pRemoteBCRMdl != NULL)
  825. {
  826. nicFreeMdl (pAdapter->BCRData.pRemoteBCRMdl);
  827. pAdapter->BCRData.pRemoteBCRMdl = NULL;
  828. }
  829. //
  830. // Temporary copy of the Address Range Context
  831. //
  832. BCRAddressRange = pAdapter->BCRData.AddressRangeContext;
  833. //
  834. // Zero out the Address Range Structure. This zeroes out AddressRangeContext.Mdl as well.
  835. // This is ok as BCRData.pLocalBCRMdl will be freed below and they both
  836. // point to the same mdl.
  837. //
  838. NdisZeroMemory (
  839. &pAdapter->BCRData.AddressRangeContext,
  840. sizeof (pAdapter->BCRData.AddressRangeContext));
  841. //
  842. // Clear out the VC. if any
  843. //
  844. if (pAdapter->BCRData.pBroadcastChanneVc != NULL)
  845. {
  846. nicDereferenceCall ((PVCCB) pAdapter->BCRData.pBroadcastChanneVc, "nicFreeBroadcastChannelRegister ");
  847. pAdapter->BCRData.pBroadcastChanneVc = NULL;
  848. }
  849. ADAPTER_RELEASE_LOCK (pAdapter);
  850. //
  851. // Free Address Range
  852. //
  853. if (BCRAddressRange.hAddressRange != NULL)
  854. {
  855. nicFreeAddressRange (pAdapter,
  856. BCRAddressRange.AddressesReturned,
  857. &BCRAddressRange.AddressRange,
  858. &BCRAddressRange.hAddressRange );
  859. }
  860. ADAPTER_ACQUIRE_LOCK (pAdapter);
  861. if (pAdapter->BCRData.pLocalBCRMdl != NULL)
  862. {
  863. nicFreeMdl (pAdapter->BCRData.pLocalBCRMdl);
  864. pAdapter->BCRData.pLocalBCRMdl = NULL;
  865. }
  866. //
  867. // Free the Adapter's BCRData. TopologyMap as that is locally allocated
  868. //
  869. if (pAdapter->BCRData.pTopologyMap)
  870. {
  871. FREE_NONPAGED (pAdapter->BCRData.pTopologyMap);
  872. pAdapter->BCRData.pTopologyMap = NULL;
  873. }
  874. //
  875. // Clear the flags to force the BCR to be reintitalized
  876. //
  877. BCR_CLEAR_ALL_FLAGS(pAdapter);
  878. BCR_SET_FLAG (pAdapter, BCR_Freed);
  879. ADAPTER_RELEASE_LOCK (pAdapter);
  880. //
  881. // Set the Event and let the halt go through
  882. //
  883. pAdapter->BCRData.BCRFreeAddressRange.EventCode = nic1394EventCode_FreedAddressRange;
  884. NdisSetEvent (&pAdapter->BCRData.BCRFreeAddressRange.NdisEvent);
  885. TRACE( TL_N, TM_Bcm, ( " nicFreeBroadcastChannelRegister BCM freed", pAdapter ) );
  886. } while (FALSE);
  887. TRACE( TL_T, TM_Bcm, ( "<== nicFreeBroadcastChannelRegister pAdapter %x", pAdapter ) );
  888. TIMESTAMP_EXIT ("<==Free BCR");
  889. }
  890. NDIS_STATUS
  891. nicInformAllRemoteNodesOfBCM (
  892. IN PADAPTERCB pAdapter
  893. )
  894. // Function Description:
  895. // This function will simply walk through the remote node list and write
  896. // to the BCR of all the remote nodes
  897. //
  898. // Arguments
  899. // pAdapter - Current local Host
  900. // Channel - Channel used for broadcast
  901. //
  902. // Return Value:
  903. //
  904. //
  905. {
  906. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  907. PREMOTE_NODE pRemoteNode = NULL;
  908. PLIST_ENTRY pPdoListEntry = NULL;
  909. IO_ADDRESS Destination;
  910. ULONG IrmGeneration ;
  911. BOOLEAN fLockAcquired = FALSE;
  912. NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
  913. BOOLEAN fReferencedCurrentRemoteNode = FALSE;
  914. PMDL pAsyncWriteBCRMdl = NULL;
  915. TRACE( TL_T, TM_Bcm, ( "==> nicInformAllRemoteNodesOfBCM pAdapter %x, Channel %x OldGeneration %x",
  916. pAdapter, pAdapter->BCRData.LocalHostBCRBigEndian, pAdapter->BCRData.IrmGeneration ) );
  917. //
  918. // Set up the constants that will be used
  919. //
  920. Destination.IA_Destination_Offset.Off_Low = INITIAL_REGISTER_SPACE_LO | NETWORK_CHANNELS_LOCATION;
  921. Destination.IA_Destination_Offset.Off_High = INITIAL_REGISTER_SPACE_HI;
  922. //
  923. // Acquire the lock and walk the list of remote nodes
  924. //
  925. ADAPTER_ACQUIRE_LOCK (pAdapter);
  926. //
  927. // Do one last check on LocalHostBCRBigEndian to ensure that no reset has cleared the bus
  928. //
  929. if ( (pAdapter->BCRData.LocalHostBCRBigEndian & BCR_VALID_BIG_ENDIAN) != BCR_VALID_BIG_ENDIAN)
  930. {
  931. //
  932. // Do not write an invalid bcr to remote nodes
  933. //
  934. ASSERT ((ADAPTER_TEST_FLAG (pAdapter, fADAPTER_InvalidGenerationCount) == TRUE) ||
  935. (BCR_TEST_FLAGS (pAdapter, BCR_Freed | BCR_BCRNeedsToBeFreed )== TRUE) );
  936. ADAPTER_RELEASE_LOCK (pAdapter);
  937. return NIC1394_STATUS_INVALID_GENERATION;
  938. }
  939. pAsyncWriteBCRMdl = pAdapter->BCRData.pAsyncWriteBCRMdl;
  940. fLockAcquired = TRUE;
  941. IrmGeneration = pAdapter->BCRData.IrmGeneration;
  942. pPdoListEntry = pAdapter->PDOList.Flink ;
  943. //
  944. // Now start the actual informing the remote nodes- asyncwrite algorithm
  945. //
  946. //
  947. // Since the loop can be broken in the middle of the while loop. the code
  948. // keeps track of lock acquire/release state
  949. //
  950. while (pPdoListEntry != &pAdapter->PDOList )
  951. {
  952. pRemoteNode = CONTAINING_RECORD (pPdoListEntry,
  953. REMOTE_NODE,
  954. linkPdo);
  955. //
  956. //Ref the remote node for the Asnyc Operation.
  957. // In case of failure, Dereference happens at the end of the function
  958. //
  959. nicReferenceRemoteNode (pRemoteNode, InformAllRemoteNodesOfBCM);
  960. fReferencedCurrentRemoteNode = TRUE;
  961. ADAPTER_RELEASE_LOCK (pAdapter);
  962. fLockAcquired = FALSE;
  963. //
  964. // First check if we are still in the same generation.
  965. //
  966. if (pAdapter->Generation != IrmGeneration)
  967. {
  968. NdisStatus = NIC1394_STATUS_INVALID_GENERATION;
  969. TRACE( TL_T, TM_Bcm, ( " nicInformAllRemoteNodesOfBCM Generation Incorrect New Gen %x, Old Gen ",
  970. pAdapter->Generation , IrmGeneration));
  971. break;
  972. }
  973. if (ADAPTER_TEST_FLAG(pAdapter, fADAPTER_LowPowerState) == TRUE)
  974. {
  975. //
  976. // As all BCMalgorithms are serialized and as Set Low Power State waits for BCM_InProgress
  977. // to be cleared, we should not hit this assert.
  978. //
  979. ASSERT (ADAPTER_TEST_FLAG(pAdapter, fADAPTER_LowPowerState) == FALSE);
  980. break;
  981. }
  982. TRACE( TL_V, TM_Bcm, ( " BCR %x, Mdl %x, IrmGeneration %x" ,
  983. pAdapter->BCRData.LocalHostBCRBigEndian,
  984. pAsyncWriteBCRMdl,
  985. IrmGeneration ) );
  986. NdisStatus = nicAsyncWrite_Synch( pRemoteNode,
  987. Destination, // Address to write to
  988. sizeof(NETWORK_CHANNELSR), // Bytes to write
  989. sizeof(NETWORK_CHANNELSR), // Block size of write
  990. 0 , //fulFlags, // Flags pertinent to write
  991. pAsyncWriteBCRMdl , // Destination buffer
  992. IrmGeneration , // Generation as known by driver
  993. &NtStatus);
  994. if (NdisStatus != NDIS_STATUS_SUCCESS)
  995. {
  996. //
  997. // Break out if the generation has changed or there are no more nodes left
  998. //
  999. if (NtStatus == STATUS_INVALID_GENERATION ||
  1000. BCR_TEST_FLAG (pAdapter, BCR_LastNodeRemoved) )
  1001. {
  1002. TRACE( TL_V, TM_Bcm, ( " nicAsyncWrite_Synch FAILED Status %x. Aborting ", NtStatus) );
  1003. nicBCMAbort (pAdapter, pRemoteNode);
  1004. break;
  1005. }
  1006. }
  1007. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1008. fLockAcquired = TRUE;
  1009. //
  1010. // If the irps succeed and then the deref happens , else it happens below
  1011. //
  1012. pPdoListEntry = ListNext (pPdoListEntry);
  1013. nicDereferenceRemoteNode (pRemoteNode , InformAllRemoteNodesOfBCM );
  1014. fReferencedCurrentRemoteNode = FALSE;
  1015. } // end of while loop while (pPdoListEntry != &pAdapter->PDOList )
  1016. //
  1017. // Clear the Informing remote nodes flag and release the lock
  1018. //
  1019. if (fLockAcquired == FALSE)
  1020. {
  1021. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1022. }
  1023. BCR_CLEAR_FLAG (pAdapter, BCR_InformingRemoteNodes);
  1024. ADAPTER_RELEASE_LOCK (pAdapter);
  1025. //
  1026. // Dereference the ref made in the beginning of the function
  1027. //
  1028. if (fReferencedCurrentRemoteNode == TRUE)
  1029. {
  1030. nicDereferenceRemoteNode (pRemoteNode , InformAllRemoteNodesOfBCM );
  1031. }
  1032. TRACE( TL_T, TM_Bcm, ( "<== nicInformAllRemoteNodesOfBCM (always returns success) Status %x", NdisStatus ) );
  1033. NdisStatus = NDIS_STATUS_SUCCESS; // No failure
  1034. return NdisStatus;
  1035. }
  1036. NDIS_STATUS
  1037. nicInitializeBroadcastChannelRegister (
  1038. PADAPTERCB pAdapter
  1039. )
  1040. // Function Description:
  1041. // This function allocates address range for the BCR with its own MDL and data.
  1042. // Allocates an MDL for the time when we try to read other node's BCR
  1043. // Initializes the IRM_BCR
  1044. //
  1045. // The Caller is expected to free the BCR in case this function fails.
  1046. //
  1047. // Return Value:
  1048. // Succss - if the IRP succeeds
  1049. //
  1050. //
  1051. //
  1052. {
  1053. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1054. PULONG pBCRBuffer = NULL;
  1055. PMDL pBCRMdl = NULL;
  1056. ADDRESS_OFFSET Required1394Offset;
  1057. ULONG AddressesReturned;
  1058. ADDRESS_RANGE BCRAddressRange;
  1059. HANDLE hAddressRange;
  1060. ULONG LocalNodeNumber;
  1061. PMDL pRemoteBCRMdl = NULL;
  1062. PMDL pAsyncWriteBCRMdl = NULL;
  1063. TRACE( TL_T, TM_Bcm, ( "==>nicInitializeBroadcastChannelRegister Adapter %x" , pAdapter ) );
  1064. do
  1065. {
  1066. BCR_CLEAR_ALL_FLAGS (pAdapter);
  1067. //
  1068. //Initialize the Local Host's BCR
  1069. //
  1070. pAdapter->BCRData.LocalHostBCRBigEndian = BCR_IMPLEMENTED_BIG_ENDIAN;
  1071. //
  1072. // Get an MDL that describes this buffer
  1073. //
  1074. if (pAdapter->BCRData.pLocalBCRMdl == NULL)
  1075. {
  1076. NdisStatus = nicGetMdl (sizeof(NETWORK_CHANNELSR),
  1077. &pAdapter->BCRData.LocalHostBCRBigEndian,
  1078. &pBCRMdl ) ;
  1079. if (pBCRMdl == NULL)
  1080. {
  1081. TRACE( TL_A, TM_Bcm, ( " nicInitializeBroadcastChannelRegister IoAllocateMdl FAILED" ) );
  1082. NdisStatus = NDIS_STATUS_RESOURCES;
  1083. break;
  1084. }
  1085. }
  1086. else
  1087. {
  1088. //
  1089. // We already have an MDL
  1090. //
  1091. pBCRMdl = pAdapter->BCRData.pLocalBCRMdl;
  1092. }
  1093. //
  1094. // Allocate an Address Range at the BCR offset and use the MDL as its descriptor
  1095. //
  1096. TRACE( TL_V, TM_Bcm, ( " LocalHostBCR Mdl %x", pBCRMdl ) );
  1097. Required1394Offset.Off_Low = INITIAL_REGISTER_SPACE_LO | NETWORK_CHANNELS_LOCATION;
  1098. Required1394Offset.Off_High = INITIAL_REGISTER_SPACE_HI ;
  1099. pAdapter->BCRData.AddressRangeContext.pMdl = pBCRMdl ;
  1100. //
  1101. // There is no reference for this address range. The last outgoing Remote Node will simply Free it.
  1102. //
  1103. NdisStatus = nicAllocateAddressRange_Synch ( pAdapter,
  1104. pBCRMdl,
  1105. 0, // Little Endian
  1106. sizeof (ULONG), // length
  1107. 0, // maxsegmentsize
  1108. ACCESS_FLAGS_TYPE_READ | ACCESS_FLAGS_TYPE_WRITE | ACCESS_FLAGS_TYPE_LOCK | ACCESS_FLAGS_TYPE_BROADCAST,
  1109. NOTIFY_FLAGS_AFTER_READ | NOTIFY_FLAGS_AFTER_WRITE | NOTIFY_FLAGS_AFTER_LOCK ,
  1110. nicBCRAccessedCallback,
  1111. (PVOID)pAdapter,
  1112. Required1394Offset,
  1113. NULL,
  1114. NULL,
  1115. &AddressesReturned,
  1116. &BCRAddressRange,
  1117. &hAddressRange
  1118. );
  1119. if (NdisStatus != NDIS_STATUS_SUCCESS)
  1120. {
  1121. TRACE( TL_A, TM_Bcm, ( " nicInitializeBroadcastChannelRegister nicAllocateAddressRange_Synch FAILED" ) );
  1122. ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
  1123. break;
  1124. }
  1125. TRACE( TL_V, TM_Bcm, ( " nicInitializeBroadcastChannelRegister nicAllocateAddressRange_Synch Succeeded" ) );
  1126. TRACE( TL_V, TM_Bcm, ( " &BCR Address Range %x, AddressesReturned %x, hAddressRange %x",
  1127. &BCRAddressRange, AddressesReturned, hAddressRange) );
  1128. NdisStatus = nicGetMdl (sizeof(NETWORK_CHANNELSR),
  1129. &pAdapter->BCRData.RemoteBCRMdlData,
  1130. &pRemoteBCRMdl);
  1131. if (NdisStatus != NDIS_STATUS_SUCCESS || pRemoteBCRMdl == NULL)
  1132. {
  1133. TRACE( TL_V, TM_Bcm, ( " nicInitializeBroadcastChannelRegister : nicGetMdl FAILED " ) );
  1134. ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
  1135. break;
  1136. }
  1137. NdisStatus = nicGetMdl ( sizeof (pAdapter->BCRData.AsyncWriteBCRBigEndian),
  1138. &pAdapter->BCRData.AsyncWriteBCRBigEndian,
  1139. &pAsyncWriteBCRMdl );
  1140. if (NdisStatus != NDIS_STATUS_SUCCESS || pAsyncWriteBCRMdl == NULL)
  1141. {
  1142. TRACE( TL_V, TM_Bcm, ( " nicInitializeBroadcastChannelRegister : nicGetMdl FAILED " ) );
  1143. ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
  1144. break;
  1145. }
  1146. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1147. pAdapter->BCRData.AddressRangeContext.AddressRange = BCRAddressRange;
  1148. pAdapter->BCRData.AddressRangeContext.AddressesReturned = AddressesReturned;
  1149. pAdapter->BCRData.AddressRangeContext.hAddressRange = hAddressRange;
  1150. pAdapter->BCRData.pLocalBCRMdl = pBCRMdl; // points to the same MDL as pAdapter->BCRData.AddressRangeContext.pMdl
  1151. pAdapter->BCRData.pRemoteBCRMdl = pRemoteBCRMdl;
  1152. pAdapter->BCRData.pAsyncWriteBCRMdl = pAsyncWriteBCRMdl ;
  1153. pAdapter->BCRData.IRM_BCR.NC_One = 1;
  1154. pAdapter->BCRData.MakeCallWaitEvent.EventCode = Nic1394EventCode_InvalidEventCode;
  1155. NdisResetEvent (&pAdapter->BCRData.MakeCallWaitEvent.NdisEvent);
  1156. BCR_SET_FLAG (pAdapter, BCR_Initialized);
  1157. ADAPTER_RELEASE_LOCK (pAdapter);
  1158. } while (FALSE);
  1159. TRACE( TL_T, TM_Bcm, ( "<==nicInitializeBroadcastChannelRegister %x", NdisStatus ) );
  1160. return NdisStatus;
  1161. }
  1162. NDIS_STATUS
  1163. nicIsLocalHostTheIrm(
  1164. IN PADAPTERCB pAdapter,
  1165. OUT PBOOLEAN pfIsLocalHostIrm,
  1166. OUT PPTOPOLOGY_MAP ppTopologyMap,
  1167. OUT PNODE_ADDRESS pLocalHostAddress
  1168. )
  1169. // Function Description:
  1170. // This function figures out if the Local Host is the IRM.
  1171. // If a remote node is specified, it will use that Node, otherwise
  1172. // it will pick one from the adapter
  1173. // It gets the 1394 address, and the topologyMap. It then figures out
  1174. // if the local host's node address makes it the IRM
  1175. //
  1176. // Arguments
  1177. //
  1178. // pAdapter - Local Host,
  1179. // pfIsLocalHostIrm, - TRUE if Local Host Is IRM, False - otherwise
  1180. // ppTopologyMap, - TopologyMap used to determine if this is the IRM
  1181. // pLocalHostAddress - LocalHost Address discovered by querying the local host
  1182. //
  1183. //
  1184. // Return Value:
  1185. //
  1186. //
  1187. //
  1188. //
  1189. {
  1190. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1191. PVOID pTopologyBuffer = NULL;
  1192. PREMOTE_NODE pRemoteNode = NULL;
  1193. NODE_ADDRESS LocalNodeAddress;
  1194. PTOPOLOGY_MAP pTopologyMap = NULL;
  1195. PTOPOLOGY_MAP pOldTopologyMap = NULL;
  1196. ULONG Length = DEFAULT_TOPOLOGY_MAP_LENGTH;
  1197. TRACE( TL_T, TM_Bcm, ( "==>nicIsLocalHostTheIrm ") );
  1198. ASSERT (pfIsLocalHostIrm != NULL);
  1199. ASSERT (ppTopologyMap!=NULL);
  1200. ASSERT (pLocalHostAddress != NULL);
  1201. do
  1202. {
  1203. //
  1204. // get the address of the local node/
  1205. //
  1206. NdisStatus = nicGet1394AddressFromDeviceObject( pAdapter->pNextDeviceObject,
  1207. &LocalNodeAddress,
  1208. USE_LOCAL_NODE );
  1209. if (NDIS_STATUS_SUCCESS != NdisStatus)
  1210. {
  1211. BREAK( TM_Bcm, ( "GetAddrFrom DevObj (Local) FAILED" ) );
  1212. }
  1213. TRACE ( TL_I, TM_Bcm, ( " NODE_ADDRESS Node Address %x, Number %x",LocalNodeAddress, LocalNodeAddress.NA_Node_Number ) );
  1214. ASSERT (LocalNodeAddress.NA_Bus_Number == 0x3ff);
  1215. //
  1216. // Now we get the TopologyMap to find out if LocalHostIsIrm. We could fail the 1st Irp because our buffer is not
  1217. // big enough, hence the do .. while loop
  1218. //
  1219. do
  1220. {
  1221. pTopologyBuffer = ALLOC_NONPAGED (Length , MTAG_DEFAULT);
  1222. if (pTopologyBuffer ==NULL)
  1223. {
  1224. NdisStatus = NDIS_STATUS_RESOURCES;
  1225. break;
  1226. }
  1227. NdisStatus = nicGetLocalHostCSRTopologyMap (pAdapter,
  1228. &Length,
  1229. pTopologyBuffer );
  1230. if (NdisStatus == NDIS_STATUS_INVALID_LENGTH)
  1231. {
  1232. FREE_NONPAGED(pTopologyBuffer);
  1233. }
  1234. } while (NdisStatus == NDIS_STATUS_INVALID_LENGTH);
  1235. TRACE ( TL_V, TM_Bcm, ( " TopologyBuffer %x",pTopologyBuffer) );
  1236. pTopologyMap = (PTOPOLOGY_MAP)pTopologyBuffer;
  1237. TRACE( TL_I, TM_Bcm, ( " Top node count = %x ", pTopologyMap->TOP_Node_Count) );
  1238. } while (FALSE);
  1239. if (NdisStatus == NDIS_STATUS_SUCCESS)
  1240. {
  1241. //
  1242. // Now update all the output parameters. The Top_Node_count can be zero.
  1243. //
  1244. if ( LocalNodeAddress.NA_Node_Number == (pTopologyMap->TOP_Node_Count -1 ) ||
  1245. pTopologyMap->TOP_Node_Count == 0)
  1246. {
  1247. *pfIsLocalHostIrm = TRUE;
  1248. BCR_SET_FLAG (pAdapter, BCR_LocalHostIsIRM);
  1249. }
  1250. else
  1251. {
  1252. *pfIsLocalHostIrm = FALSE;
  1253. }
  1254. //
  1255. // If there is a topology map in the pointer, then it means that the topology map from
  1256. // the previous query. Free it first.
  1257. //
  1258. if ( *ppTopologyMap != NULL)
  1259. {
  1260. FREE_NONPAGED(*ppTopologyMap);
  1261. }
  1262. *ppTopologyMap = pTopologyMap;
  1263. *pLocalHostAddress = LocalNodeAddress;
  1264. }
  1265. TRACE( TL_T, TM_Bcm, ( "<==nicIsLocalHostTheIrm %x NdisStatus %x",*pfIsLocalHostIrm , NdisStatus ) );
  1266. return NdisStatus;
  1267. }
  1268. NDIS_STATUS
  1269. nicLocalHostIsIrm(
  1270. IN PADAPTERCB pAdapter
  1271. )
  1272. // Function Description:
  1273. //
  1274. //
  1275. //
  1276. //
  1277. // Arguments
  1278. // pAdapter - Local adapter object
  1279. // pRemoteNode - Node to be used for submitting IRPs to the Busdriver
  1280. //
  1281. //
  1282. // Return Value:
  1283. //
  1284. //
  1285. //
  1286. //
  1287. {
  1288. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1289. ULONG Channel = BROADCAST_CHANNEL;
  1290. ULONG TimeOut = 5;
  1291. ULONG LocalHostBCRLittleEndian;
  1292. ULONG WaitBackOff = ONE_SEC;
  1293. TRACE( TL_T, TM_Bcm, ( "==>nicLocalHostIsIrm Adapter %x ", pAdapter) );
  1294. //
  1295. // Allocate BCM channel = 31
  1296. //
  1297. Channel = BROADCAST_CHANNEL;
  1298. do
  1299. {
  1300. //
  1301. // If the channel is already allocated. Do not try and reallocate it.
  1302. //
  1303. if (BCR_TEST_FLAG(pAdapter,BCR_ChannelAllocated) == TRUE)
  1304. {
  1305. ASSERT (pAdapter->BCRData.IRM_BCR.NC_Channel == Channel);
  1306. NdisStatus = NDIS_STATUS_SUCCESS;
  1307. break;
  1308. }
  1309. //
  1310. // Retry a 5 times to allocate the channel
  1311. //
  1312. while (NdisStatus != NDIS_STATUS_SUCCESS && TimeOut-- != 0 )
  1313. {
  1314. NdisStatus = nicAllocateChannel (pAdapter,
  1315. Channel,
  1316. NULL);
  1317. if (NdisStatus != NDIS_STATUS_SUCCESS )
  1318. {
  1319. TRACE( TL_V, TM_Bcm, ( " nicNodeIsIRMAlgorithm: nicallocateChannel Failed. Sleep and try again") );
  1320. if (BCR_TEST_FLAG (pAdapter, BCR_BCRNeedsToBeFreed |BCR_NewNodeArrived) == TRUE ||
  1321. ADAPTER_TEST_FLAG (pAdapter,fADAPTER_InvalidGenerationCount) == TRUE)
  1322. {
  1323. break;
  1324. }
  1325. //
  1326. // Sleep for 1 Sec and try again.
  1327. //
  1328. NdisMSleep (WaitBackOff);
  1329. WaitBackOff = WaitBackOff << 1;
  1330. //
  1331. // Someother node has alredy asked for the BroadcastChannel .Force it out.
  1332. // Eventually will need to allocate a new channel.
  1333. //
  1334. }
  1335. }
  1336. } while (FALSE);
  1337. if (NdisStatus == NDIS_STATUS_SUCCESS)
  1338. {
  1339. //
  1340. // Update our BCR and inform all the remote Nodes
  1341. //
  1342. TRACE( TL_V, TM_Bcm, ( " nicLocalHostIsIrm: nicallocateChannel succeeded %x", Channel) );
  1343. ASSERT (Channel == BROADCAST_CHANNEL);
  1344. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1345. //
  1346. // Update State - if no reset has occurred
  1347. //
  1348. if (ADAPTER_TEST_FLAG (pAdapter, fADAPTER_InvalidGenerationCount) == FALSE)
  1349. {
  1350. BCR_SET_FLAG (pAdapter, BCR_ChannelAllocated);
  1351. BCR_SET_FLAG (pAdapter, BCR_InformingRemoteNodes);
  1352. pAdapter->BCRData.IrmGeneration = pAdapter->Generation;
  1353. pAdapter->BCRData.LocalHostBCRBigEndian = 0;
  1354. NdisZeroMemory (&pAdapter->BCRData.IRM_BCR, sizeof (NETWORK_CHANNELSR) );
  1355. //
  1356. // Update the BCR
  1357. //
  1358. pAdapter->BCRData.IRM_BCR.NC_Channel = Channel; // bits 0-5
  1359. pAdapter->BCRData.IRM_BCR.NC_Valid = 1; // bit 30
  1360. pAdapter->BCRData.IRM_BCR.NC_One = 1; // bit 31
  1361. pAdapter->BCRData.LocallyAllocatedChannel = Channel;
  1362. }
  1363. else
  1364. {
  1365. TRACE( TL_V, TM_Bcm, ( " nicLocalHostIsIrm: Reset after nicallocateChannel succeeded %x", Channel) );
  1366. pAdapter->BCRData.IRM_BCR.NC_Valid = 0; // bit 30
  1367. }
  1368. TRACE( TL_V, TM_Bcm, ( " nicLocalHostIsIrm: IRM_BCR Updated to %x ",pAdapter->BCRData.IRM_BCR) );
  1369. //
  1370. // Now convert LocalHost BCR so it can be read over the network
  1371. //
  1372. pAdapter->BCRData.LocalHostBCRBigEndian = SWAPBYTES_ULONG (*(PULONG)(&pAdapter->BCRData.IRM_BCR));
  1373. TRACE( TL_V, TM_Bcm, ( " nicLocalHostIsIrm: LocalHost BCR Updated to %x ",pAdapter->BCRData.LocalHostBCRBigEndian ) );
  1374. //
  1375. // Capture the value so that we can async write it to other nodes in the network.
  1376. // this will protect us from a Reset that can clear LocalHostBCRBigEndian
  1377. //
  1378. pAdapter->BCRData.AsyncWriteBCRBigEndian = pAdapter->BCRData.LocalHostBCRBigEndian;
  1379. ADAPTER_RELEASE_LOCK (pAdapter);
  1380. if ((pAdapter->BCRData.LocalHostBCRBigEndian & BCR_VALID_BIG_ENDIAN) == (BCR_VALID_BIG_ENDIAN))
  1381. {
  1382. //
  1383. // Tell all the other nodes about the BCM and the channel.
  1384. // This will abort the process if a reset happenned just prior
  1385. // to the channel allocation.
  1386. //
  1387. nicInformAllRemoteNodesOfBCM (pAdapter);
  1388. }
  1389. }
  1390. else
  1391. {
  1392. TRACE( TL_A, TM_Bcm, ( " nicLocalHostIsIrm - Failed RESET THE BUS") );
  1393. NIC1394_LOG_PKT(pAdapter,
  1394. NIC1394_LOGFLAGS_BCM_IS_IRM_TIMEOUT,
  1395. pAdapter->Generation,
  1396. 0,
  1397. &NdisStatus,
  1398. sizeof (NDIS_STATUS));
  1399. //
  1400. // If the generation is invalid or we need to bail out of the BCM for some reason,
  1401. // then simply exit. Otherwise reset the bus
  1402. //
  1403. if (! (BCR_TEST_FLAG (pAdapter, BCR_BCRNeedsToBeFreed |BCR_NewNodeArrived) == TRUE ||
  1404. ADAPTER_TEST_FLAG (pAdapter,fADAPTER_InvalidGenerationCount) == TRUE) )
  1405. {
  1406. nicBCMReset(pAdapter);
  1407. }
  1408. }
  1409. TRACE( TL_T, TM_Bcm, ( "<==nicLocalHostIsIrm%x ",NdisStatus ) );
  1410. return NdisStatus;
  1411. }
  1412. NDIS_STATUS
  1413. nicLocalHostIsNotIrm (
  1414. IN PADAPTERCB pAdapter,
  1415. IN ULONG BCMGeneration
  1416. )
  1417. // Function Description:
  1418. // This function goes through all the remote nodes
  1419. // and attempts to read their broadcast channels register
  1420. // If the Read itself fails - means the IRM does not implement the BCR - we issue a reset
  1421. // If the generation is wrong - means the bus has been reset and we need to abort
  1422. // If the read succeeds, but BCR's MSB is not set - we issue a reset
  1423. //
  1424. // If the read succeeds and valid bit is not set, we retry for 5 min. waiting for the Valid bit
  1425. // This involves i) attempt to read the (IRM) remote Node's BCR
  1426. // If Read does not find a BCR,
  1427. // Sleep
  1428. // Check to see if RemoteNode Has written to Our BCR
  1429. // If RemoteNode has NOT written to our BCR, then go back to i)
  1430. //
  1431. //
  1432. // This function can be optimized into a do while loop. However for
  1433. // the sake of simplicity and blindly following the BCM algorithm, it is
  1434. // spread out.
  1435. //
  1436. // Arguments
  1437. //
  1438. //
  1439. //
  1440. // Return Value:
  1441. //
  1442. //
  1443. //
  1444. //
  1445. {
  1446. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1447. PLIST_ENTRY pPdoListEntry = NULL;
  1448. PREMOTE_NODE pIrmRemoteNode = NULL;
  1449. PMDL pRemoteBCRMdl = NULL;
  1450. ULONG Generation;
  1451. BOOLEAN fRemoteNodeBCRIsValid = FALSE;
  1452. BOOLEAN fNeedToReset = FALSE;
  1453. BOOLEAN fDidTheBusReset = FALSE;
  1454. BOOLEAN fExit = FALSE;
  1455. ULONG TimeOut;
  1456. ULONG LocalHostBCRLittleEndian , RemoteNodeBCRLittleEndian;
  1457. NETWORK_CHANNELSR* pBCR = NULL;
  1458. BOOLEAN fLocalHostBCRIsValid = FALSE;
  1459. ULONG BackOffWait = ONE_SEC;
  1460. TRACE( TL_T, TM_Bcm, ( "==>nicLocalHostIsNotIrm " ) );
  1461. ASSERT (pAdapter->BCRData.pTopologyMap != NULL);
  1462. do
  1463. {
  1464. //
  1465. // First do the wait - BCM algorithm requires this
  1466. //
  1467. pBCR = (NETWORK_CHANNELSR*)(&LocalHostBCRLittleEndian) ;
  1468. NdisStatus = nicLocalNotIrmMandatoryWait (pAdapter,
  1469. BCMGeneration,
  1470. pBCR);
  1471. if (NdisStatus == NDIS_STATUS_SUCCESS)
  1472. {
  1473. fLocalHostBCRIsValid = TRUE;
  1474. TRACE( TL_V, TM_Bcm, ( " BCR written to during Mandatory Wait ") );
  1475. break;
  1476. }
  1477. else
  1478. {
  1479. fLocalHostBCRIsValid = FALSE;
  1480. }
  1481. //
  1482. // Initialize variables again and move on
  1483. //
  1484. pBCR = NULL;
  1485. LocalHostBCRLittleEndian = 0;
  1486. //
  1487. // Our BCR has not been updated. Lets go and find the IRM's BCR. we will loop until we
  1488. // i)either find the IRM, ii)timeout and then reset, or iii)find a new generation and abort
  1489. //
  1490. //
  1491. NdisStatus = nicFindIrmAmongRemoteNodes (pAdapter, BCMGeneration, &pIrmRemoteNode);
  1492. if (NdisStatus != NDIS_STATUS_SUCCESS )
  1493. {
  1494. //
  1495. // If there is NO IRM , it means we have not been notified of its addition.
  1496. //
  1497. TRACE( TL_V, TM_Bcm, ( " nicLocalHostIsNotIrm : nicFindIrmAmongRemoteNodes FAILED " ) );
  1498. //
  1499. // One of two things can have caused this:
  1500. // 1. the bus has been reset - break out
  1501. // 2. we have not been notified of a new node - exit
  1502. //
  1503. if (NdisStatus == NIC1394_STATUS_INVALID_GENERATION)
  1504. {
  1505. TRACE( TL_V, TM_Bcm, ( " Invalid Generation, the bus has been reset ") );
  1506. NdisStatus = NtStatusToNdisStatus(NIC1394_STATUS_INVALID_GENERATION);
  1507. break;
  1508. }
  1509. //
  1510. // We have not been able to find the IRM and have timed out.
  1511. // If the BCR is not freed, then abort and Reset
  1512. //
  1513. if (BCR_TEST_FLAGS (pAdapter, (BCR_Freed | BCR_BCRNeedsToBeFreed) == FALSE))
  1514. {
  1515. TRACE( TL_I, TM_Bcm, ( " nicLocalHostIsNotIrm - Could Not Find IRM RESETTING ") );
  1516. fNeedToReset = TRUE;
  1517. }
  1518. break;
  1519. }
  1520. ASSERT (pIrmRemoteNode != NULL)
  1521. //
  1522. // We will now wait for the BCM to come up and initialize its BCR.
  1523. // We will attempt to read it 5 times
  1524. //
  1525. pRemoteBCRMdl = pAdapter->BCRData.pRemoteBCRMdl;
  1526. pAdapter->BCRData.RemoteBCRMdlData = 0;
  1527. TimeOut = 5; // arbitrary
  1528. while (TimeOut-- != 0 )
  1529. {
  1530. NdisStatus = nicReadIrmBcr ( pIrmRemoteNode,
  1531. pRemoteBCRMdl,
  1532. BCMGeneration,
  1533. &fDidTheBusReset);
  1534. //
  1535. // First check to see if no reset has happenned while we were reading the BCR
  1536. //
  1537. if ( fDidTheBusReset == TRUE ||
  1538. (ADAPTER_TEST_FLAG (pAdapter, fADAPTER_InvalidGenerationCount) == TRUE))
  1539. {
  1540. //
  1541. // A reset has gone through under us or the IRM has gone.
  1542. // We need to abort this round of the BCM process
  1543. //
  1544. TRACE( TL_V, TM_Bcm, ( " nicLocalHostIsNotIrm : nicReadIrmBcr FAILED Invalid generation ") );
  1545. NdisStatus = NDIS_STATUS_FAILURE;
  1546. break;
  1547. }
  1548. //
  1549. // Now check for Success and see if the BCR is implemented by the IRM
  1550. //
  1551. if (NdisStatus == NDIS_STATUS_SUCCESS )
  1552. {
  1553. TRACE( TL_V, TM_Bcm, ( " BCR is %x ", pAdapter->BCRData.RemoteBCRMdlData ) );
  1554. //
  1555. // At this point we have a guarantee that nicReadIrmBcr succeeded. If the IRM does not implement the BCR
  1556. // at all, there is no point in retrying, reset the bus and become the IRM
  1557. //
  1558. RemoteNodeBCRLittleEndian = SWAPBYTES_ULONG (pAdapter->BCRData.RemoteBCRMdlData);
  1559. pBCR = (NETWORK_CHANNELSR*)(&RemoteNodeBCRLittleEndian );
  1560. if ( IS_A_BCR (pBCR) == FALSE && NdisStatus == NDIS_STATUS_SUCCESS)
  1561. {
  1562. fNeedToReset = TRUE;
  1563. TRACE( TL_I, TM_Bcm, ( " nicLocalHostIsNotIrm : IRM does not implement the BCR %x RESETTING",RemoteNodeBCRLittleEndian ) );
  1564. break;
  1565. }
  1566. //
  1567. // The remote node implements the BCR, so now lets see if it has set up the broadcast channel by looking
  1568. // at the valid bit.
  1569. //
  1570. if (BCR_IS_VALID (pBCR) ==TRUE)
  1571. {
  1572. //
  1573. // We've succeeded and have received a Broadcast Channel. Update data structures and exit.
  1574. //
  1575. ULONG BCMCh;
  1576. fRemoteNodeBCRIsValid = TRUE;
  1577. BCMCh = pBCR->NC_Channel;
  1578. TRACE( TL_V, TM_Bcm, ( " BCM Channel %x ", BCMCh ) );
  1579. break;
  1580. }
  1581. //
  1582. // At this point we know that the IRM implements the BCR but has not set its valid bit yet.
  1583. // Lets sleep and give it som more time
  1584. //
  1585. pBCR = NULL;
  1586. RemoteNodeBCRLittleEndian = 0;
  1587. }
  1588. //
  1589. // Check to see if the Remote Node PDO is valid
  1590. //
  1591. if (REMOTE_NODE_TEST_FLAG(pIrmRemoteNode, PDO_Removed) )
  1592. {
  1593. fNeedToReset = TRUE;
  1594. fExit = TRUE;
  1595. }
  1596. //
  1597. // Remote Node's BCR is not up yet
  1598. // We need to sleep and retry to read the IRM's BCR in the
  1599. // hope that it will have allocated the
  1600. // broadcast channel by the time we read the register again.
  1601. //
  1602. NdisMSleep (BackOffWait);
  1603. BackOffWait = BackOffWait << 1;
  1604. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1605. if (BCR_TEST_FLAG (pAdapter, BCR_BCRNeedsToBeFreed) == FALSE )
  1606. {
  1607. LocalHostBCRLittleEndian = SWAPBYTES_ULONG (pAdapter->BCRData.LocalHostBCRBigEndian);
  1608. }
  1609. else
  1610. {
  1611. fExit = TRUE;
  1612. }
  1613. ADAPTER_RELEASE_LOCK (pAdapter);
  1614. //
  1615. // As Address range has been freed or the Remote Node is going away
  1616. // quietly exit the BCM algorithm
  1617. //
  1618. if (fExit== TRUE)
  1619. {
  1620. break;
  1621. }
  1622. //
  1623. // Let's read our own BCR and see if someone has written a valid BCR to it.
  1624. // Another thread will write to the LocalHost BCR
  1625. //
  1626. pBCR = (NETWORK_CHANNELSR*)(&LocalHostBCRLittleEndian);
  1627. //
  1628. // Check if the BCR is valid and that no reset has come through the in the Interim.
  1629. // The reset would have cleared the BCR_localHostBCRUpdated field
  1630. //
  1631. if ( BCR_IS_VALID (pBCR) == TRUE &&
  1632. ( BCR_TEST_FLAGS (pAdapter, BCR_LocalHostBCRUpdated ) == TRUE))
  1633. {
  1634. //
  1635. // We've succeeded. Update data structures and exit.
  1636. // The actual IRM BCR will have been updated in the BCRAccessed thread
  1637. // so we simply exit
  1638. //
  1639. ULONG BCMCh = pBCR->NC_Channel;
  1640. TRACE( TL_V, TM_Bcm, ( " BCM Channel After Backoff Wait%x ", BCMCh ) );
  1641. NdisStatus = NDIS_STATUS_SUCCESS;
  1642. fLocalHostBCRIsValid = TRUE;
  1643. fRemoteNodeBCRIsValid = FALSE;
  1644. break;
  1645. }
  1646. if (TimeOut == 0)
  1647. {
  1648. //
  1649. // We've waited, retried 5 times. The IRM has not implemented the BCM
  1650. // We need to wrest control by resetting the bus
  1651. //
  1652. // This happens when the remote node is still booting up.
  1653. //
  1654. TRACE( TL_I, TM_Bcm, ( " nicLocalHostIsNotIrm - TIMEOUT RESETTING") );
  1655. fNeedToReset = TRUE;
  1656. }
  1657. LocalHostBCRLittleEndian = 0;
  1658. pBCR = NULL;
  1659. } //while (Timeout-- != 0 )
  1660. } while (FALSE);
  1661. //
  1662. // Now do the clean up work and updating of data structures that needs to be done at the end of the BCM
  1663. // algorithm
  1664. //
  1665. nicLocalHostIsNotIrmPost (pAdapter,
  1666. pIrmRemoteNode,
  1667. fNeedToReset,
  1668. fRemoteNodeBCRIsValid ,
  1669. fLocalHostBCRIsValid ,
  1670. fDidTheBusReset,
  1671. pBCR );
  1672. //
  1673. // If the IRM was successfuly found, then it was referenced as well. We dereference it now
  1674. // Ref was made in FindIRmAmongstRemoteNode
  1675. //
  1676. if (pIrmRemoteNode != NULL)
  1677. {
  1678. nicDereferenceRemoteNode (pIrmRemoteNode, FindIrmAmongRemoteNodes);
  1679. }
  1680. TRACE( TL_T, TM_Bcm, ( "<==nicLocalHostIsNotIrm Status %x", NdisStatus ) );
  1681. return NdisStatus;
  1682. }
  1683. VOID
  1684. nicLocalHostIsNotIrmPost (
  1685. PADAPTERCB pAdapter,
  1686. PREMOTE_NODE pIrmRemoteNode,
  1687. BOOLEAN fNeedToReset,
  1688. BOOLEAN fRemoteNodeBCRIsValid ,
  1689. BOOLEAN fLocalHostBCRIsValid ,
  1690. BOOLEAN fDidTheBusReset,
  1691. NETWORK_CHANNELSR* pBCR
  1692. )
  1693. /*++
  1694. Routine Description:
  1695. This routine does the post processing after the Local Host Is Not Irm has completed.
  1696. It i)resets the bus if necessary, ii) Updates the BCR if pBCR has a valid Value
  1697. The Boolean Variables passed in indicate the state of the BCM algorithm
  1698. Arguments:
  1699. pAdapter - pAdapter in question,
  1700. pIrmRemoteNode - RemoteNode that is the IRM,
  1701. fNeedToReset - Does the bus need to be reset,
  1702. fRemoteNodeBCRIsValid - Is the RemoteNodeBCR Valid ,
  1703. fLocalHostBCRIsValid - LocalHost BCR Valid,
  1704. fDidTheBusReset - Did the bus reset during this iteration of the BCM algorithm,
  1705. pBCR - the BCR that was passed in
  1706. Return Value:
  1707. --*/
  1708. {
  1709. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1710. TRACE( TL_T, TM_Bcm, ( "==> nicLocalHostIsNotIrmPost pAdapter %x, pIrm %x, fNeedToReset%x, fRemoteNodeBCRIsValid %x, fLocalHostBCRIsValid %x, fDidTheBusReset,%x, pBCR %x",
  1711. pAdapter, pIrmRemoteNode, fNeedToReset, fRemoteNodeBCRIsValid , fLocalHostBCRIsValid, fDidTheBusReset, pBCR) );
  1712. do
  1713. {
  1714. if (fRemoteNodeBCRIsValid == TRUE || fLocalHostBCRIsValid == TRUE)
  1715. {
  1716. //
  1717. // The BCM algorithm has succeeded. We need to update our internal record of
  1718. // the IRM's BCR. In both ocde (local and Remote) the pBCR points to the BCR in little
  1719. // endian
  1720. //
  1721. ASSERT (fNeedToReset == FALSE);
  1722. //
  1723. // One final check
  1724. //
  1725. ASSERT (pBCR!= NULL);
  1726. ASSERT (pBCR->NC_Valid == 1);
  1727. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1728. pAdapter->BCRData.IRM_BCR.NC_One = 1;
  1729. pAdapter->BCRData.IRM_BCR.NC_Valid = 1;
  1730. pAdapter->BCRData.IRM_BCR.NC_Channel = pBCR->NC_Channel;
  1731. ASSERT ( BCR_IS_VALID (&pAdapter->BCRData.IRM_BCR) == TRUE);
  1732. TRACE( TL_V, TM_Bcm, ( " Updated IRM_BCM with %x ",pAdapter->BCRData.IRM_BCR ) );
  1733. ADAPTER_RELEASE_LOCK (pAdapter);
  1734. ASSERT (fDidTheBusReset == FALSE);
  1735. ASSERT (fNeedToReset == FALSE);
  1736. break;
  1737. }
  1738. if ( fNeedToReset )
  1739. {
  1740. //
  1741. // If our BCR's are invalid and the IRM has gone away
  1742. // OR if there has been a timeout, we should reset the
  1743. // bus to force a new BCM
  1744. //
  1745. BOOLEAN NoRemoteNodes = IsListEmpty(&pAdapter->PDOList) ;
  1746. //
  1747. // Reset only if there are remote nodes present
  1748. //
  1749. if (NoRemoteNodes == FALSE)
  1750. {
  1751. TRACE( TL_V, TM_Bcm, ("fNeedToReset %x, RemoteNode %p\n",fNeedToReset,pIrmRemoteNode));
  1752. nicBCMReset( pAdapter);
  1753. }
  1754. ASSERT (fRemoteNodeBCRIsValid == FALSE);
  1755. ASSERT (fDidTheBusReset == FALSE);
  1756. break;
  1757. }
  1758. } while (FALSE);
  1759. TRACE( TL_T, TM_Bcm, ( "<== nicLocalHostIsNotIrmPost ") );
  1760. }
  1761. NDIS_STATUS
  1762. nicLocalNotIrmMandatoryWait (
  1763. IN PADAPTERCB pAdapter,
  1764. IN ULONG BCMGeneration,
  1765. OUT NETWORK_CHANNELSR* pBCR
  1766. )
  1767. // Function Description:
  1768. // This function implements the mandatory portion
  1769. // of the local host is not Irm protion of the BCM algorithm
  1770. //
  1771. // Sleeps and expects that a IRM will have written to its BCR
  1772. // by the time it wakes up
  1773. //
  1774. // Arguments
  1775. // pAdapter
  1776. //
  1777. //
  1778. // Return Value:
  1779. //
  1780. //
  1781. {
  1782. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1783. ULONG HighestNode = pAdapter->BCRData.pTopologyMap->TOP_Node_Count-1;
  1784. ULONG LocalNodeNumber = pAdapter->BCRData.LocalNodeNumber;
  1785. ULONG TimeOut = 0;
  1786. ULONG Generation;
  1787. ULONG LocalHostBCRLittleEndian = 0;
  1788. ASSERT (pBCR != NULL);
  1789. TRACE( TL_T, TM_Bcm, ( "==> nicLocalNotIrmMandatoryWait pAdapter %x, HighNode %x, LocalNode %x, BCMGeneration %x",
  1790. pAdapter, HighestNode, LocalNodeNumber, BCMGeneration) );
  1791. //
  1792. // BCM algorithm states that node must wait 15ms * IRM_ID - candidate_ID
  1793. //
  1794. TimeOut = HighestNode - LocalNodeNumber;
  1795. do
  1796. {
  1797. if (TimeOut > 64)
  1798. {
  1799. ASSERT (TimeOut <= 64);
  1800. NdisStatus = NDIS_STATUS_FAILURE;
  1801. break;
  1802. }
  1803. //
  1804. // Store the generation as a reference point. The moment the bus is reset, the gen count
  1805. // will increment and we will need to bail out of this round of the BCM process
  1806. //
  1807. if (BCMGeneration != pAdapter->Generation)
  1808. {
  1809. TRACE( TL_V, TM_Bcm, ( " nicLocalHostIsNotIrm : Generations do not match " ) );
  1810. NdisStatus = NIC1394_STATUS_INVALID_GENERATION;
  1811. break;
  1812. }
  1813. //
  1814. // Sleep for 15ms * IRM_ID - CandidateNodeID
  1815. //
  1816. NdisMSleep (TimeOut * 15000);
  1817. //
  1818. // First let's read our own BCR and see if someone has written a valid BCR to it.
  1819. //
  1820. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1821. LocalHostBCRLittleEndian = pAdapter->BCRData.LocalHostBCRBigEndian;
  1822. ADAPTER_RELEASE_LOCK (pAdapter);
  1823. //
  1824. // Copy it over to what pBCR points to
  1825. //
  1826. LocalHostBCRLittleEndian = SWAPBYTES_ULONG (LocalHostBCRLittleEndian );
  1827. *pBCR = (*(NETWORK_CHANNELSR*)&LocalHostBCRLittleEndian );
  1828. if ( BCR_IS_VALID(pBCR)==TRUE)
  1829. {
  1830. //
  1831. // We've succeeded. Update data structures and exit. Nothing for us
  1832. // to do as the other thread updates everything
  1833. //
  1834. ULONG BCMChannel = -1;
  1835. NdisStatus = NDIS_STATUS_SUCCESS;
  1836. BCMChannel = pBCR->NC_Channel;
  1837. TRACE( TL_V, TM_Bcm, ( " BCM Channel %x ", BCMChannel ) );
  1838. TRACE( TL_V, TM_Bcm, ( " BCR Is valid on LocalHost BCR", pAdapter->BCRData.LocalHostBCRBigEndian) );
  1839. NdisStatus = NDIS_STATUS_SUCCESS;
  1840. ASSERT (BCMChannel == 31);
  1841. break;
  1842. }
  1843. else
  1844. {
  1845. NdisStatus = NDIS_STATUS_FAILURE;
  1846. }
  1847. } while (FALSE);
  1848. TRACE( TL_T, TM_Bcm, ( "<== nicLocalNotIrmMandatoryWait Status %x , pBCR %x", NdisStatus, pBCR) );
  1849. return NdisStatus;
  1850. }
  1851. NDIS_STATUS
  1852. nicReadIrmBcr (
  1853. PREMOTE_NODE pIrmRemoteNode,
  1854. IN PMDL pBCRMdl,
  1855. IN ULONG GivenGeneration,
  1856. OUT PBOOLEAN pfDidTheBusReset
  1857. )
  1858. // Function Description:
  1859. // Purpose is to do an async read on the IRM's BCR and see if it is set.
  1860. // Arguments
  1861. // pIrmRemoteNode - The remote node (IRM)
  1862. // pBCRMdl The MDL that will contain the remote node's BCR. Needs to preinitialized
  1863. // Return Value:
  1864. // Success - If Irp succeeded. Appropriate Error code otherwise
  1865. // If the Generation is incorrect. the call will be failed
  1866. //
  1867. //
  1868. {
  1869. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1870. IO_ADDRESS Destination;
  1871. PNETWORK_CHANNELS pBCR = NULL;
  1872. NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
  1873. TRACE( TL_T, TM_Bcm, ( "==>nicReadIrmBcr pIrm %x, pMdl %x, GivenGeneration %x",
  1874. pIrmRemoteNode, pBCRMdl, GivenGeneration) );
  1875. ASSERT (pBCRMdl != NULL);
  1876. ASSERT (pIrmRemoteNode != NULL);
  1877. pBCR = NIC_GET_SYSTEM_ADDRESS_FOR_MDL(pBCRMdl);
  1878. Destination.IA_Destination_Offset.Off_Low = INITIAL_REGISTER_SPACE_LO | NETWORK_CHANNELS_LOCATION;
  1879. Destination.IA_Destination_Offset.Off_High = INITIAL_REGISTER_SPACE_HI;
  1880. do
  1881. {
  1882. if (pBCR == NULL)
  1883. {
  1884. break;
  1885. }
  1886. pBCR->NC_Valid = 0;
  1887. if (pIrmRemoteNode->pAdapter->Generation != GivenGeneration)
  1888. {
  1889. TRACE( TL_A, TM_Bcm, ( "nicReadIrmBcr : Generation Mismatch orig %x, curr %x", GivenGeneration , pIrmRemoteNode->pAdapter->Generation) );
  1890. NdisStatus = NDIS_STATUS_DEST_OUT_OF_ORDER;
  1891. *pfDidTheBusReset = TRUE;
  1892. break;
  1893. }
  1894. if (REMOTE_NODE_TEST_FLAG (pIrmRemoteNode, PDO_Removed))
  1895. {
  1896. NdisStatus = NDIS_STATUS_DEST_OUT_OF_ORDER;
  1897. break;
  1898. }
  1899. //
  1900. // We have a correct generation count
  1901. //
  1902. *pfDidTheBusReset = FALSE;
  1903. NdisStatus = nicAsyncRead_Synch( pIrmRemoteNode,
  1904. Destination,
  1905. sizeof(NETWORK_CHANNELSR), // Number of bytes to Read
  1906. sizeof (NETWORK_CHANNELSR), // Block Size
  1907. 0, // fulFlags,
  1908. pBCRMdl ,
  1909. GivenGeneration,
  1910. &NtStatus);
  1911. } while (FALSE);
  1912. if (NtStatus == STATUS_INVALID_GENERATION )
  1913. {
  1914. *pfDidTheBusReset = TRUE;
  1915. }
  1916. TRACE( TL_I, TM_Bcm, ( " nicReadIrmBcr pBCRMdl %x, BCR %x ", pBCRMdl, *pBCR ) );
  1917. TRACE( TL_T, TM_Bcm, ( "<==nicReadIrmBcr Status %x, fDidTheBusReset %x", NdisStatus ,*pfDidTheBusReset ) );
  1918. return NdisStatus;
  1919. }
  1920. NDIS_STATUS
  1921. nicScheduleBCMWorkItem(
  1922. PADAPTERCB pAdapter
  1923. )
  1924. /*++
  1925. Routine Description:
  1926. This function queues a workitem to kick of the BCM algorithm.
  1927. If there is already a BCM in progress, (look at BCM_WorkItem flag)
  1928. it simply returns.
  1929. It is the responsiblity of the caller to mark the invocation of BCMAlgorithm as
  1930. dirty, thereby forcing it to restart the BCM (by setting the InvalidGeneration of the
  1931. new Node Arrived Flags)
  1932. Arguments:
  1933. pAdapter - Adapter
  1934. Return Value:
  1935. --*/
  1936. {
  1937. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  1938. PNDIS_WORK_ITEM pBCMWorkItem;
  1939. BOOLEAN fBCMWorkItemInProgress = FALSE;
  1940. TRACE( TL_T, TM_Bcm, ( "==>nicScheduleBCMWorkItem pAdapter %x", pAdapter ) );
  1941. do
  1942. {
  1943. if (BCR_TEST_FLAG(pAdapter, BCR_Initialized)== FALSE)
  1944. {
  1945. NdisStatus = NDIS_STATUS_FAILURE;
  1946. break;
  1947. }
  1948. pBCMWorkItem = ALLOC_NONPAGED (sizeof(NDIS_WORK_ITEM), MTAG_WORKITEM);
  1949. if (pBCMWorkItem == NULL )
  1950. {
  1951. TRACE( TL_A, TM_Cm, ( "Local Alloc failed for WorkItem" ) );
  1952. NdisStatus = NDIS_STATUS_RESOURCES;
  1953. break;
  1954. }
  1955. else
  1956. {
  1957. //
  1958. // From here on, this function cannot fail.
  1959. //
  1960. NdisStatus = NDIS_STATUS_SUCCESS;
  1961. }
  1962. //
  1963. // reference the adapter as it is going to passed to a workiter.
  1964. // decremented in the workitem
  1965. //
  1966. nicReferenceAdapter(pAdapter, "nicScheduleBCMWorkItem ");
  1967. NdisInitializeWorkItem ( pBCMWorkItem,
  1968. (NDIS_PROC) nicBCMAlgorithmWorkItem,
  1969. (PVOID) pAdapter);
  1970. TRACE( TL_V, TM_Cm, ( "Scheduling BCM WorkItem" ) );
  1971. NdisScheduleWorkItem (pBCMWorkItem);
  1972. } while (FALSE);
  1973. TRACE( TL_T, TM_Bcm, ( "<==nicScheduleBCMWorkItem %x ", NdisStatus ) );
  1974. return NdisStatus;
  1975. }
  1976. VOID
  1977. nicSetEventMakeCall (
  1978. IN PADAPTERCB pAdapter
  1979. )
  1980. // Function Description:
  1981. // The Sets the event that a Broadcast channel Make Call might be waiting for
  1982. //
  1983. // Arguments
  1984. // Adapter - this is passed to the workitem
  1985. //
  1986. //
  1987. // Return Value:
  1988. // Failure if allocation of workitem failed
  1989. //
  1990. {
  1991. TRACE( TL_T, TM_Bcm, ( "==> nicSetEventMakeCall pAdapter %x", pAdapter) );
  1992. //
  1993. // now inform a waiting channel Vc to move on. If the BCR is not active.
  1994. // it will continue waiting till the next round
  1995. //
  1996. if (BCR_IS_VALID(&(pAdapter->BCRData.IRM_BCR))==TRUE)
  1997. {
  1998. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1999. if (BCR_TEST_FLAG (pAdapter, BCR_MakeCallPending) == TRUE)
  2000. {
  2001. TRACE( TL_V, TM_Bcm, ( " We found a waiting call ") );
  2002. NdisSetEvent (&pAdapter->BCRData.MakeCallWaitEvent.NdisEvent);
  2003. }
  2004. else
  2005. {
  2006. TRACE( TL_V, TM_Bcm, ( " No Call Waiting") );
  2007. }
  2008. ADAPTER_RELEASE_LOCK (pAdapter);
  2009. }
  2010. TRACE( TL_T, TM_Bcm, ( "<==nicSetEventMakeCall ") );
  2011. }
  2012. VOID
  2013. nicUpdateLocalHostNodeAddress (
  2014. IN PADAPTERCB pAdapter
  2015. )
  2016. /*++
  2017. Routine Description:
  2018. This function queries the Bus driver for the Local Node Address of
  2019. the Adapter
  2020. If the Node Address has changed, it updates the GaspHeader
  2021. Arguments:
  2022. pAdapter - Adapter
  2023. Return Value:
  2024. --*/
  2025. {
  2026. NODE_ADDRESS LocalNodeAddress, OldNodeAddress;
  2027. NDIS_STATUS NdisStatus;
  2028. OldNodeAddress = pAdapter->NodeAddress;
  2029. NdisStatus = nicGet1394AddressFromDeviceObject( pAdapter->pNextDeviceObject,
  2030. &LocalNodeAddress,
  2031. USE_LOCAL_NODE );
  2032. if (NdisStatus == NDIS_STATUS_SUCCESS)
  2033. {
  2034. pAdapter->NodeAddress = LocalNodeAddress;
  2035. // If the Node Address has changed , then update the GaspHeader
  2036. //
  2037. if (FALSE == NdisEqualMemory (&LocalNodeAddress,&OldNodeAddress, sizeof(NODE_ADDRESS) ) )
  2038. {
  2039. nicMakeGaspHeader (pAdapter, &pAdapter->GaspHeader);
  2040. }
  2041. }
  2042. }