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

550 lines
14 KiB

  1. //
  2. // Copyright (c) 1998-1999, Microsoft Corporation, all rights reserved
  3. //
  4. // nt.c
  5. //
  6. // IEEE1394 mini-port/call-manager driver
  7. //
  8. // Main routine (DriverEntry) and global data definitions
  9. //
  10. // 12/28/98 adube
  11. // 9/5/99 alid: added callback registeration and interface to enum1394
  12. //
  13. #include "precomp.h"
  14. //-----------------------------------------------------------------------------
  15. // Local prototypes
  16. //-----------------------------------------------------------------------------
  17. extern NDIS_SPIN_LOCK g_DriverLock;
  18. extern LIST_ENTRY g_AdapterList;
  19. NDIS_STATUS
  20. DriverEntry(
  21. IN PDRIVER_OBJECT DriverObject,
  22. IN PUNICODE_STRING RegistryPath
  23. );
  24. VOID
  25. NicUnloadHandler(
  26. IN PDRIVER_OBJECT DriverObject
  27. );
  28. // Mark routine to be unloaded after initialization.
  29. //
  30. #pragma NDIS_INIT_FUNCTION(DriverEntry)
  31. //-----------------------------------------------------------------------------
  32. // Routines
  33. //-----------------------------------------------------------------------------
  34. NDIS_STATUS
  35. DriverEntry(
  36. IN PDRIVER_OBJECT DriverObject,
  37. IN PUNICODE_STRING RegistryPath )
  38. // Standard 'DriverEntry' driver initialization entrypoint called by the
  39. // I/0 system at IRQL PASSIVE_LEVEL before any other call to the driver.
  40. //
  41. // On NT, 'DriverObject' is the driver object created by the I/0 system
  42. // and 'RegistryPath' specifies where driver specific parameters are
  43. // stored. These arguments are opaque to this driver (and should remain
  44. // so for portability) which only forwards them to the NDIS wrapper.
  45. //
  46. // Returns the value returned by NdisMRegisterMiniport, per the doc on
  47. // "DriverEntry of NDIS Miniport Drivers".
  48. //
  49. {
  50. NDIS_STATUS NdisStatus;
  51. NTSTATUS NtStatus = STATUS_SUCCESS;
  52. NDIS_MINIPORT_CHARACTERISTICS nmc;
  53. NDIS_HANDLE NdisWrapperHandle;
  54. UNICODE_STRING CallbackObjectName;
  55. OBJECT_ATTRIBUTES ObjectAttr;
  56. BOOLEAN fDerefCallbackObject = FALSE, fDeregisterCallback = FALSE;
  57. PDEVICE_OBJECT pDummyDeviceObject;
  58. TRACE( TL_I, TM_Init, ( " Nic1394 - DriverEntry" ) );
  59. do
  60. {
  61. #ifdef CHANGE_MEDIUMS
  62. DbgPrint ("Nic1394 Driver Entry - Medium Type %x", &g_ulMedium);
  63. DbgBreakPoint();
  64. #else
  65. //
  66. // Now depending on the ETHERNET preprocessor, define a medium
  67. //
  68. #ifdef _ETHERNET_
  69. g_ulMedium = NdisMedium802_3;
  70. #else
  71. g_ulMedium = NdisMedium1394;
  72. #endif // _ETHERNET_
  73. #endif // CHANGE_MEDIUMS
  74. // Register this driver with the NDIS wrapper. This call must occur
  75. // before any other NdisXxx calls.
  76. //
  77. NdisMInitializeWrapper(
  78. &NdisWrapperHandle, DriverObject, RegistryPath, NULL );
  79. // Set up the mini-port characteristics table that tells NDIS how to call
  80. // our mini-port.
  81. //
  82. NdisZeroMemory( &nmc, sizeof(nmc) );
  83. nmc.MajorNdisVersion = NDIS_MajorVersion;
  84. nmc.MinorNdisVersion = NDIS_MinorVersion;
  85. // nmc.CheckForHangHandler = CheckForHang;
  86. // no DisableInterruptHandler
  87. // no EnableInterruptHandler
  88. nmc.HaltHandler = NicMpHalt;
  89. // no HandleInterruptHandler
  90. nmc.InitializeHandler = NicMpInitialize;
  91. // no ISRHandler
  92. // no QueryInformationHandler (see CoRequestHandler)
  93. nmc.ResetHandler = NicMpReset;
  94. // no SendHandler (see CoSendPacketsHandler)
  95. // no WanSendHandler (see CoSendPacketsHandler)
  96. // no SetInformationHandler (see CoRequestHandler)
  97. // no TransferDataHandler
  98. // no WanTransferDataHandler
  99. // nmc.ReturnPacketHandler = NicMpReturnPacket;
  100. // no SendPacketsHandler (see CoSendPacketsHandler)
  101. // no AllocateCompleteHandler
  102. nmc.CoActivateVcHandler = NicMpCoActivateVc;
  103. nmc.CoDeactivateVcHandler= NicMpCoDeactivateVc;
  104. nmc.CoSendPacketsHandler = NicMpCoSendPackets;
  105. nmc.CoRequestHandler = NicMpCoRequest;
  106. nmc.ReturnPacketHandler = NicReturnPacket;
  107. #ifdef _ETHERNET_
  108. nmc.QueryInformationHandler = NicEthQueryInformation;
  109. nmc.SetInformationHandler = NicEthSetInformation;
  110. nmc.SendPacketsHandler = NicMpSendPackets;
  111. #endif
  112. //
  113. // Create a dummy device object
  114. //
  115. #ifdef Win9X
  116. IoCreateDevice(DriverObject,
  117. 0,
  118. NULL,
  119. FILE_DEVICE_PHYSICAL_NETCARD,
  120. 0,
  121. FALSE,// exclusive flag
  122. &pDummyDeviceObject);
  123. #endif
  124. // Register this driver as the IEEE1394 mini-port. This will result in NDIS
  125. // calling back at NicMpInitialize.
  126. //
  127. TRACE( TL_V, TM_Init, ( "NdisMRegMp" ) );
  128. NdisStatus = NdisMRegisterMiniport( NdisWrapperHandle, &nmc, sizeof(nmc) );
  129. TRACE( TL_A, TM_Init, ( "NdisMRegMp=$%x", NdisStatus ) );
  130. //
  131. if (NdisStatus == NDIS_STATUS_SUCCESS)
  132. {
  133. {
  134. extern CALLSTATS g_stats;
  135. extern NDIS_SPIN_LOCK g_lockStats;
  136. NdisZeroMemory( &g_stats, sizeof(g_stats) );
  137. NdisAllocateSpinLock( &g_lockStats );
  138. }
  139. // Initialize driver-wide lock and adapter list.
  140. //
  141. {
  142. NdisAllocateSpinLock( &g_DriverLock );
  143. InitializeListHead( &g_AdapterList );
  144. }
  145. //
  146. // BINARY_COMPATIBILITY_BUG
  147. //
  148. #if NDIS_NT
  149. NdisMRegisterUnloadHandler(NdisWrapperHandle, NicUnloadHandler);
  150. #endif
  151. #ifdef PSDEBUG
  152. {
  153. extern LIST_ENTRY g_listDebugPs;
  154. extern NDIS_SPIN_LOCK g_lockDebugPs;
  155. InitializeListHead( &g_listDebugPs );
  156. NdisAllocateSpinLock( &g_lockDebugPs );
  157. }
  158. #endif
  159. //
  160. // create a named Callback object with os
  161. // then register a callback routine with send a notification to all modules that
  162. // have a Callback routine registered with this function
  163. // if enum1394 is already loaded, this will let it know the nic driver is loaded
  164. // the enum1394 will get the driver registeration entry points from the notification
  165. // callback and calls NicRegisterDriver to pass the enum entry points
  166. // if enum1394 is not loaded and gets loaded later, it will send a notication to modules
  167. // who have registered with this callback object and passes its own driver registeration
  168. // the purpose of passign the entry points this way vs. exporting them, is to avoid
  169. // getting loaded as a DLL which fatal for both nic1394 and enum1394
  170. //
  171. //
  172. // every Callback object is identified by a name.
  173. //
  174. RtlInitUnicodeString(&CallbackObjectName, NDIS1394_CALLBACK_NAME);
  175. InitializeObjectAttributes(&ObjectAttr,
  176. &CallbackObjectName,
  177. OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
  178. NULL,
  179. NULL);
  180. NtStatus = ExCreateCallback(&Nic1394CallbackObject,
  181. &ObjectAttr,
  182. TRUE, // allow creating the object if it does not exist
  183. TRUE); // allow mutiple callback registeration
  184. if (!NT_SUCCESS(NtStatus))
  185. {
  186. TRACE( TL_A, TM_All, ("Nic1394 DriverEntry: failed to create a Callback object. Status %lx\n", NtStatus));
  187. NtStatus = STATUS_UNSUCCESSFUL;
  188. break;
  189. }
  190. fDerefCallbackObject = TRUE;
  191. Nic1394CallbackRegisterationHandle = ExRegisterCallback(Nic1394CallbackObject,
  192. Nic1394Callback,
  193. (PVOID)NULL);
  194. if (Nic1394CallbackRegisterationHandle == NULL)
  195. {
  196. TRACE(TL_A, TM_All, ("Nic1394 DriverEntry: failed to register a Callback routine%lx\n"));
  197. NtStatus = STATUS_UNSUCCESSFUL;
  198. break;
  199. }
  200. fDeregisterCallback = TRUE;
  201. //
  202. // now notify enum1394 (if it is already loaded) use Arg1 to tell it where
  203. // the notification is coming from
  204. //
  205. ExNotifyCallback(Nic1394CallbackObject,
  206. (PVOID)NDIS1394_CALLBACK_SOURCE_NIC1394,
  207. (PVOID)&Nic1394Characteristics);
  208. NtStatus = STATUS_SUCCESS;
  209. fDerefCallbackObject = fDeregisterCallback = FALSE;
  210. }
  211. else
  212. {
  213. NdisTerminateWrapper( NdisWrapperHandle, NULL );
  214. NtStatus = NdisStatus;
  215. break;
  216. }
  217. } while (FALSE);
  218. if (fDerefCallbackObject)
  219. {
  220. ObDereferenceObject(Nic1394CallbackObject);
  221. }
  222. if (fDeregisterCallback)
  223. {
  224. ExUnregisterCallback(Nic1394CallbackRegisterationHandle);
  225. }
  226. if (NtStatus != STATUS_SUCCESS)
  227. {
  228. if (NdisEnum1394DeregisterDriver != NULL)
  229. NdisEnum1394DeregisterDriver();
  230. }
  231. return NtStatus;
  232. }
  233. VOID
  234. NicUnloadHandler(
  235. IN PDRIVER_OBJECT DriverObject
  236. )
  237. {
  238. ASSERT(IsListEmpty(&g_AdapterList));
  239. if (NdisEnum1394DeregisterDriver != NULL)
  240. {
  241. NdisEnum1394DeregisterDriver();
  242. }
  243. if (Nic1394CallbackRegisterationHandle != NULL)
  244. {
  245. ExUnregisterCallback(Nic1394CallbackRegisterationHandle);
  246. }
  247. if (Nic1394CallbackObject != NULL)
  248. {
  249. ObDereferenceObject(Nic1394CallbackObject);
  250. }
  251. return;
  252. }
  253. VOID
  254. nicDeregisterWithEnum ()
  255. {
  256. if (NdisEnum1394DeregisterDriver != NULL)
  257. {
  258. NdisEnum1394DeregisterDriver();
  259. }
  260. }
  261. VOID
  262. nicDeregisterWithKernel ()
  263. {
  264. if (Nic1394CallbackRegisterationHandle != NULL)
  265. {
  266. ExUnregisterCallback(Nic1394CallbackRegisterationHandle);
  267. }
  268. if (Nic1394CallbackObject != NULL)
  269. {
  270. ObDereferenceObject(Nic1394CallbackObject);
  271. }
  272. }
  273. //
  274. // the registeration entry for enum1394
  275. // typically this will be only called if enum1394 detects the presence of
  276. // the nic1394 through receiving a call back notification. this is how enum1394
  277. // lets nic1394 know that it is there and ready.
  278. // if nic1394 detects the presence of the enum1394 by receiving a notification
  279. // callbak, it will call NdisEunm1394RegisterDriver and in that case enum1394
  280. // will -not- call Nic1394RegisterDriver.
  281. //
  282. NTSTATUS
  283. NicRegisterEnum1394(
  284. IN PNDISENUM1394_CHARACTERISTICS NdisEnum1394Characteristcis
  285. )
  286. {
  287. PADAPTERCB pAdapter;
  288. LIST_ENTRY *pAdapterListEntry;
  289. NdisEnum1394RegisterDriver = NdisEnum1394Characteristcis->RegisterDriverHandler;
  290. NdisEnum1394DeregisterDriver = NdisEnum1394Characteristcis->DeregisterDriverHandler;
  291. NdisEnum1394RegisterAdapter = NdisEnum1394Characteristcis->RegisterAdapterHandler;
  292. NdisEnum1394DeregisterAdapter = NdisEnum1394Characteristcis->DeregisterAdapterHandler;
  293. Nic1394RegisterAdapters();
  294. return STATUS_SUCCESS;
  295. }
  296. VOID
  297. NicDeregisterEnum1394(
  298. VOID
  299. )
  300. {
  301. PADAPTERCB pAdapter;
  302. LIST_ENTRY *pAdapterListEntry;
  303. //
  304. // go through all the adapters and Deregister them if necessary
  305. //
  306. NdisAcquireSpinLock (&g_DriverLock);
  307. for (pAdapterListEntry = g_AdapterList.Flink;
  308. pAdapterListEntry != &g_AdapterList;
  309. pAdapterListEntry = pAdapterListEntry->Flink)
  310. {
  311. pAdapter = CONTAINING_RECORD(pAdapterListEntry,
  312. ADAPTERCB,
  313. linkAdapter);
  314. if (ADAPTER_TEST_FLAG(pAdapter, fADAPTER_RegisteredWithEnumerator))
  315. {
  316. nicReferenceAdapter(pAdapter,"NicDeregisterEnum1394");
  317. NdisReleaseSpinLock(&g_DriverLock);
  318. NdisEnum1394DeregisterAdapter((PVOID)pAdapter->EnumAdapterHandle);
  319. NdisAcquireSpinLock( &g_DriverLock);
  320. nicDereferenceAdapter(pAdapter, "NicDeregisterEnum1394");
  321. }
  322. ADAPTER_CLEAR_FLAG(pAdapter, fADAPTER_RegisteredWithEnumerator | fADAPTER_FailedRegisteration);
  323. }
  324. NdisReleaseSpinLock(&g_DriverLock);
  325. NdisEnum1394RegisterDriver = NULL;
  326. NdisEnum1394DeregisterDriver = NULL;
  327. NdisEnum1394RegisterAdapter = NULL;
  328. NdisEnum1394DeregisterAdapter = NULL;
  329. }
  330. VOID
  331. Nic1394Callback(
  332. PVOID CallBackContext,
  333. PVOID Source,
  334. PVOID Characteristics
  335. )
  336. {
  337. NTSTATUS Status;
  338. //
  339. // if we are the one issuing this notification, just return
  340. //
  341. if (Source == (PVOID)NDIS1394_CALLBACK_SOURCE_NIC1394)
  342. return;
  343. //
  344. // notification is coming from Nic1394. grab the entry points. call it and
  345. // let it know that you are here
  346. //
  347. ASSERT(Source == (PVOID)NDIS1394_CALLBACK_SOURCE_ENUM1394);
  348. if (Source != (PVOID)NDIS1394_CALLBACK_SOURCE_ENUM1394)
  349. {
  350. return;
  351. }
  352. NdisEnum1394RegisterDriver = ((PNDISENUM1394_CHARACTERISTICS)Characteristics)->RegisterDriverHandler;
  353. ASSERT(NdisEnum1394RegisterDriver != NULL);
  354. if (NdisEnum1394RegisterDriver == NULL)
  355. {
  356. //
  357. // invalid characteristics
  358. //
  359. return;
  360. }
  361. Status = NdisEnum1394RegisterDriver(&Nic1394Characteristics);
  362. if (Status == STATUS_SUCCESS)
  363. {
  364. NdisEnum1394DeregisterDriver = ((PNDISENUM1394_CHARACTERISTICS)Characteristics)->DeregisterDriverHandler;
  365. NdisEnum1394RegisterAdapter = ((PNDISENUM1394_CHARACTERISTICS)Characteristics)->RegisterAdapterHandler;
  366. NdisEnum1394DeregisterAdapter = ((PNDISENUM1394_CHARACTERISTICS)Characteristics)->DeregisterAdapterHandler;
  367. Nic1394RegisterAdapters();
  368. }
  369. else
  370. {
  371. NdisEnum1394RegisterDriver = NULL;
  372. }
  373. }
  374. //
  375. // This function walks the global list of the adapters and
  376. // will register those that have not been registered with enum1394
  377. //
  378. VOID
  379. Nic1394RegisterAdapters(
  380. VOID
  381. )
  382. {
  383. PADAPTERCB pAdapter;
  384. LIST_ENTRY *pAdapterListEntry;
  385. LARGE_INTEGER LocalHostUniqueId;
  386. NTSTATUS NtStatus;
  387. //
  388. // go through all the adapters and register them if necessary. if there are
  389. // any remote nodes connected to these adapters, they will be indicated back
  390. // in the context of registering the adapter
  391. //
  392. NdisAcquireSpinLock(&g_DriverLock);
  393. for (pAdapterListEntry = g_AdapterList.Flink;
  394. pAdapterListEntry != &g_AdapterList;
  395. pAdapterListEntry = pAdapterListEntry->Flink)
  396. {
  397. pAdapter = CONTAINING_RECORD(pAdapterListEntry,
  398. ADAPTERCB,
  399. linkAdapter);
  400. if (!ADAPTER_TEST_FLAG(pAdapter, fADAPTER_RegisteredWithEnumerator | fADAPTER_FailedRegisteration))
  401. {
  402. nicReferenceAdapter (pAdapter, "Nic1394RegisterAdapters");
  403. NdisReleaseSpinLock (&g_DriverLock);
  404. NtStatus = NdisEnum1394RegisterAdapter((PVOID)pAdapter,
  405. pAdapter->pNdisDeviceObject,
  406. &pAdapter->EnumAdapterHandle,
  407. &LocalHostUniqueId);
  408. NdisAcquireSpinLock(&g_DriverLock);
  409. nicDereferenceAdapter(pAdapter, "Nic1394RegisterAdapters");
  410. if (NtStatus == STATUS_SUCCESS)
  411. {
  412. ADAPTER_SET_FLAG(pAdapter, fADAPTER_RegisteredWithEnumerator);
  413. }
  414. else
  415. {
  416. ADAPTER_SET_FLAG(pAdapter, fADAPTER_FailedRegisteration);
  417. TRACE(TL_A, TM_All, ("Nic1394RegisterAdapters: failed to register Adapter %lx with enum1394. Status %lx\n", pAdapter, NtStatus));
  418. }
  419. }
  420. }
  421. NdisReleaseSpinLock(&g_DriverLock);
  422. return;
  423. }