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.

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