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.

6831 lines
176 KiB

  1. //
  2. // Copyright (c) 1998-1999, Microsoft Corporation, all rights reserved
  3. //
  4. // mp.c
  5. //
  6. // IEEE1394 mini-port/call-manager driver
  7. //
  8. // Mini-port routines
  9. //
  10. // 12/28/1998 JosephJ Created,
  11. //
  12. #include <precomp.h>
  13. #include "mp.h"
  14. #pragma hdrstop
  15. //-----------------------------------------------------------------------------
  16. // Data used in processing requests
  17. //-----------------------------------------------------------------------------
  18. NDIS_OID SupportedOids[] =
  19. {
  20. OID_GEN_CO_SUPPORTED_LIST,
  21. OID_GEN_CO_HARDWARE_STATUS,
  22. OID_GEN_CO_MEDIA_SUPPORTED,
  23. OID_GEN_CO_MEDIA_IN_USE,
  24. OID_GEN_CO_LINK_SPEED,
  25. OID_GEN_CO_VENDOR_ID,
  26. OID_GEN_CO_VENDOR_DESCRIPTION,
  27. OID_GEN_CO_DRIVER_VERSION,
  28. OID_GEN_CO_PROTOCOL_OPTIONS,
  29. OID_GEN_CO_MEDIA_CONNECT_STATUS,
  30. OID_GEN_CO_MAC_OPTIONS,
  31. OID_GEN_CO_VENDOR_DRIVER_VERSION,
  32. OID_GEN_CO_MINIMUM_LINK_SPEED,
  33. OID_GEN_CO_XMIT_PDUS_OK,
  34. OID_GEN_CO_RCV_PDUS_OK,
  35. OID_GEN_CO_XMIT_PDUS_ERROR,
  36. OID_GEN_CO_RCV_PDUS_ERROR,
  37. OID_GEN_CO_RCV_PDUS_NO_BUFFER,
  38. OID_1394_LOCAL_NODE_INFO,
  39. OID_1394_VC_INFO,
  40. OID_1394_NICINFO,
  41. OID_1394_IP1394_CONNECT_STATUS,
  42. OID_1394_ENTER_BRIDGE_MODE,
  43. OID_1394_EXIT_BRIDGE_MODE,
  44. OID_1394_ISSUE_BUS_RESET,
  45. OID_802_3_CURRENT_ADDRESS,
  46. OID_GEN_MAXIMUM_LOOKAHEAD,
  47. OID_GEN_MAXIMUM_FRAME_SIZE,
  48. OID_GEN_MAXIMUM_TOTAL_SIZE,
  49. OID_GEN_LINK_SPEED,
  50. OID_GEN_TRANSMIT_BUFFER_SPACE,
  51. OID_GEN_RECEIVE_BUFFER_SPACE,
  52. OID_GEN_TRANSMIT_BLOCK_SIZE,
  53. OID_GEN_RECEIVE_BLOCK_SIZE,
  54. OID_GEN_MAXIMUM_SEND_PACKETS,
  55. OID_GEN_CURRENT_PACKET_FILTER,
  56. OID_GEN_CURRENT_LOOKAHEAD,
  57. OID_802_3_PERMANENT_ADDRESS,
  58. OID_802_3_MULTICAST_LIST,
  59. OID_802_3_MAXIMUM_LIST_SIZE,
  60. OID_802_3_RCV_ERROR_ALIGNMENT,
  61. OID_802_3_XMIT_ONE_COLLISION,
  62. OID_802_3_XMIT_MORE_COLLISIONS,
  63. OID_GEN_PROTOCOL_OPTIONS,
  64. OID_GEN_CURRENT_PACKET_FILTER,
  65. OID_GEN_CURRENT_LOOKAHEAD,
  66. OID_GEN_PHYSICAL_MEDIUM,
  67. OID_PNP_QUERY_POWER,
  68. OID_PNP_SET_POWER,
  69. OID_1394_QUERY_EUID_NODE_MAP
  70. };
  71. //-----------------------------------------------------------------------------
  72. // Locally used function prototypes
  73. //-----------------------------------------------------------------------------
  74. NDIS_STATUS
  75. nicAllocateLoopbackPacketPool (
  76. IN PADAPTERCB pAdapter
  77. );
  78. VOID
  79. nicFreeLoopbackPacketPool (
  80. IN PADAPTERCB pAdapter
  81. );
  82. VOID
  83. nicLoopbackPacket(
  84. IN VCCB* pVc,
  85. IN PNDIS_PACKET pPacket
  86. );
  87. VOID
  88. nicQueryEuidNodeMacMap (
  89. IN PADAPTERCB pAdapter,
  90. IN PNDIS_REQUEST pRequest
  91. );
  92. VOID
  93. nicRemoveRemoteNodeFromNodeTable(
  94. IN PNODE_TABLE pNodeTable,
  95. IN PREMOTE_NODE pRemoteNode
  96. );
  97. NDIS_STATUS
  98. nicSetPower (
  99. IN PADAPTERCB pAdapter,
  100. IN NET_DEVICE_POWER_STATE DeviceState
  101. );
  102. //-----------------------------------------------------------------------------
  103. // Mini-port handlers
  104. //-----------------------------------------------------------------------------
  105. NDIS_STATUS
  106. NicMpInitialize(
  107. OUT PNDIS_STATUS OpenErrorStatus,
  108. OUT PUINT SelectedMediumIndex,
  109. IN PNDIS_MEDIUM MediumArray,
  110. IN UINT MediumArraySize,
  111. IN NDIS_HANDLE MiniportAdapterHandle,
  112. IN NDIS_HANDLE WrapperConfigurationContext
  113. )
  114. /*++
  115. Routine Description:
  116. Standard 'MiniportInitialize' routine called by NDIS to initialize a
  117. new adapter. See DDK doc. The driver will receive no requests
  118. until this initialization has completed.
  119. Arguments:
  120. See DDK docs
  121. Return Value:
  122. Appropriate Status
  123. --*/
  124. {
  125. NDIS_STATUS NdisStatus;
  126. NTSTATUS NtStatus;
  127. PADAPTERCB pAdapter= NULL;
  128. PDEVICE_OBJECT pNextDeviceObject = NULL;
  129. LARGE_INTEGER LocalHostUniqueId;
  130. REMOTE_NODE *p1394RemoteNodePdoCb = NULL;
  131. UINT64 u64LocalHostUniqueId =0;
  132. BOOLEAN FreeAdapter = FALSE;
  133. BOOLEAN DequeueAdapter = FALSE;
  134. ULONG Generation;
  135. ULONG InitStatus;
  136. //
  137. // This is the order with which the initialize routine is done.
  138. //
  139. enum
  140. {
  141. NoState,
  142. AllocatedAdapter,
  143. AdapterQueued,
  144. InitializedEvents,
  145. InitializedBcr,
  146. RegisteredResetCallback,
  147. AddedConfigRom,
  148. RegisteredEnumerator,
  149. InitializedLookasideList,
  150. InitializedPktLog,
  151. InitializedRcvThread,
  152. InitializedSendThread,
  153. InitializedReassembly,
  154. InitializedLoopbackPool
  155. };
  156. STORE_CURRENT_IRQL
  157. TIMESTAMP_ENTRY("==>IntializeHandler");
  158. TIMESTAMP_INITIALIZE();
  159. TRACE( TL_T, TM_Init, ( "==>NicMpInitialize" ) );
  160. InitStatus = NoState;
  161. NdisStatus = *OpenErrorStatus = NDIS_STATUS_SUCCESS;
  162. // Find the medium index in the array of media, looking for the only one
  163. // we support, 'NdisMedium1394'.
  164. //
  165. {
  166. UINT i;
  167. for (i = 0; i < MediumArraySize; ++i)
  168. {
  169. if (MediumArray[ i ] == g_ulMedium )
  170. {
  171. break;
  172. }
  173. }
  174. if (i >= MediumArraySize)
  175. {
  176. TRACE( TL_A, TM_Init, ( "medium?" ) );
  177. return NDIS_STATUS_FAILURE;
  178. }
  179. *SelectedMediumIndex = i;
  180. }
  181. // Allocate and zero a control block for the new adapter.
  182. //
  183. pAdapter = ALLOC_NONPAGED( sizeof(ADAPTERCB), MTAG_ADAPTERCB );
  184. TRACE( TL_N, TM_Init, ( "Acb=$%p", pAdapter ) );
  185. if (!pAdapter)
  186. {
  187. return NDIS_STATUS_RESOURCES;
  188. }
  189. FreeAdapter = TRUE;
  190. InitStatus = AllocatedAdapter;
  191. NdisZeroMemory (pAdapter, sizeof(*pAdapter) );
  192. // Add a reference that will eventually be removed by an NDIS call to
  193. // the nicFreeAdapter handler.
  194. //
  195. nicReferenceAdapter (pAdapter, "MpInitialize" );
  196. // Set a marker for easier memory dump browsing and future assertions.
  197. //
  198. pAdapter->ulTag = MTAG_ADAPTERCB;
  199. // Save the NDIS handle associated with this adapter for use in future
  200. // NdisXxx calls.
  201. //
  202. pAdapter->MiniportAdapterHandle = MiniportAdapterHandle;
  203. // Initialize the adapter-wide lock.
  204. //
  205. NdisAllocateSpinLock( &pAdapter->lock );
  206. // Initialize the various lists of top-level resources.
  207. //
  208. pAdapter->HardwareStatus = NdisHardwareStatusInitializing;
  209. //
  210. // The enumerator and bus1394 have asked us to load, therefore media
  211. // should be connected
  212. //
  213. pAdapter->MediaConnectStatus = NdisMediaStateDisconnected;
  214. InitializeListHead( &pAdapter->AFList );
  215. InitializeListHead( &pAdapter->PDOList );
  216. //
  217. // Default initialization values
  218. //
  219. pAdapter->Speed = SPEED_FLAGS_400;
  220. pAdapter->SpeedMbps = 4 * 1000000;
  221. pAdapter->SCode = SCODE_400_RATE;
  222. do
  223. {
  224. // Read this adapter's registry settings.
  225. //
  226. NdisStatus = nicGetRegistrySettings(
  227. WrapperConfigurationContext,
  228. pAdapter
  229. );
  230. if (NdisStatus != NDIS_STATUS_SUCCESS)
  231. {
  232. break;
  233. }
  234. // Inform NDIS of the attributes of our adapter. Set the
  235. // 'MiniportAdapterContext' returned to us by NDIS when it calls our
  236. // handlers to the address of our adapter control block. Turn off
  237. // hardware oriented timeouts.
  238. //
  239. NdisMSetAttributesEx(
  240. MiniportAdapterHandle,
  241. (NDIS_HANDLE)pAdapter,
  242. (UINT)0,
  243. NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT | NDIS_ATTRIBUTE_IGNORE_TOKEN_RING_ERRORS |
  244. NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND | NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT |
  245. NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK,
  246. NdisInterfaceInternal );
  247. NdisStatus = nicMCmRegisterAddressFamily (pAdapter);
  248. if (NdisStatus != NDIS_STATUS_SUCCESS)
  249. {
  250. //
  251. // If we fail, Let the next entrant try the same thing
  252. //
  253. break;
  254. }
  255. ADAPTER_SET_FLAG (pAdapter,fADAPTER_RegisteredAF);
  256. //
  257. // Insert into global list of adapters. So we will be ready to receive notifications
  258. // from the enumerator
  259. //
  260. NdisAcquireSpinLock ( &g_DriverLock);
  261. InsertHeadList (&g_AdapterList, &pAdapter->linkAdapter);
  262. DequeueAdapter = TRUE;
  263. InitStatus = AdapterQueued;
  264. NdisReleaseSpinLock (&g_DriverLock);
  265. pAdapter->HardwareStatus = NdisHardwareStatusReady;
  266. //
  267. // Set up linkages. Get the PDO for the device from Ndis
  268. //
  269. NdisMGetDeviceProperty( MiniportAdapterHandle,
  270. NULL,
  271. NULL,
  272. &pNextDeviceObject,
  273. NULL,
  274. NULL );
  275. ASSERT (pNextDeviceObject != NULL);
  276. pAdapter->Generation = 0;
  277. //
  278. // Update data structure with the local hosts VDO
  279. //
  280. pAdapter->pNextDeviceObject = pNextDeviceObject;
  281. TRACE( TL_I, TM_Mp, ( " LocalHost VDO %x", pNextDeviceObject) );
  282. nicInitializeAllEvents (pAdapter);
  283. InitStatus = InitializedEvents;
  284. //
  285. // Initialize the BCM so it is ready to handle Resets
  286. //
  287. NdisStatus = nicInitializeBroadcastChannelRegister (pAdapter);
  288. if (NdisStatus != NDIS_STATUS_SUCCESS)
  289. {
  290. BREAK( TM_Init, ( "nicMpInitialize - nicInitializeBroadcastChannelRegister ") );
  291. }
  292. InitStatus = InitializedBcr;
  293. //
  294. // Initialize the generation count , reset callback and config rom
  295. //
  296. NdisStatus = nicGetGenerationCount (pAdapter, &Generation);
  297. if (NdisStatus != NDIS_STATUS_SUCCESS)
  298. {
  299. BREAK (TM_Init, ("Initialize Handler - nicGetGeneration Failed" ) );
  300. }
  301. pAdapter->Generation = Generation;
  302. //
  303. // request notification of bus resets
  304. //
  305. NdisStatus = nicBusResetNotification (pAdapter,
  306. REGISTER_NOTIFICATION_ROUTINE,
  307. nicResetNotificationCallback,
  308. pAdapter);
  309. if (NdisStatus != NDIS_STATUS_SUCCESS)
  310. {
  311. BREAK (TM_Init, ("Initialize Handler - nicBusResetNotification Failed" ) );
  312. }
  313. InitStatus = RegisteredResetCallback;
  314. //
  315. // add ip/1394 to the config rom
  316. //
  317. NdisStatus = nicAddIP1394ToConfigRom (pAdapter);
  318. if (NdisStatus != NDIS_STATUS_SUCCESS)
  319. {
  320. BREAK (TM_Init, ("Initialize Handler - nicAddIP1394ToConfigRom Failed" ) );
  321. }
  322. InitStatus = AddedConfigRom;
  323. //
  324. // Lets find out our MaxRec.
  325. //
  326. NdisStatus = nicGetReadWriteCapLocalHost(pAdapter, &pAdapter->ReadWriteCaps);
  327. if (NdisStatus != NDIS_STATUS_SUCCESS)
  328. {
  329. break;
  330. }
  331. pAdapter->MaxRec = nicGetMaxRecFromBytes(pAdapter->ReadWriteCaps.MaxAsyncWriteRequest);
  332. TRACE (TL_V, TM_Mp, (" MaxRec %x\n", pAdapter->MaxRec ) );
  333. //
  334. // Update the Local Speed. If we fail now, we will get it again
  335. // after a Reset.
  336. //
  337. nicUpdateLocalHostSpeed (pAdapter);
  338. TRACE (TL_V, TM_Mp, (" SCode %x", pAdapter->SCode) );
  339. //
  340. // Bus Reset - used to kick off the BCM algorithm
  341. //
  342. nicIssueBusReset (pAdapter,BUS_RESET_FLAGS_FORCE_ROOT );
  343. //
  344. // Register this adapter with the enumerator.
  345. //
  346. if (NdisEnum1394DeregisterAdapter != NULL)
  347. {
  348. NtStatus = NdisEnum1394RegisterAdapter((PVOID)pAdapter,
  349. pNextDeviceObject,
  350. &pAdapter->EnumAdapterHandle,
  351. &LocalHostUniqueId);
  352. if (NtStatus != STATUS_SUCCESS)
  353. {
  354. ADAPTER_SET_FLAG(pAdapter, fADAPTER_FailedRegisteration);
  355. //
  356. // Don;t Bail Out
  357. //
  358. //NdisStatus = NDIS_STATUS_FAILURE;
  359. BREAK( TM_Init, ( "nicMpInitialize - NdisEnum1394RegisterAdapter FAILED ") );
  360. }
  361. else
  362. {
  363. ADAPTER_SET_FLAG(pAdapter, fADAPTER_RegisteredWithEnumerator);
  364. InitStatus = RegisteredEnumerator;
  365. }
  366. }
  367. else
  368. {
  369. GET_LOCAL_HOST_INFO1 Uid;
  370. //
  371. // Enum is not loaded get the Unique Id
  372. //
  373. NdisStatus = nicGetLocalHostUniqueId (pAdapter,
  374. &Uid );
  375. if (NdisStatus != NDIS_STATUS_SUCCESS)
  376. {
  377. BREAK( TM_Init, ( " nicMpInitialize - nicGetLocalHostUniqueId FAILED ") );
  378. }
  379. else
  380. {
  381. LocalHostUniqueId = Uid.UniqueId;
  382. }
  383. }
  384. //
  385. // Validate the Local Adapter's Unique Id
  386. //
  387. if (LocalHostUniqueId.QuadPart == (UINT64)(0) )
  388. {
  389. nicWriteErrorLog (pAdapter,NDIS_ERROR_CODE_HARDWARE_FAILURE, NIC_ERROR_CODE_INVALID_UNIQUE_ID_0);
  390. NdisStatus = NDIS_STATUS_FAILURE;
  391. break;
  392. }
  393. if (LocalHostUniqueId.QuadPart == (UINT64)(-1) )
  394. {
  395. nicWriteErrorLog (pAdapter,NDIS_ERROR_CODE_HARDWARE_FAILURE,NIC_ERROR_CODE_INVALID_UNIQUE_ID_FF);
  396. NdisStatus = NDIS_STATUS_FAILURE;
  397. break;
  398. }
  399. #ifdef PKT_LOG
  400. nic1394AllocPktLog (pAdapter);
  401. if (pAdapter->pPktLog == NULL)
  402. {
  403. NdisStatus = NDIS_STATUS_FAILURE;
  404. BREAK (TM_Init, ("nicMpInitialize - Could not allocate packetlog" ) );
  405. }
  406. nic1394InitPktLog(pAdapter->pPktLog);
  407. InitStatus = InitializedPktLog;
  408. #endif
  409. //
  410. // Initialize the reassembly timers
  411. //
  412. nicInitSerializedReassemblyStruct(pAdapter); // cannot fail
  413. InitStatus = InitializedReassembly;
  414. //
  415. // This swap is done so that the byte reported by the bus driver matches that
  416. // which is used in the notification of add nodes, remove nodes and make call
  417. //
  418. LocalHostUniqueId.LowPart = SWAPBYTES_ULONG (LocalHostUniqueId.LowPart );
  419. LocalHostUniqueId.HighPart = SWAPBYTES_ULONG (LocalHostUniqueId.HighPart );
  420. u64LocalHostUniqueId = LocalHostUniqueId.QuadPart;
  421. pAdapter->UniqueId = u64LocalHostUniqueId;
  422. pAdapter->HardwareStatus = NdisHardwareStatusReady;
  423. //
  424. // Get Our local Fake Mac address
  425. //
  426. nicGetFakeMacAddress (&u64LocalHostUniqueId, &pAdapter->MacAddressEth);
  427. //
  428. // Initialize the lookaside lists
  429. //
  430. nicInitializeAdapterLookasideLists (pAdapter);
  431. InitStatus = InitializedLookasideList;
  432. //
  433. // Initialize the remote node table
  434. //
  435. nicUpdateRemoteNodeTable (pAdapter);
  436. //
  437. // initialize the gasp header
  438. //
  439. nicMakeGaspHeader (pAdapter, &pAdapter->GaspHeader);
  440. //
  441. // Assign a MAC address to this Adapter
  442. //
  443. {
  444. AdapterNum++;
  445. //
  446. // generate a locally
  447. // administered address by manipulating the first two bytes.
  448. //
  449. }
  450. //
  451. // Allocate the loopback pools
  452. //
  453. NdisStatus= nicAllocateLoopbackPacketPool (pAdapter);
  454. if (NdisStatus != NDIS_STATUS_SUCCESS)
  455. {
  456. BREAK (TM_Init, ("nicMpInitialize - nicAllocateLoopbackPacketPool FAILED" ) );
  457. }
  458. InitStatus = InitializedLoopbackPool;
  459. ADAPTER_SET_FLAG (pAdapter, fADAPTER_DoStatusIndications);
  460. pAdapter->PowerState = NetDeviceStateD0;
  461. } while (FALSE);
  462. if (NdisStatus != NDIS_STATUS_SUCCESS)
  463. {
  464. NDIS_STATUS FailureStatus = NDIS_STATUS_FAILURE;
  465. // Failed, so undo whatever portion succeeded.
  466. //
  467. TRACE( TL_I, TM_Init, ( "NicMpInitialize FAILING InitStatus %x", InitStatus) );
  468. ADAPTER_SET_FLAG (pAdapter, fADAPTER_FailedInit);
  469. ADAPTER_CLEAR_FLAG (pAdapter, fADAPTER_DoStatusIndications);
  470. //
  471. // This is in reverse order of the init and there are no breaks here.
  472. // The implicit assumption is that if the code failed at a certain point
  473. // it will have to undo whatever was previously allocated
  474. //
  475. switch (InitStatus)
  476. {
  477. case InitializedLoopbackPool:
  478. {
  479. nicFreeLoopbackPacketPool(pAdapter);
  480. FALL_THROUGH;
  481. }
  482. case InitializedLookasideList:
  483. {
  484. nicDeleteAdapterLookasideLists(pAdapter);
  485. FALL_THROUGH;
  486. }
  487. case InitializedReassembly:
  488. {
  489. nicDeInitSerializedReassmblyStruct(pAdapter);
  490. FALL_THROUGH;
  491. }
  492. case InitializedSendThread:
  493. {
  494. FALL_THROUGH;
  495. }
  496. case InitializedRcvThread:
  497. {
  498. FALL_THROUGH;
  499. }
  500. case InitializedPktLog:
  501. {
  502. #ifdef PKT_LOG
  503. nic1394DeallocPktLog(pAdapter);
  504. #endif
  505. FALL_THROUGH
  506. }
  507. case RegisteredEnumerator:
  508. {
  509. //
  510. // If we registered with the enumerator , then deregister
  511. //
  512. if ((NdisEnum1394DeregisterAdapter != NULL) &&
  513. ADAPTER_TEST_FLAG(pAdapter, fADAPTER_RegisteredWithEnumerator))
  514. {
  515. //
  516. // deregister this adapter with enumerator
  517. //
  518. TRACE( TL_V, TM_Init, ( " Deregistering with the Enum %x", pAdapter->EnumAdapterHandle) );
  519. NdisEnum1394DeregisterAdapter(pAdapter->EnumAdapterHandle);
  520. ADAPTER_CLEAR_FLAG(pAdapter, fADAPTER_RegisteredWithEnumerator | fADAPTER_FailedRegisteration);
  521. }
  522. FALL_THROUGH
  523. }
  524. case AddedConfigRom:
  525. {
  526. TRACE( TL_V, TM_Init, ( " removing config rom handle %x", pAdapter->hCromData ) );
  527. FailureStatus = nicSetLocalHostPropertiesCRom(pAdapter,
  528. (PUCHAR)&Net1394ConfigRom,
  529. sizeof(Net1394ConfigRom),
  530. SLHP_FLAG_REMOVE_CROM_DATA,
  531. &pAdapter->hCromData,
  532. &pAdapter->pConfigRomMdl);
  533. FALL_THROUGH
  534. }
  535. case RegisteredResetCallback:
  536. {
  537. TRACE( TL_V, TM_Init, ( " Deregistering reset callback ") );
  538. //
  539. // Deregeister the reset callback
  540. //
  541. FailureStatus = nicBusResetNotification (pAdapter,
  542. DEREGISTER_NOTIFICATION_ROUTINE,
  543. nicResetNotificationCallback,
  544. pAdapter) ;
  545. FALL_THROUGH
  546. }
  547. case InitializedBcr:
  548. case InitializedEvents:
  549. {
  550. TRACE( TL_V, TM_Init, ( " Freeing BCR ") );
  551. nicFreeBroadcastChannelRegister(pAdapter);
  552. NdisWaitEvent (&pAdapter->BCRData.BCRFreeAddressRange.NdisEvent, WAIT_INFINITE);
  553. FALL_THROUGH
  554. }
  555. case AdapterQueued:
  556. {
  557. NdisAcquireSpinLock ( &g_DriverLock);
  558. nicRemoveEntryList (&pAdapter->linkAdapter);
  559. NdisReleaseSpinLock (&g_DriverLock);
  560. FALL_THROUGH
  561. }
  562. case AllocatedAdapter:
  563. {
  564. nicDereferenceAdapter(pAdapter, "NicMpInitialize");
  565. break;
  566. }
  567. default :
  568. {
  569. ASSERT (0);
  570. }
  571. }
  572. }
  573. TRACE( TL_T, TM_Init, ( "<==NicMpInitialize=$%08x", NdisStatus ) );
  574. MATCH_IRQL;
  575. TRACE( TL_I, TM_Init, ( "NicMpInitialize Status %x, pAdapter %p", NdisStatus,pAdapter ) );
  576. TIMESTAMP_EXIT("<==IntializeHandler");
  577. return NdisStatus;
  578. }
  579. VOID
  580. NicMpHalt(
  581. IN NDIS_HANDLE MiniportAdapterContext
  582. )
  583. /*++
  584. Routine Description:
  585. Standard 'MiniportHalt' routine called by NDIS to deallocate all
  586. resources attached to the adapter. NDIS does not make any other calls
  587. for this mini-port adapter during or after this call. NDIS will not
  588. call this routine when packets indicated as received have not been
  589. returned, or when any VC is created and known to NDIS. Runs at PASSIVE
  590. IRQL.
  591. Arguments:
  592. Return Value:
  593. --*/
  594. {
  595. PADAPTERCB pAdapter = (PADAPTERCB) MiniportAdapterContext;
  596. BOOLEAN TimerCancelled = FALSE;
  597. STORE_CURRENT_IRQL
  598. TIMESTAMP_ENTRY("==>Haltandler");
  599. TRACE( TL_T, TM_Mp, ( "==>NicMpHalt" ) );
  600. TRACE( TL_I, TM_Mp, ( " Adapter %x Halted", pAdapter ) );
  601. if (pAdapter->ulTag != MTAG_ADAPTERCB)
  602. {
  603. ASSERT( !"Atag?" );
  604. return;
  605. }
  606. ADAPTER_CLEAR_FLAG (pAdapter, fADAPTER_DoStatusIndications);
  607. //
  608. // Unload the Arp module if necessary. This is necessary if
  609. // the nic is forced to operate in a non-power managed environment
  610. // by the user.
  611. //
  612. if (pAdapter->fIsArpStarted == TRUE)
  613. {
  614. nicQueueRequestToArp(pAdapter, UnloadArpNoRequest, NULL);
  615. }
  616. ADAPTER_SET_FLAG (pAdapter, fADAPTER_Halting);
  617. //
  618. // Stop the reassembly timer
  619. //
  620. nicDeInitSerializedReassmblyStruct(pAdapter);
  621. //
  622. // Deallocating the packet log
  623. //
  624. #ifdef PKT_LOG
  625. nic1394DeallocPktLog(pAdapter);
  626. #endif
  627. //
  628. // remove the config rom
  629. //
  630. nicSetLocalHostPropertiesCRom(pAdapter,
  631. (PUCHAR)&Net1394ConfigRom,
  632. sizeof(Net1394ConfigRom),
  633. SLHP_FLAG_REMOVE_CROM_DATA,
  634. &pAdapter->hCromData,
  635. &pAdapter->pConfigRomMdl);
  636. pAdapter->hCromData = NULL;
  637. //
  638. // free the apapter packet pool
  639. nicFreeLoopbackPacketPool(pAdapter);
  640. //
  641. // Free the BCR
  642. //
  643. nicFreeBroadcastChannelRegister(pAdapter);
  644. TRACE (TL_V, TM_Mp, ("About to Wait for Free AddressRange\n" ) );
  645. NdisWaitEvent (&pAdapter->BCRData.BCRFreeAddressRange.NdisEvent, WAIT_INFINITE);
  646. TRACE (TL_V, TM_Mp, ("Wait Completed for Free AddressRange\n" ) );
  647. nicBusResetNotification (pAdapter,
  648. DEREGISTER_NOTIFICATION_ROUTINE,
  649. nicResetNotificationCallback,
  650. pAdapter);
  651. //
  652. // deregister this adapter with enumerator
  653. //
  654. if ((NdisEnum1394DeregisterAdapter != NULL) &&
  655. ADAPTER_TEST_FLAG(pAdapter, fADAPTER_RegisteredWithEnumerator))
  656. {
  657. //
  658. // deregister this adapter with enumerator
  659. //
  660. NdisEnum1394DeregisterAdapter(pAdapter->EnumAdapterHandle);
  661. ADAPTER_CLEAR_FLAG(pAdapter, fADAPTER_RegisteredWithEnumerator | fADAPTER_FailedRegisteration);
  662. }
  663. //
  664. // No more Irps on this adapter's VDO
  665. //
  666. ADAPTER_SET_FLAG (pAdapter, fADAPTER_VDOInactive);
  667. //
  668. // Cancel Outstanding Timer
  669. //
  670. ADAPTER_SET_FLAG (pAdapter, fADAPTER_FreedTimers);
  671. //
  672. // Cancel Outstanding WorItems
  673. //
  674. while (pAdapter->OutstandingWorkItems != 0)
  675. {
  676. NdisMSleep (10000);
  677. }
  678. ADAPTER_SET_FLAG (pAdapter, fADAPTER_DeletedWorkItems);
  679. // Remove this adapter from the global list of adapters.
  680. //
  681. NdisAcquireSpinLock(&g_DriverLock);
  682. nicRemoveEntryList(&pAdapter->linkAdapter);
  683. NdisReleaseSpinLock(&g_DriverLock);
  684. ADAPTER_ACQUIRE_LOCK (pAdapter);
  685. // do Adapter Specific Work here
  686. pAdapter->HardwareStatus = NdisHardwareStatusClosing;
  687. //
  688. // Free all lookaside lists
  689. //
  690. nicDeleteAdapterLookasideLists (pAdapter);
  691. ADAPTER_SET_FLAG (pAdapter, fADAPTER_DeletedLookasideLists);
  692. ADAPTER_RELEASE_LOCK (pAdapter);
  693. NdisFreeSpinLock (&pAdapter->lock);
  694. while (pAdapter->lRef != 1)
  695. {
  696. //
  697. // sleep for 1 second waiting for outstanding operations to complete
  698. //
  699. NdisMSleep (1000);
  700. }
  701. nicDereferenceAdapter( pAdapter, "nicMpHalt" );
  702. //ASSERT (g_AdapterFreed == TRUE);
  703. TRACE( TL_T, TM_Mp, ( "<==NicMpHalt " ) );
  704. TIMESTAMP_EXIT("<==Haltandler");
  705. TIMESTAMP_HALT();
  706. TRACE( TL_I, TM_Init, ( "Nic1394 Halted %p ", pAdapter ) );
  707. MATCH_IRQL
  708. }
  709. NDIS_STATUS
  710. NicMpReset(
  711. OUT PBOOLEAN AddressingReset,
  712. IN NDIS_HANDLE MiniportAdapterContext
  713. )
  714. /*++
  715. Routine Description:
  716. Do Nothing
  717. Arguments:
  718. Return Value:
  719. --*/
  720. {
  721. TRACE( TL_T, TM_Mp, ( "NicMpReset" ) );
  722. return NDIS_STATUS_SUCCESS;
  723. }
  724. NDIS_STATUS
  725. NicMpCoActivateVc(
  726. IN NDIS_HANDLE MiniportVcContext,
  727. IN OUT PCO_CALL_PARAMETERS CallParameters
  728. )
  729. /*++
  730. Routine Description:
  731. Do Nothing
  732. Standard 'MiniportCoActivateVc' routine called by NDIS in response to a
  733. protocol's request to activate a virtual circuit.
  734. The only "protocol" to call us is our call manager half, which knows
  735. exactly what it's doing and so we don't have to do anything here.
  736. It does expect us to return success synchronously.
  737. Arguments:
  738. Return Value:
  739. Always Succeed
  740. --*/
  741. {
  742. return NDIS_STATUS_SUCCESS;
  743. }
  744. NDIS_STATUS
  745. NicMpCoDeactivateVc(
  746. IN NDIS_HANDLE MiniportVcContext
  747. )
  748. /*++
  749. Routine Description:
  750. Standard 'MiniportCoDeactivateVc' routine called by NDIS in response to
  751. a protocol's request to de-activate a virtual circuit.
  752. The only "protocol" to call us is our call manager half, which knows
  753. exactly what it's doing and so we don't have to do anything here.
  754. It does expect us to return success synchronously.
  755. Arguments:
  756. Return Value:
  757. --*/
  758. {
  759. return NDIS_STATUS_SUCCESS;
  760. }
  761. VOID
  762. NicMpCoSendPackets(
  763. IN NDIS_HANDLE MiniportVcContext,
  764. IN PPNDIS_PACKET PacketArray,
  765. IN UINT NumberOfPackets
  766. )
  767. /*++
  768. Routine Description:
  769. Co Send Handler for the Miniport
  770. Any broadcast packets have to be looped back as 1394 does
  771. not loop back packets sent on a channel
  772. Arguments:
  773. See DDK
  774. Return Value:
  775. None: After the first failure, call NdisMCoSendComplete(..)
  776. on all packets
  777. --*/
  778. {
  779. UINT i;
  780. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  781. NDIS_PACKET** ppPacket;
  782. VCCB* pVc;
  783. extern UINT NicSends;
  784. TRACE( TL_V, TM_Send, ( "==>NicMpCoSendPackets(%d), Vc %.8x", NumberOfPackets, MiniportVcContext ) );
  785. pVc = (VCCB* )MiniportVcContext;
  786. ASSERT( pVc->Hdr.ulTag == MTAG_VCCB );
  787. for (i = 0, ppPacket = PacketArray;
  788. i < NumberOfPackets;
  789. ++i, ++ppPacket)
  790. {
  791. NDIS_PACKET* pPacket = *ppPacket;
  792. // SendPacket sends the packet and eventually calls
  793. // NdisMCoSendComplete to notify caller of the result.
  794. //
  795. NDIS_SET_PACKET_STATUS( pPacket, NDIS_STATUS_PENDING );
  796. nicIncrementSends (pVc);
  797. nicDumpPkt (pPacket , "Sending ");
  798. //
  799. // Loopback the packet it is a broadcast packet
  800. //
  801. if (pVc->Hdr.VcType == NIC1394_SendRecvChannel ||
  802. pVc->Hdr.VcType == NIC1394_MultiChannel ||
  803. pVc->Hdr.VcType == NIC1394_SendChannel)
  804. {
  805. nicLoopbackPacket(pVc, pPacket);
  806. }
  807. nicUpdatePacketState (pPacket, NIC1394_TAG_IN_SEND);
  808. NdisStatus = pVc->Hdr.VcHandlers.SendPackets (pVc, pPacket);
  809. if (NT_SUCCESS (NdisStatus) == FALSE)
  810. {
  811. TRACE( TL_N, TM_Send, ( "SendHandler failed Status %.8x", NdisStatus ) );
  812. break;
  813. }
  814. }
  815. // If the call to the VC's Send handler was not successful
  816. // Indicate failure for that packet and all packets following it
  817. //
  818. if (NT_SUCCESS(NdisStatus) == FALSE) // can pend also
  819. {
  820. // Start from the packet which caused the break and indicate
  821. // Failure (call the completion handler for each packet
  822. //
  823. for ( ; i < NumberOfPackets;++i,++ppPacket)
  824. {
  825. TRACE( TL_V, TM_Send, ( "Calling NdisCoSendComplete, status %x, VcHandle %x, pPkt %x",
  826. NDIS_STATUS_FAILURE , pVc->Hdr.NdisVcHandle, *ppPacket ) );
  827. nicMpCoSendComplete (NDIS_STATUS_FAILURE, pVc,*ppPacket);
  828. }
  829. }
  830. TRACE( TL_T, TM_Send, ( "<==NicMpCoSendPackets " ) );
  831. }
  832. NDIS_STATUS
  833. NicMpCoRequest(
  834. IN NDIS_HANDLE MiniportAdapterContext,
  835. IN NDIS_HANDLE MiniportVcContext,
  836. IN OUT PNDIS_REQUEST NdisRequest
  837. )
  838. /*++
  839. Routine Description:
  840. Standard CoRequest handler. It branches off into a Query function
  841. and a Set Function.
  842. Arguments:
  843. See DDK
  844. Return Value:
  845. --*/
  846. {
  847. ADAPTERCB* pAdapter;
  848. VCCB* pVc;
  849. NDIS_STATUS status;
  850. TRACE( TL_T, TM_Mp, ( "NicMpCoReq, Request %.8x", NdisRequest ) );
  851. pAdapter = (ADAPTERCB* )MiniportAdapterContext;
  852. if (pAdapter->ulTag != MTAG_ADAPTERCB)
  853. {
  854. ASSERT( !"Atag?" );
  855. return NDIS_STATUS_INVALID_DATA;
  856. }
  857. pVc = (VCCB* )MiniportVcContext;
  858. if (pVc && pVc->Hdr.ulTag != MTAG_VCCB)
  859. {
  860. ASSERT( !"Vtag?" );
  861. return NDIS_STATUS_INVALID_DATA;
  862. }
  863. switch (NdisRequest->RequestType)
  864. {
  865. case NdisRequestQueryStatistics:
  866. case NdisRequestQueryInformation:
  867. {
  868. status = nicQueryInformation(
  869. pAdapter,
  870. pVc,
  871. NdisRequest
  872. );
  873. break;
  874. }
  875. case NdisRequestSetInformation:
  876. {
  877. status = nicSetInformation(
  878. pAdapter,
  879. pVc,
  880. NdisRequest
  881. );
  882. break;
  883. }
  884. default:
  885. {
  886. status = NDIS_STATUS_NOT_SUPPORTED;
  887. TRACE( TL_V, TM_Mp, ( "type=%d?", NdisRequest->RequestType ) );
  888. break;
  889. }
  890. }
  891. TRACE( TL_T, TM_Mp, ( "NicMpCoReq, Status=$%x", status ) );
  892. return status;
  893. }
  894. //-----------------------------------------------------------------------------
  895. // Mini-port utility routines (alphabetically)
  896. // Some are used externally
  897. //-----------------------------------------------------------------------------
  898. VOID
  899. nicDereferenceAdapter(
  900. IN PADAPTERCB pAdapter,
  901. IN PCHAR pDebugPrint
  902. )
  903. /*++
  904. Routine Description:
  905. Dereferences the Adapter, If the Ref is zero, it will free
  906. the adapter object.
  907. It expects that this will happen in the Halt Handler.
  908. The Ref Count cannot bounce back up from zero because the last refernce
  909. is Dereferenced only after no new operations can be started on the adapter.
  910. Arguments:
  911. Adapter
  912. DebugString
  913. Return Value:
  914. --*/
  915. {
  916. LONG lRef;
  917. lRef = NdisInterlockedDecrement( &pAdapter->lRef );
  918. TRACE( TL_V, TM_Ref, ( "**nicDereferenceAdapter pAdapter %x, to %d, %s ", pAdapter, pAdapter->lRef, pDebugPrint ) );
  919. ASSERT( lRef >= 0 );
  920. if (lRef == 0)
  921. {
  922. nicFreeAdapter( pAdapter );
  923. }
  924. }
  925. VOID
  926. nicFreeAdapter(
  927. IN ADAPTERCB* pAdapter
  928. )
  929. /*++
  930. Routine Description:
  931. Free the memory for the adapter structure
  932. Arguments:
  933. Return Value:
  934. --*/
  935. {
  936. pAdapter->ulTag = MTAG_FREED;
  937. ASSERT (pAdapter->lRef == 0);
  938. FREE_NONPAGED( pAdapter );
  939. g_AdapterFreed = TRUE;
  940. }
  941. NDIS_STATUS
  942. nicGetRegistrySettings(
  943. IN NDIS_HANDLE WrapperConfigurationContext,
  944. IN ADAPTERCB * pAdapter
  945. )
  946. /*++
  947. Routine Description:
  948. nic1394 reads 1 registry parameter and that is the name of the
  949. NDIS miniport so that it can be used if the miniport is ever
  950. set into Bridge mode
  951. Arguments:
  952. Return Value:
  953. --*/
  954. {
  955. NDIS_STATUS status;
  956. NDIS_HANDLE hCfg;
  957. NDIS_CONFIGURATION_PARAMETER* pncp;
  958. PNDIS_CONFIGURATION_PARAMETER pNameConfig;
  959. NDIS_STRING strMiniportName = NDIS_STRING_CONST("MiniportName");
  960. ULONG AdapterNameSizeInBytes = 0;
  961. NdisOpenConfiguration( &status, &hCfg, WrapperConfigurationContext );
  962. if (status != NDIS_STATUS_SUCCESS)
  963. return status;
  964. do
  965. {
  966. //
  967. // Read the Miniport Name. First setup the buffer
  968. //
  969. NdisReadConfiguration(&status,
  970. &pNameConfig,
  971. hCfg,
  972. &strMiniportName,
  973. NdisParameterString);
  974. if (status != NDIS_STATUS_SUCCESS)
  975. {
  976. break;
  977. }
  978. AdapterNameSizeInBytes = pNameConfig->ParameterData.StringData.Length;
  979. //
  980. // Only Copy the Adapter name if the size of the string from the registry
  981. // is smaller than the size we have allocated in the adapter structure.
  982. // There should also be room for the trailing L'\0' character.
  983. //
  984. if ((ADAPTER_NAME_SIZE*sizeof(WCHAR)) > (AdapterNameSizeInBytes+2))
  985. {
  986. PUCHAR pAdapterName = (PUCHAR)&pAdapter->AdapterName[0];
  987. pAdapter->AdapterNameSize = AdapterNameSizeInBytes;
  988. NdisMoveMemory (pAdapterName, // Destination
  989. pNameConfig->ParameterData.StringData.Buffer, // Source
  990. AdapterNameSizeInBytes ); // number of characters
  991. //
  992. // NULL - terminate the string by adding the L'\0' Unicode character
  993. //
  994. pAdapterName[AdapterNameSizeInBytes]= 0;
  995. pAdapterName[AdapterNameSizeInBytes+1]= 0;
  996. }
  997. }
  998. while (FALSE);
  999. NdisCloseConfiguration( hCfg );
  1000. TRACE( TL_N, TM_Init,
  1001. ( "Reg: Name %s", &pAdapter->AdapterName));
  1002. return status;
  1003. }
  1004. NDIS_STATUS
  1005. nicQueryInformation(
  1006. IN ADAPTERCB* pAdapter,
  1007. IN VCCB* pVc,
  1008. IN OUT PNDIS_REQUEST NdisRequest
  1009. )
  1010. /*++
  1011. Routine Description:
  1012. NOTE: this function can be called in at least two contexts:
  1013. 1: in the context of an NdisRequest
  1014. 2: in the context of our own work item, if the request needs to be completed
  1015. at passive.
  1016. Arguments:
  1017. Return Value:
  1018. --*/
  1019. {
  1020. NDIS_STATUS status;
  1021. ULONG ulInfo;
  1022. VOID* pInfo;
  1023. ULONG ulInfoLen;
  1024. USHORT usInfo;
  1025. NDIS_OID Oid;
  1026. PVOID InformationBuffer;
  1027. ULONG InformationBufferLength;
  1028. PULONG BytesWritten;
  1029. PULONG BytesNeeded;
  1030. NDIS_CO_LINK_SPEED CoLinkSpeed;
  1031. NIC1394_LOCAL_NODE_INFO LocalNodeInfo;
  1032. NIC1394_VC_INFO VcInfo;
  1033. NDIS_PNP_CAPABILITIES PnpCaps;
  1034. NIC1394_NICINFO NicInfo;
  1035. Oid = NdisRequest->DATA.QUERY_INFORMATION.Oid;
  1036. InformationBuffer = NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
  1037. InformationBufferLength =
  1038. NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;
  1039. BytesWritten = &NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
  1040. BytesNeeded = &NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;
  1041. // The next variables are used to setup the data structures that are
  1042. // used to respond to the OIDs they correspond to
  1043. //
  1044. TRACE( TL_T, TM_Init, ( "==>nicQueryInformation, Adapter %.8x, Vc %.8x, Oid %.8x",pAdapter, pVc, Oid ));
  1045. // The cases in this switch statement find or create a buffer containing
  1046. // the requested information and point 'pInfo' at it, noting it's length
  1047. // in 'ulInfoLen'. Since many of the OIDs return a ULONG, a 'ulInfo'
  1048. // buffer is set up as the default.
  1049. //
  1050. ulInfo = 0;
  1051. pInfo = &ulInfo;
  1052. ulInfoLen = sizeof(ulInfo);
  1053. status = NDIS_STATUS_SUCCESS;
  1054. switch (Oid)
  1055. {
  1056. case OID_GEN_CO_SUPPORTED_LIST:
  1057. {
  1058. pInfo = &SupportedOids[0];
  1059. ulInfoLen = sizeof(SupportedOids);
  1060. break;
  1061. }
  1062. case OID_GEN_CO_HARDWARE_STATUS:
  1063. {
  1064. //
  1065. // Copy the hardware status into the users buffer.
  1066. //
  1067. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_CO_HARDWARE_STATUS)" ) );
  1068. NdisAcquireSpinLock (&pAdapter->lock);
  1069. pInfo = (PUCHAR) &pAdapter->HardwareStatus;
  1070. NdisReleaseSpinLock (&pAdapter->lock);
  1071. ulInfoLen = sizeof(pAdapter->HardwareStatus);
  1072. break;
  1073. }
  1074. case OID_GEN_MAXIMUM_LOOKAHEAD:
  1075. {
  1076. // Report the maximum number of bytes we can always provide as
  1077. // lookahead data on receive indications. We always indicate full
  1078. // packets so this is the same as the receive block size. And
  1079. // since we always allocate enough for a full packet, the receive
  1080. // block size is the same as the frame size.
  1081. //
  1082. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_MAXIMUM_LOOKAHEAD)" ) );
  1083. ulInfo = Nic1394_MaxFrameSize;
  1084. break;
  1085. }
  1086. case OID_GEN_CO_MAC_OPTIONS:
  1087. {
  1088. // Report a bitmask defining optional properties of the driver.
  1089. //
  1090. // NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA promises that our receive
  1091. // buffer is not on a device-specific card.
  1092. //
  1093. // NDIS_MAC_OPTION_TRANSFERS_NOT_PEND promises we won't return
  1094. // NDIS_STATUS_PENDING from our TransferData handler which is true
  1095. // since we don't have one.
  1096. //
  1097. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_CO_MAC_OPTIONS)" ) );
  1098. ulInfo = 0;
  1099. break;
  1100. }
  1101. case OID_GEN_CO_MEDIA_SUPPORTED:
  1102. case OID_GEN_CO_MEDIA_IN_USE:
  1103. {
  1104. //
  1105. // We support 1394.
  1106. //
  1107. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_CO_MEDIA_SUPPORTED or OID_GEN_CO_MEDIA_IN_USE)" ) );
  1108. ulInfo = g_ulMedium;
  1109. break;
  1110. }
  1111. case OID_GEN_CO_MINIMUM_LINK_SPEED:
  1112. {
  1113. //
  1114. // Link speed depends upon the type of adapter. We will need to
  1115. // add support for different speeds and so forth
  1116. //
  1117. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_CO_MINIMUM_LINK_SPEED or OID_GEN_CO_LINK_SPEED)" ) );
  1118. CoLinkSpeed.Inbound = CoLinkSpeed.Outbound = pAdapter->SpeedMbps; //10 Mbps ????
  1119. pInfo = (PUCHAR)&CoLinkSpeed;
  1120. ulInfoLen = sizeof(CoLinkSpeed);
  1121. TRACE( TL_V, TM_Mp, ( "Link Speed %x" ,CoLinkSpeed.Outbound ) );
  1122. break;
  1123. }
  1124. case OID_GEN_CO_VENDOR_ID:
  1125. {
  1126. //
  1127. // We need to add the appropriate vendor id for the nic1394
  1128. //
  1129. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_CO_VENDOR_ID)" ) );
  1130. ulInfo = 0xFFFFFFFF;
  1131. break;
  1132. }
  1133. case OID_GEN_CO_VENDOR_DESCRIPTION:
  1134. {
  1135. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_CO_VENDOR_DESCRIPTION)" ) );
  1136. pInfo = (PUCHAR)pnic1394DriverDescription;
  1137. ulInfoLen = strlen(pnic1394DriverDescription);
  1138. break;
  1139. }
  1140. case OID_GEN_VENDOR_DRIVER_VERSION:
  1141. {
  1142. pInfo =(PVOID) &nic1394DriverGeneration;
  1143. ulInfoLen = sizeof(nic1394DriverGeneration);
  1144. break;
  1145. }
  1146. case OID_GEN_CO_DRIVER_VERSION:
  1147. {
  1148. //
  1149. // Return the version of NDIS that we expect.
  1150. //
  1151. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_CO_DRIVER_VERSION)" ) );
  1152. usInfo = ((NDIS_MajorVersion << 8) | NDIS_MinorVersion);
  1153. pInfo = (PUCHAR)&usInfo;
  1154. ulInfoLen = sizeof(USHORT);
  1155. break;
  1156. }
  1157. case OID_GEN_CO_PROTOCOL_OPTIONS:
  1158. {
  1159. //
  1160. // We don't support protocol options.
  1161. //
  1162. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_CO_PROTOCOL_OPTIONS)" ) );
  1163. ulInfo = 0;
  1164. break;
  1165. }
  1166. case OID_GEN_CO_MEDIA_CONNECT_STATUS:
  1167. {
  1168. //
  1169. // Return our true state only if we have ever received a
  1170. // remote node in this boot.
  1171. //
  1172. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_CO_MEDIA_CONNECT_STATUS)" ) );
  1173. if (ADAPTER_TEST_FLAG(pAdapter, fADAPTER_RemoteNodeInThisBoot) == FALSE)
  1174. {
  1175. ulInfo = NdisMediaStateConnected;
  1176. }
  1177. else
  1178. {
  1179. ulInfo = pAdapter->MediaConnectStatus;
  1180. }
  1181. break;
  1182. }
  1183. case OID_1394_IP1394_CONNECT_STATUS:
  1184. {
  1185. //
  1186. // Return whether or not we have a link. This is used by the Arp
  1187. // module to set connectivity
  1188. //
  1189. TRACE( TL_V, TM_Mp, ( "QInfo(OID_1394_IP1394_CONNECT_STATUS)" ) );
  1190. ulInfo = pAdapter->MediaConnectStatus;
  1191. break;
  1192. }
  1193. case OID_1394_LOCAL_NODE_INFO:
  1194. {
  1195. // This Oid return information about the local node
  1196. // on the machine
  1197. // Need to change this with real values that will be present
  1198. // in the header structures
  1199. //
  1200. TRACE( TL_V, TM_Mp, ( "QInfo(OID_1394_LOCAL_NODE_INFO)" ) );
  1201. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1202. LocalNodeInfo.UniqueID = pAdapter->UniqueId;
  1203. LocalNodeInfo.BusGeneration = pAdapter->Generation;
  1204. LocalNodeInfo.NodeAddress = pAdapter->NodeAddress;
  1205. LocalNodeInfo.MaxRecvBlockSize = pAdapter->MaxRec;
  1206. LocalNodeInfo.MaxRecvSpeed = pAdapter->SCode;
  1207. ADAPTER_RELEASE_LOCK (pAdapter);
  1208. pInfo = &LocalNodeInfo;
  1209. ulInfoLen = sizeof(LocalNodeInfo);
  1210. break;
  1211. }
  1212. case OID_1394_VC_INFO:
  1213. {
  1214. // Returns information about the VC that is being queried
  1215. //
  1216. TRACE( TL_V, TM_Mp, ("QInfo(OID_1394_VC_INFO)") );
  1217. if (pVc != NULL)
  1218. {
  1219. VcInfo.Destination = pVc->Hdr.Nic1394MediaParams.Destination;
  1220. pInfo = &VcInfo;
  1221. ulInfoLen = sizeof(VcInfo);
  1222. }
  1223. else
  1224. {
  1225. status = NDIS_STATUS_FAILURE;
  1226. }
  1227. break;
  1228. }
  1229. case OID_1394_NICINFO:
  1230. {
  1231. if (InformationBufferLength >= sizeof(NicInfo))
  1232. {
  1233. //
  1234. // We need to call nicFillNicInfo at passive, so we switch
  1235. // to a work item context.
  1236. //
  1237. if (KeGetCurrentIrql() > PASSIVE_LEVEL)
  1238. {
  1239. PNIC_WORK_ITEM pNicWorkItem;
  1240. pNicWorkItem = ALLOC_NONPAGED (sizeof(NIC_WORK_ITEM), MTAG_WORKITEM);
  1241. if (pNicWorkItem != NULL)
  1242. {
  1243. NdisZeroMemory(pNicWorkItem, sizeof(*pNicWorkItem));
  1244. pNicWorkItem->RequestInfo.pNdisRequest = NdisRequest;
  1245. pNicWorkItem->RequestInfo.pVc = NULL;
  1246. NdisInitializeWorkItem ( &pNicWorkItem->NdisWorkItem,
  1247. (NDIS_PROC) nicQueryInformationWorkItem,
  1248. (PVOID) pAdapter);
  1249. TRACE( TL_V, TM_Cm, ( "Scheduling QueryInformation WorkItem" ) );
  1250. nicReferenceAdapter (pAdapter, "nicFillBusInfo ");
  1251. NdisInterlockedIncrement(&pAdapter->OutstandingWorkItems);
  1252. NdisScheduleWorkItem (&pNicWorkItem->NdisWorkItem);
  1253. status = NDIS_STATUS_PENDING;
  1254. }
  1255. else
  1256. {
  1257. status = NDIS_STATUS_RESOURCES;
  1258. }
  1259. }
  1260. else
  1261. {
  1262. status = nicFillNicInfo (
  1263. pAdapter,
  1264. (PNIC1394_NICINFO) InformationBuffer, // Input
  1265. &NicInfo // Output
  1266. );
  1267. ASSERT(status != NDIS_STATUS_PENDING);
  1268. }
  1269. }
  1270. pInfo = &NicInfo;
  1271. ulInfoLen = sizeof(NicInfo);
  1272. break;
  1273. }
  1274. case OID_1394_QUERY_EUID_NODE_MAP:
  1275. {
  1276. if (sizeof (EUID_TOPOLOGY) <= InformationBufferLength )
  1277. {
  1278. nicQueryEuidNodeMacMap (pAdapter, NdisRequest);
  1279. status = NDIS_STATUS_PENDING;
  1280. }
  1281. else
  1282. {
  1283. //
  1284. // This will cause NDIS_STATUS_INVALID_LENGTH to be returned
  1285. //
  1286. ulInfoLen = sizeof (EUID_TOPOLOGY);
  1287. }
  1288. break;
  1289. }
  1290. case OID_GEN_CO_XMIT_PDUS_OK:
  1291. {
  1292. ulInfo = pAdapter->AdaptStats.ulXmitOk;
  1293. break;
  1294. }
  1295. case OID_GEN_CO_RCV_PDUS_OK:
  1296. {
  1297. ulInfo = pAdapter->AdaptStats.ulRcvOk;
  1298. break;
  1299. }
  1300. case OID_GEN_CO_XMIT_PDUS_ERROR:
  1301. {
  1302. ulInfo = pAdapter->AdaptStats.ulXmitError;
  1303. break;
  1304. }
  1305. case OID_GEN_CO_RCV_PDUS_ERROR:
  1306. {
  1307. ulInfo = pAdapter->AdaptStats.ulRcvError;
  1308. break;
  1309. }
  1310. case OID_GEN_CO_RCV_PDUS_NO_BUFFER:
  1311. {
  1312. ulInfo = 0;
  1313. break;
  1314. }
  1315. case OID_GEN_PHYSICAL_MEDIUM:
  1316. {
  1317. TRACE( TL_V, TM_Mp, ( " OID_GEN_PHYSICAL_MEDIUM" ) );
  1318. ulInfo = NdisPhysicalMedium1394;
  1319. break;
  1320. }
  1321. case OID_1394_ISSUE_BUS_RESET:
  1322. {
  1323. TRACE( TL_V, TM_Mp, ( " OID_1394_ISSUE_BUS_RESET" ) );
  1324. //
  1325. // The ndistester is currently the only user of this oid and does not set the flag
  1326. //
  1327. if (InformationBufferLength == sizeof(ULONG))
  1328. {
  1329. nicIssueBusReset (pAdapter, BUS_RESET_FLAGS_FORCE_ROOT );
  1330. }
  1331. break;
  1332. }
  1333. case OID_PNP_CAPABILITIES:
  1334. {
  1335. TRACE( TL_V, TM_Mp, ("QInfo(OID_PNP_CAPABILITIES)") );
  1336. PnpCaps.Flags = 0;
  1337. PnpCaps.WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
  1338. PnpCaps.WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
  1339. PnpCaps.WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
  1340. pInfo = &PnpCaps;
  1341. ulInfoLen = sizeof (PnpCaps);
  1342. break;
  1343. }
  1344. case OID_PNP_QUERY_POWER:
  1345. {
  1346. //
  1347. // The miniport is always ready to go into low power state.
  1348. //
  1349. *BytesWritten = sizeof (NDIS_DEVICE_POWER_STATE );
  1350. *BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE );
  1351. status = NDIS_STATUS_SUCCESS;
  1352. break;
  1353. }
  1354. //
  1355. // Now do the Ethernet OIDS
  1356. //
  1357. case OID_GEN_CURRENT_LOOKAHEAD:
  1358. case OID_GEN_MAXIMUM_FRAME_SIZE:
  1359. case OID_GEN_MAXIMUM_TOTAL_SIZE:
  1360. case OID_GEN_TRANSMIT_BLOCK_SIZE:
  1361. case OID_GEN_RECEIVE_BLOCK_SIZE:
  1362. case OID_GEN_MAXIMUM_SEND_PACKETS:
  1363. case OID_GEN_TRANSMIT_BUFFER_SPACE:
  1364. case OID_GEN_RECEIVE_BUFFER_SPACE:
  1365. case OID_802_3_PERMANENT_ADDRESS:
  1366. case OID_802_3_CURRENT_ADDRESS:
  1367. case OID_802_3_MULTICAST_LIST:
  1368. case OID_802_3_MAXIMUM_LIST_SIZE:
  1369. case OID_802_3_RCV_ERROR_ALIGNMENT:
  1370. case OID_802_3_XMIT_ONE_COLLISION:
  1371. case OID_802_3_XMIT_MORE_COLLISIONS:
  1372. case OID_GEN_LINK_SPEED:
  1373. case OID_GEN_CURRENT_PACKET_FILTER:
  1374. {
  1375. status = NicEthQueryInformation((NDIS_HANDLE)pAdapter,
  1376. Oid,
  1377. InformationBuffer,
  1378. InformationBufferLength,
  1379. BytesWritten,
  1380. BytesNeeded
  1381. );
  1382. if (status == NDIS_STATUS_SUCCESS)
  1383. {
  1384. pInfo = InformationBuffer;
  1385. ulInfoLen = *BytesWritten;
  1386. }
  1387. else
  1388. {
  1389. if (status == NDIS_STATUS_INVALID_LENGTH)
  1390. {
  1391. ulInfoLen = *BytesNeeded;
  1392. }
  1393. else
  1394. {
  1395. status = NDIS_STATUS_NOT_SUPPORTED;
  1396. TRACE( TL_V, TM_Mp, ( "Q-OID=$%08x?", Oid ) );
  1397. }
  1398. }
  1399. break;
  1400. }
  1401. default:
  1402. {
  1403. TRACE( TL_V, TM_Mp, ( "Q-OID=$%08x?", Oid ) );
  1404. status = NDIS_STATUS_NOT_SUPPORTED;
  1405. ulInfoLen = 0;
  1406. break;
  1407. }
  1408. }
  1409. if (ulInfoLen > InformationBufferLength)
  1410. {
  1411. // Caller's buffer is too small. Tell him what he needs.
  1412. //
  1413. *BytesNeeded = ulInfoLen;
  1414. *BytesWritten = 0;
  1415. status = NDIS_STATUS_INVALID_LENGTH;
  1416. }
  1417. else
  1418. {
  1419. //
  1420. // If the request has not been pended then, fill
  1421. // out the retuen values
  1422. //
  1423. if (status == NDIS_STATUS_SUCCESS )
  1424. {
  1425. // Copy the found result to caller's buffer.
  1426. //
  1427. if (ulInfoLen > 0)
  1428. {
  1429. NdisMoveMemory( InformationBuffer, pInfo, ulInfoLen );
  1430. DUMPDW( TL_V, TM_Mp, pInfo, ulInfoLen );
  1431. }
  1432. *BytesNeeded = *BytesWritten = ulInfoLen;
  1433. }
  1434. }
  1435. TRACE( TL_N, TM_Mp, ( " Q-OID=$%08x, Status %x, Bytes Written %x", Oid, status, *BytesWritten ) );
  1436. TRACE( TL_T, TM_Init, ( "<==nicQueryInformation, Status %.8x", status ));
  1437. return status;
  1438. }
  1439. VOID
  1440. nicReferenceAdapter(
  1441. IN ADAPTERCB* pAdapter ,
  1442. IN PCHAR pDebugPrint
  1443. )
  1444. /*++
  1445. Routine Description:
  1446. Arguments:
  1447. Return Value:
  1448. --*/
  1449. // Adds areference to the adapter block, 'pAdapter'.
  1450. //
  1451. {
  1452. LONG lRef;
  1453. lRef = NdisInterlockedIncrement( &pAdapter->lRef );
  1454. TRACE( TL_V, TM_Ref, ( "**nicReferenceAdapter pAdapter %x, to %d, %s ", pAdapter, pAdapter->lRef, pDebugPrint ) );
  1455. }
  1456. NDIS_STATUS
  1457. nicSetInformation(
  1458. IN ADAPTERCB* pAdapter,
  1459. IN VCCB* pVc,
  1460. IN OUT PNDIS_REQUEST NdisRequest
  1461. )
  1462. /*++
  1463. Routine Description:
  1464. Handle SetInformation requests. Arguments are as for the standard NDIS
  1465. 'MiniportQueryInformation' handler except this routine does not count
  1466. on being serialized with respect to other requests.
  1467. Arguments:
  1468. Return Value:
  1469. --*/
  1470. {
  1471. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1472. ULONG ulInfo = 0;
  1473. VOID* pInfo= NULL;
  1474. ULONG ulInfoLen= 0;
  1475. USHORT usInfo = 0;
  1476. NDIS_OID Oid;
  1477. PVOID InformationBuffer;
  1478. ULONG InformationBufferLength;
  1479. PULONG BytesRead;
  1480. PULONG BytesNeeded;
  1481. //
  1482. // Initialize the REquest Variables
  1483. //
  1484. Oid = NdisRequest->DATA.SET_INFORMATION.Oid;
  1485. InformationBuffer = NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
  1486. InformationBufferLength =
  1487. NdisRequest->DATA.SET_INFORMATION.InformationBufferLength;
  1488. BytesRead = &NdisRequest->DATA.SET_INFORMATION.BytesRead;
  1489. BytesNeeded = &NdisRequest->DATA.SET_INFORMATION.BytesNeeded;
  1490. TRACE( TL_T, TM_Init, ( "==>nicSetInformation , Adapter %.8x, Vc %.8x, Oid %.8x",pAdapter, pVc, Oid ));
  1491. Status = NDIS_STATUS_SUCCESS;
  1492. switch (Oid)
  1493. {
  1494. case OID_GEN_CURRENT_PACKET_FILTER:
  1495. {
  1496. ULONG Filter;
  1497. if (InformationBufferLength < sizeof (ULONG))
  1498. {
  1499. Status = NDIS_STATUS_INVALID_LENGTH;
  1500. break;
  1501. }
  1502. else
  1503. {
  1504. *BytesNeeded = sizeof (ULONG);
  1505. }
  1506. //
  1507. // Store the new value.
  1508. //
  1509. NdisMoveMemory(&Filter, InformationBuffer, sizeof(ULONG));
  1510. //
  1511. // Don't allow promisc mode, because we can't support that.
  1512. //
  1513. if (Filter & NDIS_PACKET_TYPE_PROMISCUOUS)
  1514. {
  1515. Status = NDIS_STATUS_FAILURE;
  1516. break;
  1517. }
  1518. pAdapter->CurPacketFilter = Filter;
  1519. Status = NDIS_STATUS_SUCCESS;
  1520. ulInfoLen = sizeof (ULONG);
  1521. break;
  1522. }
  1523. case OID_1394_ENTER_BRIDGE_MODE:
  1524. {
  1525. *BytesNeeded = 0;
  1526. nicInitializeLoadArpStruct(pAdapter);
  1527. Status = nicQueueRequestToArp (pAdapter,
  1528. LoadArp, // Load Arp Module
  1529. NdisRequest);
  1530. if (Status == NDIS_STATUS_SUCCESS)
  1531. {
  1532. //
  1533. // we have successfully queued a Workitem
  1534. // so this request needs to be pended
  1535. //
  1536. Status = NDIS_STATUS_PENDING;
  1537. }
  1538. ulInfoLen = sizeof (ULONG);
  1539. break;
  1540. }
  1541. case OID_1394_EXIT_BRIDGE_MODE:
  1542. {
  1543. *BytesNeeded = 0;
  1544. if (pAdapter->fIsArpStarted == TRUE)
  1545. {
  1546. Status = nicQueueRequestToArp (pAdapter,
  1547. UnloadArp, //Unload Arp Module
  1548. NdisRequest);
  1549. if (Status == NDIS_STATUS_SUCCESS)
  1550. {
  1551. //
  1552. // we have successfully queued a Workitem
  1553. // so this request needs to be pended
  1554. //
  1555. Status = NDIS_STATUS_PENDING;
  1556. }
  1557. ulInfoLen = sizeof (ULONG);
  1558. }
  1559. else
  1560. {
  1561. Status = NDIS_STATUS_SUCCESS;
  1562. ulInfoLen = sizeof (ULONG);
  1563. }
  1564. break;
  1565. }
  1566. case OID_802_3_MULTICAST_LIST:
  1567. case OID_GEN_CURRENT_LOOKAHEAD:
  1568. case OID_GEN_NETWORK_LAYER_ADDRESSES:
  1569. {
  1570. Status = NicEthSetInformation(pAdapter,
  1571. Oid,
  1572. InformationBuffer,
  1573. InformationBufferLength,
  1574. BytesRead ,
  1575. BytesNeeded
  1576. );
  1577. break;
  1578. }
  1579. case OID_1394_ISSUE_BUS_RESET:
  1580. {
  1581. TRACE( TL_V, TM_Mp, ( " OID_1394_ISSUE_BUS_RESET" ) );
  1582. //
  1583. // The ndistester is currently the only user of this oid and does not set the flag
  1584. //
  1585. if (InformationBufferLength == sizeof(ULONG))
  1586. {
  1587. nicIssueBusReset (pAdapter, BUS_RESET_FLAGS_FORCE_ROOT );
  1588. }
  1589. break;
  1590. }
  1591. case OID_PNP_SET_POWER:
  1592. TRACE( TL_V, TM_Mp, ( "QInfo OID_PNP_SET_POWER %x", Oid ) );
  1593. *BytesRead = sizeof (NDIS_DEVICE_POWER_STATE );
  1594. *BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE );
  1595. if (InformationBufferLength >= sizeof (NDIS_DEVICE_POWER_STATE))
  1596. {
  1597. NDIS_DEVICE_POWER_STATE PoState;
  1598. NdisMoveMemory (&PoState,InformationBuffer,sizeof (PoState));
  1599. Status = nicSetPower(pAdapter,PoState);
  1600. }
  1601. break;
  1602. default:
  1603. {
  1604. TRACE( TL_A, TM_Mp, ( "S-OID=$%08x?", Oid ) );
  1605. Status = NDIS_STATUS_NOT_SUPPORTED;
  1606. *BytesRead = *BytesNeeded = 0;
  1607. break;
  1608. }
  1609. }
  1610. if (*BytesNeeded > InformationBufferLength)
  1611. {
  1612. // Caller's buffer is too small. Tell him what he needs.
  1613. //
  1614. *BytesRead = 0;
  1615. Status = NDIS_STATUS_INVALID_LENGTH;
  1616. }
  1617. else
  1618. {
  1619. *BytesNeeded = *BytesRead = ulInfoLen;
  1620. }
  1621. TRACE( TL_A, TM_Mp, ( " S-OID=$%08x, Status %x, Bytes Read %x", Oid, Status, *BytesRead ) );
  1622. TRACE( TL_T, TM_Init, ( "<==nicSetInformation, Status %.8x", Status ));
  1623. return Status;
  1624. }
  1625. //------------------------------------------------------------------------------
  1626. // C O N N E C T I O N L E S S F U N T I O N S S T A R T H E R E
  1627. //
  1628. NDIS_STATUS
  1629. NicEthSetInformation(
  1630. IN NDIS_HANDLE MiniportAdapterContext,
  1631. NDIS_OID Oid,
  1632. PVOID InformationBuffer,
  1633. ULONG InformationBufferLength,
  1634. PULONG BytesRead,
  1635. PULONG BytesNeeded
  1636. )
  1637. /*++
  1638. Routine Description:
  1639. This is the Set information that will be used by the CL edge
  1640. Arguments:
  1641. Return Value:
  1642. --*/
  1643. {
  1644. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  1645. UINT BytesLeft = InformationBufferLength;
  1646. PUCHAR InfoBuffer = (PUCHAR)(InformationBuffer);
  1647. UINT OidLength;
  1648. ULONG LookAhead;
  1649. ULONG Filter;
  1650. PADAPTERCB pAdapter;
  1651. BOOLEAN IsShuttingDown;
  1652. STORE_CURRENT_IRQL;
  1653. pAdapter = (PADAPTERCB)MiniportAdapterContext;
  1654. TRACE( TL_T, TM_Init, ( "==>nicEthSetInformation , Adapter %.8x, Oid %.8x",pAdapter, Oid ));
  1655. //
  1656. // IS the adapter shutting down
  1657. //
  1658. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1659. IsShuttingDown = (! ADAPTER_ACTIVE(pAdapter)) ;
  1660. ADAPTER_RELEASE_LOCK (pAdapter);
  1661. if (IsShuttingDown)
  1662. {
  1663. TRACE( TL_T, TM_Init, ( " nicSetInformation Shutting Down , Adapter %.8x, Oid %.8x",pAdapter, Oid ));
  1664. *BytesRead = 0;
  1665. *BytesNeeded = 0;
  1666. NdisStatus = NDIS_STATUS_SUCCESS;
  1667. return (NdisStatus);
  1668. }
  1669. //
  1670. // Get Oid and Length of request
  1671. //
  1672. OidLength = BytesLeft;
  1673. switch (Oid)
  1674. {
  1675. case OID_802_3_MULTICAST_LIST:
  1676. if (OidLength % sizeof(MAC_ADDRESS))
  1677. {
  1678. NdisStatus = NDIS_STATUS_INVALID_LENGTH;
  1679. *BytesRead = 0;
  1680. *BytesNeeded = 0;
  1681. break;
  1682. }
  1683. if (OidLength > (MCAST_LIST_SIZE * sizeof(MAC_ADDRESS)))
  1684. {
  1685. NdisStatus= NDIS_STATUS_MULTICAST_FULL;
  1686. *BytesRead = 0;
  1687. *BytesNeeded = 0;
  1688. break;
  1689. }
  1690. NdisZeroMemory(
  1691. &pAdapter->McastAddrs[0],
  1692. MCAST_LIST_SIZE * sizeof(MAC_ADDRESS)
  1693. );
  1694. NdisMoveMemory(
  1695. &pAdapter->McastAddrs[0],
  1696. InfoBuffer,
  1697. OidLength
  1698. );
  1699. pAdapter->McastAddrCount = OidLength / sizeof(MAC_ADDRESS);
  1700. break;
  1701. case OID_GEN_CURRENT_PACKET_FILTER:
  1702. //
  1703. // Verify length
  1704. //
  1705. if (OidLength != sizeof(ULONG))
  1706. {
  1707. NdisStatus = NDIS_STATUS_INVALID_LENGTH;
  1708. *BytesRead = 0;
  1709. *BytesNeeded = sizeof(ULONG);
  1710. break;
  1711. }
  1712. //
  1713. // Store the new value.
  1714. //
  1715. NdisMoveMemory(&Filter, InfoBuffer, sizeof(ULONG));
  1716. //
  1717. // Don't allow promisc mode, because we can't support that.
  1718. //
  1719. if (Filter & NDIS_PACKET_TYPE_PROMISCUOUS)
  1720. {
  1721. NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
  1722. break;
  1723. }
  1724. ADAPTER_ACQUIRE_LOCK (pAdapter);
  1725. pAdapter->CurPacketFilter = Filter;
  1726. ADAPTER_RELEASE_LOCK (pAdapter);
  1727. break;
  1728. case OID_GEN_CURRENT_LOOKAHEAD:
  1729. //
  1730. // Verify length
  1731. //
  1732. if (OidLength != 4)
  1733. {
  1734. NdisStatus = NDIS_STATUS_INVALID_LENGTH;
  1735. *BytesRead = 0;
  1736. *BytesNeeded = 0;
  1737. break;
  1738. }
  1739. //
  1740. // Store the new value.
  1741. //
  1742. NdisMoveMemory(&LookAhead, InfoBuffer, sizeof(LookAhead));
  1743. pAdapter->CurLookAhead = LookAhead;
  1744. break;
  1745. case OID_GEN_NETWORK_LAYER_ADDRESSES:
  1746. NdisStatus = NDIS_STATUS_SUCCESS;
  1747. *BytesRead = InformationBufferLength;
  1748. *BytesNeeded = InformationBufferLength;
  1749. break;
  1750. case OID_PNP_SET_POWER:
  1751. TRACE( TL_V, TM_Mp, ( "QInfo OID_PNP_SET_POWER %x", Oid ) );
  1752. *BytesRead = sizeof (NDIS_DEVICE_POWER_STATE );
  1753. *BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE );
  1754. if (InformationBufferLength >= sizeof (NDIS_DEVICE_POWER_STATE))
  1755. {
  1756. NDIS_DEVICE_POWER_STATE PoState;
  1757. NdisMoveMemory (&PoState,InformationBuffer,sizeof (PoState));
  1758. NdisStatus = nicSetPower(pAdapter,PoState);
  1759. }
  1760. break;
  1761. case OID_1394_ISSUE_BUS_RESET:
  1762. {
  1763. TRACE( TL_V, TM_Mp, ( " OID_1394_ISSUE_BUS_RESET" ) );
  1764. if (InformationBufferLength == sizeof(ULONG))
  1765. {
  1766. nicIssueBusReset (pAdapter, (*(PULONG)InformationBuffer));
  1767. }
  1768. else
  1769. {
  1770. nicIssueBusReset (pAdapter, BUS_RESET_FLAGS_FORCE_ROOT );
  1771. }
  1772. break;
  1773. }
  1774. default:
  1775. NdisStatus = NDIS_STATUS_INVALID_OID;
  1776. *BytesRead = 0;
  1777. *BytesNeeded = 0;
  1778. break;
  1779. }
  1780. if (NdisStatus == NDIS_STATUS_SUCCESS)
  1781. {
  1782. DUMPDW( TL_V, TM_Mp, InformationBuffer, InformationBufferLength );
  1783. *BytesRead = BytesLeft;
  1784. *BytesNeeded = 0;
  1785. }
  1786. TRACE( TL_T, TM_Init, ( "<==NicEthSetInformation , Adapter %.8x, Oid %.8x, NdisStatus %x",pAdapter, Oid, NdisStatus ));
  1787. MATCH_IRQL;
  1788. return NdisStatus;
  1789. }
  1790. NDIS_STATUS
  1791. NicEthQueryInformation(
  1792. IN NDIS_HANDLE MiniportAdapterContext,
  1793. IN NDIS_OID Oid,
  1794. IN PVOID InformationBuffer,
  1795. IN ULONG InformationBufferLength,
  1796. OUT PULONG BytesWritten,
  1797. OUT PULONG BytesNeeded
  1798. )
  1799. /*++
  1800. Routine Description:
  1801. This is the Query information that will be used by the CL edge
  1802. Arguments:
  1803. Return Value:
  1804. --*/
  1805. {
  1806. UINT BytesLeft = InformationBufferLength;
  1807. PUCHAR InfoBuffer = (PUCHAR)(InformationBuffer);
  1808. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  1809. NDIS_HARDWARE_STATUS HardwareStatus = NdisHardwareStatusReady;
  1810. NDIS_MEDIA_STATE MediaState;
  1811. NDIS_MEDIUM Medium;
  1812. PADAPTERCB pAdapter;
  1813. ULONG GenericULong;
  1814. USHORT GenericUShort;
  1815. UCHAR GenericArray[6];
  1816. UINT MoveBytes = sizeof(GenericULong);
  1817. PVOID MoveSource = (PVOID)(&GenericULong);
  1818. ULONG i;
  1819. STORE_CURRENT_IRQL;
  1820. pAdapter = (PADAPTERCB)MiniportAdapterContext;
  1821. TRACE( TL_T, TM_Init, ( "==>NicEthQueryInformation , Adapter %.8x, Oid %.8x",pAdapter, Oid ));
  1822. //
  1823. // Switch on request type
  1824. //
  1825. switch (Oid)
  1826. {
  1827. case OID_GEN_MAC_OPTIONS:
  1828. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_MAC_OPTIONS)" ) );
  1829. GenericULong = NDIS_MAC_OPTION_NO_LOOPBACK;
  1830. break;
  1831. case OID_GEN_SUPPORTED_LIST:
  1832. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_SUPPORTED_LIST)" ) );
  1833. MoveSource = (PVOID)(SupportedOids);
  1834. MoveBytes = sizeof(SupportedOids);
  1835. break;
  1836. case OID_GEN_HARDWARE_STATUS:
  1837. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_HARDWARE_STATUS)" ) );
  1838. HardwareStatus = NdisHardwareStatusReady;
  1839. MoveSource = (PVOID)(&HardwareStatus);
  1840. MoveBytes = sizeof(NDIS_HARDWARE_STATUS);
  1841. break;
  1842. case OID_GEN_MEDIA_CONNECT_STATUS:
  1843. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_MEDIA_CONNECT_STATUS)" ) );
  1844. if (ADAPTER_TEST_FLAG(pAdapter, fADAPTER_RemoteNodeInThisBoot) == FALSE)
  1845. {
  1846. MediaState = NdisMediaStateConnected;
  1847. }
  1848. else
  1849. {
  1850. MediaState = pAdapter->MediaConnectStatus;
  1851. }
  1852. MoveSource = (PVOID)(&MediaState);
  1853. MoveBytes = sizeof(NDIS_MEDIA_STATE);
  1854. break;
  1855. case OID_GEN_MEDIA_SUPPORTED:
  1856. case OID_GEN_MEDIA_IN_USE:
  1857. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_MEDIA_SUPPORTED)" ) );
  1858. Medium = g_ulMedium;
  1859. MoveSource = (PVOID) (&Medium);
  1860. MoveBytes = sizeof(NDIS_MEDIUM);
  1861. break;
  1862. case OID_GEN_MAXIMUM_LOOKAHEAD:
  1863. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_MAXIMUM_LOOKAHEAD)" ) );
  1864. GenericULong = pAdapter->MaxRecvBufferSize;
  1865. break;
  1866. case OID_GEN_CURRENT_LOOKAHEAD:
  1867. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_CURRENT_LOOKAHEAD)" ) );
  1868. GenericULong = pAdapter->MaxRecvBufferSize;
  1869. break;
  1870. case OID_GEN_MAXIMUM_FRAME_SIZE:
  1871. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_MAXIMUM_FRAME_SIZE)" ) );
  1872. GenericULong = IP1394_RFC_FRAME_SIZE; //pAdapter->MaxRecvBufferSize;
  1873. break;
  1874. case OID_GEN_MAXIMUM_TOTAL_SIZE:
  1875. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_MAXIMUM_TOTAL_SIZE)" ) );
  1876. GenericULong = IP1394_RFC_FRAME_SIZE; //pAdapter->MaxRecvBufferSize;
  1877. break;
  1878. case OID_GEN_TRANSMIT_BLOCK_SIZE:
  1879. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_TRANSMIT_BLOCK_SIZE)" ) );
  1880. GenericULong = pAdapter->MaxRecvBufferSize - sizeof (NDIS1394_UNFRAGMENTED_HEADER);
  1881. break;
  1882. case OID_GEN_RECEIVE_BLOCK_SIZE:
  1883. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_RECEIVE_BLOCK_SIZE)" ) );
  1884. GenericULong = pAdapter->MaxRecvBufferSize - sizeof (NDIS1394_UNFRAGMENTED_HEADER);
  1885. break;
  1886. case OID_GEN_MAXIMUM_SEND_PACKETS:
  1887. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_MAXIMUM_SEND_PACKETS)" ) );
  1888. GenericULong = 32; // XXX What is our limit? From adapter?
  1889. break;
  1890. case OID_GEN_LINK_SPEED:
  1891. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_LINK_SPEED)" ) );
  1892. GenericULong = pAdapter->SpeedMbps;
  1893. break;
  1894. case OID_GEN_TRANSMIT_BUFFER_SPACE:
  1895. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_TRANSMIT_BUFFER_SPACE)" ) );
  1896. GenericULong = pAdapter->MaxSendBufferSize;;
  1897. break;
  1898. case OID_GEN_RECEIVE_BUFFER_SPACE:
  1899. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_RECEIVE_BUFFER_SPACE)" ) );
  1900. GenericULong = pAdapter->MaxRecvBufferSize;
  1901. break;
  1902. case OID_GEN_VENDOR_ID:
  1903. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_VENDOR_ID)" ) );
  1904. GenericULong = 0xFFFFFFFF;
  1905. break;
  1906. case OID_GEN_VENDOR_DESCRIPTION:
  1907. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_VENDOR_DESCRIPTION)" ) );
  1908. MoveSource = pnic1394DriverDescription;
  1909. MoveBytes = strlen(pnic1394DriverDescription);
  1910. break;
  1911. case OID_GEN_DRIVER_VERSION:
  1912. case OID_GEN_VENDOR_DRIVER_VERSION:
  1913. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_DRIVER_VERSION)" ) );
  1914. GenericULong = 2;
  1915. break;
  1916. case OID_802_3_PERMANENT_ADDRESS:
  1917. case OID_802_3_CURRENT_ADDRESS:
  1918. TRACE( TL_V, TM_Mp, ( "QInfo(OID_802_3_CURRENT_ADDRESS)" ) );
  1919. NdisMoveMemory((PCHAR)GenericArray,
  1920. &pAdapter->MacAddressEth,
  1921. sizeof(MAC_ADDRESS));
  1922. MoveSource = (PVOID)(GenericArray);
  1923. MoveBytes = sizeof(MAC_ADDRESS);
  1924. break;
  1925. case OID_802_3_MULTICAST_LIST:
  1926. TRACE( TL_V, TM_Mp, ( "QInfo(OID_802_3_MULTICAST_LIST)" ) );
  1927. MoveSource = (PVOID) &pAdapter->McastAddrs[0];
  1928. MoveBytes = pAdapter->McastAddrCount * sizeof(MAC_ADDRESS);
  1929. break;
  1930. case OID_802_3_MAXIMUM_LIST_SIZE:
  1931. TRACE( TL_V, TM_Mp, ( "QInfo(OID_802_3_MAXIMUM_LIST_SIZE)" ) );
  1932. GenericULong = MCAST_LIST_SIZE;
  1933. break;
  1934. case OID_GEN_XMIT_OK:
  1935. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_XMIT_OK)" ) );
  1936. GenericULong = pAdapter->AdaptStats.ulXmitOk;;
  1937. break;
  1938. case OID_GEN_RCV_OK:
  1939. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_RCV_OK)" ) );
  1940. GenericULong = pAdapter->AdaptStats.ulRcvOk ;
  1941. break;
  1942. case OID_GEN_CURRENT_PACKET_FILTER:
  1943. TRACE( TL_V, TM_Mp, ( "QInfo(OID_GEN_CURRENT_PACKET_FILTER)" ) );
  1944. GenericULong = pAdapter->CurPacketFilter ;
  1945. break;
  1946. case OID_GEN_XMIT_ERROR:
  1947. case OID_GEN_RCV_ERROR:
  1948. case OID_GEN_RCV_NO_BUFFER:
  1949. case OID_802_3_RCV_ERROR_ALIGNMENT:
  1950. case OID_802_3_XMIT_ONE_COLLISION:
  1951. case OID_802_3_XMIT_MORE_COLLISIONS:
  1952. GenericULong = 0;
  1953. TRACE( TL_V, TM_Mp, ( "QInfo oid %x", Oid ) );
  1954. break;
  1955. case OID_PNP_QUERY_POWER:
  1956. TRACE( TL_V, TM_Mp, ( "QInfo OID_PNP_QUERY_POWER %x", Oid ) );
  1957. *BytesWritten = sizeof (NDIS_DEVICE_POWER_STATE );
  1958. *BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE );
  1959. NdisStatus = NDIS_STATUS_SUCCESS;
  1960. break;
  1961. default:
  1962. NdisStatus = NDIS_STATUS_INVALID_OID;
  1963. break;
  1964. }
  1965. if (NdisStatus == NDIS_STATUS_SUCCESS)
  1966. {
  1967. if (MoveBytes > BytesLeft)
  1968. {
  1969. //
  1970. // Not enough room in InformationBuffer. Punt
  1971. //
  1972. *BytesNeeded = MoveBytes;
  1973. NdisStatus = NDIS_STATUS_INVALID_LENGTH;
  1974. }
  1975. else
  1976. {
  1977. //
  1978. // Store result.
  1979. //
  1980. NdisMoveMemory(InfoBuffer, MoveSource, MoveBytes);
  1981. //(*BytesWritten) += MoveBytes;
  1982. *BytesWritten = MoveBytes;
  1983. DUMPDW( TL_V, TM_Mp, InfoBuffer, *BytesWritten);
  1984. }
  1985. }
  1986. TRACE( TL_T, TM_Init, ( "<==NicEthQueryInformation , Adapter %.8x, Oid %.8x, Status %x Bytes Written %x ",pAdapter, Oid, NdisStatus, *BytesWritten ));
  1987. //MATCH_IRQL;
  1988. return NdisStatus;
  1989. }
  1990. VOID
  1991. NicMpSendPackets(
  1992. IN NDIS_HANDLE MiniportAdapterContext,
  1993. IN PPNDIS_PACKET PacketArray,
  1994. IN UINT NumberOfPackets
  1995. )
  1996. /*++
  1997. Routine Description:
  1998. The is the SendPacket handler used by the ConnectionLess interface
  1999. The Bridge Protocol will send packets here and this function will
  2000. wrap the data into a new NDIS_PACKET and indicate it up on the
  2001. Ethernet VC to the ARP module
  2002. Arguments:
  2003. Return Value:
  2004. --*/
  2005. {
  2006. PADAPTERCB pAdapter = (PADAPTERCB)MiniportAdapterContext;
  2007. PETHERNET_VCCB pEthernetVc = NULL;
  2008. BOOLEAN fVcActive = FALSE;
  2009. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  2010. NDIS_STATUS IndicatedStatus = NDIS_STATUS_FAILURE;
  2011. ULONG i;
  2012. TRACE( TL_T, TM_Init, ( "==> NicMpSendPackets , Adapter %.8x, ppPacket %x, Num %x",pAdapter, PacketArray, NumberOfPackets ));
  2013. do
  2014. {
  2015. if (pAdapter->pEthernetVc == NULL)
  2016. {
  2017. break;
  2018. }
  2019. ADAPTER_ACQUIRE_LOCK (pAdapter);
  2020. pEthernetVc = pAdapter->pEthernetVc;
  2021. fVcActive = VC_ACTIVE(pEthernetVc);
  2022. if (fVcActive == TRUE)
  2023. {
  2024. for (i =0 ; i < NumberOfPackets; i++)
  2025. {
  2026. //
  2027. // Reference the Vc for each packet
  2028. //
  2029. nicReferenceCall((PVCCB)pEthernetVc, "NicMpSendPackets");
  2030. }
  2031. }
  2032. ADAPTER_RELEASE_LOCK (pAdapter);
  2033. if (fVcActive)
  2034. {
  2035. //
  2036. //Set resource and indicate the packet array up to ndis
  2037. //
  2038. for (i =0 ; i < NumberOfPackets; i++)
  2039. {
  2040. PNDIS_PACKET pMyPacket = NULL, pPacket = NULL;
  2041. PPKT_CONTEXT pPktContext = NULL;
  2042. pPacket = PacketArray[i];
  2043. //
  2044. // Now allocate a new packet
  2045. //
  2046. nicAllocatePacket (&NdisStatus,
  2047. &pMyPacket,
  2048. &pEthernetVc->PacketPool);
  2049. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2050. {
  2051. pMyPacket = NULL;
  2052. break;
  2053. }
  2054. //
  2055. // Set the original packet as the packet context
  2056. //
  2057. pPktContext = (PPKT_CONTEXT)&pMyPacket->MiniportReservedEx;
  2058. pPktContext->EthernetSend.pOrigPacket = pPacket;
  2059. IndicatedStatus = NDIS_STATUS_RESOURCES;
  2060. NDIS_SET_PACKET_STATUS (pMyPacket, IndicatedStatus);
  2061. //
  2062. // Chain the NdisBuffers
  2063. //
  2064. pMyPacket->Private.Head = pPacket->Private.Head;
  2065. pMyPacket->Private.Tail = pPacket->Private.Tail;
  2066. //
  2067. // Dump the packet
  2068. //
  2069. {
  2070. nicDumpPkt (pMyPacket, "Conn Less Send ");
  2071. nicCheckForEthArps (pMyPacket);
  2072. }
  2073. //
  2074. // We are in Ndis' context so we do not need a timer
  2075. //
  2076. NdisMCoIndicateReceivePacket(pEthernetVc->Hdr.NdisVcHandle, &pMyPacket,NumberOfPackets );
  2077. if (IndicatedStatus == NDIS_STATUS_RESOURCES)
  2078. {
  2079. //
  2080. // Return Packets work
  2081. //
  2082. pPktContext = (PPKT_CONTEXT)&pMyPacket->MiniportReservedEx;
  2083. ASSERT ( pPacket == pPktContext->EthernetSend.pOrigPacket );
  2084. //
  2085. // Free the locally allocated packet
  2086. //
  2087. nicFreePacket(pMyPacket, &pEthernetVc->PacketPool);
  2088. }
  2089. }
  2090. NdisMCoReceiveComplete(pAdapter->MiniportAdapterHandle);
  2091. }
  2092. }while (FALSE);
  2093. //
  2094. // Regardless of success, we need to complete the sends
  2095. //
  2096. for ( i = 0 ; i < NumberOfPackets; i++)
  2097. {
  2098. if (fVcActive == TRUE)
  2099. {
  2100. nicDereferenceCall ((PVCCB)pEthernetVc, "NicMpSendPackets" );
  2101. }
  2102. NdisMSendComplete ( pAdapter->MiniportAdapterHandle,
  2103. PacketArray[i],
  2104. NDIS_STATUS_SUCCESS);
  2105. }
  2106. TRACE( TL_T, TM_Init, ( "<== NicMpSendPackets "));
  2107. }
  2108. //----------------------------------------------------------------------------
  2109. // R E M O T E N O D E F U N C T I O N S S T A R T H E R E
  2110. //
  2111. NTSTATUS
  2112. nicAddRemoteNode(
  2113. IN PVOID Nic1394AdapterContext, // Nic1394 handle for the local host adapter
  2114. IN PVOID Enum1394NodeHandle, // Enum1394 handle for the remote node
  2115. IN PDEVICE_OBJECT RemoteNodePhysicalDeviceObject, // physical device object for the remote node
  2116. IN ULONG UniqueId0, // unique ID Low for the remote node
  2117. IN ULONG UniqueId1, // unique ID High for the remote node
  2118. OUT PVOID * pNic1394NodeContext // Nic1394 context for the remote node
  2119. )
  2120. /*++
  2121. Routine Description:
  2122. This function does updates all the required nic1394 data
  2123. structures to signal the arrival of a new remote node.
  2124. Inserts itself into the correct list and allocates an address range
  2125. for itself.
  2126. The calls to AddRemoteNode and RemoveRemoteNode are serialized because
  2127. they only happen in the when enum1394 gets a Start and Stop
  2128. Arguments:
  2129. Explained above
  2130. Return Value:
  2131. --*/
  2132. {
  2133. NTSTATUS Status = STATUS_SUCCESS;
  2134. REMOTE_NODE *pRemoteNode = NULL;
  2135. PADAPTERCB pAdapter = (PADAPTERCB)Nic1394AdapterContext;
  2136. UINT64 RemoteNodeUniqueId;
  2137. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  2138. BOOLEAN fNeedToRequestResetNotification = FALSE;
  2139. ULONG Generation = 0;
  2140. BOOLEAN fIsOnlyNode = FALSE;
  2141. STORE_CURRENT_IRQL;
  2142. RemoteNodeUniqueId = 0;
  2143. RemoteNodeUniqueId = UniqueId0;
  2144. RemoteNodeUniqueId = RemoteNodeUniqueId<<32;
  2145. RemoteNodeUniqueId = RemoteNodeUniqueId | UniqueId1 ;
  2146. TRACE( TL_N, TM_Mp, ( "** nicAddRemoteNode Remote %.8x, UniqueId %I64x", RemoteNodePhysicalDeviceObject, RemoteNodeUniqueId) );
  2147. // Initialize a PdoCb with the 1394 Pdo and insert it into the Pdo list
  2148. //
  2149. do
  2150. {
  2151. NdisStatus = nicInitializeRemoteNode(&pRemoteNode,
  2152. RemoteNodePhysicalDeviceObject,
  2153. RemoteNodeUniqueId);
  2154. *pNic1394NodeContext = pRemoteNode;
  2155. if (NdisStatus!=NDIS_STATUS_SUCCESS)
  2156. {
  2157. TRACE( TL_A, TM_Mp, ( "NicMpInitializePdoCb FAILED %.8x", RemoteNodePhysicalDeviceObject) );
  2158. break;
  2159. }
  2160. pRemoteNode->pAdapter = pAdapter;
  2161. pRemoteNode->Enum1394NodeHandle = Enum1394NodeHandle;
  2162. pAdapter->MediaConnectStatus = NdisMediaStateConnected;
  2163. //
  2164. // We need to go through the RecvFiFo List and get allocate any address ranges on this pdo as well
  2165. //
  2166. ADAPTER_ACQUIRE_LOCK (pAdapter);
  2167. //
  2168. // Increment the Refcount. This signifies that the pRemoteNode has been created and will
  2169. // be derefed only when the nic gets a notification of removal.
  2170. //
  2171. pRemoteNode->pAdapter = pAdapter;
  2172. //
  2173. // Add a reference to the adapter as the Pdo Block, now has a pointer to it
  2174. // Will be derefed in the RemoveRemoteNode
  2175. //
  2176. nicReferenceAdapter (pAdapter, "nicAddRemoteNode");
  2177. //
  2178. // Figure out if there are no remote node in the Adapter's list. that will make this node the only remote node
  2179. // and we will have to kickstart the BCM algorithm
  2180. //
  2181. fIsOnlyNode = IsListEmpty (&pAdapter->PDOList);
  2182. TRACE( TL_V, TM_Mp, ( " nicAddRemoteNode: fIsOnlyNode %x", fIsOnlyNode ) );
  2183. //
  2184. // Insert the PDO into the adapter's RemoteNode List
  2185. //
  2186. InsertTailList (&pAdapter->PDOList, &pRemoteNode->linkPdo);
  2187. NdisInterlockedIncrement (&pAdapter->AdaptStats.ulNumRemoteNodes);
  2188. //
  2189. // Increment the ref on the Pdo block as the adapter, now has a pointer to it
  2190. // Will be derefed whereve the remote node is popped of the list
  2191. //
  2192. nicReferenceRemoteNode (pRemoteNode, AddRemoteNode);
  2193. //
  2194. // Now set the flag that the Pdo Block is activated, and that
  2195. // it is ready to receive Irps
  2196. //
  2197. REMOTE_NODE_SET_FLAG (pRemoteNode, PDO_Activated);
  2198. ADAPTER_RELEASE_LOCK (pAdapter);
  2199. {
  2200. NODE_ADDRESS RemoteNodeAddress;
  2201. NdisStatus = nicGet1394AddressOfRemoteNode( pRemoteNode,
  2202. &RemoteNodeAddress,
  2203. 0 );
  2204. if (NdisStatus == NDIS_STATUS_SUCCESS)
  2205. {
  2206. TRACE( TL_V, TM_Mp, ( " RemoteNode %x , NodeAddress %",
  2207. pRemoteNode, RemoteNodeAddress.NA_Node_Number) );
  2208. ADAPTER_ACQUIRE_LOCK (pAdapter);
  2209. pAdapter->NodeTable.RemoteNode[RemoteNodeAddress.NA_Node_Number] = pRemoteNode;
  2210. pRemoteNode->RemoteAddress = RemoteNodeAddress;
  2211. ADAPTER_RELEASE_LOCK (pAdapter);
  2212. }
  2213. else
  2214. {
  2215. ASSERT (!" Unable to get Address from remote node");
  2216. //
  2217. // Do not fail the Add Node
  2218. //
  2219. REMOTE_NODE_SET_FLAG (pRemoteNode, PDO_NotInsertedInTable);
  2220. NdisStatus = NDIS_STATUS_SUCCESS;
  2221. }
  2222. }
  2223. //
  2224. // Update the local host's speed values
  2225. //
  2226. nicUpdateLocalHostSpeed (pAdapter);
  2227. //
  2228. // Update the remote node's cached caps.
  2229. //
  2230. {
  2231. UINT SpeedTo;
  2232. UINT EffectiveMaxBufferSize;
  2233. UINT MaxRec;
  2234. // Specifying FALSE (!from cache) below causes pRemoteNode's cached caps
  2235. // to be refreshed. Ignore return value.
  2236. //
  2237. (VOID) nicQueryRemoteNodeCaps (pAdapter,
  2238. pRemoteNode,
  2239. &SpeedTo,
  2240. &EffectiveMaxBufferSize,
  2241. &MaxRec
  2242. );
  2243. }
  2244. //
  2245. // We have received a remote node in this boot.
  2246. // Set the flag. No need to hold the lock
  2247. //
  2248. ADAPTER_SET_FLAG(pAdapter, fADAPTER_RemoteNodeInThisBoot);
  2249. //
  2250. // Kick start the BCM algorithm if this is the only node in the Adapter's list. also need to initialize the BCR
  2251. // if necessary. All done in this BCMAddRemoteNode function
  2252. //
  2253. nicBCMAddRemoteNode (pAdapter,
  2254. fIsOnlyNode );
  2255. //
  2256. // Inform the protocols of this new node, so that
  2257. // it can query us for a new Euid Map
  2258. //
  2259. nicInformProtocolsOfReset(pAdapter);
  2260. }while (FALSE);
  2261. TRACE( TL_T, TM_Mp, ("<==nicAddRemoteNode Remote %.8x, Status %.8x", RemoteNodePhysicalDeviceObject, Status));
  2262. MATCH_IRQL;
  2263. return NdisStatus;
  2264. }
  2265. VOID
  2266. nicDeleteLookasideList (
  2267. IN OUT PNIC_NPAGED_LOOKASIDE_LIST pLookasideList
  2268. )
  2269. /*++
  2270. Routine Description:
  2271. Deletes a nic1394 Lookaside list
  2272. Arguments:
  2273. Return Value:
  2274. --*/
  2275. {
  2276. TRACE( TL_T, TM_Cm, ( "==> nicDeleteLookasideList pLookaside List %x", pLookasideList ) );
  2277. if (pLookasideList)
  2278. {
  2279. ASSERT (pLookasideList->OutstandingPackets == 0);
  2280. NdisDeleteNPagedLookasideList (&pLookasideList->List);
  2281. }
  2282. TRACE( TL_T, TM_Cm, ( "<== nicDeleteLookasideList pLookaside List %x", pLookasideList) );
  2283. }
  2284. NDIS_STATUS
  2285. nicFreeRemoteNode(
  2286. IN REMOTE_NODE *pRemoteNode
  2287. )
  2288. /*++
  2289. Routine Description:
  2290. Frees a Remote Node when the refcount goes to zero
  2291. Arguments:
  2292. Return Value:
  2293. --*/
  2294. {
  2295. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  2296. TRACE( TL_T, TM_Mp, ( "==>nicFreeRemoteNodepRemoteNode %.8x", pRemoteNode ) );
  2297. ASSERT (pRemoteNode->Ref.ReferenceCount == 0);
  2298. nicFreeNicSpinLock (&pRemoteNode->ReassemblyLock);
  2299. pRemoteNode->pPdo = NULL;
  2300. pRemoteNode->ulTag = MTAG_FREED;
  2301. FREE_NONPAGED (pRemoteNode);
  2302. TRACE( TL_T, TM_Mp, ( "<==nicFreeRemoteNode" ) );
  2303. return NdisStatus;
  2304. }
  2305. VOID
  2306. nicInitializeLookasideList(
  2307. IN OUT PNIC_NPAGED_LOOKASIDE_LIST pLookasideList,
  2308. ULONG Size,
  2309. ULONG Tag,
  2310. USHORT Depth
  2311. )
  2312. /*++
  2313. Routine Description:
  2314. Allocates and initializes a nic Lookaside list
  2315. Arguments:
  2316. Return Value:
  2317. --*/
  2318. {
  2319. TRACE( TL_T, TM_Cm, ( "==> nicInitializeLookasideList pLookaside List %x, size %x, Tag %x, Depth %x, ",
  2320. pLookasideList, Size, Tag, Depth) );
  2321. NdisInitializeNPagedLookasideList( &pLookasideList->List,
  2322. NULL, //Allocate
  2323. NULL, // Free
  2324. 0, // Flags
  2325. Size,
  2326. MTAG_CBUF,
  2327. Depth ); // Depth
  2328. pLookasideList->Size = Size;
  2329. TRACE( TL_T, TM_Cm, ( "<== nicInitializeLookasideList " ) );
  2330. }
  2331. NDIS_STATUS
  2332. nicInitializeRemoteNode(
  2333. OUT REMOTE_NODE **ppRemoteNode,
  2334. IN PDEVICE_OBJECT p1394DeviceObject,
  2335. IN UINT64 UniqueId
  2336. )
  2337. /*++
  2338. Routine Description:
  2339. This function allocates and initializes a control block for the Device Object
  2340. that is being passed . Also sets the initalize flag and, intialized the Vc List
  2341. Copies the unique id, Initializes the reassembly structures ( lock and list)
  2342. Arguments:
  2343. pRemoteNode - Pointer to remote node that was allocated
  2344. pDevice Object for the remote node
  2345. Unique Id - UID of the remote node
  2346. Return Value:
  2347. Resources - if the Allocation failed
  2348. Success - otherwise
  2349. --*/
  2350. {
  2351. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  2352. PREMOTE_NODE pRemoteNode = NULL;
  2353. TRACE( TL_T, TM_Mp, ( "==>NicInitializeRemoteNode PDO %.8x UniqueId %I64x", p1394DeviceObject, UniqueId) );
  2354. do
  2355. {
  2356. pRemoteNode = ALLOC_NONPAGED( sizeof(REMOTE_NODE), MTAG_REMOTE_NODE);
  2357. if (pRemoteNode == NULL)
  2358. {
  2359. TRACE( TL_A, TM_Mp, ( "Memory Allocation for Pdo Block FAILED" ) );
  2360. *ppRemoteNode = NULL;
  2361. NdisStatus = NDIS_STATUS_RESOURCES;
  2362. break;
  2363. }
  2364. //
  2365. // Zero out the strcuture
  2366. //
  2367. NdisZeroMemory ( pRemoteNode , sizeof(REMOTE_NODE) );
  2368. //
  2369. // Set up the tag
  2370. //
  2371. pRemoteNode ->ulTag = MTAG_REMOTE_NODE;
  2372. //
  2373. // Set up the remote device's PDO
  2374. //
  2375. pRemoteNode ->pPdo = p1394DeviceObject;
  2376. //
  2377. // Set up the Unique ID
  2378. //
  2379. pRemoteNode ->UniqueId = UniqueId;
  2380. //
  2381. // Set up a Fake Mac Address for the Unique ID
  2382. //
  2383. nicGetMacAddressFromEuid(&UniqueId, &pRemoteNode->ENetAddress) ;
  2384. //
  2385. // Initialize the VC that are open on this Remote Node
  2386. //
  2387. InitializeListHead ( &(pRemoteNode->VcList));
  2388. //
  2389. // Initialize the ref count
  2390. //
  2391. nicInitializeRef (&pRemoteNode->Ref);
  2392. //
  2393. // allocate the spin lock to control reassembly
  2394. //
  2395. nicInitializeNicSpinLock (&(pRemoteNode ->ReassemblyLock));
  2396. //
  2397. // list for all reassemblies happenning on the remote node
  2398. //
  2399. InitializeListHead (&pRemoteNode->ReassemblyList);
  2400. *ppRemoteNode = pRemoteNode ;
  2401. } while (FALSE);
  2402. TRACE( TL_T, TM_Mp, ( "<==NicInitializeRemoteNode, Status %.8x, pRemoteNode %.8x", NdisStatus, *ppRemoteNode) );
  2403. return NdisStatus;
  2404. }
  2405. VOID
  2406. nicNoRemoteNodesLeft (
  2407. IN PADAPTERCB pAdapter
  2408. )
  2409. /*++
  2410. Routine Description:
  2411. Called from the RemoveRemote Node codepath
  2412. This means that the last node has gone away.
  2413. Indicate a Media Disconnect.
  2414. Arguments:
  2415. Return Value:
  2416. --*/
  2417. {
  2418. BOOLEAN fBCMInProgress;
  2419. ADDRESS_RANGE_CONTEXT BCRAddressRange;
  2420. TRACE( TL_T, TM_Bcm, ( "==>nicNoRemoteNodesLeft pAdapter %x ",pAdapter ) );
  2421. pAdapter->MediaConnectStatus = NdisMediaStateDisconnected;
  2422. if (ADAPTER_TEST_FLAG( pAdapter, fADAPTER_Halting) == FALSE)
  2423. {
  2424. nicMIndicateStatus ( pAdapter,NDIS_STATUS_MEDIA_DISCONNECT, NULL,0);
  2425. }
  2426. TRACE( TL_T, TM_Bcm, ( "<==nicNoRemoteNodesLeft pAdapter %x ",pAdapter ) );
  2427. }
  2428. VOID
  2429. nicReallocateChannels (
  2430. IN PNDIS_WORK_ITEM pWorkItem,
  2431. IN PVOID Context
  2432. )
  2433. /*++
  2434. Routine Description:
  2435. Walk through all the channel VCs and reallocate all
  2436. the previously allocated channels except the BCM channel .
  2437. The BCM will reallocate this
  2438. Tell the protocol that the 1394 bus has been reset. after all the channels have
  2439. been allocated
  2440. Arguments:
  2441. Return Value:
  2442. --*/
  2443. {
  2444. ULONGLONG ChannelsAllocatedByLocalHost = 0;
  2445. ULONG Channel = 0;
  2446. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  2447. PADAPTERCB pAdapter = (PADAPTERCB) Context;
  2448. ULONGLONG One = 1;
  2449. TRACE( TL_T, TM_Mp, ( "==>nicReallocateChannels pAdpater %x", pAdapter) );
  2450. TRACE( TL_V, TM_Mp, (" nicReallocateChannels ChannelsAllocatedByLocalHost %I64x ", ChannelsAllocatedByLocalHost) );
  2451. Channel =0;
  2452. while (Channel < NIC1394_MAX_NUMBER_CHANNELS )
  2453. {
  2454. //
  2455. // Does the channel 'i' need to be allocated
  2456. //
  2457. ADAPTER_ACQUIRE_LOCK (pAdapter);
  2458. ChannelsAllocatedByLocalHost = pAdapter->ChannelsAllocatedByLocalHost ;
  2459. ADAPTER_RELEASE_LOCK (pAdapter);
  2460. if ( (( g_ullOne<<Channel ) & ChannelsAllocatedByLocalHost) == TRUE)
  2461. {
  2462. if (Channel == BROADCAST_CHANNEL)
  2463. {
  2464. //
  2465. // The broadcast channel will be allocated by the BCM. skip it.
  2466. //
  2467. continue;
  2468. }
  2469. NdisStatus = nicAllocateChannel (pAdapter,
  2470. Channel,
  2471. NULL);
  2472. //
  2473. // If allocation fails ... Have not implemented recovery yet.
  2474. //
  2475. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2476. {
  2477. ASSERT (NdisStatus == NDIS_STATUS_SUCCESS)
  2478. }
  2479. }
  2480. Channel ++;
  2481. }
  2482. //
  2483. // Now that the channels are reallocated, inform the protocols of the reset
  2484. //
  2485. nicInformProtocolsOfReset(pAdapter);
  2486. //
  2487. // Dereference the ref that was added prior to scheduling this workitem
  2488. //
  2489. NdisInterlockedDecrement(&pAdapter->OutstandingWorkItems);
  2490. nicDereferenceAdapter(pAdapter, "nicResetReallocateChannels ");
  2491. FREE_NONPAGED(pWorkItem);
  2492. TRACE( TL_T, TM_Mp, ( "<==nicReallocateChannels " ) );
  2493. }
  2494. NDIS_STATUS
  2495. nicRemoteNodeRemoveVcCleanUp(
  2496. IN REMOTE_NODE *pRemoteNode
  2497. )
  2498. /*++
  2499. Routine Description:
  2500. This function walks through the Pdo's Vc list annd closes
  2501. the calls on each of them. These are SendFIFO VCs.
  2502. Channel VC's will not be closed when the remote node is removed.
  2503. This is typically called from a remove remote node function
  2504. Arguments:
  2505. PdoCb Pdo Control block that is getting removed
  2506. Return Value:
  2507. --*/
  2508. {
  2509. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  2510. PVCCB pVc = NULL;
  2511. PLIST_ENTRY pVcList = NULL;
  2512. STORE_CURRENT_IRQL;
  2513. TRACE( TL_T, TM_Mp, ( "==>nicRemoteNodeRemoveVcCleanUp pRemoteNode %.8x", pRemoteNode ) );
  2514. pVcList = ListNext (&pRemoteNode->VcList);
  2515. while (pVcList != &pRemoteNode->VcList)
  2516. {
  2517. pVc = (VCCB*) CONTAINING_RECORD (pVcList, VCHDR, SinglePdoVcLink);
  2518. //
  2519. // move to the next Vc in the list
  2520. //
  2521. pVcList = ListNext (pVcList);
  2522. TRACE( TL_V, TM_Mp, ( " nicRemoteNodeRemoveVcCleanUp VcType %x",pVc->Hdr.VcType ) );
  2523. switch(pVc->Hdr.VcType)
  2524. {
  2525. case NIC1394_SendRecvChannel:
  2526. case NIC1394_RecvChannel:
  2527. case NIC1394_SendChannel:
  2528. {
  2529. PCHANNEL_VCCB pChannelVc = (PCHANNEL_VCCB)pVc;
  2530. PREMOTE_NODE pNewChannelNode = NULL;
  2531. //
  2532. // Nothing to do here now
  2533. //
  2534. break;
  2535. }
  2536. case NIC1394_SendFIFO:
  2537. {
  2538. //
  2539. // We know that it is a Send FIFO and the call needs to be closed
  2540. //
  2541. VC_SET_FLAG (pVc, VCBF_VcDispatchedCloseCall);
  2542. //
  2543. // This is to guarantee that we have the Vc Structure around at the end of the call
  2544. //
  2545. nicReferenceVc (pVc);
  2546. REMOTE_NODE_RELEASE_LOCK (pRemoteNode);
  2547. TRACE( TL_V, TM_Mp, ( "Dispatching a close call for Vc%.8x ",pVc ) );
  2548. NdisMCmDispatchIncomingCloseCall (NDIS_STATUS_SUCCESS,
  2549. pVc->Hdr.NdisVcHandle,
  2550. NULL,
  2551. 0 );
  2552. REMOTE_NODE_ACQUIRE_LOCK (pRemoteNode);
  2553. //
  2554. // Deref the ref made above.
  2555. //
  2556. nicDereferenceVc (pVc);
  2557. break;
  2558. }
  2559. default:
  2560. {
  2561. //
  2562. // There should be no other VC types here
  2563. //
  2564. TRACE( TL_A, TM_Mp, ( " Invalid VC %x Type nicRemoteNodeRemoveVcCleanUp ", pVc ) );
  2565. ASSERT (0);
  2566. }
  2567. }
  2568. }
  2569. MATCH_IRQL;
  2570. TRACE( TL_T, TM_Mp, ( "<==nicRemoteNodeRemoveVcCleanUp " ) );
  2571. return NDIS_STATUS_SUCCESS;
  2572. }
  2573. NTSTATUS
  2574. nicRemoveRemoteNode(
  2575. IN PVOID Nic1394NodeContext // Nic1394 context for the remote node
  2576. )
  2577. /*++
  2578. Routine Description:
  2579. This function does all the hard work when the nic gets notification
  2580. of a remote node going away.
  2581. Closes all calls on the Pdo ,
  2582. Removes the Remote Node from the adapter's listPdo
  2583. frees all the reassemblies on this node
  2584. and then waits for the refcount to go to zero
  2585. The calls to AddRemoteNode and RemoveRemoteNode are serialized because
  2586. they only happen in the when enum1394 gets a Start and Stop
  2587. Arguments:
  2588. Return Value:
  2589. --*/
  2590. {
  2591. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  2592. NTSTATUS Status = STATUS_SUCCESS;
  2593. PREMOTE_NODE pRemoteNode = (REMOTE_NODE *)Nic1394NodeContext;
  2594. PADAPTERCB pAdapter = pRemoteNode->pAdapter;
  2595. PLIST_ENTRY pVcListEntry = NULL;
  2596. PVCCB pVc = NULL;
  2597. BOOLEAN FreeAddressRange = TRUE;
  2598. BOOLEAN fIsPdoListEmpty = FALSE;
  2599. LIST_ENTRY ReassemblyList;
  2600. STORE_CURRENT_IRQL;
  2601. TRACE( TL_T, TM_Mp, ( " ** nicRemoveRemoteNode Node Context %x , Pdo %x",Nic1394NodeContext, pRemoteNode->pPdo ) );
  2602. do
  2603. {
  2604. pAdapter->pLastRemoteNode = pRemoteNode;
  2605. REMOTE_NODE_ACQUIRE_LOCK (pRemoteNode);
  2606. //
  2607. // We should tell everyone that the Pdo is being removed. However keep the node active
  2608. // because there are Vc's which might need to submit Irps
  2609. //
  2610. REMOTE_NODE_SET_FLAG (pRemoteNode, PDO_Removed);
  2611. //
  2612. // Dispatch Close call requests for active calls on this Pdo.
  2613. // However, keep the VCs in the pdocb's list
  2614. // The NicCmCloseCall is the only function that removes Pdo's from the list
  2615. // Will need to free the address range for any recv Vcs seperately
  2616. //
  2617. NdisStatus = nicRemoteNodeRemoveVcCleanUp (pRemoteNode);
  2618. //
  2619. // Remove the remote node from the RemoteNode Table
  2620. //
  2621. //
  2622. nicRemoveRemoteNodeFromNodeTable(&pAdapter->NodeTable,pRemoteNode);
  2623. //
  2624. // Free All reassembly operations on this remopte node
  2625. //
  2626. nicFreeReassembliesOnRemoteNode (pRemoteNode, &ReassemblyList);
  2627. //
  2628. // Dereference the ref that was added when the Pdo block was inserted in the Adapter's list
  2629. // The actual removal will take place later. We still have close calls to be completed and they
  2630. // will need the PdoCb. So it remains in the adapter's queue
  2631. //
  2632. nicDereferenceRemoteNode (pRemoteNode, RemoveRemoteNode);
  2633. //
  2634. // Need to Deref the Reference made in NicInitializeRemoteNode function
  2635. //
  2636. nicDereferenceRemoteNode (pRemoteNode, RemoveRemoteNode);
  2637. //
  2638. // Dequeue the remote node here
  2639. //
  2640. nicRemoveEntryList (&pRemoteNode->linkPdo);
  2641. NdisInterlockedDecrement (&pAdapter->AdaptStats.ulNumRemoteNodes);
  2642. //
  2643. // If this was the last remote node, then some special cleaning will be done
  2644. //
  2645. fIsPdoListEmpty = IsListEmpty (&pAdapter->PDOList);
  2646. TRACE( TL_T, TM_Mp, ( " nicRemoveRemoteNode fIsOnlyNode %x ",fIsPdoListEmpty ) );
  2647. REMOTE_NODE_RELEASE_LOCK (pRemoteNode);
  2648. //
  2649. // Now, we wait forever for all the reference to go away
  2650. //
  2651. TRACE( TL_V, TM_Mp, ( "About ot Wait RemoteNode Ref's to go to zero" ) );
  2652. NdisWaitEvent (&pRemoteNode->Ref.RefZeroEvent, WAIT_INFINITE);
  2653. TRACE( TL_V, TM_Mp, ( "Wait Succeeded Ref == 0, pRemoteNode %.8x, RefCount %.8x ",
  2654. pRemoteNode, pRemoteNode->Ref.ReferenceCount) );
  2655. //
  2656. // If this was the last node, and the remote node list is empty, we need to clean up the BCR
  2657. //
  2658. if (fIsPdoListEmpty == TRUE)
  2659. {
  2660. nicNoRemoteNodesLeft (pAdapter);
  2661. }
  2662. //
  2663. // Delete the reassemblies that belong to this remote node and free them
  2664. //
  2665. if (IsListEmpty (&ReassemblyList) == FALSE)
  2666. {
  2667. nicAbortReassemblyList (&ReassemblyList);
  2668. }
  2669. nicFreeRemoteNode(pRemoteNode);
  2670. //
  2671. // Now update the speed on the adapter
  2672. //
  2673. nicUpdateLocalHostSpeed(pAdapter);
  2674. //
  2675. // Inform the protocols of the node removal, so that
  2676. // it can query us for a new Euid Map
  2677. //
  2678. nicInformProtocolsOfReset(pAdapter);
  2679. //
  2680. // Careful this could cause the adapter refcounts to go to zero
  2681. //
  2682. nicDereferenceAdapter(pAdapter, "nicRemoveRemoteNode ");
  2683. } while (FALSE);
  2684. TRACE( TL_T, TM_Mp, ( "<== nicRemoveRemoteNode Status %.8x ",
  2685. NdisStatus ) );
  2686. MATCH_IRQL;
  2687. return NDIS_STATUS_SUCCESS;
  2688. }
  2689. VOID
  2690. nicResetNotificationCallback (
  2691. IN PVOID pContext
  2692. )
  2693. /*++
  2694. Routine Description:
  2695. This routine will be called whenever the bus is reset.
  2696. It will be called at DISPATCH Level
  2697. Arguments:
  2698. Context : a Remote Node
  2699. Return Value:
  2700. --*/
  2701. {
  2702. PADAPTERCB pAdapter = (PADAPTERCB) pContext;
  2703. BOOLEAN fNeedToQueueBCMWorkItem = FALSE;
  2704. TRACE( TL_T, TM_Mp, ( "==>nicResetNotificationCallback Context %.8x ", pContext ) );
  2705. NdisInterlockedIncrement (&pAdapter->AdaptStats.ulNumResetCallbacks);
  2706. pAdapter->AdaptStats.ulResetTime = nicGetSystemTime();
  2707. TRACE( TL_I, TM_Mp, ( " BUS RESET Callback Context %x, Old Gen %x ", pContext , pAdapter->Generation) );
  2708. //
  2709. // Restart the BCM
  2710. //
  2711. nicResetRestartBCM (pAdapter);
  2712. //
  2713. // reallocate all channels that were opened by this node
  2714. //
  2715. nicResetReallocateChannels( pAdapter);
  2716. //
  2717. // Invalidate all pending reassemblies
  2718. //
  2719. nicFreeAllPendingReassemblyStructures(pAdapter);
  2720. TRACE( TL_T, TM_Mp, ( "<==nicResetNotificationCallback " ) );
  2721. }
  2722. VOID
  2723. nicResetReallocateChannels (
  2724. IN PADAPTERCB pAdapter
  2725. )
  2726. /*++
  2727. Routine Description:
  2728. Fires off a workitem to reallocate channels.
  2729. ONLY To be called from a reset.
  2730. Once all the channels have been re-allocated,
  2731. it causes an indication to the protocols,
  2732. Arguments:
  2733. Return Value:
  2734. --*/
  2735. {
  2736. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  2737. PNDIS_WORK_ITEM pResetChannelWorkItem;
  2738. TRACE( TL_T, TM_Mp, ( "==>nicResetReallocateChannels " ) );
  2739. //
  2740. // reference the adapter as it is going to passed to a workiter.
  2741. // decremented in the workitem
  2742. //
  2743. nicReferenceAdapter(pAdapter, "nicResetReallocateChannels");
  2744. do
  2745. {
  2746. pResetChannelWorkItem = ALLOC_NONPAGED (sizeof(NDIS_WORK_ITEM), MTAG_WORKITEM);
  2747. if (pResetChannelWorkItem== NULL)
  2748. {
  2749. TRACE( TL_A, TM_Cm, ( "nicResetReallocateChannels : Local Alloc failed for WorkItem" ) );
  2750. NdisStatus = NDIS_STATUS_RESOURCES;
  2751. break;
  2752. }
  2753. else
  2754. {
  2755. //
  2756. // From here on, this function cannot fail.
  2757. //
  2758. NdisStatus = NDIS_STATUS_SUCCESS;
  2759. }
  2760. NdisInitializeWorkItem ( pResetChannelWorkItem,
  2761. (NDIS_PROC) nicReallocateChannels ,
  2762. (PVOID) pAdapter);
  2763. TRACE( TL_V, TM_Cm, ( "Scheduling Channels WorkItem" ) );
  2764. NdisInterlockedIncrement(&pAdapter->OutstandingWorkItems);
  2765. NdisScheduleWorkItem (pResetChannelWorkItem);
  2766. } while (FALSE);
  2767. TRACE( TL_T, TM_Mp, ( "<==nicResetReallocateChannels %x ", NdisStatus ) );
  2768. }
  2769. VOID
  2770. nicResetRestartBCM (
  2771. IN PADAPTERCB pAdapter
  2772. )
  2773. /*++
  2774. Routine Description:
  2775. Clean up the adapter's data structure and restart the BCM algorithm
  2776. Arguments:
  2777. Return Value:
  2778. --*/
  2779. {
  2780. TRACE( TL_T, TM_Mp, ( "==>nicResetRestartBCM pAdpater %x", pAdapter ) );
  2781. //
  2782. // Now set up the data structures so we can restart the BCM for this generation
  2783. //
  2784. ADAPTER_ACQUIRE_LOCK(pAdapter);
  2785. pAdapter->BCRData.LocalHostBCRBigEndian = BCR_IMPLEMENTED_BIG_ENDIAN;
  2786. pAdapter->BCRData.IRM_BCR.NC_One = 1;
  2787. pAdapter->BCRData.IRM_BCR.NC_Valid = 0;
  2788. pAdapter->BCRData.IRM_BCR.NC_Channel = 0x3f;
  2789. //
  2790. // Clear the flags that are only valid through a single run of the BCM algorithm
  2791. //
  2792. BCR_CLEAR_FLAG (pAdapter, BCR_BCMFailed | BCR_LocalHostBCRUpdated | BCR_ChannelAllocated | BCR_LocalHostIsIRM);
  2793. //
  2794. // This will inform any BCM algorithm that a new reset happened
  2795. //
  2796. ADAPTER_SET_FLAG (pAdapter, fADAPTER_InvalidGenerationCount);
  2797. //
  2798. // We might have a thread waiting in FindIrmAmongRemoteNodes. .. Let it go and make it
  2799. // abort the BCM
  2800. //
  2801. pAdapter->BCRData.BCRWaitForNewRemoteNode.EventCode = nic1394EventCode_BusReset;
  2802. NdisSetEvent (&pAdapter->BCRData.BCRWaitForNewRemoteNode.NdisEvent);
  2803. ADAPTER_RELEASE_LOCK(pAdapter);
  2804. //
  2805. // Now reschedule a work item to do the BCM algorithm
  2806. //
  2807. TRACE( TL_A, TM_Bcm , ("Reset - scheduling the BCM" ) );
  2808. nicScheduleBCMWorkItem(pAdapter);
  2809. TRACE( TL_T, TM_Mp, ( "<==nicResetRestartBCM " ) );
  2810. }
  2811. VOID
  2812. nicBusResetWorkItem(
  2813. NDIS_WORK_ITEM* pResetWorkItem,
  2814. IN PVOID Context
  2815. )
  2816. /*++
  2817. Routine Description:
  2818. Calls nicBusReset and exits
  2819. Arguments:
  2820. Return Value:
  2821. --*/
  2822. {
  2823. PADAPTERCB pAdapter= (PADAPTERCB) Context;
  2824. TRACE( TL_T, TM_Mp, ( "==>nicBusResetWorkItem " ) );
  2825. nicBusReset (pAdapter,
  2826. BUS_RESET_FLAGS_FORCE_ROOT );
  2827. NdisInterlockedDecrement(&pAdapter->OutstandingWorkItems);
  2828. nicDereferenceAdapter(pAdapter, "nicBusResetWorkItem");
  2829. TRACE( TL_T, TM_Mp, ( "<==nicBusResetWorkItem" ) );
  2830. FREE_NONPAGED (pResetWorkItem);
  2831. }
  2832. VOID
  2833. nicIssueBusReset (
  2834. PADAPTERCB pAdapter,
  2835. ULONG Flags
  2836. )
  2837. /*++
  2838. Routine Description:
  2839. Picks up a PDO and issues a bus reset on that PDO
  2840. As this can come down through an NdisRequest, it can be at IRQL <=DISPATCH_LEVEL
  2841. Arguments:
  2842. Return Value:
  2843. --*/
  2844. {
  2845. PREMOTE_NODE pRemoteNode = NULL;
  2846. TRACE( TL_T, TM_Mp, ( "==> nicIssueBusReset %x ",Flags ) );
  2847. if (PASSIVE_LEVEL == KeGetCurrentIrql () )
  2848. {
  2849. nicBusReset (pAdapter, Flags);
  2850. }
  2851. else
  2852. {
  2853. //
  2854. // Dereferenced in the workitem
  2855. //
  2856. nicReferenceAdapter (pAdapter, "nicIssueBusReset ");
  2857. do
  2858. {
  2859. PNDIS_WORK_ITEM pReset;
  2860. NDIS_STATUS NdisStatus;
  2861. pReset = ALLOC_NONPAGED (sizeof(NDIS_WORK_ITEM), MTAG_WORKITEM);
  2862. if (pReset == NULL)
  2863. {
  2864. TRACE( TL_A, TM_Cm, ( "Local Alloc failed for WorkItem" ) );
  2865. break;
  2866. }
  2867. NdisInitializeWorkItem ( pReset,
  2868. (NDIS_PROC)nicBusResetWorkItem,
  2869. (PVOID)pAdapter);
  2870. TRACE( TL_A, TM_Cm, ( "Setting WorkItem" ) );
  2871. NdisInterlockedIncrement(&pAdapter->OutstandingWorkItems);
  2872. NdisScheduleWorkItem (pReset);
  2873. }while (FALSE);
  2874. }
  2875. TRACE( TL_T, TM_Mp, ( "<== nicIssueBusReset " ) );
  2876. }
  2877. VOID
  2878. nicUpdateLocalHostSpeed (
  2879. IN PADAPTERCB pAdapter
  2880. )
  2881. /*++
  2882. Routine Description:
  2883. Updates the speed for the local host and updates the payload for
  2884. all ChannelVCs
  2885. This also updates the SCode that goes to the ARP module..
  2886. The SCode will never be updated unless this function is called
  2887. via the BCM algorithm
  2888. Arguments:
  2889. Return Value:
  2890. --*/
  2891. {
  2892. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  2893. PREMOTE_NODE pRemoteNode = NULL;
  2894. PDEVICE_OBJECT PdoTable[MAX_LOCAL_NODES];
  2895. ULONG Num = 0;
  2896. ULONG SpeedMbps = 10000000;
  2897. ULONG PrevSpeed = pAdapter->Speed;
  2898. ULONG Speed =0;
  2899. ULONG MaxRecvBufferSize = 0;
  2900. ULONG MaxSendBufferSize = 0;
  2901. ULONG SCode = 0;
  2902. TRACE( TL_T, TM_Bcm, ( "==> nicUpdateLocalHostSpeed " ) );
  2903. do
  2904. {
  2905. PLIST_ENTRY pRemoteNodeList;
  2906. NODE_ADDRESS RemoteNodeAddress;
  2907. NODE_TABLE RefNodeTable;
  2908. ULONG NumRemoteNodes = 0;
  2909. NdisZeroMemory (&RefNodeTable, sizeof(RefNodeTable));
  2910. NumRemoteNodes = 0;
  2911. ADAPTER_ACQUIRE_LOCK (pAdapter);
  2912. pRemoteNodeList = ListNext (&pAdapter->PDOList);
  2913. //
  2914. // Walk through the entire list and make a copy of the current list.
  2915. // Reference each remote node on the list.
  2916. // The lock will ensure that the list is valid and that no removed remote nodes
  2917. // get into our RefNodeTable list.
  2918. //
  2919. while (pRemoteNodeList != &pAdapter->PDOList)
  2920. {
  2921. pRemoteNode = CONTAINING_RECORD (pRemoteNodeList, REMOTE_NODE, linkPdo);
  2922. //
  2923. // Reference the remote node. This guarantees that the remote node will
  2924. // remain valid and in the list until it is dereferenced (deref happens below)
  2925. //
  2926. nicReferenceRemoteNode (pRemoteNode, UpdateLocalHostSpeed);
  2927. RefNodeTable.RemoteNode[NumRemoteNodes] = pRemoteNode;
  2928. ASSERT (REMOTE_NODE_TEST_FLAG (pRemoteNode,PDO_Removed) == FALSE);
  2929. //
  2930. // Increment the Cursors and go to the next RemoteNode
  2931. //
  2932. pRemoteNodeList = ListNext (pRemoteNodeList);
  2933. NumRemoteNodes++;
  2934. //
  2935. // We only do 63 nodes .
  2936. //
  2937. if (NumRemoteNodes > (NIC1394_MAX_NICINFO_NODES - 1))
  2938. {
  2939. break;
  2940. }
  2941. } //while (pRemoteNodeList != &pAdapter->PDOList)
  2942. ADAPTER_RELEASE_LOCK (pAdapter);
  2943. //
  2944. // Now Create the Array of Remote Node PDOs that will be send down into the
  2945. // bus driver
  2946. //
  2947. NdisZeroMemory (&PdoTable[0], sizeof (PdoTable) );
  2948. Num = 0;
  2949. while (Num < NumRemoteNodes)
  2950. {
  2951. PdoTable[Num] = RefNodeTable.RemoteNode[Num]->pPdo;
  2952. Num++;
  2953. }
  2954. //
  2955. // Now send the Array down to the Bus Driver and get the speed of
  2956. // the 1394 network.
  2957. //
  2958. NdisStatus = nicGetMaxSpeedBetweenDevices( pAdapter,
  2959. Num,
  2960. PdoTable,
  2961. &Speed);
  2962. //
  2963. // Now Dereference all the Remote Nodes that were referenced above
  2964. //
  2965. ADAPTER_ACQUIRE_LOCK(pAdapter)
  2966. //
  2967. // We're done, Now Dereference the Remote Node References Made above
  2968. //
  2969. {
  2970. USHORT RefIndex=0;
  2971. PREMOTE_NODE pCurrRemoteNode;
  2972. //
  2973. // Initialize the structures
  2974. //
  2975. pCurrRemoteNode = RefNodeTable.RemoteNode[0];
  2976. RefIndex =0;
  2977. while (pCurrRemoteNode != NULL)
  2978. {
  2979. nicDereferenceRemoteNode(pCurrRemoteNode, UpdateRemoteNodeTable);
  2980. RefIndex++;
  2981. pCurrRemoteNode = RefNodeTable.RemoteNode[RefIndex];
  2982. }
  2983. }
  2984. ADAPTER_RELEASE_LOCK (pAdapter);
  2985. if (NdisStatus != NDIS_STATUS_SUCCESS)
  2986. {
  2987. break;
  2988. }
  2989. //
  2990. // By looking at the speed constants 1 -> 100Mbps
  2991. //
  2992. SpeedMbps = Speed*1000000;
  2993. //
  2994. // update the scode -- default 400.
  2995. // As 400+ hardware is prototype from WinXP, we default to 400 for now
  2996. //
  2997. SCode = SCODE_400_RATE;
  2998. if (Speed > SPEED_FLAGS_400)
  2999. {
  3000. Speed = SPEED_FLAGS_400;
  3001. }
  3002. switch (Speed)
  3003. {
  3004. case SPEED_FLAGS_400 :
  3005. {
  3006. SCode = SCODE_400_RATE ;
  3007. MaxRecvBufferSize = ISOCH_PAYLOAD_400_RATE;
  3008. MaxSendBufferSize = ASYNC_PAYLOAD_400_RATE;
  3009. break;
  3010. }
  3011. case SPEED_FLAGS_100 :
  3012. {
  3013. SCode = SCODE_100_RATE;
  3014. MaxRecvBufferSize = ISOCH_PAYLOAD_100_RATE;
  3015. MaxSendBufferSize = ASYNC_PAYLOAD_100_RATE;
  3016. break;
  3017. }
  3018. case SPEED_FLAGS_200 :
  3019. {
  3020. SCode = SCODE_200_RATE;
  3021. MaxRecvBufferSize = ISOCH_PAYLOAD_200_RATE;
  3022. MaxSendBufferSize = ASYNC_PAYLOAD_200_RATE;
  3023. break;
  3024. }
  3025. default:
  3026. {
  3027. SCode = SCODE_400_RATE ;
  3028. MaxRecvBufferSize = ISOCH_PAYLOAD_400_RATE;
  3029. MaxSendBufferSize = ASYNC_PAYLOAD_400_RATE;
  3030. break;
  3031. }
  3032. }
  3033. ADAPTER_ACQUIRE_LOCK(pAdapter);
  3034. pAdapter->Speed = Speed;
  3035. pAdapter->SpeedMbps = SpeedMbps;
  3036. pAdapter->SCode = SCode;
  3037. pAdapter->MaxRecvBufferSize = MaxRecvBufferSize;
  3038. pAdapter->MaxSendBufferSize = MaxSendBufferSize;
  3039. ADAPTER_RELEASE_LOCK (pAdapter);
  3040. TRACE( TL_V, TM_Mp, ( " nicUpdateLocalHostSpeed Speed returned %d",SpeedMbps ) );
  3041. //
  3042. // Now update the speed value in all the channel VC's as they are dependent on this parameter
  3043. //
  3044. if (Speed == PrevSpeed ||
  3045. Speed > SPEED_FLAGS_1600 )
  3046. {
  3047. //
  3048. // either the speed has not changed or it has invalid value, break out
  3049. //
  3050. TRACE (TL_V, TM_Init, ("Will not update - Speed %x, Prev Speed %x", Speed, PrevSpeed) );
  3051. break;
  3052. }
  3053. //
  3054. // The speed and the payload have changed. Update all the channel Vc's
  3055. // and Recv FIFOVc's payload
  3056. //
  3057. nicUpdateSpeedInAllVCs (pAdapter,
  3058. Speed
  3059. );
  3060. } while (FALSE);
  3061. TRACE( TL_T, TM_Mp, ( "<== nicUpdateLocalHostSpeed SpeedCode %x, Num %x" , pAdapter->Speed, Num) );
  3062. }
  3063. VOID
  3064. nicUpdateSpeedInAllVCs (
  3065. PADAPTERCB pAdapter,
  3066. ULONG Speed
  3067. )
  3068. /*++
  3069. Routine Description:
  3070. This routine updates the speed flag in all Channel Vcs
  3071. It assumes that the new speed is different from the old speed
  3072. Arguments:
  3073. pAdapter- Local Adapter intance
  3074. Speed - new speed
  3075. Return Value:
  3076. --*/
  3077. {
  3078. PAFCB pAfcb = NULL;
  3079. PVCCB pVc = NULL;
  3080. PLIST_ENTRY pAfEntry = NULL;
  3081. PLIST_ENTRY pVcEntry = NULL;
  3082. ULONG MaxPayload = 0;
  3083. ULONG SCode = 0;
  3084. TRACE( TL_T, TM_Mp, ( "==> nicUpdateSpeedInAllVCs ") );
  3085. switch (Speed)
  3086. {
  3087. case SPEED_FLAGS_100 :
  3088. {
  3089. SCode = SCODE_100_RATE;
  3090. MaxPayload = ISOCH_PAYLOAD_100_RATE;
  3091. break;
  3092. }
  3093. case SPEED_FLAGS_200 :
  3094. {
  3095. SCode = SCODE_200_RATE;
  3096. MaxPayload = ISOCH_PAYLOAD_200_RATE ;
  3097. break;
  3098. }
  3099. case SPEED_FLAGS_400 :
  3100. {
  3101. SCode = SCODE_400_RATE;
  3102. MaxPayload = ISOCH_PAYLOAD_400_RATE;
  3103. break;
  3104. }
  3105. case SPEED_FLAGS_800 :
  3106. {
  3107. SCode = SCODE_800_RATE;
  3108. MaxPayload = ISOCH_PAYLOAD_400_RATE;
  3109. break;
  3110. }
  3111. case SPEED_FLAGS_1600 :
  3112. {
  3113. SCode = SCODE_1600_RATE;
  3114. MaxPayload = ISOCH_PAYLOAD_400_RATE;
  3115. break;
  3116. }
  3117. case SPEED_FLAGS_3200 :
  3118. {
  3119. SCode = SCODE_1600_RATE;
  3120. MaxPayload = ISOCH_PAYLOAD_400_RATE;
  3121. break;
  3122. }
  3123. default :
  3124. {
  3125. ASSERT (Speed <= SPEED_FLAGS_3200 && Speed != 0 );
  3126. break;
  3127. }
  3128. }
  3129. ADAPTER_ACQUIRE_LOCK (pAdapter);
  3130. pAfEntry = ListNext (&pAdapter->AFList);
  3131. //
  3132. // Walk through all the Vc and set the value on the channelVcs
  3133. //
  3134. while (pAfEntry != &pAdapter->AFList)
  3135. {
  3136. pAfcb = CONTAINING_RECORD (pAfEntry, AFCB, linkAFCB);
  3137. pAfEntry = ListNext (pAfEntry);
  3138. pVcEntry = ListNext (&pAfcb->AFVCList);
  3139. //
  3140. // Now walk through the VCs on the Af
  3141. //
  3142. while (pVcEntry != &pAfcb->AFVCList)
  3143. {
  3144. pVc = (PVCCB) CONTAINING_RECORD (pVcEntry, VCHDR, linkAFVcs );
  3145. pVcEntry = ListNext ( pVcEntry );
  3146. //
  3147. // If it is a channel Send Vc update the Speed and Payload
  3148. //
  3149. if (pVc->Hdr.VcType == NIC1394_SendRecvChannel || pVc->Hdr.VcType == NIC1394_SendChannel)
  3150. {
  3151. PCHANNEL_VCCB pChannelVc = (PCHANNEL_VCCB)pVc;
  3152. pChannelVc->Speed = Speed;
  3153. pVc->Hdr.MaxPayload = MaxPayload;
  3154. }
  3155. } //while (pVcEntry != &pAfcb->AFVCList)
  3156. } //while (pAfEntry != &pAdapter->AFList)
  3157. pAdapter->SCode = SCode;
  3158. ADAPTER_RELEASE_LOCK (pAdapter);
  3159. TRACE( TL_T, TM_Mp, ( "<== nicUpdateSpeedInAllVCs ") );
  3160. }
  3161. VOID
  3162. nicInitializeAllEvents (
  3163. IN PADAPTERCB pAdapter
  3164. )
  3165. /*++
  3166. Routine Description:
  3167. Self Explanatory
  3168. Arguments:
  3169. Return Value:
  3170. --*/
  3171. // Function Description:
  3172. // Initialize all the events in the adapter block
  3173. //
  3174. // Arguments
  3175. // pAdapter - The local host in question.
  3176. //
  3177. // Return Value:
  3178. // None
  3179. {
  3180. TRACE( TL_T, TM_Mp, ( "==> nicInitializeAllEvents " ) );
  3181. NdisInitializeEvent (&pAdapter->RecvFIFOEvent);
  3182. NdisInitializeEvent (&pAdapter->WaitForRemoteNode.NdisEvent);
  3183. pAdapter->WaitForRemoteNode.EventCode = Nic1394EventCode_InvalidEventCode;
  3184. NdisInitializeEvent (&pAdapter->BCRData.MakeCallWaitEvent.NdisEvent);
  3185. pAdapter->BCRData.MakeCallWaitEvent.EventCode = Nic1394EventCode_InvalidEventCode;
  3186. NdisInitializeEvent (&pAdapter->BCRData.BCRWaitForNewRemoteNode.NdisEvent);
  3187. pAdapter->BCRData.BCRWaitForNewRemoteNode.EventCode = Nic1394EventCode_InvalidEventCode;
  3188. NdisInitializeEvent (&pAdapter->BCRData.BCRFreeAddressRange.NdisEvent);
  3189. pAdapter->BCRData.BCRFreeAddressRange.EventCode = Nic1394EventCode_InvalidEventCode;
  3190. TRACE( TL_T, TM_Mp, ( "<== nicInitializeAllEvents " ) );
  3191. }
  3192. VOID
  3193. nicInitializeAdapterLookasideLists (
  3194. IN PADAPTERCB pAdapter
  3195. )
  3196. /*++
  3197. Routine Description:
  3198. Initialize all the lookaside lists in the adapter block
  3199. Arguments:
  3200. Return Value:
  3201. --*/
  3202. {
  3203. USHORT DefaultDepth = 15;
  3204. TRACE( TL_T, TM_Mp, ( "==> nicInitializeAdapterLookasideLists pAdpater %x ", pAdapter ) );
  3205. nicInitializeLookasideList ( &pAdapter->SendLookasideList100,
  3206. sizeof (PAYLOAD_100_LOOKASIDE_BUFFER),
  3207. MTAG_CBUF,
  3208. DefaultDepth );
  3209. pAdapter->SendLookasideList100.MaxSendSize = PAYLOAD_100;
  3210. TRACE( TL_V, TM_Mp, ( " SendLookasideList100 Payload %x", PAYLOAD_100) );
  3211. nicInitializeLookasideList ( &pAdapter->SendLookasideList2K,
  3212. sizeof (PAYLOAD_2K_LOOKASIDE_BUFFER),
  3213. MTAG_CBUF,
  3214. DefaultDepth );
  3215. pAdapter->SendLookasideList2K.MaxSendSize = PAYLOAD_2K;
  3216. TRACE( TL_V, TM_Mp, ( " SendLookasideList2K Payload %x", PAYLOAD_2K) );
  3217. TRACE( TL_T, TM_Mp, ( "<== nicInitializeAdapterLookasideLists " ) );
  3218. }
  3219. VOID
  3220. nicDeleteAdapterLookasideLists (
  3221. IN PADAPTERCB pAdapter
  3222. )
  3223. /*++
  3224. Routine Description:
  3225. Delete all the lookaside lists in the adapter block
  3226. Arguments:
  3227. Return Value:
  3228. --*/
  3229. {
  3230. TRACE( TL_T, TM_Mp, ( "==> nicDeleteAdapterLookasideLists pAdapter %x ", pAdapter ) );
  3231. TRACE( TL_T, TM_Mp, ( " Delete NonFragmentationLookasideList %x ", &pAdapter->SendLookasideList2K) );
  3232. nicDeleteLookasideList (&pAdapter->SendLookasideList2K);
  3233. TRACE( TL_T, TM_Mp, ( " Delete FragmentationLookasideList %x ", &pAdapter->SendLookasideList100) );
  3234. nicDeleteLookasideList (&pAdapter->SendLookasideList100);
  3235. TRACE( TL_T, TM_Mp, ( "<== nicDeleteAdapterLookasideLists " ) );
  3236. }
  3237. VOID
  3238. ReassemblyTimerFunction (
  3239. IN PVOID SystemSpecific1,
  3240. IN PVOID FunctionContext,
  3241. IN PVOID SystemSpecific2,
  3242. IN PVOID SystemSpecific3
  3243. )
  3244. /*++
  3245. Routine Description:
  3246. Walk through all the pending reassembly operations and
  3247. take out the ones that need to be freed (Have been untouched
  3248. since the timer last fired)
  3249. Append the ToBeFreed reassemblies into a seperate linked list
  3250. and free them after releasing the spin locks
  3251. If the there are any pending reassemblies then the timer requeues
  3252. itself
  3253. Arguments:
  3254. Return Value:
  3255. --*/
  3256. {
  3257. PREMOTE_NODE pRemoteNode = NULL;
  3258. PLIST_ENTRY pRemoteNodeList = NULL;
  3259. PLIST_ENTRY pReassemblyList = NULL;
  3260. LIST_ENTRY ToBeFreedList;
  3261. PNDIS1394_REASSEMBLY_STRUCTURE pReassembly = NULL;
  3262. PADAPTERCB pAdapter = (PADAPTERCB) FunctionContext;
  3263. ULONG RefValue = 0;
  3264. STORE_CURRENT_IRQL;
  3265. ( TL_T, TM_Mp, ( "==> ReassemblyTimerFunction pAdapter %x", pAdapter ) );
  3266. InitializeListHead(&ToBeFreedList);
  3267. ADAPTER_ACQUIRE_LOCK (pAdapter);
  3268. pRemoteNodeList = ListNext (&pAdapter->PDOList);
  3269. pAdapter->Reassembly.PktsInQueue =0;
  3270. //
  3271. // Walking through the remote nodes
  3272. //
  3273. while (pRemoteNodeList != &pAdapter->PDOList)
  3274. {
  3275. pRemoteNode = CONTAINING_RECORD(pRemoteNodeList, REMOTE_NODE, linkPdo);
  3276. pRemoteNodeList = ListNext (pRemoteNodeList);
  3277. RefValue = pRemoteNode->Ref.ReferenceCount; ;
  3278. //
  3279. // Reference the remote node, so we can guarantee its presence
  3280. //
  3281. if (REMOTE_NODE_ACTIVE (pRemoteNode) == FALSE)
  3282. {
  3283. //
  3284. // The remote node is going away. Skip this remote node
  3285. //
  3286. continue;
  3287. }
  3288. if (nicReferenceRemoteNode (pRemoteNode, ReassemblyTimer )== FALSE )
  3289. {
  3290. //
  3291. // The remote node is going away. Skip this remote node
  3292. //
  3293. continue;
  3294. }
  3295. REMOTE_NODE_REASSEMBLY_ACQUIRE_LOCK (pRemoteNode);
  3296. //
  3297. // Now walking through all the reassembly structures on that remote node
  3298. //
  3299. pReassemblyList = ListNext(&pRemoteNode->ReassemblyList);
  3300. while (pReassemblyList != &pRemoteNode->ReassemblyList)
  3301. {
  3302. pReassembly = CONTAINING_RECORD (pReassemblyList,
  3303. NDIS1394_REASSEMBLY_STRUCTURE,
  3304. ReassemblyListEntry);
  3305. pReassemblyList = ListNext(pReassemblyList);
  3306. //
  3307. // If the reassembly has not been touched since the last timer it needs to be freed.
  3308. // Other threads can ask us to free the reassembly by setting the aborted flag
  3309. //
  3310. if (REASSEMBLY_TEST_FLAG (pReassembly, REASSEMBLY_FREED) == TRUE)
  3311. {
  3312. continue;
  3313. }
  3314. if (REASSEMBLY_TEST_FLAG (pReassembly, (REASSEMBLY_NOT_TOUCHED| REASSEMBLY_ABORTED)) == TRUE)
  3315. {
  3316. REASSEMBLY_SET_FLAG (pReassembly, REASSEMBLY_FREED);
  3317. //
  3318. // We have the lock, so we can remove this reassembly structure from the remote node
  3319. //
  3320. TRACE( TL_V, TM_Reas, ( "Removing Reassembly %x", pReassembly) );
  3321. RemoveEntryList(&pReassembly->ReassemblyListEntry);
  3322. //
  3323. // dereference the remote node . ref was made when the reassembly was added
  3324. // to the remote node
  3325. //
  3326. nicDereferenceRemoteNode (pRemoteNode, ReassemblyTimer_Removing );
  3327. nicDereferenceReassembly (pReassembly, "ReassemblyTimerFunction - Removing reassembly");
  3328. //
  3329. // add this reassembly to the to be freed list.
  3330. //
  3331. InsertTailList(&ToBeFreedList,&pReassembly->ReassemblyListEntry);
  3332. }
  3333. else
  3334. {
  3335. //
  3336. // Mark the Reassembly as Not Touched. If a fragment is received, it will clear the flag
  3337. //
  3338. REASSEMBLY_SET_FLAG (pReassembly, REASSEMBLY_NOT_TOUCHED);
  3339. pAdapter->Reassembly.PktsInQueue ++;
  3340. }
  3341. }// while (pReassemblyList != &pRemoteNode->ReassemblyList)
  3342. REMOTE_NODE_REASSEMBLY_RELEASE_LOCK(pRemoteNode);
  3343. nicDereferenceRemoteNode(pRemoteNode , ReassemblyTimer );
  3344. } //while (pRemoteNodeList != &pAdapter->PDOList)
  3345. //
  3346. // Clear the timer set flag , so that any new reassenblies will restart the timer
  3347. //
  3348. pAdapter->Reassembly.bTimerAlreadySet = FALSE;
  3349. ADAPTER_RELEASE_LOCK (pAdapter);
  3350. //
  3351. // Now we walk the ToBeFreedList and free each of the reasembly structures
  3352. //
  3353. if (IsListEmpty (&ToBeFreedList) == FALSE)
  3354. {
  3355. nicAbortReassemblyList (&ToBeFreedList);
  3356. }
  3357. if (pAdapter->Reassembly.PktsInQueue > 0)
  3358. {
  3359. //
  3360. // Requeue the timer, as there are still fragments remaining in the list.
  3361. // This will fail in the case, that the adapter is being halted or Set
  3362. // To Low Power
  3363. //
  3364. ASSERT (ADAPTER_TEST_FLAG (pAdapter, fADAPTER_NoMoreReassembly) == FALSE);
  3365. nicQueueReassemblyTimer(pAdapter, FALSE);
  3366. }
  3367. pAdapter->Reassembly.CompleteEvent.EventCode = nic1394EventCode_ReassemblyTimerComplete;
  3368. NdisSetEvent (&pAdapter->Reassembly.CompleteEvent.NdisEvent);
  3369. TRACE( TL_T, TM_Mp, ( "<== ReassemblyTimerFunction " ) );
  3370. MATCH_IRQL;
  3371. }
  3372. NDIS_STATUS
  3373. nicAddIP1394ToConfigRom (
  3374. IN PADAPTERCB pAdapter
  3375. )
  3376. /*++
  3377. Routine Description:
  3378. Adds thE IP1394 Config Rom entry to the OHCI device.
  3379. Arguments:
  3380. Return Value:
  3381. --*/
  3382. {
  3383. HANDLE hCromData = NULL;
  3384. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  3385. PMDL pConfigRomMdl = NULL;
  3386. TRACE( TL_T, TM_Mp, ( "==> nicAddIP1394ToConfigRom pAdapter %x", pAdapter ) );
  3387. NdisStatus = nicSetLocalHostPropertiesCRom(pAdapter,
  3388. (PUCHAR)&Net1394ConfigRom,
  3389. sizeof(Net1394ConfigRom),
  3390. SLHP_FLAG_ADD_CROM_DATA,
  3391. &hCromData,
  3392. &pConfigRomMdl);
  3393. ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
  3394. if (NdisStatus == NDIS_STATUS_SUCCESS)
  3395. {
  3396. pAdapter->hCromData = hCromData;
  3397. pAdapter->pConfigRomMdl = pConfigRomMdl;
  3398. }
  3399. TRACE( TL_T, TM_Mp, ( "<== nicAddIP1394ToConfigRom pAdapter %x", pAdapter ) );
  3400. return NdisStatus;
  3401. }
  3402. NDIS_STATUS
  3403. nicMCmRegisterAddressFamily (
  3404. IN PADAPTERCB pAdapter
  3405. )
  3406. /*++
  3407. Routine Description:
  3408. This function will only be called once per local host
  3409. This will cause the ARP module to send Create Vc's etc
  3410. Arguments:
  3411. Return Value:
  3412. --*/
  3413. {
  3414. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  3415. BOOLEAN fDoRegister = TRUE;
  3416. TRACE( TL_T, TM_Mp, ( "==> nicCmRegisterAddressFamily pAdapter %x", pAdapter ) );
  3417. do
  3418. {
  3419. // Register the address family of our call manager with NDIS for the
  3420. // newly bound adapter. We use the mini-port form of
  3421. // RegisterAddressFamily instead of the protocol form because
  3422. // we are a miniport/callmanager combo. The mini-port form
  3423. // causes the call manager VC context to
  3424. // automatically map to the mini-port VC context, which is exactly
  3425. // what we want.
  3426. //
  3427. // NDIS notifies all call manager clients of the new family we
  3428. // register.
  3429. //
  3430. {
  3431. NDIS_CALL_MANAGER_CHARACTERISTICS ncmc;
  3432. CO_ADDRESS_FAMILY family;
  3433. NdisZeroMemory( &family, sizeof(family) );
  3434. family.MajorVersion = NDIS_MajorVersion;
  3435. family.MinorVersion = NDIS_MinorVersion;
  3436. family.AddressFamily = CO_ADDRESS_FAMILY_1394;
  3437. NdisZeroMemory( &ncmc, sizeof(ncmc) );
  3438. ncmc.MajorVersion = NDIS_MajorVersion;
  3439. ncmc.MinorVersion = NDIS_MinorVersion;
  3440. ncmc.CmCreateVcHandler = NicCmCreateVc;
  3441. ncmc.CmDeleteVcHandler = NicCmDeleteVc;
  3442. ncmc.CmOpenAfHandler = NicCmOpenAf;
  3443. ncmc.CmCloseAfHandler = NicCmCloseAf;
  3444. ncmc.CmRegisterSapHandler = nicRegisterSapHandler;
  3445. ncmc.CmDeregisterSapHandler = nicDeregisterSapHandler;
  3446. ncmc.CmMakeCallHandler = NicCmMakeCall;
  3447. ncmc.CmCloseCallHandler = NicCmCloseCall;
  3448. // NEW for 1394 no ncmc.CmIncomingCallCompleteHandler
  3449. ncmc.CmAddPartyHandler = nicCmAddPartyHandler;
  3450. ncmc.CmDropPartyHandler = nicCmDropPartyHandler;
  3451. // no CmDropPartyHandler
  3452. // NEW for 1394 no ncmc.CmActivateVcCompleteHandler
  3453. // NEW for 1394 no ncmc.CmDeactivateVcCompleteHandler
  3454. ncmc.CmModifyCallQoSHandler = NicCmModifyCallQoS;
  3455. ncmc.CmRequestHandler = NicCmRequest;
  3456. // no CmRequestCompleteHandler
  3457. TRACE( TL_I, TM_Cm, ( "NdisMCmRegAf" ) );
  3458. NdisStatus = NdisMCmRegisterAddressFamily (pAdapter->MiniportAdapterHandle,
  3459. &family,
  3460. &ncmc,
  3461. sizeof(ncmc) );
  3462. TRACE( TL_I, TM_Cm, ( "NdisMCmRegAf=$%x", NdisStatus ) );
  3463. }
  3464. } while (FALSE);
  3465. TRACE( TL_T, TM_Mp, ( "<== nicCmRegisterAddressFamily NdisStatus %x", NdisStatus ) );
  3466. return NdisStatus;
  3467. }
  3468. VOID
  3469. nicFreeReassembliesOnRemoteNode (
  3470. IN PREMOTE_NODE pRemoteNode,
  3471. PLIST_ENTRY pToBeFreedList
  3472. )
  3473. /*++
  3474. Routine Description:
  3475. Free All reassemblies that are on this remote node.
  3476. Acquires the reassembly Lock , pops the reassemblies off the list and then aborts them
  3477. This functions is an exception to our reassembly garbage collection. algorithm as the context of this function
  3478. requires immediate freeing of the reassembly structures
  3479. Expects the remote node lock to be held
  3480. Arguments:
  3481. pRemote Node - Remote Node that is being pulled out
  3482. Return Value:
  3483. --*/
  3484. {
  3485. ULONG NumFreed=0;
  3486. PLIST_ENTRY pReassemblyList = NULL;
  3487. PNDIS1394_REASSEMBLY_STRUCTURE pReassembly = NULL;
  3488. STORE_CURRENT_IRQL;
  3489. TRACE( TL_T, TM_Mp, ( "==> nicFreeReassembliesOnRemoteNode pRemoteNode %x", pRemoteNode) );
  3490. InitializeListHead(pToBeFreedList);
  3491. //
  3492. // Now walking through all the reassembly structures on that remote node
  3493. //
  3494. //
  3495. // If the remtoe node is in the list, it is fair game for us to extract it
  3496. //
  3497. REMOTE_NODE_REASSEMBLY_ACQUIRE_LOCK (pRemoteNode);
  3498. pReassemblyList = ListNext(&pRemoteNode->ReassemblyList);
  3499. while (pReassemblyList != &pRemoteNode->ReassemblyList)
  3500. {
  3501. pReassembly = CONTAINING_RECORD (pReassemblyList,
  3502. NDIS1394_REASSEMBLY_STRUCTURE,
  3503. ReassemblyListEntry);
  3504. pReassemblyList = ListNext(pReassemblyList);
  3505. //
  3506. // Once the reassembly has been marked as free, it should no longer be in the remote
  3507. // node's list .
  3508. //
  3509. ASSERT (REASSEMBLY_TEST_FLAG (pReassembly, REASSEMBLY_FREED) == FALSE);
  3510. REASSEMBLY_SET_FLAG (pReassembly, REASSEMBLY_FREED);
  3511. //
  3512. // We have the lock, so we can remove this reassembly structure from the remote node
  3513. //
  3514. TRACE( TL_V, TM_Mp, ( "Removing Reassembly %x", pReassembly) );
  3515. RemoveEntryList(&pReassembly->ReassemblyListEntry);
  3516. //
  3517. // dereference the remote node . ref was made when the reassembly was added
  3518. // to the remote node
  3519. //
  3520. nicDereferenceRemoteNode (pRemoteNode, FreeReassembliesOnRemoteNode );
  3521. nicDereferenceReassembly(pReassembly, "nicFreeReassembliesOnRemoteNode " );
  3522. //
  3523. // add this reassembly to the to be freed list.
  3524. //
  3525. InsertTailList(pToBeFreedList,&pReassembly->ReassemblyListEntry);
  3526. }// while (pReassemblyList != &pRemoteNode->ReassemblyList)
  3527. REMOTE_NODE_REASSEMBLY_RELEASE_LOCK(pRemoteNode);
  3528. TRACE( TL_T, TM_Mp, ( "<== nicFreeReassembliesOnRemoteNode NumFreed %x",NumFreed ) );
  3529. MATCH_IRQL;
  3530. }
  3531. UCHAR
  3532. nicGetMaxRecFromBytes(
  3533. IN ULONG ByteSize
  3534. )
  3535. /*++
  3536. Routine Description:
  3537. Converts Size in bytes to MaxRec
  3538. 512 - 8
  3539. 1024 - 9
  3540. Arguments:
  3541. ULONG Bytes Size
  3542. Return Value:
  3543. --*/
  3544. {
  3545. TRACE( TL_T ,TM_Mp, ( "==>nicGetMaxRecFromBytes ByteSize %x",ByteSize) );
  3546. if (ByteSize == ASYNC_PAYLOAD_100_RATE) return MAX_REC_100_RATE;
  3547. if (ByteSize == ASYNC_PAYLOAD_200_RATE) return MAX_REC_200_RATE;
  3548. if (ByteSize == ASYNC_PAYLOAD_400_RATE) return MAX_REC_400_RATE;
  3549. if (ByteSize == ASYNC_PAYLOAD_800_RATE_LOCAL) return MAX_REC_800_RATE_LOCAL;
  3550. if (ByteSize == ASYNC_PAYLOAD_1600_RATE_LOCAL) return MAX_REC_1600_RATE_LOCAL;
  3551. if (ByteSize == ASYNC_PAYLOAD_3200_RATE_LOCAL) return MAX_REC_3200_RATE_LOCAL;
  3552. //
  3553. // Default to 400 for all greater values
  3554. //
  3555. return MAX_REC_400_RATE;
  3556. }
  3557. UCHAR
  3558. nicGetMaxRecFromSpeed(
  3559. IN ULONG Scode
  3560. )
  3561. /*++
  3562. Routine Description:
  3563. Converts Speed to MaxRec
  3564. Arguments:
  3565. ULONG Bytes Size
  3566. Return Value:
  3567. --*/
  3568. {
  3569. TRACE( TL_T ,TM_Mp, ( "==>nicGetMaxRecFromSpeed Scode %x",Scode) );
  3570. if (Scode == SPEED_FLAGS_100) return MAX_REC_100_RATE;
  3571. if (Scode == SPEED_FLAGS_200 ) return MAX_REC_200_RATE;
  3572. if (Scode == SPEED_FLAGS_400 ) return MAX_REC_400_RATE;
  3573. if (Scode == SPEED_FLAGS_800 ) return MAX_REC_800_RATE_LOCAL ;
  3574. if (Scode == SPEED_FLAGS_1600 ) return MAX_REC_1600_RATE_LOCAL ;
  3575. if (Scode == SPEED_FLAGS_3200 ) return MAX_REC_3200_RATE_LOCAL ;
  3576. //
  3577. // default
  3578. //
  3579. return MAX_REC_400_RATE;
  3580. }
  3581. PREMOTE_NODE
  3582. nicGetRemoteNodeFromTable (
  3583. ULONG NodeNumber,
  3584. PADAPTERCB pAdapter
  3585. )
  3586. /*++
  3587. Routine Description:
  3588. Looks up the remote node in a locked table , references the remote
  3589. node and returns
  3590. Arguments:
  3591. ULONG NodeNumber
  3592. Return Value:
  3593. pRemoteNode
  3594. --*/
  3595. {
  3596. PREMOTE_NODE pRemoteNode = NULL;
  3597. ADAPTER_ACQUIRE_LOCK (pAdapter);
  3598. pRemoteNode = pAdapter->NodeTable.RemoteNode[NodeNumber];
  3599. if (pRemoteNode != NULL)
  3600. {
  3601. nicReferenceRemoteNode (pRemoteNode, GetRemoteNodeFromTable);
  3602. }
  3603. ADAPTER_RELEASE_LOCK (pAdapter);
  3604. return pRemoteNode;
  3605. }
  3606. NDIS_STATUS
  3607. nicFillNicInfo (
  3608. IN PADAPTERCB pAdapter,
  3609. PNIC1394_NICINFO pInNicInfo,
  3610. PNIC1394_NICINFO pOutNicInfo
  3611. )
  3612. /*++
  3613. Routine Description:
  3614. Takes the Buffer passed in, makes sure that it is big enough
  3615. and then puts all our statistics into that buffer
  3616. Arguments:
  3617. Return Value:
  3618. --*/
  3619. {
  3620. NDIS_STATUS Status = NDIS_STATUS_INVALID_DATA;
  3621. do
  3622. {
  3623. //
  3624. // First check internal version
  3625. //
  3626. if (pInNicInfo->Hdr.Version != NIC1394_NICINFO_VERSION)
  3627. {
  3628. TRACE( TL_A, TM_Mp, ( " NICINFO.Version mismatch. Want %lu got %lu\n",
  3629. NIC1394_NICINFO_VERSION,
  3630. pInNicInfo->Hdr.Version
  3631. ));
  3632. break;
  3633. }
  3634. //
  3635. // Struct-copy the old to the new. It's wasteful, but we don't want
  3636. // to dig into how much of the in buffer contains valid data.
  3637. //
  3638. *pOutNicInfo = *pInNicInfo;
  3639. //
  3640. // Rest is op-specific
  3641. //
  3642. switch(pOutNicInfo->Hdr.Op)
  3643. {
  3644. case NIC1394_NICINFO_OP_BUSINFO:
  3645. Status = nicFillBusInfo(pAdapter, &pOutNicInfo->BusInfo);
  3646. break;
  3647. case NIC1394_NICINFO_OP_REMOTENODEINFO:
  3648. Status = nicFillRemoteNodeInfo(pAdapter, &pOutNicInfo->RemoteNodeInfo);
  3649. break;
  3650. case NIC1394_NICINFO_OP_CHANNELINFO:
  3651. Status = nicFillChannelInfo(pAdapter, &pOutNicInfo->ChannelInfo);
  3652. break;
  3653. case NIC1394_NICINFO_OP_RESETSTATS:
  3654. Status = nicResetStats (pAdapter, &pOutNicInfo->ResetStats);
  3655. default:
  3656. TRACE( TL_A, TM_Mp, ( " NICINFO.Op (%lu) is unknown.\n",
  3657. pInNicInfo->Hdr.Op
  3658. ));
  3659. break;
  3660. }
  3661. } while (FALSE);
  3662. return Status;
  3663. }
  3664. NDIS_STATUS
  3665. nicResetStats (
  3666. IN PADAPTERCB pAdapter,
  3667. PNIC1394_RESETSTATS pResetStats
  3668. )
  3669. /*++
  3670. Routine Description:
  3671. Self explanatory
  3672. Arguments:
  3673. Return Value:
  3674. --*/
  3675. {
  3676. NdisZeroMemory (&pAdapter->AdaptStats.TempStats, sizeof (pAdapter->AdaptStats.TempStats) );
  3677. return NDIS_STATUS_SUCCESS;
  3678. }
  3679. NDIS_STATUS
  3680. nicFillBusInfo(
  3681. IN PADAPTERCB pAdapter,
  3682. IN OUT PNIC1394_BUSINFO pBi
  3683. )
  3684. /*++
  3685. Routine Description:
  3686. Colpied all the statistics that we have into the buffer
  3687. that was passed in.
  3688. Arguments:
  3689. Return Value:
  3690. --*/
  3691. {
  3692. ULARGE_INTEGER BusMap, ActiveMap;
  3693. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  3694. NIC_SEND_RECV_STATS* pNicStats = NULL;
  3695. PADAPT_STATS pAdaptStats = &pAdapter->AdaptStats;
  3696. //
  3697. // Fill with Dummy data
  3698. //
  3699. pBi->NumBusResets = pAdaptStats->ulNumResetCallbacks;
  3700. pBi->SecondsSinceBusReset = nicGetSystemTime() - pAdaptStats->ulResetTime;
  3701. pBi->Flags = (BCR_TEST_FLAG( pAdapter, BCR_LocalHostIsIRM) == TRUE ) ? NIC1394_BUSINFO_LOCAL_IS_IRM : 0;
  3702. //
  3703. // CHANNEL RELATED INFORMATION
  3704. //
  3705. NdisStatus = nicQueryChannelMap( pAdapter, &BusMap);
  3706. if (NdisStatus == NDIS_STATUS_SUCCESS)
  3707. {
  3708. pBi->Channel.BusMap = BusMap.QuadPart;
  3709. }
  3710. //
  3711. // For now
  3712. //
  3713. ActiveMap.QuadPart = pAdapter->ChannelsAllocatedByLocalHost;
  3714. //
  3715. // First zero out some info
  3716. //
  3717. NdisZeroMemory( &pBi->Channel.SendPktStats, sizeof (pBi->Channel.SendPktStats ));
  3718. NdisZeroMemory( &pBi->Fifo.SendPktStats, sizeof (pBi->Fifo.SendPktStats) ) ;
  3719. //
  3720. // Now go through each Vc and extract the relevant information
  3721. //
  3722. ADAPTER_ACQUIRE_LOCK (pAdapter);
  3723. #define GARBAGE 9999
  3724. pBi->Channel.Bcr = *((PULONG) &pAdapter->BCRData.IRM_BCR);
  3725. pBi->LocalNodeInfo.UniqueID = pAdapter->UniqueId; // This node's 64-bit Unique ID.
  3726. pBi->LocalNodeInfo.BusGeneration = pAdapter->Generation; // 1394 Bus generation ID.
  3727. pBi->LocalNodeInfo.NodeAddress = pAdapter->NodeAddress;
  3728. pBi->LocalNodeInfo.MaxRecvBlockSize = pAdapter->MaxRec;
  3729. pBi->LocalNodeInfo.MaxRecvSpeed = pAdapter->SCode;
  3730. //
  3731. // Fill up Recv Vc Stats
  3732. //
  3733. if (pAdapter->pRecvFIFOVc != NULL)
  3734. {
  3735. PRECVFIFO_VCCB pRecvVc = pAdapter->pRecvFIFOVc;
  3736. pBi->Fifo.Recv_Off_Low = pRecvVc->VcAddressRange.AR_Off_Low;
  3737. pBi->Fifo.Recv_Off_High = pRecvVc ->VcAddressRange.AR_Off_High;
  3738. nicCopyPacketStats(&pBi->Fifo.RecvPktStats
  3739. ,pAdapter->AdaptStats.TempStats.Fifo.ulRecv,
  3740. GARBAGE ,
  3741. GARBAGE ,
  3742. GARBAGE);
  3743. pBi->Fifo.NumFreeRecvBuffers = pRecvVc->NumAllocatedFifos - pRecvVc->NumIndicatedFifos;
  3744. pBi->Fifo.MinFreeRecvBuffers = GARBAGE ; // todo
  3745. }
  3746. //
  3747. // Fifo Send Stats
  3748. //
  3749. pNicStats = &pAdaptStats->TempStats.Fifo;
  3750. nicCopyPacketStats ( &pBi->Fifo.SendPktStats,
  3751. pNicStats->ulSendNicSucess,
  3752. pNicStats->ulSendNicFail,
  3753. pNicStats->ulSendBusSuccess,
  3754. pNicStats->ulSendBusFail );
  3755. nicCopyPacketStats ( &pBi->Fifo.RecvPktStats,
  3756. pNicStats->ulRecv,
  3757. 0,
  3758. 0,
  3759. 0);
  3760. //
  3761. // Channel Send Stats
  3762. //
  3763. pNicStats = &pAdapter->AdaptStats.TempStats.Channel;
  3764. nicCopyPacketStats ( &pBi->Channel.SendPktStats,
  3765. pNicStats->ulSendNicSucess,
  3766. pNicStats->ulSendNicFail,
  3767. pNicStats->ulSendBusSuccess,
  3768. pNicStats->ulSendBusFail );
  3769. //
  3770. // Broadcast channel data - same as channel
  3771. //
  3772. nicCopyPacketStats ( &pBi->Channel.BcSendPktStats,
  3773. pNicStats->ulSendNicSucess,
  3774. pNicStats->ulSendNicFail,
  3775. pNicStats->ulSendBusSuccess,
  3776. pNicStats->ulSendBusFail );
  3777. //
  3778. // Recv Channels
  3779. //
  3780. nicCopyPacketStats ( &pBi->Channel.BcRecvPktStats ,
  3781. pNicStats->ulRecv,
  3782. 0,
  3783. 0,
  3784. 0);
  3785. ADAPTER_RELEASE_LOCK (pAdapter);
  3786. pBi->Channel.ActiveChannelMap= ActiveMap.QuadPart;
  3787. pBi->Fifo.NumOutstandingReassemblies = pAdaptStats->TempStats.ulNumOutstandingReassemblies;
  3788. pBi->Fifo.MaxOutstandingReassemblies =pAdaptStats->TempStats.ulMaxOutstandingReassemblies;
  3789. //pBi->Fifo.NumAbortedReassemblies = ReassemblyCompleted;
  3790. //
  3791. // Information about remote nodes. More information about each of these nodes
  3792. // may be queried using *OP_REMOTE_NODEINFO
  3793. //
  3794. pBi->NumRemoteNodes = pAdaptStats->ulNumRemoteNodes;
  3795. ADAPTER_ACQUIRE_LOCK (pAdapter);
  3796. {
  3797. UINT i = 0;
  3798. PLIST_ENTRY pRemoteEntry = ListNext(&pAdapter->PDOList);
  3799. while (pRemoteEntry != &pAdapter->PDOList)
  3800. {
  3801. PREMOTE_NODE pRemote = CONTAINING_RECORD (pRemoteEntry,
  3802. REMOTE_NODE,
  3803. linkPdo);
  3804. pRemoteEntry = ListNext(pRemoteEntry);
  3805. pBi->RemoteNodeUniqueIDS[i] = pRemote->UniqueId;
  3806. i++;
  3807. }
  3808. }
  3809. ADAPTER_RELEASE_LOCK (pAdapter);
  3810. return NDIS_STATUS_SUCCESS;
  3811. }
  3812. NDIS_STATUS
  3813. nicFillChannelInfo(
  3814. IN PADAPTERCB pAdapter,
  3815. IN OUT PNIC1394_CHANNELINFO pCi
  3816. )
  3817. /*++
  3818. Routine Description:
  3819. Simply return success.
  3820. Arguments:
  3821. Return Value:
  3822. --*/
  3823. {
  3824. return NDIS_STATUS_SUCCESS;
  3825. }
  3826. NDIS_STATUS
  3827. nicFillRemoteNodeInfo(
  3828. IN PADAPTERCB pAdapter,
  3829. IN OUT PNIC1394_REMOTENODEINFO pRni
  3830. )
  3831. /*++
  3832. Routine Description:
  3833. Captures the information from our Remote Nodes.
  3834. Arguments:
  3835. Return Value:
  3836. --*/
  3837. {
  3838. NDIS_STATUS NdisStatus;
  3839. REMOTE_NODE *pRemoteNode = NULL;
  3840. do
  3841. {
  3842. //
  3843. // First let's find the remote node, based on the unique ID.
  3844. // nicFindRemoteNodeFromAdapter refs pRemoteNode on success.
  3845. //
  3846. NdisStatus = nicFindRemoteNodeFromAdapter(pAdapter,
  3847. NULL, // pPDO OPTIONAL
  3848. pRni->UniqueID,
  3849. &pRemoteNode);
  3850. if (NdisStatus != NDIS_STATUS_SUCCESS)
  3851. {
  3852. pRemoteNode = NULL;
  3853. break;
  3854. }
  3855. NdisStatus = nicQueryRemoteNodeCaps (pAdapter,
  3856. pRemoteNode,
  3857. &pRni->MaxSpeedBetweenNodes,
  3858. &pRni->EffectiveMaxBlockSize,
  3859. &pRni->MaxRec
  3860. );
  3861. REMOTE_NODE_ACQUIRE_LOCK (pRemoteNode);
  3862. pRni->NodeAddress = *(PUSHORT) &pRemoteNode->RemoteAddress;
  3863. if (REMOTE_NODE_ACTIVE (pRemoteNode))
  3864. {
  3865. pRni->Flags = NIC1394_REMOTEINFO_ACTIVE;
  3866. }
  3867. else
  3868. {
  3869. pRni->Flags = NIC1394_REMOTEINFO_UNLOADING; // we assume it's unloading.
  3870. }
  3871. REMOTE_NODE_RELEASE_LOCK (pRemoteNode);
  3872. //
  3873. // Don't support the following yet.
  3874. //
  3875. NdisZeroMemory (&pRni->SendFifoPktStats, sizeof (pRni->SendFifoPktStats) );
  3876. NdisZeroMemory (&pRni->SendFifoPktStats, sizeof (pRni->SendFifoPktStats));
  3877. NdisZeroMemory (&pRni->RecvFifoPktStats, sizeof (pRni->SendFifoPktStats));
  3878. NdisZeroMemory (&pRni->RecvChannelPktStats , sizeof (pRni->SendFifoPktStats));
  3879. } while (FALSE);
  3880. if (pRemoteNode != NULL)
  3881. {
  3882. nicDereferenceRemoteNode(pRemoteNode, FillRemoteNodeInfo);
  3883. }
  3884. return NdisStatus;
  3885. }
  3886. VOID
  3887. nicCopyPacketStats (
  3888. NIC1394_PACKET_STATS* pStats,
  3889. UINT TotNdisPackets, // Total number of NDIS packets sent/indicated
  3890. UINT NdisPacketsFailures,// Number of NDIS packets failed/discarded
  3891. UINT TotBusPackets, // Total number of BUS-level reads/writes
  3892. UINT BusPacketFailures // Number of BUS-level failures(sends)/discards(recv)
  3893. )
  3894. /*++
  3895. Routine Description:
  3896. Self Explanatory
  3897. Arguments:
  3898. Return Value:
  3899. --*/
  3900. {
  3901. pStats->TotNdisPackets= TotNdisPackets; // Total number of NDIS packets sent/indicated
  3902. pStats->NdisPacketsFailures= NdisPacketsFailures;// Number of NDIS packets failed/discarded
  3903. pStats->TotBusPackets = TotBusPackets; // Total number of BUS-level reads/writes
  3904. pStats->TotBusPackets = BusPacketFailures; // Number of BUS-level failures(sends)/discards(recv)
  3905. }
  3906. VOID
  3907. nicAddPacketStats(
  3908. NIC1394_PACKET_STATS* pStats,
  3909. UINT TotNdisPackets, // Total number of NDIS packets sent/indicated
  3910. UINT NdisPacketsFailures,// Number of NDIS packets failed/discarded
  3911. UINT TotBusPackets, // Total number of BUS-level reads/writes
  3912. UINT BusPacketFailures // Number of BUS-level failures(sends)/discards(recv)
  3913. )
  3914. /*++
  3915. Routine Description:
  3916. Self Explanatory
  3917. Arguments:
  3918. Return Value:
  3919. --*/
  3920. {
  3921. pStats->TotNdisPackets+= TotNdisPackets; // Total number of NDIS packets sent/indicated
  3922. pStats->NdisPacketsFailures+= NdisPacketsFailures;// Number of NDIS packets failed/discarded
  3923. pStats->TotBusPackets += TotBusPackets; // Total number of BUS-level reads/writes
  3924. pStats->TotBusPackets += BusPacketFailures; // Number of BUS-level failures(sends)/discards(recv)
  3925. }
  3926. VOID
  3927. nicInformProtocolsOfReset(
  3928. IN PADAPTERCB pAdapter
  3929. )
  3930. /*++
  3931. Routine Description:
  3932. Informs protocols of reset. Does an NdisMCoIndicateStatus with a locally allocated structure
  3933. which includes the new Local Node Address and Generation
  3934. Arguments:
  3935. Return Value:
  3936. --*/
  3937. {
  3938. NIC1394_STATUS_BUFFER StatusBuffer;
  3939. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  3940. TRACE( TL_T, TM_Mp, ( "==> nicInformProtocolsOfReset ") );
  3941. do
  3942. {
  3943. NdisZeroMemory (&StatusBuffer, sizeof (StatusBuffer) );
  3944. StatusBuffer.Signature = NIC1394_MEDIA_SPECIFIC;
  3945. StatusBuffer.Event = NIC1394_EVENT_BUS_RESET;
  3946. NdisMCoIndicateStatus(pAdapter->MiniportAdapterHandle,
  3947. NULL,
  3948. NDIS_STATUS_MEDIA_SPECIFIC_INDICATION,
  3949. &StatusBuffer,
  3950. sizeof(StatusBuffer));
  3951. } while (FALSE);
  3952. TRACE( TL_T, TM_Mp, ( "<== nicInformProtocolsOfReset ") );
  3953. }
  3954. VOID
  3955. nicUpdateRemoteNodeCaps(
  3956. PADAPTERCB pAdapter
  3957. )
  3958. /*++
  3959. Routine Description:
  3960. Update the caps (maxrec, maxspeed-to, max effective buffer size) for all
  3961. nodes that we have connections to.
  3962. Arguments:
  3963. Return Value:
  3964. --*/
  3965. {
  3966. ULONG i = 0;
  3967. ULONG NumNodes = 0;
  3968. PREMOTE_NODE pRemoteNode = NULL;
  3969. NODE_ADDRESS NodeAddress;
  3970. NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
  3971. for (i=0; i<NIC1394_MAX_NICINFO_NODES; i++)
  3972. {
  3973. UINT SpeedTo;
  3974. UINT EffectiveMaxBufferSize;
  3975. UINT MaxRec;
  3976. if (pAdapter->NodeTable.RemoteNode[i] == NULL)
  3977. {
  3978. continue; // ******************* CONTINUE ****************
  3979. }
  3980. ADAPTER_ACQUIRE_LOCK (pAdapter);
  3981. pRemoteNode = pAdapter->NodeTable.RemoteNode[i];
  3982. // We check again, with the lock held.
  3983. //
  3984. if (pRemoteNode == NULL || !REMOTE_NODE_ACTIVE (pRemoteNode))
  3985. {
  3986. ADAPTER_RELEASE_LOCK (pAdapter);
  3987. continue; // ******************* CONTINUE ****************
  3988. }
  3989. nicReferenceRemoteNode (pRemoteNode, UpdateRemoteNodeCaps);
  3990. ADAPTER_RELEASE_LOCK (pAdapter);
  3991. // Specifying FALSE (!from cache) below causes pRemoteNode's cached caps
  3992. // to be refreshed.
  3993. //
  3994. NdisStatus = nicQueryRemoteNodeCaps (pAdapter,
  3995. pRemoteNode,
  3996. &SpeedTo,
  3997. &EffectiveMaxBufferSize,
  3998. &MaxRec
  3999. );
  4000. if (NdisStatus != NDIS_STATUS_SUCCESS)
  4001. {
  4002. TRACE( TL_A, TM_Mp, ( "nicUpdateRemoteNodeCaps couldn't update caps fo node %x", pRemoteNode));
  4003. }
  4004. nicDereferenceRemoteNode (pRemoteNode, UpdateRemoteNodeCaps);
  4005. }
  4006. }
  4007. VOID
  4008. nicQueryInformationWorkItem(
  4009. IN PNDIS_WORK_ITEM pWorkItem,
  4010. IN PVOID Context
  4011. )
  4012. /*++
  4013. Routine Description:
  4014. This is the WorkItem that we have allocated for
  4015. our querying information.
  4016. Arguments:
  4017. Return Value:
  4018. --*/
  4019. {
  4020. PADAPTERCB pAdapter= (PADAPTERCB) Context;
  4021. PNIC_WORK_ITEM pNicWorkItem = (PNIC_WORK_ITEM) pWorkItem;
  4022. NDIS_STATUS Status;
  4023. Status = nicQueryInformation(
  4024. pAdapter,
  4025. pNicWorkItem->RequestInfo.pVc,
  4026. pNicWorkItem->RequestInfo.pNdisRequest
  4027. );
  4028. //
  4029. // We call at passive, so we should never be pending here.
  4030. //
  4031. ASSERT(Status != NDIS_STATUS_PENDING);
  4032. //
  4033. // Asynchronously complete the work item.
  4034. //
  4035. NdisMCoRequestComplete(
  4036. Status,
  4037. pAdapter->MiniportAdapterHandle,
  4038. pNicWorkItem->RequestInfo.pNdisRequest
  4039. );
  4040. //
  4041. // Deref the work item adapter reference.
  4042. //
  4043. FREE_NONPAGED (pWorkItem);
  4044. NdisInterlockedDecrement(&pAdapter->OutstandingWorkItems);
  4045. nicDereferenceAdapter(pAdapter, "nicQueryInfoWorkItem");
  4046. }
  4047. VOID
  4048. nicMIndicateStatus(
  4049. IN PADAPTERCB pAdapter ,
  4050. IN NDIS_STATUS GeneralStatus,
  4051. IN PVOID StatusBuffer,
  4052. IN UINT StatusBufferSize
  4053. )
  4054. /*++
  4055. Routine Description:
  4056. This function inserts a packet into the send queue. If there is no timer servicing the queue
  4057. then it queues a timer to dequeue the packet in Global Event's context
  4058. Arguments:
  4059. Self explanatory
  4060. Return Value:
  4061. Success - if inserted into the the queue
  4062. --*/
  4063. {
  4064. if (ADAPTER_TEST_FLAG (pAdapter, fADAPTER_DoStatusIndications) == FALSE)
  4065. {
  4066. return;
  4067. }
  4068. NdisMCoIndicateStatus (pAdapter->MiniportAdapterHandle ,
  4069. NULL,
  4070. GeneralStatus,
  4071. StatusBuffer,
  4072. StatusBufferSize
  4073. );
  4074. }
  4075. NDIS_STATUS
  4076. nicAllocateLoopbackPacketPool (
  4077. IN PADAPTERCB pAdapter
  4078. )
  4079. /*++
  4080. Routine Description:
  4081. allocate a packet and buffer pool for loopback packet
  4082. Arguments:
  4083. Return Value:
  4084. --*/
  4085. {
  4086. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  4087. do
  4088. {
  4089. //
  4090. // Allocate a packet pool to indicate loopback receives from.
  4091. //
  4092. NdisAllocatePacketPoolEx(
  4093. &NdisStatus,
  4094. &pAdapter->LoopbackPool.Handle,
  4095. 32,
  4096. 32,
  4097. sizeof(LOOPBACK_RSVD)
  4098. );
  4099. if (NdisStatus != NDIS_STATUS_SUCCESS)
  4100. {
  4101. break;
  4102. }
  4103. pAdapter->LoopbackPool.AllocatedPackets = 0;
  4104. NdisAllocateBufferPool(
  4105. &NdisStatus,
  4106. &pAdapter->LoopbackBufferPool,
  4107. 64
  4108. );
  4109. if (NdisStatus != NDIS_STATUS_SUCCESS)
  4110. {
  4111. break;
  4112. }
  4113. } while (FALSE);
  4114. return NdisStatus;
  4115. }
  4116. VOID
  4117. nicFreeLoopbackPacketPool (
  4118. IN PADAPTERCB pAdapter
  4119. )
  4120. /*++
  4121. Routine Description:
  4122. free the packet and buffer pool for loopback packet
  4123. Arguments:
  4124. Return Value:
  4125. --*/
  4126. {
  4127. if (pAdapter->LoopbackPool.Handle != NULL)
  4128. {
  4129. nicFreePacketPool (&pAdapter->LoopbackPool);
  4130. }
  4131. if (pAdapter->LoopbackBufferPool != NULL)
  4132. {
  4133. NdisFreeBufferPool(pAdapter->LoopbackBufferPool);
  4134. pAdapter->LoopbackBufferPool = NULL;
  4135. }
  4136. }
  4137. VOID
  4138. nicLoopbackPacket(
  4139. IN VCCB* pVc,
  4140. IN PNDIS_PACKET pPacket
  4141. )
  4142. /*++
  4143. Routine Description:
  4144. Allocate a packet and indicate it up on the Broadcast vc
  4145. Arguments:
  4146. Return Value:
  4147. --*/
  4148. {
  4149. NDIS_STATUS Status;
  4150. PNDIS_BUFFER pFirstBuffer;
  4151. ULONG TotalLength;
  4152. PNDIS_PACKET pLoopbackPacket;
  4153. PUCHAR pCopyBuf;
  4154. PNDIS_BUFFER pLoopbackBuffer;
  4155. ULONG BytesCopied;
  4156. ADAPTERCB* pAdapter;
  4157. PLOOPBACK_RSVD pLoopbackRsvd;
  4158. pAdapter = pVc->Hdr.pAF->pAdapter;
  4159. TRACE( TL_T, TM_Recv, ("NIC1394: loopback pkt %p on VC %p, type %d\n",
  4160. pPacket, pVc, pVc->Hdr.VcType));
  4161. pLoopbackPacket = NULL;
  4162. pLoopbackBuffer = NULL;
  4163. pCopyBuf = NULL;
  4164. do
  4165. {
  4166. nicAllocatePacket(&Status, &pLoopbackPacket, &pAdapter->LoopbackPool);
  4167. if (Status != NDIS_STATUS_SUCCESS)
  4168. {
  4169. break;
  4170. }
  4171. NdisQueryPacket(
  4172. pPacket,
  4173. NULL,
  4174. NULL,
  4175. &pFirstBuffer,
  4176. &TotalLength
  4177. );
  4178. pCopyBuf = ALLOC_NONPAGED (TotalLength, MTAG_RBUF);
  4179. if (pCopyBuf == NULL)
  4180. {
  4181. Status = NDIS_STATUS_RESOURCES;
  4182. break;
  4183. }
  4184. NdisAllocateBuffer(
  4185. &Status,
  4186. &pLoopbackBuffer,
  4187. pAdapter->LoopbackBufferPool,
  4188. pCopyBuf,
  4189. TotalLength
  4190. );
  4191. if (Status != NDIS_STATUS_SUCCESS)
  4192. {
  4193. break;
  4194. }
  4195. pLoopbackBuffer->Next = NULL;
  4196. NdisChainBufferAtFront(pLoopbackPacket, pLoopbackBuffer);
  4197. NdisCopyFromPacketToPacket(
  4198. pLoopbackPacket,
  4199. 0,
  4200. TotalLength,
  4201. pPacket,
  4202. 0,
  4203. &BytesCopied
  4204. );
  4205. //
  4206. // Make sure we can reclaim the packet after the receive indicate
  4207. // returns.
  4208. //
  4209. // If the status is made async, then the loopback Tag will
  4210. // break in the return packet handler
  4211. //
  4212. NDIS_SET_PACKET_STATUS(pLoopbackPacket, NDIS_STATUS_RESOURCES);
  4213. // Set the Loopback Tag.
  4214. pLoopbackRsvd = (PLOOPBACK_RSVD) pLoopbackPacket->ProtocolReserved;
  4215. pLoopbackRsvd->LoopbackTag = NIC_LOOPBACK_TAG;
  4216. NdisSetPacketFlags (pLoopbackPacket, NDIS_FLAGS_IS_LOOPBACK_PACKET);
  4217. NdisMCoIndicateReceivePacket(
  4218. pVc->Hdr.NdisVcHandle,
  4219. &pLoopbackPacket,
  4220. 1);
  4221. NdisFreeBuffer(pLoopbackBuffer);
  4222. nicFreePacket(pLoopbackPacket, &pAdapter->LoopbackPool);
  4223. FREE_NONPAGED(pCopyBuf);
  4224. }
  4225. while (FALSE);
  4226. if (Status != NDIS_STATUS_SUCCESS)
  4227. {
  4228. if (pCopyBuf)
  4229. {
  4230. FREE_NONPAGED(pCopyBuf);
  4231. }
  4232. if (pLoopbackBuffer)
  4233. {
  4234. NdisFreeBuffer(pLoopbackBuffer);
  4235. }
  4236. if (pLoopbackPacket)
  4237. {
  4238. nicFreePacket(pLoopbackPacket, &pAdapter->LoopbackPool);
  4239. }
  4240. }
  4241. }
  4242. VOID
  4243. nicWriteErrorLog (
  4244. IN PADAPTERCB pAdapter,
  4245. IN NDIS_ERROR_CODE ErrorCode,
  4246. IN ULONG ErrorValue
  4247. )
  4248. /*++
  4249. Routine Description:
  4250. Self Explanatory - See DDK
  4251. Arguments:
  4252. Return Value:
  4253. --*/
  4254. {
  4255. NdisWriteErrorLogEntry( pAdapter->MiniportAdapterHandle,
  4256. ErrorCode,
  4257. 1,
  4258. ErrorValue
  4259. );
  4260. }
  4261. VOID
  4262. nicUpdateRemoteNodeTable (
  4263. IN PADAPTERCB pAdapter
  4264. )
  4265. /*++
  4266. Routine Description:
  4267. Go through all the remote nodes in the system and query its Node Address
  4268. Make two tables, one contains all the remote nodes that have been refed. The
  4269. other contains the Nodes according to their Node Addresses(TempNodeTable).
  4270. Simple algorithm:
  4271. Take a snapshot of the current RemoteNodes List into RefNodeTable
  4272. Ref all the remote nodes in a local structure.
  4273. Get their new remote node addresses (TempNodeTable)
  4274. Copy the TempNodeTable into the Adapter Structure - it is now official
  4275. Update the address in the remote node themselves
  4276. Dereference the Ref made above
  4277. Arguments:
  4278. Return Value:
  4279. --*/
  4280. {
  4281. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  4282. PNODE_TABLE pNodeTable = &pAdapter->NodeTable;
  4283. PLIST_ENTRY pRemoteNodeList;
  4284. NODE_ADDRESS RemoteNodeAddress;
  4285. NODE_TABLE RefNodeTable;
  4286. NODE_TABLE TempNodeTable;
  4287. ULONG NumRemoteNodes = 0;
  4288. ULONG MaxNumRefNodeTable = 0;
  4289. USHORT RefIndex=0;
  4290. PREMOTE_NODE pCurrRemoteNode;
  4291. STORE_CURRENT_IRQL;
  4292. TRACE( TL_T, TM_Mp, ( " ==>nicUpdateRemoteNodeTable pAdapter %x, TempNodeTable%x", pAdapter , &TempNodeTable) );
  4293. NdisZeroMemory (&TempNodeTable, sizeof (NODE_TABLE) );
  4294. NdisZeroMemory (&RefNodeTable, sizeof(RefNodeTable));
  4295. NumRemoteNodes = 0;
  4296. ADAPTER_ACQUIRE_LOCK (pAdapter);
  4297. pRemoteNodeList = ListNext (&pAdapter->PDOList);
  4298. //
  4299. // Walk through the entire list and make a copy of the current list.
  4300. // Reference each remote node on the list.
  4301. // The lock will ensure that the list is valid and that no removed remote nodes
  4302. // get into our RefNodeTable list.
  4303. //
  4304. while (pRemoteNodeList != &pAdapter->PDOList)
  4305. {
  4306. PREMOTE_NODE pRemoteNode;
  4307. pRemoteNode = CONTAINING_RECORD (pRemoteNodeList, REMOTE_NODE, linkPdo);
  4308. //
  4309. // Reference the remote node. This guarantees that the remote node will
  4310. // remain valid and in the list until it is dereferenced (deref happens below)
  4311. //
  4312. nicReferenceRemoteNode (pRemoteNode, UpdateRemoteNodeTable);
  4313. RefNodeTable.RemoteNode[MaxNumRefNodeTable] = pRemoteNode;
  4314. ASSERT (REMOTE_NODE_TEST_FLAG (pRemoteNode,PDO_Removed) == FALSE);
  4315. //
  4316. // Increment the Cursors and go to the next RemoteNode
  4317. //
  4318. pRemoteNodeList = ListNext (pRemoteNodeList);
  4319. MaxNumRefNodeTable++;
  4320. } //while (pRemoteNodeList != &pAdapter->PDOList)
  4321. ADAPTER_RELEASE_LOCK (pAdapter);
  4322. //
  4323. // Without the lock, call into the Bus Driver to get the remote address
  4324. // of each remote node
  4325. //
  4326. {
  4327. //
  4328. // Initialize the structures
  4329. //
  4330. pCurrRemoteNode = RefNodeTable.RemoteNode[0];
  4331. RefIndex =0;
  4332. while (pCurrRemoteNode != NULL)
  4333. {
  4334. // Get the Node Address of the current Remote Node
  4335. //
  4336. NdisStatus = nicGet1394AddressOfRemoteNode (pCurrRemoteNode,
  4337. &RemoteNodeAddress,
  4338. 0);
  4339. if (NdisStatus == NDIS_STATUS_SUCCESS)
  4340. {
  4341. //
  4342. // Fill in the Temp Remote Node Table
  4343. //
  4344. PREMOTE_NODE *ppRemoteNode;
  4345. ppRemoteNode = &TempNodeTable.RemoteNode[RemoteNodeAddress.NA_Node_Number];
  4346. if (*ppRemoteNode == NULL)
  4347. {
  4348. //
  4349. // Update the value in the table
  4350. //
  4351. *ppRemoteNode = pCurrRemoteNode;
  4352. NumRemoteNodes ++;
  4353. }
  4354. }
  4355. // Move to the next node in our local RefNodeTable
  4356. //
  4357. RefIndex++;
  4358. pCurrRemoteNode = RefNodeTable.RemoteNode[RefIndex];
  4359. }
  4360. }
  4361. ADAPTER_ACQUIRE_LOCK(pAdapter)
  4362. //
  4363. // Use the results of our queries to update our internal structures
  4364. // Regardless of success or failure, copy the temp node table over
  4365. // into the adapter
  4366. //
  4367. NdisMoveMemory (&pAdapter->NodeTable, &TempNodeTable, sizeof (NODE_TABLE) );
  4368. pAdapter->NumRemoteNodes = NumRemoteNodes;
  4369. //
  4370. // Update the node address within each of these remote nodes
  4371. //
  4372. {
  4373. ULONG NumUpdated = 0;
  4374. USHORT i=0;
  4375. //
  4376. // Update the Remote Node structures with their new Node Addresses
  4377. //
  4378. while (NumUpdated != NumRemoteNodes)
  4379. {
  4380. if (i >= (sizeof(TempNodeTable.RemoteNode)/sizeof(TempNodeTable.RemoteNode[0])))
  4381. {
  4382. // We've gone past the end of the array. Should never do that.
  4383. //
  4384. ASSERT(!"Walked off the end of the NodeTable");
  4385. break;
  4386. }
  4387. if (TempNodeTable.RemoteNode[i] != NULL)
  4388. {
  4389. TempNodeTable.RemoteNode[i]->RemoteAddress.NA_Node_Number = i;
  4390. NumUpdated ++;
  4391. }
  4392. i++; // Use i to check if we have walked off the end of the table
  4393. TRACE( TL_V, TM_Mp, ( " UpdatingRemoteNodeAddresses NumUpdated %x, i %x, NumRemoteNodes %x",
  4394. NumUpdated, i, NumRemoteNodes) );
  4395. } // while (TRUE)
  4396. }
  4397. //
  4398. // We're done, Now Dereference the Remote Node References Made above
  4399. //
  4400. pCurrRemoteNode = RefNodeTable.RemoteNode[0];
  4401. RefIndex =0;
  4402. while (pCurrRemoteNode != NULL)
  4403. {
  4404. if (REMOTE_NODE_TEST_FLAG (pCurrRemoteNode, PDO_Removed) )
  4405. {
  4406. //
  4407. // If the node is being removed, then do not re-insert it
  4408. // into the node table, by clearing it out of the NodeTable
  4409. //
  4410. ULONG CurrNodeNumber = pCurrRemoteNode->RemoteAddress.NA_Node_Number;
  4411. RefNodeTable.RemoteNode[RefIndex] = NULL;
  4412. if (pAdapter->NodeTable.RemoteNode[CurrNodeNumber] == pCurrRemoteNode)
  4413. {
  4414. pAdapter->NodeTable.RemoteNode[CurrNodeNumber] = NULL;
  4415. }
  4416. }
  4417. nicDereferenceRemoteNode(pCurrRemoteNode, UpdateRemoteNodeTable);
  4418. RefIndex++;
  4419. pCurrRemoteNode = RefNodeTable.RemoteNode[RefIndex];
  4420. }
  4421. ADAPTER_RELEASE_LOCK (pAdapter);
  4422. TRACE( TL_T, TM_Mp, ( "<== nicUpdateRemoteNodeTable pAdapter %x, NumRemoteNodes %x", pAdapter, NumRemoteNodes ) );
  4423. MATCH_IRQL;
  4424. }
  4425. VOID
  4426. nicRemoveRemoteNodeFromNodeTable(
  4427. IN PNODE_TABLE pNodeTable,
  4428. IN PREMOTE_NODE pRemoteNode
  4429. )
  4430. /*++
  4431. Routine Description:
  4432. Remove the Remove Node from the Table and decrement any refcounts
  4433. associated with it.
  4434. Arguments:
  4435. Return Value:
  4436. --*/
  4437. {
  4438. //
  4439. // This function assumes that the adapter lock is held.
  4440. //
  4441. PPREMOTE_NODE ppRemoteNode = NULL;
  4442. //
  4443. // find the remote node and delete it from the node table.
  4444. //
  4445. //
  4446. // The RemoteNode is probably already in the correct place in the Node Table. We'll look there first
  4447. //
  4448. ppRemoteNode = &pNodeTable->RemoteNode[pRemoteNode->RemoteAddress.NA_Node_Number] ;
  4449. if (*ppRemoteNode != pRemoteNode)
  4450. {
  4451. //
  4452. //We did not find the remote node, now we need to go through all the entries and see
  4453. // if the remote node is there
  4454. //
  4455. UINT i =0;
  4456. while (i<NIC1394_MAX_NICINFO_NODES)
  4457. {
  4458. ppRemoteNode = &pNodeTable->RemoteNode[i];
  4459. if (*ppRemoteNode == pRemoteNode)
  4460. {
  4461. //
  4462. // we have found the remote node in the node table-- remove it
  4463. //
  4464. *ppRemoteNode = NULL;
  4465. }
  4466. i++; // try the next node
  4467. } // while ()
  4468. }
  4469. //
  4470. // if we were able to find the remote node either by the
  4471. // node number or through our iterative search
  4472. // then remove it from the Node Table
  4473. //
  4474. if (*ppRemoteNode == pRemoteNode)
  4475. {
  4476. *ppRemoteNode = NULL;
  4477. }
  4478. }
  4479. VOID
  4480. nicVerifyEuidTopology(
  4481. IN PADAPTERCB pAdapter,
  4482. IN PEUID_TOPOLOGY pEuidMap
  4483. )
  4484. /*++
  4485. Routine Description:
  4486. Update THe node address of each remote node
  4487. and then fills up the euid Map structre
  4488. Arguments:
  4489. Return Value:
  4490. --*/
  4491. {
  4492. EUID_TOPOLOGY EuidTopology;
  4493. PLIST_ENTRY pRemoteNodeList;
  4494. PREMOTE_NODE pRemoteNode = NULL;
  4495. //
  4496. // Requery each remote node for its latest HW address
  4497. //
  4498. nicUpdateRemoteNodeTable (pAdapter);
  4499. //
  4500. // Recreate the list and verify that the topology has not changed from under us.
  4501. //
  4502. NdisZeroMemory (pEuidMap, sizeof(*pEuidMap));
  4503. ADAPTER_ACQUIRE_LOCK(pAdapter);
  4504. pRemoteNodeList = ListNext (&pAdapter->PDOList);
  4505. //
  4506. // Walk through the entire list and fire of a request for each RemoteNode
  4507. // The lock will ensure that the list is valid
  4508. //
  4509. while (pRemoteNodeList != &pAdapter->PDOList)
  4510. {
  4511. USHORT NodeNumber;
  4512. pEuidMap->NumberOfRemoteNodes++;
  4513. pRemoteNode = CONTAINING_RECORD (pRemoteNodeList, REMOTE_NODE, linkPdo);
  4514. pRemoteNodeList = ListNext (pRemoteNodeList);
  4515. NodeNumber = pRemoteNode->RemoteAddress.NA_Node_Number;
  4516. pEuidMap->Node[NodeNumber].Euid = pRemoteNode->UniqueId;
  4517. pEuidMap->Node[NodeNumber].ENetAddress = pRemoteNode->ENetAddress;
  4518. } //while (pRemoteNodeList != &pAdapter->PDOList)
  4519. ADAPTER_RELEASE_LOCK (pAdapter);
  4520. }
  4521. nicVerifyEuidMapWorkItem (
  4522. NDIS_WORK_ITEM* pWorkItem,
  4523. IN PVOID Context
  4524. )
  4525. /*++
  4526. Routine Description:
  4527. This routine is a workitem routine.
  4528. It is called whenever we are asked to report back our Mapping and is always
  4529. called in the context of the miniport getting a request from arp1394.sys.
  4530. Arguments:
  4531. pAdapter Local host
  4532. Return Value:
  4533. --*/
  4534. {
  4535. PNIC_WORK_ITEM pNicWorkItem = (PNIC_WORK_ITEM )pWorkItem;
  4536. PNDIS_REQUEST pRequest = pNicWorkItem->RequestInfo.pNdisRequest;
  4537. PADAPTERCB pAdapter = (PADAPTERCB)Context;
  4538. PEUID_TOPOLOGY pEuidMap = (PEUID_TOPOLOGY) pRequest->DATA.QUERY_INFORMATION.InformationBuffer;
  4539. //
  4540. // Verify the contents of the Euid Map
  4541. //
  4542. nicVerifyEuidTopology(pAdapter,pEuidMap);
  4543. //
  4544. // As we atleast have the old data (before verification),
  4545. // we should always succeed the request
  4546. //
  4547. NdisMCoRequestComplete(NDIS_STATUS_SUCCESS,
  4548. pAdapter->MiniportAdapterHandle,
  4549. pRequest);
  4550. FREE_NONPAGED (pNicWorkItem);
  4551. NdisInterlockedDecrement(&pAdapter->OutstandingWorkItems);
  4552. }
  4553. VOID
  4554. nicQueryEuidNodeMacMap (
  4555. IN PADAPTERCB pAdapter,
  4556. IN PNDIS_REQUEST pRequest
  4557. )
  4558. /*++
  4559. Routine Description:
  4560. Goes through all the remote nodes and extracts their Euid, Node Number and Mac
  4561. address.
  4562. This function first tries to query each remote node to get
  4563. its latest address either via by directly asking the remote node or thorough a work item.
  4564. If that fails, then it takes the last known good values and reports it to the Arp module.
  4565. Arguments:
  4566. Return Value:
  4567. --*/
  4568. {
  4569. PLIST_ENTRY pRemoteNodeList;
  4570. PREMOTE_NODE pRemoteNode;
  4571. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  4572. PEUID_TOPOLOGY pEuidMap = (PEUID_TOPOLOGY) pRequest->DATA.QUERY_INFORMATION.InformationBuffer;
  4573. PNIC_WORK_ITEM pUpdateTableWorkItem = NULL;
  4574. NdisZeroMemory (pEuidMap, sizeof (*pEuidMap));
  4575. Status = NDIS_STATUS_SUCCESS;
  4576. do
  4577. {
  4578. if (KeGetCurrentIrql() == PASSIVE_LEVEL)
  4579. {
  4580. //
  4581. // This thread queries and completes the request
  4582. //
  4583. nicVerifyEuidTopology(pAdapter, pEuidMap);
  4584. break;
  4585. }
  4586. //
  4587. // We need to update the generation count
  4588. //
  4589. pUpdateTableWorkItem = ALLOC_NONPAGED (sizeof(NIC_WORK_ITEM), MTAG_WORKITEM);
  4590. if (pUpdateTableWorkItem !=NULL)
  4591. {
  4592. //
  4593. // Set the Workitem
  4594. //
  4595. NdisInitializeWorkItem ( &pUpdateTableWorkItem->NdisWorkItem,
  4596. (NDIS_PROC)nicVerifyEuidMapWorkItem,
  4597. (PVOID)pAdapter );
  4598. pUpdateTableWorkItem->RequestInfo.pNdisRequest = pRequest;
  4599. NdisInterlockedIncrement(&pAdapter->OutstandingWorkItems);
  4600. NdisScheduleWorkItem (&pUpdateTableWorkItem->NdisWorkItem);
  4601. //
  4602. // Only code path that pends the request -because of the workitem
  4603. //
  4604. Status = NDIS_STATUS_PENDING;
  4605. }
  4606. else
  4607. {
  4608. //
  4609. // Allocation failure - We report the results without verifying them.
  4610. //
  4611. ADAPTER_ACQUIRE_LOCK(pAdapter);
  4612. pRemoteNodeList = ListNext (&pAdapter->PDOList);
  4613. //
  4614. // Walk through the entire list and fire of a request for each RemoteNode
  4615. // The lock will ensure that the list is valid
  4616. //
  4617. while (pRemoteNodeList != &pAdapter->PDOList)
  4618. {
  4619. USHORT NodeNumber;
  4620. pEuidMap->NumberOfRemoteNodes++;
  4621. pRemoteNode = CONTAINING_RECORD (pRemoteNodeList, REMOTE_NODE, linkPdo);
  4622. pRemoteNodeList = ListNext (pRemoteNodeList);
  4623. NodeNumber = pRemoteNode->RemoteAddress.NA_Node_Number;
  4624. pEuidMap->Node[NodeNumber].Euid = pRemoteNode->UniqueId;
  4625. pEuidMap->Node[NodeNumber].ENetAddress = pRemoteNode->ENetAddress;
  4626. } //while (pRemoteNodeList != &pAdapter->PDOList)
  4627. ADAPTER_RELEASE_LOCK (pAdapter);
  4628. //
  4629. // This thread completes the request with possibly stale data.
  4630. //
  4631. break;
  4632. }
  4633. }while (FALSE);
  4634. if (NDIS_STATUS_PENDING != Status)
  4635. {
  4636. NdisMCoRequestComplete(Status,
  4637. pAdapter->MiniportAdapterHandle,
  4638. pRequest);
  4639. }
  4640. }
  4641. NDIS_STATUS
  4642. nicSetPower (
  4643. IN PADAPTERCB pAdapter,
  4644. IN NET_DEVICE_POWER_STATE DeviceState
  4645. )
  4646. /*++
  4647. Routine Description:
  4648. if PowerState is LowPower, then we
  4649. 1) there are no outstanding VCs or AFs open in the miniport
  4650. 2) free the Broadcast Channel Register,
  4651. If the PowerState is On, then
  4652. 1) we reallocate the BroadcastChannel Register
  4653. 2) if we are in bridge mode, Start the Arp module
  4654. Arguments:
  4655. Return Value:
  4656. --*/
  4657. {
  4658. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  4659. switch (DeviceState)
  4660. {
  4661. case NetDeviceStateD0:
  4662. {
  4663. //
  4664. // Initialize the BCM so it is ready to handle Resets
  4665. //
  4666. ADAPTER_CLEAR_FLAG(pAdapter, fADAPTER_LowPowerState);
  4667. NdisStatus = nicInitializeBroadcastChannelRegister (pAdapter);
  4668. if (NdisStatus != NDIS_STATUS_SUCCESS)
  4669. {
  4670. nicFreeBroadcastChannelRegister(pAdapter);
  4671. break;
  4672. }
  4673. ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
  4674. nicScheduleBCMWorkItem (pAdapter);
  4675. //
  4676. // If we are in bridge mode, then start the arp module
  4677. //
  4678. if (ADAPTER_TEST_FLAG (pAdapter, fADAPTER_BridgeMode) == TRUE)
  4679. {
  4680. nicQueueRequestToArp(pAdapter, BindArp, NULL);
  4681. }
  4682. //
  4683. // Re-initialize the Reassembly Timer
  4684. //
  4685. nicInitSerializedReassemblyStruct(pAdapter); // cannot fail
  4686. NdisStatus = NDIS_STATUS_SUCCESS;
  4687. }
  4688. break;
  4689. case NetDeviceStateD1:
  4690. case NetDeviceStateD2:
  4691. case NetDeviceStateD3:
  4692. {
  4693. //
  4694. // Free the Broadcast Channel Register
  4695. //
  4696. nicFreeBroadcastChannelRegister(pAdapter);
  4697. //
  4698. // Wait for the Free to complete.
  4699. //
  4700. NdisWaitEvent (&pAdapter->BCRData.BCRFreeAddressRange.NdisEvent,0);
  4701. NdisResetEvent (&pAdapter->BCRData.BCRFreeAddressRange.NdisEvent);
  4702. ADAPTER_SET_FLAG(pAdapter, fADAPTER_LowPowerState);
  4703. //
  4704. // ReStart any pending broadcast channel make calls
  4705. //
  4706. pAdapter->BCRData.MakeCallWaitEvent.EventCode = nic1394EventCode_FreedAddressRange;
  4707. NdisSetEvent (&pAdapter->BCRData.MakeCallWaitEvent.NdisEvent);
  4708. //
  4709. // Wait for Outstanding WorItems and timers
  4710. //
  4711. nicDeInitSerializedReassmblyStruct(pAdapter);
  4712. while (pAdapter->OutstandingWorkItems != 0)
  4713. {
  4714. NdisMSleep (10000);
  4715. }
  4716. NdisStatus = NDIS_STATUS_SUCCESS;
  4717. }
  4718. break;
  4719. default:
  4720. {
  4721. ASSERT (0);
  4722. break;
  4723. }
  4724. }
  4725. ASSERT (NDIS_STATUS_SUCCESS == NdisStatus);
  4726. pAdapter->PowerState = DeviceState;
  4727. return NdisStatus;
  4728. }