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.

2018 lines
58 KiB

  1. /*++
  2. Copyright (c) 1998-99 Microsoft Corporation
  3. Module Name:
  4. enum1394.c
  5. Abstract:
  6. 1394 ndis enumerator
  7. Author: Alireza Dabagh (alid)
  8. Environment:
  9. Kernel mode
  10. Revision History :
  11. --*/
  12. #include <wdm.h>
  13. //
  14. // extra stuff to keep ks.h happy
  15. //
  16. #ifndef CDECL
  17. #define CDECL
  18. #endif
  19. #ifndef BOOL
  20. #define BOOL int
  21. #endif
  22. #define ENUM1394_NT 1
  23. #include "1394.h"
  24. #include "ndis1394.h"
  25. #include "enum1394.h"
  26. #include "ntdd1394.h"
  27. #define NDISENUM1394_DEVICE_NAME L"\\Device\\NdisEnum1394"
  28. #define NDISENUM1394_SYMBOLIC_NAME L"\\DosDevices\\NDISENUM1394"
  29. NDISENUM1394_CHARACTERISTICS NdisEnum1394Characteristics =
  30. {
  31. 1,
  32. 0,
  33. 0,
  34. NdisEnum1394RegisterDriver,
  35. NdisEnum1394DeregisterDriver,
  36. NdisEnum1394RegisterAdapter,
  37. NdisEnum1394DeregisterAdapter
  38. };
  39. KSPIN_LOCK ndisEnum1394GlobalLock;
  40. ULONG Enum1394DebugLevel = ENUM1394_DBGLEVEL_ERROR ;
  41. PNDISENUM1394_LOCAL_HOST LocalHostList = (PNDISENUM1394_LOCAL_HOST)NULL;
  42. NIC1394_ADD_NODE_HANLDER AddNodeHandler = NULL;
  43. NIC1394_REMOVE_NODE_HANLDER RemoveNodeHandler = NULL;
  44. NIC1394_REGISTER_DRIVER_HANDLER RegisterDriverHandler = NULL;
  45. NIC1394_DEREGISTER_DRIVER_HANDLER DeRegisterDriverHandler = NULL;
  46. PDEVICE_OBJECT ndisEnum1394DeviceObject = NULL;
  47. PDRIVER_OBJECT ndisEnum1394DriverObject = NULL;
  48. PCALLBACK_OBJECT ndisEnum1394CallbackObject = NULL;
  49. PVOID ndisEnum1394CallbackRegisterationHandle = NULL;
  50. NTSTATUS
  51. DriverEntry(
  52. IN PDRIVER_OBJECT DriverObject,
  53. IN PUNICODE_STRING RegistryPath
  54. )
  55. /*++
  56. Routine Description:
  57. This routine is called at system initialization time so we can fill in the basic dispatch points
  58. Arguments:
  59. DriverObject - Supplies the driver object.
  60. RegistryPath - Supplies the registry path for this driver.
  61. Return Value:
  62. STATUS_SUCCESS
  63. --*/
  64. {
  65. OBJECT_ATTRIBUTES ObjectAttr;
  66. UNICODE_STRING CallBackObjectName;
  67. NTSTATUS Status;
  68. UNICODE_STRING DeviceName;
  69. UNICODE_STRING SymbolicLinkName;
  70. BOOLEAN fDerefCallbackObject = FALSE;
  71. BOOLEAN fDeregisterCallback = FALSE;
  72. DBGPRINT(ENUM1394_DBGLEVEL_INFO,("Enum1394 DriverEntry.\n"));
  73. do
  74. {
  75. KeInitializeSpinLock(&ndisEnum1394GlobalLock);
  76. RtlInitUnicodeString(&DeviceName, NDISENUM1394_DEVICE_NAME);
  77. ndisEnum1394DriverObject = DriverObject;
  78. RtlInitUnicodeString(&CallBackObjectName, NDIS1394_CALLBACK_NAME);
  79. InitializeObjectAttributes(&ObjectAttr,
  80. &CallBackObjectName,
  81. OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
  82. NULL,
  83. NULL);
  84. Status = ExCreateCallback(&ndisEnum1394CallbackObject,
  85. &ObjectAttr,
  86. TRUE,
  87. TRUE);
  88. if (!NT_SUCCESS(Status))
  89. {
  90. DBGPRINT(ENUM1394_DBGLEVEL_ERROR,("Enum1394 DriverEntry: failed to create a Callback object. Status %lx\n", Status));
  91. Status = STATUS_UNSUCCESSFUL;
  92. break;
  93. }
  94. fDerefCallbackObject = TRUE;
  95. ndisEnum1394CallbackRegisterationHandle = ExRegisterCallback(ndisEnum1394CallbackObject,
  96. Enum1394Callback,
  97. (PVOID)NULL);
  98. if (ndisEnum1394CallbackRegisterationHandle == NULL)
  99. {
  100. DBGPRINT(ENUM1394_DBGLEVEL_ERROR,("Enum1394 DriverEntry: failed to register a Callback routine%lx\n"));
  101. Status = STATUS_UNSUCCESSFUL;
  102. break;
  103. }
  104. fDeregisterCallback = TRUE;
  105. ExNotifyCallback(ndisEnum1394CallbackObject,
  106. (PVOID)NDIS1394_CALLBACK_SOURCE_ENUM1394,
  107. (PVOID)&NdisEnum1394Characteristics);
  108. //
  109. // Initialize the Driver Object with driver's entry points
  110. //
  111. DriverObject->DriverExtension->AddDevice = ndisEnum1394AddDevice;
  112. //
  113. // Fill in the Mandatory handlers
  114. //
  115. DriverObject->DriverUnload = ndisEnum1394Unload;
  116. DriverObject->MajorFunction[IRP_MJ_CREATE] = ndisEnum1394CreateIrpHandler;
  117. DriverObject->MajorFunction[IRP_MJ_CLOSE] = ndisEnum1394CloseIrpHandler;
  118. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ndisEnum1394DeviceIoControl;
  119. DriverObject->MajorFunction[IRP_MJ_PNP] = ndisEnum1394PnpDispatch;
  120. DriverObject->MajorFunction[IRP_MJ_POWER] = ndisEnum1394PowerDispatch;
  121. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = ndisEnum1394WMIDispatch;
  122. fDerefCallbackObject = fDeregisterCallback = FALSE;
  123. Status = STATUS_SUCCESS;
  124. } while(FALSE);
  125. if (fDeregisterCallback)
  126. {
  127. ExUnregisterCallback(ndisEnum1394CallbackRegisterationHandle);
  128. }
  129. if (fDerefCallbackObject)
  130. {
  131. ObDereferenceObject(ndisEnum1394CallbackObject);
  132. }
  133. if (Status != STATUS_SUCCESS)
  134. {
  135. if (DeRegisterDriverHandler != NULL)
  136. DeRegisterDriverHandler();
  137. }
  138. return Status;
  139. }
  140. NTSTATUS
  141. ndisEnum1394AddDevice(
  142. PDRIVER_OBJECT DriverObject,
  143. PDEVICE_OBJECT PhysicalDeviceObject
  144. )
  145. /*++
  146. Routine Description:
  147. This is our PNP AddDevice called with the PDO ejected from the bus driver
  148. Arguments:
  149. Return Value:
  150. --*/
  151. {
  152. NTSTATUS Status;
  153. PNDISENUM1394_REMOTE_NODE RemoteNode;
  154. PDEVICE_OBJECT DeviceObject, NextDeviceObject;
  155. KIRQL OldIrql;
  156. PNDISENUM1394_LOCAL_HOST LocalHost;
  157. BOOLEAN FreeDevice = FALSE;
  158. BOOLEAN fNewHost = FALSE;
  159. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394AddDevice: PDO %lx\n", PhysicalDeviceObject));
  160. do
  161. {
  162. //
  163. // first create a FDO
  164. //
  165. Status = IoCreateDevice(
  166. DriverObject,
  167. sizeof (NDISENUM1394_REMOTE_NODE), // extension size
  168. NULL, // name (null for now)
  169. FILE_DEVICE_NETWORK, // device type
  170. 0, // characteristics
  171. FALSE,
  172. &DeviceObject);
  173. if (!NT_SUCCESS(Status))
  174. {
  175. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("ndisEnum1394AddDevice: failed to create FDO. Status %lx, PDO %lx\n", Status, PhysicalDeviceObject));
  176. break;
  177. }
  178. FreeDevice = TRUE;
  179. DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  180. PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  181. //
  182. // Mark the device as being pageable.
  183. //
  184. DeviceObject->Flags |= DO_POWER_PAGABLE;
  185. //
  186. // Attach our FDO to the PDO. This routine will return the top most
  187. // device that is attached to the PDO or the PDO itself if no other
  188. // device objects have attached to it.
  189. //
  190. NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
  191. RtlZeroMemory(DeviceObject->DeviceExtension, sizeof (NDISENUM1394_REMOTE_NODE));
  192. RemoteNode = (PNDISENUM1394_REMOTE_NODE)DeviceObject->DeviceExtension;
  193. RemoteNode->DeviceObject = DeviceObject;
  194. RemoteNode->PhysicalDeviceObject = PhysicalDeviceObject;
  195. RemoteNode->NextDeviceObject = NextDeviceObject;
  196. RemoteNode->PnPDeviceState = PnPDeviceAdded;
  197. KeInitializeSpinLock(&RemoteNode->Lock);
  198. ndisEnum1394InitializeRef(&RemoteNode->Reference);
  199. Status = ndisEnum1394GetLocalHostForRemoteNode(RemoteNode, &LocalHost);
  200. if (Status != STATUS_SUCCESS)
  201. {
  202. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("ndisEnum1394AddDevice: ndisEnum1394GetLocalHostForRemoteNode failed. Status %lx\n", Status));
  203. break;
  204. }
  205. RemoteNode->LocalHost = LocalHost;
  206. ExAcquireSpinLock(&LocalHost->Lock, &OldIrql);
  207. RemoteNode->Next = LocalHost->RemoteNodeList;
  208. LocalHost->RemoteNodeList = RemoteNode;
  209. ExReleaseSpinLock(&LocalHost->Lock, OldIrql);
  210. FreeDevice = FALSE;
  211. } while(FALSE);
  212. if (FreeDevice)
  213. {
  214. IoDeleteDevice(DeviceObject);
  215. }
  216. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394AddDevice: Status %lx, PDO %lx, FDO %lx\n", Status, PhysicalDeviceObject, DeviceObject));
  217. return (Status);
  218. }
  219. NTSTATUS
  220. ndisEnum1394PowerDispatch(
  221. IN PDEVICE_OBJECT DeviceObject,
  222. IN PIRP Irp
  223. )
  224. {
  225. PIO_STACK_LOCATION IrpSp, NextIrpSp;
  226. NTSTATUS Status = STATUS_SUCCESS;
  227. PDEVICE_OBJECT NextDeviceObject;
  228. PNDISENUM1394_REMOTE_NODE RemoteNode;
  229. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394PowerDispatch: DeviceObject %lx, Irp %lx\n", DeviceObject, Irp));
  230. Irp->IoStatus.Status = STATUS_SUCCESS;
  231. PoStartNextPowerIrp(Irp);
  232. //
  233. // Set up the Irp for passing it down, no completion routine is needed
  234. //
  235. IoSkipCurrentIrpStackLocation(Irp);
  236. RemoteNode = (PNDISENUM1394_REMOTE_NODE)DeviceObject->DeviceExtension;
  237. //
  238. // Get a pointer to the next miniport.
  239. //
  240. NextDeviceObject = RemoteNode->NextDeviceObject;
  241. //
  242. // Call the lower device
  243. //
  244. PoCallDriver (NextDeviceObject, Irp);
  245. Status = STATUS_SUCCESS;
  246. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394PowerDispatch: DeviceObject %lx, Irp %lx\n", DeviceObject, Irp));
  247. return Status;
  248. }
  249. NTSTATUS
  250. ndisEnum1394WMIDispatch(
  251. IN PDEVICE_OBJECT DeviceObject,
  252. IN PIRP Irp
  253. )
  254. {
  255. PIO_STACK_LOCATION NextIrpStack;
  256. NTSTATUS ntStatus = STATUS_SUCCESS;
  257. PNDISENUM1394_REMOTE_NODE RemoteNode = NULL;
  258. PDEVICE_OBJECT NextDeviceObject = NULL;
  259. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394WMIDispatch: DeviceObject %lx, Irp %lx\n", DeviceObject, Irp));
  260. //
  261. // Get a pointer to the adapter block and miniport block then determine
  262. // which one we should use.
  263. //
  264. RemoteNode = (PNDISENUM1394_REMOTE_NODE)DeviceObject->DeviceExtension;
  265. //
  266. // Get a pointer to the next miniport.
  267. //
  268. NextDeviceObject = RemoteNode->NextDeviceObject;
  269. //
  270. // Pass the Irp Down
  271. //
  272. //
  273. // Set up the Irp for passing it down, no completion routine is needed
  274. //
  275. IoSkipCurrentIrpStackLocation(Irp);
  276. ntStatus = IoCallDriver (NextDeviceObject, Irp);
  277. return ntStatus;
  278. }
  279. NTSTATUS
  280. ndisEnum1394StartDevice(
  281. IN PDEVICE_OBJECT DeviceObject,
  282. IN PIRP Irp
  283. )
  284. {
  285. PNDISENUM1394_REMOTE_NODE RemoteNode, TmpRemoteNode;
  286. PNDISENUM1394_LOCAL_HOST LocalHost;
  287. NTSTATUS Status = STATUS_SUCCESS;
  288. KIRQL OldIrql;
  289. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394StartDevice: DeviceObject %lx, Irp %lx\n", DeviceObject, Irp));
  290. RemoteNode = (PNDISENUM1394_REMOTE_NODE)DeviceObject->DeviceExtension;
  291. LocalHost = RemoteNode->LocalHost;
  292. ExAcquireSpinLock(&LocalHost->Lock, &OldIrql);
  293. do
  294. {
  295. //
  296. // if this is a duplicate node, leave it in the queue. but don't tag it as
  297. // being started so we don't end up indicating it
  298. //
  299. for (TmpRemoteNode = LocalHost->RemoteNodeList;
  300. TmpRemoteNode != NULL;
  301. TmpRemoteNode = TmpRemoteNode->Next)
  302. {
  303. if ((TmpRemoteNode->UniqueId[0] == RemoteNode->UniqueId[0]) &&
  304. (TmpRemoteNode->UniqueId[1] == RemoteNode->UniqueId[1]) &&
  305. ENUM_TEST_FLAG(TmpRemoteNode, NDISENUM1394_NODE_PNP_STARTED))
  306. break;
  307. }
  308. if (TmpRemoteNode != NULL)
  309. {
  310. //
  311. // duplicate node
  312. //
  313. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394StartDevice: duplicate node. new node %lx, original Node %lx\n",
  314. TmpRemoteNode, RemoteNode));
  315. ENUM_CLEAR_FLAG(RemoteNode, NDISENUM1394_NODE_PNP_STARTED);
  316. break;
  317. }
  318. ENUM_SET_FLAG(RemoteNode, NDISENUM1394_NODE_PNP_STARTED);
  319. if((AddNodeHandler != NULL) && (LocalHost->Nic1394AdapterContext != NULL))
  320. {
  321. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394StartDevice: Notifying Nic1394 of device arrival, Miniport PDO %lx, Node PDO %lx\n", LocalHost->PhysicalDeviceObject, RemoteNode->PhysicalDeviceObject));
  322. if (!ENUM_TEST_FLAG(RemoteNode, NDISENUM1394_NODE_INDICATED))
  323. {
  324. ENUM_SET_FLAG(RemoteNode, NDISENUM1394_NODE_INDICATED);
  325. ExReleaseSpinLock(&LocalHost->Lock, OldIrql);
  326. Status = AddNodeHandler(LocalHost->Nic1394AdapterContext,
  327. (PVOID)RemoteNode,
  328. RemoteNode->PhysicalDeviceObject,
  329. RemoteNode->UniqueId[0],
  330. RemoteNode->UniqueId[1],
  331. &RemoteNode->Nic1394NodeContext);
  332. ASSERT(Status == STATUS_SUCCESS);
  333. ExAcquireSpinLock(&LocalHost->Lock, &OldIrql);
  334. if (Status == STATUS_SUCCESS)
  335. {
  336. ENUM_SET_FLAG(RemoteNode, NDISENUM1394_NODE_ADDED);
  337. }
  338. else
  339. {
  340. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("ndisEnum1394StartDevice: AddAdapter failed %lx\n", Status));
  341. }
  342. }
  343. }
  344. } while (FALSE);
  345. ExReleaseSpinLock(&LocalHost->Lock, OldIrql);
  346. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394StartDevice: Status %lx, DeviceObject %lx, Irp %lx\n", Status, DeviceObject, Irp));
  347. return Status;
  348. }
  349. VOID
  350. ndisEnum1394IndicateNodes(
  351. PNDISENUM1394_LOCAL_HOST LocalHost
  352. )
  353. {
  354. PNDISENUM1394_REMOTE_NODE RemoteNode;
  355. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  356. KIRQL OldIrql;
  357. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394IndicateNodes: LocalHost %lx\n", LocalHost));
  358. //
  359. // notify 1394 NIC driver
  360. //
  361. if (AddNodeHandler == NULL)
  362. {
  363. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394IndicateNodes: LocalHost %lx\n", LocalHost));
  364. return;
  365. }
  366. ExAcquireSpinLock(&LocalHost->Lock, &OldIrql);
  367. if (ENUM_TEST_FLAG(LocalHost, NDISENUM1394_LOCALHOST_REGISTERED))
  368. {
  369. next:
  370. for (RemoteNode = LocalHost->RemoteNodeList;
  371. RemoteNode != NULL;
  372. RemoteNode = RemoteNode->Next)
  373. {
  374. if ((!ENUM_TEST_FLAG(RemoteNode, NDISENUM1394_NODE_INDICATED)) &&
  375. ENUM_TEST_FLAG(RemoteNode, NDISENUM1394_NODE_PNP_STARTED))
  376. {
  377. ENUM_SET_FLAG(RemoteNode, NDISENUM1394_NODE_INDICATED);
  378. break;
  379. }
  380. }
  381. if (RemoteNode != NULL)
  382. {
  383. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394IndicateNodes: Notifying Nic1394 of device arrival, Miniport PDO %lx, Node PDO %lx\n", LocalHost->PhysicalDeviceObject, RemoteNode->PhysicalDeviceObject));
  384. ExReleaseSpinLock(&LocalHost->Lock, OldIrql);
  385. Status = AddNodeHandler(LocalHost->Nic1394AdapterContext,
  386. (PVOID)RemoteNode,
  387. RemoteNode->PhysicalDeviceObject,
  388. RemoteNode->UniqueId[0],
  389. RemoteNode->UniqueId[1],
  390. &RemoteNode->Nic1394NodeContext);
  391. ASSERT(Status == STATUS_SUCCESS);
  392. if (Status == STATUS_SUCCESS)
  393. {
  394. ENUM_SET_FLAG(RemoteNode, NDISENUM1394_NODE_ADDED);
  395. }
  396. else
  397. {
  398. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("ndisEnum1394IndicateNodes: AddAdapter failed %lx\n", Status));
  399. }
  400. ExAcquireSpinLock(&LocalHost->Lock, &OldIrql);
  401. goto next;
  402. }
  403. }
  404. else
  405. {
  406. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("ndisEnum1394IndicateNodes: LocalHost is not registered %lx\n", Status));
  407. }
  408. ExReleaseSpinLock(&LocalHost->Lock, OldIrql);
  409. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394IndicateNodes: LocalHost %lx\n", LocalHost));
  410. }
  411. NTSTATUS
  412. ndisEnum1394CreateIrpHandler(
  413. IN PDEVICE_OBJECT DeviceObject,
  414. IN PIRP Irp
  415. )
  416. {
  417. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394CreateIrpHandler: DeviceObject %lx, Irp %lx\n", DeviceObject, Irp));
  418. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394CreateIrpHandler: DeviceObject %lx, Irp %lx\n", DeviceObject, Irp));
  419. return STATUS_SUCCESS;
  420. }
  421. NTSTATUS
  422. ndisEnum1394CloseIrpHandler(
  423. IN PDEVICE_OBJECT DeviceObject,
  424. IN PIRP Irp
  425. )
  426. {
  427. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394CloseIrpHandler: DeviceObject %lx, Irp %lx\n", DeviceObject, Irp));
  428. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394CloseIrpHandler: DeviceObject %lx, Irp %lx\n", DeviceObject, Irp));
  429. return STATUS_SUCCESS;
  430. }
  431. NTSTATUS
  432. ndisEnum1394DeviceIoControl(
  433. IN PDEVICE_OBJECT DeviceObject,
  434. IN PIRP Irp
  435. )
  436. {
  437. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394DeviceIoControl: DeviceObject %lx, Irp %lx\n", DeviceObject, Irp));
  438. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394DeviceIoControl: DeviceObject %lx, Irp %lx\n", DeviceObject, Irp));
  439. return STATUS_SUCCESS;
  440. }
  441. VOID
  442. ndisEnum1394Unload(
  443. IN PDRIVER_OBJECT DriverObject
  444. )
  445. {
  446. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394Unload: DriverObject %lx\n", DriverObject));
  447. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394Unload: DriverObject %lx\n", DriverObject));
  448. //
  449. // Tell nic1394 that we are going away
  450. //
  451. if (DeRegisterDriverHandler != NULL )
  452. {
  453. DeRegisterDriverHandler() ;
  454. }
  455. //
  456. // Deregister our callback structure
  457. //
  458. ExUnregisterCallback(ndisEnum1394CallbackRegisterationHandle);
  459. //
  460. // Dereference our callback structure
  461. //
  462. ObDereferenceObject(ndisEnum1394CallbackObject);
  463. return;
  464. }
  465. /*
  466. EXPORT
  467. NTSTATUS
  468. NdisEnum1394RegisterAdapter(
  469. IN PVOID Nic1394AdapterContext,
  470. IN PDEVICE_OBJECT PhysicalDeviceObject,
  471. OUT PVOID* pEnum1394AdapterHandle,
  472. OUT PLARGE_INTEGER pLocalHostUniqueId
  473. );
  474. This routine is called at system initialization time so we can fill in the basic dispatch points
  475. Arguments:
  476. DriverObject - Supplies the driver object.
  477. RegistryPath - Supplies the registry path for this driver.
  478. Return Value:
  479. STATUS_SUCCESS
  480. Routine Description:
  481. This function is called by Nic1394 during its Ndis IntializeHandler to register a new
  482. Adapter. each registered adapter corresponds to a local host controller.
  483. in response Enum1394 finds the local host and for each remote node on the local host
  484. that have not been indicated yet calls the Nic1394 AddNodes handler.
  485. Arguments:
  486. Nic1394AdapterContext Nic1394 context for the local host
  487. PhysicalDeviceObject PDO created by 1394 Bus driver for the local host
  488. pEnum1394AdapterHandle a pointer a pointer to be initialized to Enum1394 LocalHost context
  489. pLocalHostUniqueId a pointer to a LARGE_INTEGER to be initialized to local host unique ID
  490. */
  491. NTSTATUS
  492. NdisEnum1394RegisterAdapter(
  493. IN PVOID Nic1394AdapterContext,
  494. IN PDEVICE_OBJECT PhysicalDeviceObject,
  495. OUT PVOID* pEnum1394AdapterHandle,
  496. OUT PLARGE_INTEGER pLocalHostUniqueId
  497. )
  498. {
  499. PNDISENUM1394_LOCAL_HOST LocalHost;
  500. PNDISENUM1394_REMOTE_NODE LocalNode;
  501. NTSTATUS Status;
  502. KIRQL OldIrql;
  503. IRB Irb;
  504. GET_LOCAL_HOST_INFO1 uId;
  505. PDEVICE_OBJECT DeviceObject;
  506. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>NdisEnum1394RegisterAdapter, PhysicalDeviceObject %lx\n", PhysicalDeviceObject));
  507. do
  508. {
  509. //
  510. // get the unique ID for the local host for this adapter
  511. //
  512. RtlZeroMemory(&Irb, sizeof(IRB));
  513. Irb.FunctionNumber = REQUEST_GET_LOCAL_HOST_INFO;
  514. Irb.u.GetLocalHostInformation.nLevel = GET_HOST_UNIQUE_ID;
  515. Irb.u.GetLocalHostInformation.Information = (PVOID)&uId;
  516. Status = ndisEnum1394BusRequest(PhysicalDeviceObject, &Irb);
  517. if (Status != STATUS_SUCCESS)
  518. {
  519. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("NdisEnum1394RegisterAdapter: ndisEnum1394BusRequest for REQUEST_GET_LOCAL_HOST_INFO failed. Status %lx\n", Status));
  520. break;
  521. }
  522. //
  523. // GetLocal Host Refs the LocalHost - Derefed in DeRegisterAdapter
  524. //
  525. ndisEnum1394GetLocalHostForUniqueId(uId.UniqueId, &LocalHost);
  526. #if 0
  527. ExAcquireSpinLock(&ndisEnum1394GlobalLock, &OldIrql);
  528. for (LocalHost = LocalHostList; LocalHost != NULL; LocalHost = LocalHost->Next)
  529. {
  530. if ((LocalHost->UniqueId.LowPart == uId.UniqueId.LowPart) &&
  531. (LocalHost->UniqueId.HighPart == uId.UniqueId.HighPart))
  532. {
  533. break;
  534. }
  535. }
  536. ExReleaseSpinLock(&ndisEnum1394GlobalLock, OldIrql);
  537. #endif
  538. ASSERT(LocalHost != NULL);
  539. if (LocalHost == NULL)
  540. {
  541. Status = STATUS_UNSUCCESSFUL;
  542. break;
  543. }
  544. *pEnum1394AdapterHandle = (PVOID)LocalHost;
  545. LocalHost->Nic1394AdapterContext = Nic1394AdapterContext;
  546. LocalHost->PhysicalDeviceObject = PhysicalDeviceObject;
  547. *pLocalHostUniqueId = LocalHost->UniqueId;
  548. ENUM_SET_FLAG(LocalHost, NDISENUM1394_LOCALHOST_REGISTERED);
  549. ndisEnum1394IndicateNodes(LocalHost);
  550. Status = STATUS_SUCCESS;
  551. } while (FALSE);
  552. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==NdisEnum1394RegisterAdapter: Status %lx\n", Status));
  553. return Status;
  554. }
  555. VOID
  556. NdisEnum1394DeregisterAdapter(
  557. IN PVOID Enum1394AdapterHandle
  558. )
  559. {
  560. PNDISENUM1394_LOCAL_HOST LocalHost = (PNDISENUM1394_LOCAL_HOST)Enum1394AdapterHandle;
  561. KIRQL OldIrql;
  562. PNDISENUM1394_REMOTE_NODE RemoteNode;
  563. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>NdisEnum1394DeregisterAdapter: LocalHost %lx\n", Enum1394AdapterHandle));
  564. //
  565. // go through all the nodes and remove them
  566. //
  567. ExAcquireSpinLock(&LocalHost->Lock, &OldIrql);
  568. //
  569. // make sure we will not try to indicate any new dev node on this
  570. //
  571. ENUM_CLEAR_FLAG(LocalHost, NDISENUM1394_LOCALHOST_REGISTERED);
  572. next:
  573. for (RemoteNode = LocalHost->RemoteNodeList;
  574. RemoteNode != NULL;
  575. RemoteNode = RemoteNode->Next)
  576. {
  577. ENUM_CLEAR_FLAG(RemoteNode, NDISENUM1394_NODE_INDICATED);
  578. if (ENUM_TEST_FLAG(RemoteNode, NDISENUM1394_NODE_ADDED))
  579. {
  580. break;
  581. }
  582. }
  583. if (RemoteNode != NULL)
  584. {
  585. DBGPRINT(ENUM1394_DBGLEVEL_INFO,
  586. ("NdisEnum1394DeregisterAdapter: Notifying Nic1394 of device removal, Miniport PDO %lx, Node PDO %lx\n", LocalHost->PhysicalDeviceObject, RemoteNode->PhysicalDeviceObject));
  587. ExReleaseSpinLock(&LocalHost->Lock, OldIrql);
  588. RemoveNodeHandler(RemoteNode->Nic1394NodeContext);
  589. ExAcquireSpinLock(&LocalHost->Lock, &OldIrql);
  590. ENUM_CLEAR_FLAG(RemoteNode, NDISENUM1394_NODE_ADDED);
  591. goto next;
  592. }
  593. LocalHost->Nic1394AdapterContext = NULL;
  594. LocalHost->PhysicalDeviceObject = NULL;
  595. ExReleaseSpinLock(&LocalHost->Lock, OldIrql);
  596. //
  597. // Dereference the Ref made in RegisterAdapter by calling GetLocalHost for Unique ID
  598. //
  599. {
  600. BOOLEAN bIsRefZero;
  601. bIsRefZero = ndisEnum1394DereferenceLocalHost(LocalHost);
  602. if (bIsRefZero == TRUE)
  603. {
  604. ndisEnum1394FreeLocalHost(LocalHost);
  605. }
  606. }
  607. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==NdisEnum1394DeregisterAdapter: LocalHost %lx\n", Enum1394AdapterHandle));
  608. }
  609. NTSTATUS
  610. ndisEnum1394GetLocalHostForRemoteNode(
  611. IN PNDISENUM1394_REMOTE_NODE RemoteNode,
  612. OUT PNDISENUM1394_LOCAL_HOST * pLocalHost
  613. )
  614. {
  615. NTSTATUS Status;
  616. PNDISENUM1394_LOCAL_HOST LocalHost;
  617. KIRQL OldIrql;
  618. IRB Irb;
  619. GET_LOCAL_HOST_INFO1 uId;
  620. ULONG SizeNeeded;
  621. PVOID ConfigInfoBuffer = NULL;
  622. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394GetLocalHostForRemoteNode: RemoteNode %lx\n", RemoteNode));
  623. do
  624. {
  625. //
  626. // get the unique ID for the local host which this device
  627. // is connected on. then walk through all the existing local
  628. // hosts and see if this a new local host or not.
  629. //
  630. RtlZeroMemory(&Irb, sizeof(IRB));
  631. Irb.FunctionNumber = REQUEST_GET_LOCAL_HOST_INFO;
  632. Irb.u.GetLocalHostInformation.nLevel = GET_HOST_UNIQUE_ID;
  633. Irb.u.GetLocalHostInformation.Information = (PVOID)&uId;
  634. Status = ndisEnum1394BusRequest(RemoteNode->NextDeviceObject, &Irb);
  635. if (Status != STATUS_SUCCESS)
  636. {
  637. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("ndisEnum1394GetLocalHostForRemoteNode: ndisEnum1394BusRequest for REQUEST_GET_LOCAL_HOST_INFO failed. Status %lx\n", Status));
  638. break;
  639. }
  640. //
  641. // now get the unique ID for the remote node
  642. //
  643. // we have to make this call twice. first to get the size, then the actual data
  644. //
  645. RtlZeroMemory(&Irb, sizeof(IRB));
  646. Irb.FunctionNumber = REQUEST_GET_CONFIGURATION_INFO;
  647. Status = ndisEnum1394BusRequest(RemoteNode->NextDeviceObject, &Irb);
  648. if (Status != STATUS_SUCCESS)
  649. {
  650. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("ndisEnum1394GetLocalHostForRemoteNode: ndisEnum1394BusRequest for REQUEST_GET_CONFIGURATION_INFO (size) failed. Status %lx\n", Status));
  651. break;
  652. }
  653. SizeNeeded = sizeof(CONFIG_ROM) +
  654. Irb.u.GetConfigurationInformation.UnitDirectoryBufferSize +
  655. Irb.u.GetConfigurationInformation.UnitDependentDirectoryBufferSize +
  656. Irb.u.GetConfigurationInformation.VendorLeafBufferSize +
  657. Irb.u.GetConfigurationInformation.ModelLeafBufferSize;
  658. ConfigInfoBuffer = (PVOID)ALLOC_FROM_POOL(SizeNeeded, ' 4N');
  659. if (ConfigInfoBuffer == NULL)
  660. {
  661. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("ndisEnum1394GetLocalHostForRemoteNode: Failed to allocate memory for config info.\n"));
  662. Status = STATUS_INSUFFICIENT_RESOURCES;
  663. break;
  664. }
  665. Irb.u.GetConfigurationInformation.ConfigRom = (PCONFIG_ROM)ConfigInfoBuffer;
  666. Irb.u.GetConfigurationInformation.UnitDirectory = (PVOID)((PUCHAR)ConfigInfoBuffer + sizeof(CONFIG_ROM));
  667. Irb.u.GetConfigurationInformation.UnitDependentDirectory = (PVOID)((PUCHAR)Irb.u.GetConfigurationInformation.UnitDirectory +
  668. Irb.u.GetConfigurationInformation.UnitDirectoryBufferSize);
  669. Irb.u.GetConfigurationInformation.VendorLeaf = (PVOID)((PUCHAR)Irb.u.GetConfigurationInformation.UnitDependentDirectory +
  670. Irb.u.GetConfigurationInformation.UnitDependentDirectoryBufferSize);
  671. Irb.u.GetConfigurationInformation.ModelLeaf = (PVOID)((PUCHAR)Irb.u.GetConfigurationInformation.VendorLeaf +
  672. Irb.u.GetConfigurationInformation.VendorLeafBufferSize);
  673. Irb.FunctionNumber = REQUEST_GET_CONFIGURATION_INFO;
  674. Status = ndisEnum1394BusRequest(RemoteNode->NextDeviceObject, &Irb);
  675. if (Status != STATUS_SUCCESS)
  676. {
  677. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("ndisEnum1394GetLocalHostForRemoteNode: ndisEnum1394BusRequest for REQUEST_GET_CONFIGURATION_INFO failed. Status %lx\n", Status));
  678. break;
  679. }
  680. ASSERT(Irb.u.GetConfigurationInformation.ConfigRom != NULL);
  681. RemoteNode->UniqueId[0] = Irb.u.GetConfigurationInformation.ConfigRom->CR_Node_UniqueID[0];
  682. RemoteNode->UniqueId[1] = Irb.u.GetConfigurationInformation.ConfigRom->CR_Node_UniqueID[1];
  683. #if DBG
  684. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("Unique ID for Node %lx: %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x\n",
  685. RemoteNode->PhysicalDeviceObject,
  686. *((PUCHAR)&RemoteNode->UniqueId[0]),
  687. *(((PUCHAR)&RemoteNode->UniqueId[0])+1),
  688. *(((PUCHAR)&RemoteNode->UniqueId[0])+2),
  689. *(((PUCHAR)&RemoteNode->UniqueId[0])+3),
  690. *((PUCHAR)&RemoteNode->UniqueId[1]),
  691. *(((PUCHAR)&RemoteNode->UniqueId[1])+1),
  692. *(((PUCHAR)&RemoteNode->UniqueId[1])+2),
  693. *(((PUCHAR)&RemoteNode->UniqueId[1])+3)));
  694. #endif
  695. ndisEnum1394GetLocalHostForUniqueId(uId.UniqueId, &LocalHost);
  696. if (LocalHost == NULL)
  697. {
  698. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("ndisEnum1394GetLocalHostForUniqueId: Failed to get the local host.\n"));
  699. Status = STATUS_UNSUCCESSFUL;
  700. break;
  701. }
  702. *pLocalHost = LocalHost;
  703. Status = STATUS_SUCCESS;
  704. } while (FALSE);
  705. if (ConfigInfoBuffer != NULL)
  706. {
  707. FREE_POOL(ConfigInfoBuffer);
  708. }
  709. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394GetLocalHostForRemoteNode: Status %lx, RemoteNode %lx, LocalHostList %lx\n", Status, RemoteNode, LocalHostList));
  710. return Status;
  711. }
  712. NTSTATUS
  713. ndisEnum1394IrpCompletion(
  714. IN PDEVICE_OBJECT DeviceObject,
  715. IN PIRP Irp,
  716. IN PVOID Context
  717. )
  718. /*++
  719. Routine Description:
  720. This routine will get called after the next device object in the stack
  721. processes the IRP_MN_QUERY_CAPABILITIES IRP this needs to be merged with
  722. the miniport's capabilites and completed.
  723. Arguments:
  724. DeviceObject
  725. Irp
  726. Context
  727. Return Value:
  728. --*/
  729. {
  730. SET_EVENT(Context);
  731. return(STATUS_MORE_PROCESSING_REQUIRED);
  732. }
  733. NTSTATUS
  734. ndisEnum1394PassIrpDownTheStack(
  735. IN PIRP pIrp,
  736. IN PDEVICE_OBJECT pNextDeviceObject
  737. )
  738. /*++
  739. Routine Description:
  740. This routine will simply pass the IRP down to the next device object to
  741. process.
  742. Arguments:
  743. pIrp - Pointer to the IRP to process.
  744. pNextDeviceObject - Pointer to the next device object that wants
  745. the IRP.
  746. Return Value:
  747. --*/
  748. {
  749. KEVENT Event;
  750. NTSTATUS Status = STATUS_SUCCESS;
  751. //
  752. // Initialize the event structure.
  753. //
  754. INITIALIZE_EVENT(&Event);
  755. //
  756. // Set the completion routine so that we can process the IRP when
  757. // our PDO is done.
  758. //
  759. IoSetCompletionRoutine(pIrp,
  760. (PIO_COMPLETION_ROUTINE)ndisEnum1394IrpCompletion,
  761. &Event,
  762. TRUE,
  763. TRUE,
  764. TRUE);
  765. //
  766. // Pass the IRP down to the PDO.
  767. //
  768. Status = IoCallDriver(pNextDeviceObject, pIrp);
  769. if (Status == STATUS_PENDING)
  770. {
  771. //
  772. // Wait for completion.
  773. //
  774. WAIT_FOR_OBJECT(&Event, NULL);
  775. Status = pIrp->IoStatus.Status;
  776. }
  777. return(Status);
  778. }
  779. NTSTATUS
  780. ndisEnum1394PnpDispatch(
  781. IN PDEVICE_OBJECT DeviceObject,
  782. IN PIRP Irp
  783. )
  784. /*++
  785. Routine Description:
  786. The handler for IRP_MJ_PNP_POWER.
  787. Arguments:
  788. DeviceObject - The adapter's functional device object.
  789. Irp - The IRP.
  790. Return Value:
  791. --*/
  792. {
  793. PIO_STACK_LOCATION IrpSp, NextIrpSp;
  794. NTSTATUS Status = STATUS_SUCCESS;
  795. PDEVICE_OBJECT NextDeviceObject;
  796. PNDISENUM1394_REMOTE_NODE RemoteNode;
  797. ULONG PnPDeviceState;
  798. KEVENT RemoveReadyEvent;
  799. BOOLEAN fSendIrpDown = TRUE;
  800. BOOLEAN fCompleteIrp = TRUE;
  801. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394PnpDispatch: DeviceObject %lx, Irp %lx\n", DeviceObject, Irp));
  802. if (DbgIsNull(Irp))
  803. {
  804. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("ndisEnum1394PnpDispatch: Null Irp\n"));
  805. DBGBREAK();
  806. }
  807. //
  808. // Get a pointer to the adapter block and miniport block then determine
  809. // which one we should use.
  810. //
  811. RemoteNode = (PNDISENUM1394_REMOTE_NODE)DeviceObject->DeviceExtension;
  812. //
  813. // Get a pointer to the next miniport.
  814. //
  815. NextDeviceObject = RemoteNode->NextDeviceObject;
  816. IrpSp = IoGetCurrentIrpStackLocation (Irp);
  817. switch(IrpSp->MinorFunction)
  818. {
  819. case IRP_MN_START_DEVICE:
  820. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394PnpDispatch: RemoteNode %lx, IRP_MN_START_DEVICE\n", RemoteNode));
  821. IoCopyCurrentIrpStackLocationToNext(Irp);
  822. Status = ndisEnum1394PassIrpDownTheStack(Irp, NextDeviceObject);
  823. //
  824. // If the bus driver succeeded the start irp then proceed.
  825. //
  826. if (NT_SUCCESS(Status))
  827. {
  828. Status = ndisEnum1394StartDevice(DeviceObject, Irp);
  829. }
  830. else
  831. {
  832. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("ndisEnum1394PnpDispatch: bus driver failed START IRP RemoteNode %lx\n", RemoteNode));
  833. }
  834. RemoteNode->PnPDeviceState = PnPDeviceStarted;
  835. Irp->IoStatus.Status = Status;
  836. fSendIrpDown = FALSE; // we already did send the IRP down
  837. break;
  838. case IRP_MN_QUERY_REMOVE_DEVICE:
  839. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394PnpDispatch: RemoteNode %lx, IRP_MN_QUERY_REMOVE_DEVICE\n", RemoteNode));
  840. RemoteNode->PnPDeviceState = PnPDeviceQueryRemoved;
  841. Irp->IoStatus.Status = STATUS_SUCCESS;
  842. //
  843. // if we failed query_remove, no point sending this irp down
  844. //
  845. fSendIrpDown = TRUE;
  846. break;
  847. case IRP_MN_CANCEL_REMOVE_DEVICE:
  848. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394PnpDispatch: RemoteNode %lx, IRP_MN_CANCEL_REMOVE_DEVICE\n", RemoteNode));
  849. RemoteNode->PnPDeviceState = PnPDeviceStarted;
  850. Irp->IoStatus.Status = STATUS_SUCCESS;
  851. fSendIrpDown = TRUE;
  852. break;
  853. case IRP_MN_REMOVE_DEVICE:
  854. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394PnpDispatch: RemoteNode %lx, IRP_MN_REMOVE_DEVICE\n", RemoteNode));
  855. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  856. //
  857. // call notify handler
  858. //
  859. PnPDeviceState = RemoteNode->PnPDeviceState;
  860. if (PnPDeviceState != PnPDeviceSurpriseRemoved)
  861. {
  862. RemoteNode->PnPDeviceState = PnPDeviceRemoved;
  863. Status = ndisEnum1394RemoveDevice(DeviceObject,
  864. Irp,
  865. NdisEnum1394_RemoveDevice);
  866. Irp->IoStatus.Status = Status;
  867. }
  868. else
  869. {
  870. Irp->IoStatus.Status = STATUS_SUCCESS;
  871. }
  872. //
  873. // when we are done, send the Irp down here
  874. // we have some post-processing to do
  875. //
  876. IoSkipCurrentIrpStackLocation(Irp);
  877. Status = IoCallDriver(NextDeviceObject, Irp);
  878. IoDetachDevice(NextDeviceObject);
  879. IoDeleteDevice(DeviceObject);
  880. fSendIrpDown = FALSE;
  881. fCompleteIrp = FALSE;
  882. break;
  883. case IRP_MN_SURPRISE_REMOVAL:
  884. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394PnpDispatch: RemoteNode %lx, IRP_MN_SURPRISE_REMOVAL\n", RemoteNode));
  885. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  886. RemoteNode->PnPDeviceState = PnPDeviceSurpriseRemoved;
  887. Status = ndisEnum1394RemoveDevice(DeviceObject,
  888. Irp,
  889. NdisEnum1394_SurpriseRemoveDevice);
  890. Irp->IoStatus.Status = Status;
  891. //
  892. // when we are done, send the Irp down here
  893. // we have some post-processing to do
  894. //
  895. IoSkipCurrentIrpStackLocation(Irp);
  896. Status = IoCallDriver(NextDeviceObject, Irp);
  897. fSendIrpDown = FALSE;
  898. fCompleteIrp = FALSE;
  899. break;
  900. case IRP_MN_QUERY_STOP_DEVICE:
  901. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394PnpDispatch: RemoteNode %lx, IRP_MN_QUERY_STOP_DEVICE\n", RemoteNode));
  902. RemoteNode->PnPDeviceState = PnPDeviceQueryStopped;
  903. Irp->IoStatus.Status = STATUS_SUCCESS;
  904. fSendIrpDown = TRUE;
  905. break;
  906. case IRP_MN_CANCEL_STOP_DEVICE:
  907. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394PnpDispatch: RemoteNode %lx, IRP_MN_CANCEL_STOP_DEVICE\n", RemoteNode));
  908. RemoteNode->PnPDeviceState = PnPDeviceStarted;
  909. Irp->IoStatus.Status = STATUS_SUCCESS;
  910. fSendIrpDown = TRUE;
  911. break;
  912. case IRP_MN_STOP_DEVICE:
  913. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394PnpDispatch: RemoteNode %lx, IRP_MN_STOP_DEVICE\n", RemoteNode));
  914. RemoteNode->PnPDeviceState = PnPDeviceStopped;
  915. Status = ndisEnum1394RemoveDevice(DeviceObject, Irp,NdisEnum1394_StopDevice);
  916. Irp->IoStatus.Status = Status;
  917. fSendIrpDown = TRUE;
  918. break;
  919. case IRP_MN_QUERY_CAPABILITIES:
  920. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394PnpDispatch: RemoteNode, IRP_MN_QUERY_CAPABILITIES\n", RemoteNode));
  921. IoCopyCurrentIrpStackLocationToNext(Irp);
  922. Status = ndisEnum1394PassIrpDownTheStack(Irp, NextDeviceObject);
  923. #ifdef ENUM1394_NT
  924. //
  925. // Memphis does not support SurpriseRemovalOK bit
  926. //
  927. // If the bus driver succeeded the start irp then proceed.
  928. //
  929. if (NT_SUCCESS(Status))
  930. {
  931. //
  932. // Modify the capabilities so that the device is not suprise removable.
  933. //
  934. IrpSp->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = 1;
  935. }
  936. #endif // NDIS_NT
  937. fSendIrpDown = FALSE;
  938. break;
  939. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  940. Irp->IoStatus.Status = Status;
  941. fSendIrpDown = TRUE ;
  942. break;
  943. case IRP_MN_QUERY_DEVICE_RELATIONS:
  944. case IRP_MN_QUERY_INTERFACE:
  945. case IRP_MN_QUERY_RESOURCES:
  946. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  947. case IRP_MN_READ_CONFIG:
  948. case IRP_MN_WRITE_CONFIG:
  949. case IRP_MN_EJECT:
  950. case IRP_MN_SET_LOCK:
  951. case IRP_MN_QUERY_ID:
  952. default:
  953. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394PnpDispatch: RemoteNode %lx, MinorFunction 0x%x\n", RemoteNode, IrpSp->MinorFunction));
  954. //
  955. // We don't handle the irp so pass it down.
  956. //
  957. fSendIrpDown = TRUE;
  958. break;
  959. }
  960. //
  961. // First check to see if we need to send the irp down.
  962. // If we don't pass the irp on then check to see if we need to complete it.
  963. //
  964. if (fSendIrpDown)
  965. {
  966. IoSkipCurrentIrpStackLocation(Irp);
  967. Status = IoCallDriver(NextDeviceObject, Irp);
  968. }
  969. else if (fCompleteIrp)
  970. {
  971. Irp->IoStatus.Status = Status;
  972. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  973. }
  974. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394PnpDispatch: Status %lx, RemoteNode %lx\n", Status, RemoteNode));
  975. return(Status);
  976. }
  977. NTSTATUS
  978. ndisEnum1394RemoveDevice(
  979. PDEVICE_OBJECT DeviceObject,
  980. PIRP Irp,
  981. NDISENUM1394_PNP_OP PnpOp
  982. )
  983. /*++
  984. Routine Description:
  985. This function is called in the RemoveDevice and Stop Device code path.
  986. In the case of a Stop the function should undo whatever it received in the Start
  987. and it the case of a Remove it Should do undo the work done in AddDevice
  988. Arguments:
  989. DeviceObject - The adapter's functional device object.
  990. Irp - The IRP.
  991. Return Value:
  992. --*/
  993. {
  994. PNDISENUM1394_REMOTE_NODE RemoteNode, *ppDB;
  995. PNDISENUM1394_LOCAL_HOST LocalHost;
  996. KIRQL OldIrql;
  997. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394RemoveDevice: DeviceObject %lx, Irp %lx\n", DeviceObject, Irp));
  998. ASSERT(KeGetCurrentIrql()==PASSIVE_LEVEL );
  999. //
  1000. // call 1394Nic about this device getting removed
  1001. // if this is the last PDO on local host, get rid of
  1002. // the PDO created for the local host
  1003. //
  1004. RemoteNode = (PNDISENUM1394_REMOTE_NODE)DeviceObject->DeviceExtension;
  1005. LocalHost = RemoteNode->LocalHost;
  1006. //
  1007. // if the node has been indicated, let the nic1394 know
  1008. // it is going away
  1009. //
  1010. if ((RemoveNodeHandler != NULL) && (ENUM_TEST_FLAGS(RemoteNode, NDISENUM1394_NODE_ADDED)))
  1011. {
  1012. RemoveNodeHandler(RemoteNode->Nic1394NodeContext);
  1013. ENUM_CLEAR_FLAG(RemoteNode, NDISENUM1394_NODE_ADDED);
  1014. }
  1015. //
  1016. // If this is a stop device then do NOT do any software specific cleanup work ..
  1017. // leave it for the RemoveDevice
  1018. //
  1019. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394RemoveDevice: - pRemoteNode %p LocalHost %p Op %x\n",
  1020. RemoteNode,
  1021. LocalHost,
  1022. PnpOp));
  1023. if (PnpOp != NdisEnum1394_StopDevice && LocalHost != NULL)
  1024. {
  1025. //
  1026. // find the device block and remove it from local host
  1027. //
  1028. ExAcquireSpinLock(&LocalHost->Lock, &OldIrql);
  1029. for (ppDB = &LocalHost->RemoteNodeList; *ppDB != NULL; ppDB = &(*ppDB)->Next)
  1030. {
  1031. if (*ppDB == RemoteNode)
  1032. {
  1033. *ppDB = RemoteNode->Next;
  1034. break;
  1035. }
  1036. }
  1037. ExReleaseSpinLock(&LocalHost->Lock, OldIrql);
  1038. ASSERT(*ppDB == RemoteNode->Next);
  1039. //
  1040. // Remove the Ref made in the Add Devive when calling GetLocalHost for Unique ID
  1041. //
  1042. {
  1043. BOOLEAN bIsRefZero;
  1044. RemoteNode->LocalHost = NULL;
  1045. bIsRefZero = ndisEnum1394DereferenceLocalHost(LocalHost);
  1046. if (bIsRefZero == TRUE)
  1047. {
  1048. ndisEnum1394FreeLocalHost(LocalHost);
  1049. }
  1050. }
  1051. }
  1052. ENUM_CLEAR_FLAG(RemoteNode, NDISENUM1394_NODE_PNP_STARTED);
  1053. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394RemoveDevice: DeviceObject %lx, Irp %lx\n", DeviceObject, Irp));
  1054. return STATUS_SUCCESS;
  1055. }
  1056. /*+++
  1057. NTSTATUS
  1058. ndisEnum1394BusRequest(
  1059. PDEVICE_OBJECT DeviceObject,
  1060. PIRB Irb
  1061. );
  1062. Routine Description:
  1063. this function issues a 1394 bus request to the device object. the device
  1064. object could be the NextDeviceObject of the remote PDO or the virtual PDO
  1065. 1394 bus ejected (net PDO)
  1066. Arguments:
  1067. DeviceObject: the target device object to send the request to
  1068. Irb: the request block
  1069. Return Value:
  1070. as appropriate
  1071. ---*/
  1072. NTSTATUS
  1073. ndisEnum1394BusRequest(
  1074. PDEVICE_OBJECT DeviceObject,
  1075. PIRB Irb
  1076. )
  1077. {
  1078. NTSTATUS Status;
  1079. PIRP Irp;
  1080. PIO_STACK_LOCATION IrpSp;
  1081. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394BusRequest: DeviceObject %lx, Irb %lx\n", DeviceObject, Irb));
  1082. do
  1083. {
  1084. Irp = IoAllocateIrp((CCHAR)(DeviceObject->StackSize + 1),
  1085. FALSE);
  1086. if (Irp == NULL)
  1087. {
  1088. Status = STATUS_INSUFFICIENT_RESOURCES;
  1089. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("ndisEnum1394BusRequest: IoAllocateIrp failed. Status %lx\n", Status));
  1090. break;
  1091. }
  1092. IrpSp = IoGetNextIrpStackLocation(Irp);
  1093. ASSERT(IrpSp != NULL);
  1094. RtlZeroMemory(IrpSp, sizeof(IO_STACK_LOCATION ));
  1095. IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1096. IrpSp->DeviceObject = DeviceObject;
  1097. IrpSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_1394_CLASS;
  1098. IrpSp->Parameters.Others.Argument1 = Irb;
  1099. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  1100. Status = ndisEnum1394PassIrpDownTheStack(Irp, DeviceObject);
  1101. if (Status != STATUS_SUCCESS)
  1102. {
  1103. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("ndisEnum1394BusRequest: 1394 Bus driver failed the IRB. Status %lx\n", Status));
  1104. }
  1105. }while (FALSE);
  1106. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394BusRequest: DeviceObject %lx, Irb %lx\n", DeviceObject, Irb));
  1107. return Status;
  1108. }
  1109. BOOLEAN
  1110. ndisEnum1394ReferenceLocalHost(
  1111. IN PNDISENUM1394_LOCAL_HOST LocalHost
  1112. )
  1113. {
  1114. BOOLEAN rc;
  1115. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394ReferenceLocalHost : LocalHost %p\n", LocalHost));
  1116. rc = ndisEnum1394ReferenceRef(&LocalHost->Reference);
  1117. return rc;
  1118. }
  1119. BOOLEAN
  1120. ndisEnum1394DereferenceLocalHost(
  1121. IN PNDISENUM1394_LOCAL_HOST LocalHost
  1122. )
  1123. {
  1124. BOOLEAN rc;
  1125. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("ndisEnum1394DereferenceLocalHost : LocalHost %p\n", LocalHost));
  1126. rc = ndisEnum1394DereferenceRef(&LocalHost->Reference);
  1127. return rc;
  1128. }
  1129. VOID
  1130. ndisEnum1394FreeLocalHost(
  1131. IN PNDISENUM1394_LOCAL_HOST LocalHost
  1132. )
  1133. {
  1134. KIRQL OldIrql;
  1135. PNDISENUM1394_LOCAL_HOST * ppLH;
  1136. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394FreeLocalHost: LocalHost %p\n", LocalHost));
  1137. ASSERT(LocalHost->RemoteNodeList == NULL);
  1138. ASSERT(LocalHost->Reference.ReferenceCount == 0);
  1139. //
  1140. // make sure we have not created a PDO for this local host
  1141. //
  1142. ASSERT(LocalHost->PhysicalDeviceObject == NULL);
  1143. ExAcquireSpinLock(&ndisEnum1394GlobalLock, &OldIrql);
  1144. for (ppLH = &LocalHostList; *ppLH != NULL; ppLH = &(*ppLH)->Next)
  1145. {
  1146. if (*ppLH == LocalHost)
  1147. {
  1148. *ppLH = LocalHost->Next;
  1149. break;
  1150. }
  1151. }
  1152. ExReleaseSpinLock(&ndisEnum1394GlobalLock, OldIrql);
  1153. ASSERT(*ppLH == LocalHost->Next);
  1154. FREE_POOL(LocalHost);
  1155. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394FreeLocalHost: LocalHost %p\n", LocalHost));
  1156. }
  1157. VOID
  1158. ndisEnum1394InitializeRef(
  1159. IN PREFERENCE RefP
  1160. )
  1161. /*++
  1162. Routine Description:
  1163. Initialize a reference count structure.
  1164. Arguments:
  1165. RefP - The structure to be initialized.
  1166. Return Value:
  1167. None.
  1168. --*/
  1169. {
  1170. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394InitializeRef\n"));
  1171. RefP->Closing = FALSE;
  1172. RefP->ReferenceCount = 1;
  1173. KeInitializeSpinLock(&RefP->SpinLock);
  1174. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394InitializeRef\n"));
  1175. }
  1176. BOOLEAN
  1177. ndisEnum1394ReferenceRef(
  1178. IN PREFERENCE RefP
  1179. )
  1180. /*++
  1181. Routine Description:
  1182. Adds a reference to an object.
  1183. Arguments:
  1184. RefP - A pointer to the REFERENCE portion of the object.
  1185. Return Value:
  1186. TRUE if the reference was added.
  1187. FALSE if the object was closing.
  1188. --*/
  1189. {
  1190. BOOLEAN rc = TRUE;
  1191. KIRQL OldIrql;
  1192. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394ReferenceRef\n"));
  1193. ExAcquireSpinLock(&RefP->SpinLock, &OldIrql);
  1194. if (RefP->Closing)
  1195. {
  1196. rc = FALSE;
  1197. }
  1198. else
  1199. {
  1200. ++(RefP->ReferenceCount);
  1201. }
  1202. ExReleaseSpinLock(&RefP->SpinLock, OldIrql);
  1203. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394ReferenceRef: RefCount %lx\n", RefP->ReferenceCount));
  1204. return(rc);
  1205. }
  1206. BOOLEAN
  1207. ndisEnum1394DereferenceRef(
  1208. IN PREFERENCE RefP
  1209. )
  1210. /*++
  1211. Routine Description:
  1212. Removes a reference to an object.
  1213. Arguments:
  1214. RefP - A pointer to the REFERENCE portion of the object.
  1215. Return Value:
  1216. TRUE if the reference count is now 0.
  1217. FALSE otherwise.
  1218. --*/
  1219. {
  1220. BOOLEAN rc = FALSE;
  1221. KIRQL OldIrql;
  1222. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394DereferenceRef\n"));
  1223. ExAcquireSpinLock(&RefP->SpinLock, &OldIrql);
  1224. --(RefP->ReferenceCount);
  1225. if (RefP->ReferenceCount == 0)
  1226. {
  1227. rc = TRUE;
  1228. }
  1229. ExReleaseSpinLock(&RefP->SpinLock, OldIrql);
  1230. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394DereferenceRef: RefCount %lx\n", RefP->ReferenceCount));
  1231. return(rc);
  1232. }
  1233. BOOLEAN
  1234. ndisEnum1394CloseRef(
  1235. IN PREFERENCE RefP
  1236. )
  1237. /*++
  1238. Routine Description:
  1239. Closes a reference count structure.
  1240. Arguments:
  1241. RefP - The structure to be closed.
  1242. Return Value:
  1243. FALSE if it was already closing.
  1244. TRUE otherwise.
  1245. --*/
  1246. {
  1247. KIRQL OldIrql;
  1248. BOOLEAN rc = TRUE;
  1249. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394CloseRef\n"));
  1250. ExAcquireSpinLock(&RefP->SpinLock, &OldIrql);
  1251. if (RefP->Closing)
  1252. {
  1253. rc = FALSE;
  1254. }
  1255. else RefP->Closing = TRUE;
  1256. ExReleaseSpinLock(&RefP->SpinLock, OldIrql);
  1257. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394CloseRef\n"));
  1258. return(rc);
  1259. }
  1260. NTSTATUS
  1261. NdisEnum1394RegisterDriver(
  1262. IN PNIC1394_CHARACTERISTICS Characteristics
  1263. )
  1264. {
  1265. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>NdisEnum1394RegisterDriver\n"));
  1266. //
  1267. // Todo: do some check for the version, etc. and make sure the handlers are
  1268. // not null and this is not a dup registeration
  1269. //
  1270. AddNodeHandler = Characteristics->AddNodeHandler;
  1271. RemoveNodeHandler = Characteristics->RemoveNodeHandler;
  1272. RegisterDriverHandler = Characteristics->RegisterDriverHandler;
  1273. DeRegisterDriverHandler = Characteristics->DeRegisterDriverHandler;
  1274. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==NdisEnum1394RegisterDriver\n"));
  1275. return STATUS_SUCCESS;
  1276. }
  1277. VOID
  1278. NdisEnum1394DeregisterDriver(
  1279. )
  1280. {
  1281. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>NdisEnum1394DeregisterDriver\n"));
  1282. AddNodeHandler = NULL;
  1283. RemoveNodeHandler = NULL;
  1284. RegisterDriverHandler = NULL;
  1285. DeRegisterDriverHandler = NULL;
  1286. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==NdisEnum1394DeregisterDriver\n"));
  1287. }
  1288. /*+++
  1289. this routine will call the 1394 bus driver to create a virtual PDO
  1290. on the local host with matching unique ID
  1291. ---*/
  1292. NTSTATUS
  1293. ndisEnum1394CreateVirtualPdo(
  1294. IN PDEVICE_OBJECT PhysicalDeviceObject,
  1295. IN LARGE_INTEGER UniqueId
  1296. )
  1297. {
  1298. PDEVICE_OBJECT BusDeviceObject = NULL;
  1299. PIRP pirp;
  1300. PIO_STACK_LOCATION pirpSpN;
  1301. NTSTATUS Status;
  1302. PIEEE1394_API_REQUEST pApiReq;
  1303. PIEEE1394_VDEV_PNP_REQUEST pDevPnpReq;
  1304. PSTR DeviceId = "NIC1394";
  1305. ULONG ulStrLen;
  1306. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394CreateVirtualPdo\n"));
  1307. do
  1308. {
  1309. pirp = IoAllocateIrp((CCHAR)(PhysicalDeviceObject->StackSize + 1),FALSE);
  1310. if (NULL == pirp)
  1311. {
  1312. DBGPRINT(ENUM1394_DBGLEVEL_ERROR,
  1313. ("ndisEnum1394CreateVirtualPdo failed to allcoate IRP\n"));
  1314. Status = STATUS_INSUFFICIENT_RESOURCES;
  1315. break;
  1316. }
  1317. ulStrLen = strlen(DeviceId) + sizeof(UCHAR);
  1318. pApiReq = ALLOC_FROM_POOL(sizeof(IEEE1394_API_REQUEST) + ulStrLen, NDISENUM1394_TAG_1394API_REQ);
  1319. if (pApiReq == NULL)
  1320. {
  1321. DBGPRINT(ENUM1394_DBGLEVEL_ERROR,
  1322. ("ndisEnum1394CreateVirtualPdo failed to allcoate 1394 request\n"));
  1323. Status = STATUS_INSUFFICIENT_RESOURCES;
  1324. break;
  1325. }
  1326. RtlZeroMemory(pApiReq, sizeof(IEEE1394_API_REQUEST) + ulStrLen);
  1327. pApiReq->RequestNumber = IEEE1394_API_ADD_VIRTUAL_DEVICE;
  1328. pApiReq->Flags = 0;
  1329. pDevPnpReq = &pApiReq->u.AddVirtualDevice;
  1330. pDevPnpReq->fulFlags = 0;
  1331. pDevPnpReq->Reserved = 0;
  1332. pDevPnpReq->InstanceId.LowPart = (ULONG)UniqueId.LowPart;
  1333. pDevPnpReq->InstanceId.HighPart = (ULONG)UniqueId.HighPart;
  1334. strncpy(&pDevPnpReq->DeviceId, DeviceId, ulStrLen);
  1335. //
  1336. // Get the stack pointer.
  1337. //
  1338. pirpSpN = IoGetNextIrpStackLocation(pirp);
  1339. ASSERT(pirpSpN != NULL);
  1340. RtlZeroMemory(pirpSpN, sizeof(IO_STACK_LOCATION ) );
  1341. //
  1342. // Set the default device state to full on.
  1343. //
  1344. pirpSpN->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1345. pirpSpN->MinorFunction = 0;
  1346. pirpSpN->Parameters.DeviceIoControl.IoControlCode = IOCTL_IEEE1394_API_REQUEST;
  1347. pirpSpN->Parameters.DeviceIoControl.InputBufferLength = sizeof(IEEE1394_API_REQUEST) + ulStrLen;
  1348. pirp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  1349. pirp->AssociatedIrp.SystemBuffer = pApiReq;
  1350. Status = ndisEnum1394PassIrpDownTheStack(pirp, PhysicalDeviceObject);
  1351. if (Status != STATUS_SUCCESS)
  1352. {
  1353. DBGPRINT(ENUM1394_DBGLEVEL_ERROR,
  1354. ("ndisEnum1394CreateVirtualPdo IOCTL to create the virtual PDO failed with Status %lx\n", Status));
  1355. }
  1356. IoFreeIrp(pirp);
  1357. FREE_POOL(pApiReq);
  1358. } while (FALSE);
  1359. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394CreateVirtualPdo: Status %lx\n", Status));
  1360. return Status;
  1361. }
  1362. //
  1363. // this functions searchs through the list of local hosts trying to find one
  1364. // with matching unique ID. if it does not, it will allocate a new one
  1365. //
  1366. VOID
  1367. ndisEnum1394GetLocalHostForUniqueId(
  1368. LARGE_INTEGER UniqueId,
  1369. OUT PNDISENUM1394_LOCAL_HOST * pLocalHost
  1370. )
  1371. {
  1372. PNDISENUM1394_LOCAL_HOST TempLocalHost;
  1373. PNDISENUM1394_LOCAL_HOST LocalHost;
  1374. KIRQL OldIrql;
  1375. BOOLEAN bFreeTempLocalHost = FALSE;
  1376. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>ndisEnum1394GetLocalHostForUniqueId\n"));
  1377. do
  1378. {
  1379. ExAcquireSpinLock(&ndisEnum1394GlobalLock, &OldIrql);
  1380. for (LocalHost = LocalHostList; LocalHost != NULL; LocalHost = LocalHost->Next)
  1381. {
  1382. if (LocalHost->UniqueId.QuadPart == UniqueId.QuadPart)
  1383. break;
  1384. }
  1385. ExReleaseSpinLock(&ndisEnum1394GlobalLock, OldIrql);
  1386. if (LocalHost == NULL)
  1387. {
  1388. TempLocalHost = (PNDISENUM1394_LOCAL_HOST)ALLOC_FROM_POOL(sizeof(NDISENUM1394_LOCAL_HOST), NDISENUM1394_TAG_LOCAL_HOST);
  1389. if (TempLocalHost == NULL)
  1390. {
  1391. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("ndisEnum1394GetLocalHostForUniqueId: Failed to allocate memory LocalHost.\n"));
  1392. break;
  1393. }
  1394. RtlZeroMemory(TempLocalHost, sizeof (NDISENUM1394_LOCAL_HOST));
  1395. ExAcquireSpinLock(&ndisEnum1394GlobalLock, &OldIrql);
  1396. //
  1397. // need to do the search again just in case between the time we release the
  1398. // spinlock and now, we have added the local host
  1399. //
  1400. for (LocalHost = LocalHostList; LocalHost != NULL; LocalHost = LocalHost->Next)
  1401. {
  1402. if (LocalHost->UniqueId.QuadPart == UniqueId.QuadPart)
  1403. break;
  1404. }
  1405. if (LocalHost == NULL)
  1406. {
  1407. LocalHost = TempLocalHost;
  1408. LocalHost->Next = LocalHostList;
  1409. LocalHostList = LocalHost;
  1410. LocalHost->RemoteNodeList = NULL;
  1411. LocalHost->UniqueId.QuadPart = UniqueId.QuadPart;
  1412. KeInitializeSpinLock(&LocalHost->Lock);
  1413. ndisEnum1394InitializeRef(&LocalHost->Reference);
  1414. }
  1415. else
  1416. {
  1417. bFreeTempLocalHost = TRUE;
  1418. }
  1419. ExReleaseSpinLock(&ndisEnum1394GlobalLock, OldIrql);
  1420. if (bFreeTempLocalHost)
  1421. FREE_POOL(TempLocalHost);
  1422. }
  1423. else
  1424. {
  1425. //
  1426. // Give the caller a reference to our struct
  1427. //
  1428. ndisEnum1394ReferenceLocalHost(LocalHost);
  1429. }
  1430. } while (FALSE);
  1431. *pLocalHost = LocalHost;
  1432. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==ndisEnum1394GetLocalHostForUniqueId: LocalHost %lx\n", LocalHost));
  1433. return;
  1434. }
  1435. VOID
  1436. Enum1394Callback(
  1437. PVOID CallBackContext,
  1438. PVOID Source,
  1439. PVOID Characteristics
  1440. )
  1441. {
  1442. NTSTATUS Status;
  1443. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("==>Enum1394Callback: Source %lx, Characteristics %lx\n", Source, Characteristics));
  1444. //
  1445. // if we are the one issuing this notification, just return
  1446. //
  1447. if (Source == NDIS1394_CALLBACK_SOURCE_ENUM1394)
  1448. return;
  1449. //
  1450. // notification is coming from Nic1394. grab the entry points. call it and
  1451. // let it know that you are here
  1452. //
  1453. ASSERT(Source == (PVOID)NDIS1394_CALLBACK_SOURCE_NIC1394);
  1454. RegisterDriverHandler = ((PNIC1394_CHARACTERISTICS)Characteristics)->RegisterDriverHandler;
  1455. ASSERT(RegisterDriverHandler != NULL);
  1456. if (RegisterDriverHandler == NULL)
  1457. {
  1458. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("Enum1394Callback: Callback called with invalid Characteristics. Characteristics %lx\n", Characteristics));
  1459. return;
  1460. }
  1461. Status = RegisterDriverHandler(&NdisEnum1394Characteristics);
  1462. if (Status == STATUS_SUCCESS)
  1463. {
  1464. AddNodeHandler = ((PNIC1394_CHARACTERISTICS)Characteristics)->AddNodeHandler;
  1465. RemoveNodeHandler = ((PNIC1394_CHARACTERISTICS)Characteristics)->RemoveNodeHandler;
  1466. DeRegisterDriverHandler = ((PNIC1394_CHARACTERISTICS)Characteristics)->DeRegisterDriverHandler;
  1467. }
  1468. else
  1469. {
  1470. DBGPRINT(ENUM1394_DBGLEVEL_ERROR, ("Enum1394Callback: RegisterDriverHandler failed: Status %lx\n", Status));
  1471. RegisterDriverHandler = NULL;
  1472. }
  1473. DBGPRINT(ENUM1394_DBGLEVEL_INFO, ("<==Enum1394Callback: Source, %lx\n", Source));
  1474. }