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.

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