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.

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