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.

2118 lines
61 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. 1394f.C
  5. Abstract:
  6. Environment:
  7. kernel mode only
  8. Notes:
  9. Revision History:
  10. --*/
  11. #include <wdm.h>
  12. #include "stdarg.h"
  13. #include "stdio.h"
  14. #include "dbci.h"
  15. #include "dbclass.h" //private data strutures
  16. #include "dbfilter.h"
  17. #include "1394.h"
  18. #if DBG
  19. VOID
  20. DBCLASS_PrintTopologyMap(
  21. PTOPOLOGY_MAP TopologyMap
  22. )
  23. /* ++
  24. *
  25. * Routine Description:
  26. *
  27. * Passes a IRB to the 1394 stack, and waits for return.
  28. *
  29. * Arguments:
  30. *
  31. * DeviceObject - Device object of the to of the port driver
  32. * stack
  33. *
  34. * Return Value:
  35. *
  36. * STATUS_SUCCESS if successful
  37. *
  38. * -- */
  39. {
  40. USHORT nodeCount, selfIdCount;
  41. ULONG i;
  42. DBCLASS_KdPrint((2, "'***********************\n"));
  43. DBCLASS_KdPrint((2, "'TopologyMap = (%08X)\n", TopologyMap));
  44. DBCLASS_KdPrint((2, "'TOP_Length = (%08X)\n", TopologyMap->TOP_Length));
  45. DBCLASS_KdPrint((2, "'TOP_CRC = (%08X)\n", TopologyMap->TOP_CRC));
  46. DBCLASS_KdPrint((2, "'TOP_Generation = (%08X)\n", TopologyMap->TOP_Generation));
  47. DBCLASS_KdPrint((2, "'TOP_Node_Count = (%08X)\n", TopologyMap->TOP_Node_Count));
  48. DBCLASS_KdPrint((2, "'TOP_Self_ID_Count = (%08X)\n", TopologyMap->TOP_Self_ID_Count));
  49. nodeCount = TopologyMap->TOP_Node_Count;
  50. selfIdCount = TopologyMap->TOP_Self_ID_Count;
  51. DBCLASS_KdPrint((2, "'nodeCount = (%08X) selfIdCount = (%08X)\n",
  52. nodeCount, selfIdCount));
  53. for (i=0; i< selfIdCount; i++) {
  54. SELF_ID selfId;
  55. SELF_ID_MORE selfIdMore;
  56. selfId = TopologyMap->TOP_Self_ID_Array[i];
  57. DBCLASS_KdPrint((2, "'TOP_Self_ID = (%08X)\n",
  58. selfId));
  59. DBCLASS_KdPrint((2, "'SID_Phys_ID = (%08X)\n", (ULONG)
  60. selfId.SID_Phys_ID));
  61. DBCLASS_KdPrint((2, "'SID_Port1 = (%08X)\n", (ULONG)
  62. selfId.SID_Port1));
  63. DBCLASS_KdPrint((2, "'SID_Port2 = (%08X)\n", (ULONG)
  64. selfId.SID_Port2));
  65. DBCLASS_KdPrint((2, "'SID_Port3 = (%08X)\n", (ULONG)
  66. selfId.SID_Port3));
  67. DBCLASS_KdPrint((2, "'SID_More_Packets = (%08X)\n", (ULONG)
  68. selfId.SID_More_Packets));
  69. if (selfId.SID_More_Packets)
  70. {
  71. do
  72. {
  73. i++;
  74. RtlCopyMemory(&selfIdMore,
  75. &TopologyMap->TOP_Self_ID_Array[i],
  76. sizeof(ULONG));
  77. DBCLASS_KdPrint((2, "'SID_Phys_ID = (%08X)\n", (ULONG)
  78. selfIdMore.SID_Phys_ID));
  79. DBCLASS_KdPrint((2, "'SID_PortA = (%08X)\n", (ULONG)
  80. selfIdMore.SID_PortA));
  81. DBCLASS_KdPrint((2, "'SID_PortB = (%08X)\n", (ULONG)
  82. selfIdMore.SID_PortB));
  83. DBCLASS_KdPrint((2, "'SID_PortC = (%08X)\n", (ULONG)
  84. selfIdMore.SID_PortC));
  85. DBCLASS_KdPrint((2, "'SID_PortD = (%08X)\n", (ULONG)
  86. selfIdMore.SID_PortD));
  87. DBCLASS_KdPrint((2, "'SID_PortE = (%08X)\n", (ULONG)
  88. selfIdMore.SID_PortE));
  89. DBCLASS_KdPrint((2, "'SID_PortF = (%08X)\n", (ULONG)
  90. selfIdMore.SID_PortF));
  91. DBCLASS_KdPrint((2, "'SID_PortG = (%08X)\n", (ULONG)
  92. selfIdMore.SID_PortG));
  93. DBCLASS_KdPrint((2, "'SID_PortH = (%08X)\n", (ULONG)
  94. selfIdMore.SID_PortH));
  95. } while (selfIdMore.SID_More_Packets);
  96. }
  97. } /* for */
  98. DBCLASS_KdPrint((2, "'***********************\n"));
  99. }
  100. #else
  101. #define DBCLASS_PrintTopologyMap(x) x
  102. #endif /* DBG */
  103. NTSTATUS
  104. DBCLASS_SyncSubmitIrb(
  105. IN PDEVICE_OBJECT DeviceObject,
  106. IN PIRB Irb
  107. )
  108. /* ++
  109. *
  110. * Routine Description:
  111. *
  112. * Passes a IRB to the 1394 stack, and waits for return.
  113. *
  114. * Arguments:
  115. *
  116. * DeviceObject - Device object of the to of the port driver
  117. * stack
  118. *
  119. * Return Value:
  120. *
  121. * STATUS_SUCCESS if successful
  122. *
  123. * -- */
  124. {
  125. NTSTATUS ntStatus, status;
  126. PIRP irp;
  127. KEVENT event;
  128. IO_STATUS_BLOCK ioStatus;
  129. PIO_STACK_LOCATION nextStack;
  130. #ifdef DEADMAN_TIMER
  131. BOOLEAN haveTimer = FALSE;
  132. KDPC timeoutDpc;
  133. KTIMER timeoutTimer;
  134. #endif
  135. PAGED_CODE();
  136. KeInitializeEvent(&event, NotificationEvent, FALSE);
  137. irp = IoBuildDeviceIoControlRequest(IOCTL_1394_CLASS,
  138. DeviceObject,
  139. NULL,
  140. 0,
  141. NULL,
  142. 0,
  143. TRUE, // INTERNAL
  144. &event,
  145. &ioStatus);
  146. if (NULL == irp) {
  147. DBCLASS_KdPrint((0, "'could not allocate an irp!\n"));
  148. TRAP();
  149. return STATUS_INSUFFICIENT_RESOURCES;
  150. }
  151. //
  152. // Call the port driver to perform the operation. If the returned
  153. // status
  154. // is PENDING, wait for the request to complete.
  155. //
  156. nextStack = IoGetNextIrpStackLocation(irp);
  157. //
  158. // pass the DRB
  159. //
  160. nextStack->Parameters.Others.Argument1 = Irb;
  161. ntStatus = IoCallDriver(DeviceObject, irp);
  162. if (ntStatus == STATUS_PENDING)
  163. {
  164. #ifdef DEADMAN_TIMER
  165. LARGE_INTEGER dueTime;
  166. KeInitializeTimer(&timeoutTimer);
  167. KeInitializeDpc(&timeoutDpc,
  168. UsbhTimeoutDPC,
  169. irp);
  170. dueTime.QuadPart = -10000 * DEADMAN_TIMEOUT;
  171. KeSetTimer(&timeoutTimer,
  172. dueTime,
  173. &timeoutDpc);
  174. haveTimer = TRUE;
  175. #endif
  176. status = KeWaitForSingleObject(&event,
  177. Suspended,
  178. KernelMode,
  179. FALSE,
  180. NULL);
  181. } else {
  182. ioStatus.Status = ntStatus;
  183. }
  184. #ifdef DEADMAN_TIMER
  185. //
  186. // remove our timeoutDPC from the queue
  187. //
  188. if (haveTimer)
  189. {
  190. KeCancelTimer(&timeoutTimer);
  191. }
  192. #endif /* DEADMAN_TIMER */
  193. ntStatus = ioStatus.Status;
  194. DBCLASS_KdPrint((2,"'DBCLASS_SyncSubmitIrb (%x)\n", ntStatus));
  195. return ntStatus;
  196. }
  197. #define DBCLASS_COUNT_PORT(s, d) (d)->NumberOf1394Ports++;
  198. USHORT
  199. DBCLASS_GetNodeId(
  200. PTOPOLOGY_MAP TopologyMap,
  201. USHORT Index,
  202. USHORT Connect
  203. )
  204. /*++
  205. Routine Description:
  206. Given an index walk the map and return the NodeId
  207. Arguments:
  208. Return Value:
  209. zero if not a device bay PDO.
  210. --*/
  211. {
  212. USHORT i;
  213. USHORT nodeCount;
  214. USHORT nodeId = 0xffff;
  215. USHORT idCount = 0;
  216. USHORT selfIdCount;
  217. nodeCount = TopologyMap->TOP_Node_Count;
  218. selfIdCount = TopologyMap->TOP_Self_ID_Count;
  219. DBCLASS_KdPrint((2, "'>GetNodeId Index = %d\n", Index));
  220. for (i=0; i< selfIdCount; i++)
  221. {
  222. SELF_ID selfId;
  223. SELF_ID_MORE selfIdMore;
  224. selfId = TopologyMap->TOP_Self_ID_Array[i];
  225. if (idCount == Index &&
  226. ((USHORT)selfId.SID_Port1 == Connect ||
  227. (USHORT)selfId.SID_Port2 == Connect ||
  228. (USHORT)selfId.SID_Port3 == Connect))
  229. {
  230. nodeId = (USHORT) selfId.SID_Phys_ID;
  231. break;
  232. }
  233. if (selfId.SID_More_Packets)
  234. {
  235. do
  236. {
  237. i++;
  238. RtlCopyMemory(&selfIdMore,
  239. &TopologyMap->TOP_Self_ID_Array[i],
  240. sizeof(ULONG));
  241. if (idCount == Index &&
  242. ((USHORT)selfIdMore.SID_PortA == Connect ||
  243. (USHORT)selfIdMore.SID_PortB == Connect ||
  244. (USHORT)selfIdMore.SID_PortC == Connect ||
  245. (USHORT)selfIdMore.SID_PortD == Connect ||
  246. (USHORT)selfIdMore.SID_PortE == Connect ||
  247. (USHORT)selfIdMore.SID_PortF == Connect ||
  248. (USHORT)selfIdMore.SID_PortG == Connect ||
  249. (USHORT)selfIdMore.SID_PortH == Connect)) {
  250. nodeId = (USHORT) selfId.SID_Phys_ID;
  251. goto DBCLASS_GetNodeId_Done;
  252. }
  253. } while (selfIdMore.SID_More_Packets);
  254. }
  255. idCount++;
  256. }
  257. DBCLASS_KdPrint((2, "'>nodeId = (%08X)\n", nodeId));
  258. DBCLASS_GetNodeId_Done:
  259. return nodeId;
  260. }
  261. PBUS1394_PORT_INFO
  262. DBCLASS_SetNodeId(
  263. PTOPOLOGY_MAP TopologyMap,
  264. SELF_ID HcSelfId,
  265. USHORT SelfIdPortX,
  266. PUSHORT ChildIdx,
  267. PUSHORT ParentIdx,
  268. PBUS1394_PORT_INFO Bus1394PortInfo
  269. )
  270. /*++
  271. Routine Description:
  272. Arguments:
  273. Return Value:
  274. zero if not a device bay PDO.
  275. --*/
  276. {
  277. ULONG flags = 0;
  278. USHORT nodeId = 0xffff, idCount;
  279. idCount = TopologyMap->TOP_Self_ID_Count;
  280. DBCLASS_KdPrint((2, "'ParentIdx = %d ChildIdx = %d count = %d\n",
  281. *ParentIdx, *ChildIdx, idCount));
  282. //Scan forward through the map looking for potential children
  283. if (SelfIdPortX == SELF_ID_CONNECTED_TO_CHILD)
  284. {
  285. DBCLASS_KdPrint((2, "'find child\n"));
  286. do
  287. {
  288. (*ChildIdx)++;
  289. // are we out of children?
  290. if (*ChildIdx > idCount)
  291. {
  292. // yes, check the root
  293. *ChildIdx = 0;
  294. }
  295. flags = DBCLASS_PORTFLAG_DEVICE_CONNECTED;
  296. // find the child node id
  297. nodeId = DBCLASS_GetNodeId(TopologyMap, *ChildIdx, SELF_ID_CONNECTED_TO_PARENT);
  298. } while (nodeId == 0xffff);
  299. DBCLASS_KdPrint((2, "'Found ChildIdx = %d nodeId = %d\n", *ChildIdx, nodeId));
  300. }
  301. else if (SelfIdPortX == SELF_ID_CONNECTED_TO_PARENT)
  302. {
  303. do
  304. {
  305. (*ParentIdx)++;
  306. // are we out of parents?
  307. if (*ParentIdx > idCount)
  308. {
  309. // yes, check the root
  310. *ParentIdx = 0;
  311. }
  312. flags = DBCLASS_PORTFLAG_DEVICE_CONNECTED;
  313. nodeId = DBCLASS_GetNodeId(TopologyMap, *ParentIdx, SELF_ID_CONNECTED_TO_CHILD);
  314. } while (nodeId == 0xffff);
  315. DBCLASS_KdPrint((2, "'Found ParentIdx = %d nodeId = %d\n", *ParentIdx, nodeId));
  316. }
  317. Bus1394PortInfo->Flags = flags;
  318. Bus1394PortInfo->NodeId = nodeId;
  319. Bus1394PortInfo->BayNumber = 0;
  320. Bus1394PortInfo++;
  321. return Bus1394PortInfo;
  322. }
  323. #if DBG
  324. VOID
  325. DBCLASS_KdPrintGuid(
  326. ULONG Level,
  327. PUCHAR P
  328. )
  329. {
  330. DBCLASS_KdPrint((Level, "'>>>>GUID1 = [%02.2x] [%02.2x] [%02.2x] [%02.2x]\n",
  331. *P, *(P+1), *(P+2), *(P+3)));
  332. DBCLASS_KdPrint((Level, "'>>>>GUID2 = [%02.2x] [%02.2x] [%02.2x] [%02.2x]\n",
  333. *(P+4), *(P+5), *(P+6), *(P+7)));
  334. }
  335. #endif
  336. BOOLEAN
  337. DBCLASS_IsLinkDeviceObject(
  338. PDBC_CONTEXT DbcContext,
  339. PDEVICE_OBJECT Pdo1394
  340. )
  341. /*++
  342. Routine Description:
  343. check the link guid in dbcContext against the link guid for a
  344. 1394 device,
  345. Arguments:
  346. Return Value:
  347. true if link guid matches
  348. --*/
  349. {
  350. PNODE_DEVICE_EXTENSION nodeExtension;
  351. nodeExtension = Pdo1394->DeviceExtension;
  352. DBCLASS_KdPrint((2, "'>NodeExt (%08X) ConfigRom (%08X)\n", nodeExtension, nodeExtension->ConfigRom));
  353. DBCLASS_KdPrint((2, "'>1394 PDO GUID\n"));
  354. if(nodeExtension->ConfigRom)
  355. {
  356. #if DBG
  357. DBCLASS_KdPrintGuid(2, (PUCHAR)&nodeExtension->ConfigRom->CR_Node_UniqueID[0]);
  358. #endif
  359. DBCLASS_KdPrint((2, "'>DBC Link GUID\n"));
  360. #if DBG
  361. DBCLASS_KdPrintGuid(2, &DbcContext->SubsystemDescriptor.guid1394Link[0]);
  362. #endif
  363. return RtlCompareMemory(&DbcContext->SubsystemDescriptor.guid1394Link[0],
  364. &nodeExtension->ConfigRom->CR_Node_UniqueID[0],
  365. 8) == 8;
  366. }
  367. else
  368. return FALSE;
  369. }
  370. NTSTATUS
  371. DBCLASS_GetSpeedAndTopologyMaps(
  372. PTOPOLOGY_MAP *TopologyMap,
  373. PDEVICE_OBJECT BusFilterMdo
  374. )
  375. /*++
  376. Routine Description:
  377. Arguments:
  378. Return Value:
  379. topology map or NULL
  380. --*/
  381. {
  382. NTSTATUS ntStatus = STATUS_SUCCESS;
  383. IRB irb;
  384. PDEVICE_EXTENSION deviceExtension;
  385. GET_LOCAL_HOST_INFO6 info6;
  386. PUCHAR buffer = NULL;
  387. if(BusFilterMdo == NULL)
  388. return STATUS_UNSUCCESSFUL;
  389. deviceExtension = BusFilterMdo->DeviceExtension;
  390. DBCLASS_KdPrint((2, "'>Get 1394 Speed & Topology Maps MDO (%08X)\n", BusFilterMdo));
  391. BRK_ON_TRAP();
  392. irb.FunctionNumber = REQUEST_GET_LOCAL_HOST_INFO;
  393. irb.u.GetLocalHostInformation.nLevel = GET_HOST_CSR_CONTENTS;
  394. info6.CsrBaseAddress.Off_High = 0xffff;
  395. info6.CsrBaseAddress.Off_Low = TOPOLOGY_MAP_LOCATION;
  396. info6.CsrDataLength = 0;
  397. info6.CsrDataBuffer = buffer;
  398. irb.u.GetLocalHostInformation.Information = &info6;
  399. ntStatus = DBCLASS_SyncSubmitIrb(
  400. deviceExtension->TopOfStackDeviceObject,
  401. &irb);
  402. DBCLASS_KdPrint((2, "'GetLocalHostInfo(), first call = (%08X)\n", ntStatus));
  403. if (ntStatus == STATUS_INVALID_BUFFER_SIZE)
  404. {
  405. // try again with correct size
  406. buffer = DbcExAllocatePool(NonPagedPool,
  407. info6.CsrDataLength);
  408. if (buffer)
  409. {
  410. info6.CsrDataBuffer = buffer;
  411. ntStatus = DBCLASS_SyncSubmitIrb(
  412. deviceExtension->TopOfStackDeviceObject,
  413. &irb);
  414. }
  415. else
  416. {
  417. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  418. }
  419. DBCLASS_KdPrint((2, "'GetLocalHostInfo(), second call = (%08X) buffer = %x\n",
  420. ntStatus, buffer));
  421. }
  422. if (NT_SUCCESS(ntStatus))
  423. {
  424. *TopologyMap = (PTOPOLOGY_MAP) buffer;
  425. DBCLASS_PrintTopologyMap(*TopologyMap);
  426. }
  427. return ntStatus;
  428. }
  429. NTSTATUS
  430. DBCLASS_Get1394BayPortMapping(
  431. PDEVICE_OBJECT BusFilterMdo,
  432. PDBC_CONTEXT DbcContext
  433. )
  434. /*++
  435. Routine Description:
  436. Arguments:
  437. Return Value:
  438. zero if not a device bay PDO.
  439. --*/
  440. {
  441. NTSTATUS ntStatus = STATUS_SUCCESS;
  442. IRB irb;
  443. PDEVICE_EXTENSION deviceExtension;
  444. PTOPOLOGY_MAP topologyMap = NULL;
  445. USHORT i, nodeCount, selfIdCount, linkNodeId;
  446. USHORT linkSelfId_Index = 0;
  447. PDEVICE_OBJECT linkDeviceObject;
  448. DBCLASS_KdPrint((1, "'>Get 1394 Port Mapping\n"));
  449. DBCLASS_ASSERT(DbcContext);
  450. BRK_ON_TRAP();
  451. //
  452. // get the topology map & local node id from the 1394 port driver
  453. //
  454. // our mission her is to find the parent nodeid
  455. //
  456. // if the DBC controller is ACPI then this will be the 1394 host controller
  457. // if it is USB based it will be the PHY for DBC
  458. if (DbcContext->ControllerSig == DBC_ACPI_CONTROLLER_SIG)
  459. {
  460. //
  461. // link device object is the PDO for the 1394 HC
  462. //
  463. DBCLASS_KdPrint((2, "'DBC is ACPI \n"));
  464. deviceExtension = DbcContext->BusFilterMdo1394->DeviceExtension;
  465. DBCLASS_ASSERT(DbcContext->BusFilterMdo1394 == BusFilterMdo);
  466. DBCLASS_ASSERT(DbcContext->LinkDeviceObject == NULL);
  467. linkDeviceObject = deviceExtension->TopOfStackDeviceObject;
  468. }
  469. else
  470. {
  471. //
  472. // for USBDBC the link is stored in the dbcContext
  473. //
  474. DBCLASS_KdPrint((2, "'DBC is USB \n"));
  475. linkDeviceObject = DbcContext->LinkDeviceObject;
  476. BRK_ON_TRAP();
  477. }
  478. DBCLASS_KdPrint((2, "'DbcContext (%08X) LinkDeviceObject (%08X)\n", DbcContext, linkDeviceObject));
  479. // check for invalid device object
  480. if(((linkDeviceObject) == (PDEVICE_OBJECT)(-1)) || (linkDeviceObject == NULL))
  481. {
  482. ntStatus = STATUS_UNSUCCESSFUL;
  483. goto BayPort_End;
  484. }
  485. // should only get here if the db controller
  486. // has been found
  487. DBCLASS_ASSERT(linkDeviceObject != NULL);
  488. irb.u.Get1394AddressFromDeviceObject.fulFlags = 0;
  489. irb.FunctionNumber = REQUEST_GET_ADDR_FROM_DEVICE_OBJECT;
  490. ntStatus = DBCLASS_SyncSubmitIrb(linkDeviceObject,
  491. &irb);
  492. DBCLASS_KdPrint((2, "'GetLocalNodeId() = (%08X)\n", ntStatus));
  493. if (NT_SUCCESS(ntStatus))
  494. {
  495. linkNodeId = irb.u.Get1394AddressFromDeviceObject.NodeAddress.NA_Node_Number;
  496. DBCLASS_KdPrint((2, "'link node id (%08X)\n", linkNodeId));
  497. ntStatus = DBCLASS_GetSpeedAndTopologyMaps(
  498. &topologyMap,
  499. DbcContext->BusFilterMdo1394);
  500. DBCLASS_KdPrint((2, "'GetTopologyMap() = (%08X)\n", ntStatus));
  501. }
  502. if(NT_SUCCESS(ntStatus))
  503. {
  504. DBCLASS_ASSERT(topologyMap != NULL);
  505. DbcContext->NumberOf1394Ports = 0;
  506. // free the old information
  507. if (DbcContext->Bus1394PortInfo)
  508. {
  509. DbcExFreePool(DbcContext->Bus1394PortInfo);
  510. DbcContext->Bus1394PortInfo = NULL;
  511. }
  512. //
  513. // parse the map
  514. //
  515. if(topologyMap)
  516. {
  517. nodeCount = topologyMap->TOP_Node_Count;
  518. selfIdCount = topologyMap->TOP_Self_ID_Count;
  519. // walk the topology map and find the node for the
  520. // for the link
  521. //
  522. // first pass we just count up the ports
  523. // we count all SID entries for ports if if
  524. // not present.
  525. //
  526. for (i=0; i< selfIdCount; i++)
  527. {
  528. SELF_ID selfId;
  529. SELF_ID_MORE selfIdMore;
  530. selfId = topologyMap->TOP_Self_ID_Array[i];
  531. if (selfId.SID_Phys_ID == linkNodeId)
  532. {
  533. // this is the host, count the ports
  534. linkSelfId_Index = i;
  535. DBCLASS_COUNT_PORT(selfId.SID_Port1, DbcContext);
  536. DBCLASS_COUNT_PORT(selfId.SID_Port2, DbcContext);
  537. DBCLASS_COUNT_PORT(selfId.SID_Port3, DbcContext);
  538. }
  539. if (selfId.SID_More_Packets)
  540. {
  541. do
  542. {
  543. i++;
  544. RtlCopyMemory(&selfIdMore,
  545. &topologyMap->TOP_Self_ID_Array[i],
  546. sizeof(ULONG));
  547. if (selfIdMore.SID_Phys_ID == linkNodeId)
  548. {
  549. // this is the link, count the ports
  550. DBCLASS_COUNT_PORT(selfIdMore.SID_PortA, DbcContext);
  551. DBCLASS_COUNT_PORT(selfIdMore.SID_PortB, DbcContext);
  552. DBCLASS_COUNT_PORT(selfIdMore.SID_PortC, DbcContext);
  553. DBCLASS_COUNT_PORT(selfIdMore.SID_PortD, DbcContext);
  554. DBCLASS_COUNT_PORT(selfIdMore.SID_PortE, DbcContext);
  555. DBCLASS_COUNT_PORT(selfIdMore.SID_PortF, DbcContext);
  556. DBCLASS_COUNT_PORT(selfIdMore.SID_PortG, DbcContext);
  557. DBCLASS_COUNT_PORT(selfIdMore.SID_PortH, DbcContext);
  558. }
  559. } while(selfIdMore.SID_More_Packets);
  560. }
  561. }
  562. }
  563. // now set up the port map
  564. DbcContext->Bus1394PortInfo =
  565. DbcExAllocatePool(NonPagedPool, sizeof(BUS1394_PORT_INFO) *
  566. DbcContext->NumberOf1394Ports);
  567. DBCLASS_KdPrint((2, "'link index = %d\n", linkSelfId_Index));
  568. DBCLASS_KdPrint((2, "'link id = %d\n", linkNodeId));
  569. if(DbcContext->Bus1394PortInfo && topologyMap)
  570. {
  571. SELF_ID selfId;
  572. SELF_ID_MORE selfIdMore;
  573. USHORT parentIdx, childIdx;
  574. PBUS1394_PORT_INFO bus1394PortInfo = DbcContext->Bus1394PortInfo;
  575. // scan children and parents
  576. // now parse the self id for the link and fill in the port map
  577. // fill in the phys ids for all child devices
  578. selfId = topologyMap->TOP_Self_ID_Array[linkSelfId_Index];
  579. parentIdx = childIdx = linkNodeId;
  580. DBCLASS_ASSERT(selfId.SID_Phys_ID == linkNodeId);
  581. bus1394PortInfo =
  582. DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfId.SID_Port1,
  583. &parentIdx, &childIdx, bus1394PortInfo);
  584. bus1394PortInfo =
  585. DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfId.SID_Port2,
  586. &parentIdx, &childIdx, bus1394PortInfo);
  587. bus1394PortInfo =
  588. DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfId.SID_Port3,
  589. &parentIdx, &childIdx, bus1394PortInfo);
  590. if (selfId.SID_More_Packets)
  591. {
  592. do
  593. {
  594. linkSelfId_Index++;
  595. RtlCopyMemory(&selfIdMore,
  596. &topologyMap->TOP_Self_ID_Array[linkSelfId_Index],
  597. sizeof(ULONG));
  598. bus1394PortInfo =
  599. DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortA,
  600. &parentIdx, &childIdx, bus1394PortInfo);
  601. bus1394PortInfo =
  602. DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortB,
  603. &parentIdx, &childIdx, bus1394PortInfo);
  604. bus1394PortInfo =
  605. DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortC,
  606. &parentIdx, &childIdx, bus1394PortInfo);
  607. bus1394PortInfo =
  608. DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortD,
  609. &parentIdx, &childIdx, bus1394PortInfo);
  610. bus1394PortInfo =
  611. DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortE,
  612. &parentIdx, &childIdx, bus1394PortInfo);
  613. bus1394PortInfo =
  614. DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortF,
  615. &parentIdx, &childIdx, bus1394PortInfo);
  616. bus1394PortInfo =
  617. DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortG,
  618. &parentIdx, &childIdx, bus1394PortInfo);
  619. bus1394PortInfo =
  620. DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortH,
  621. &parentIdx, &childIdx, bus1394PortInfo);
  622. } while (selfIdMore.SID_More_Packets);
  623. }
  624. // now update the bay/port map
  625. for (i=0; i< DbcContext->NumberOf1394Ports; i++)
  626. {
  627. USHORT bay;
  628. // find the bay for this port
  629. // note: phy port index start at 1
  630. for (bay=1; bay <=NUMBER_OF_BAYS(DbcContext); bay++)
  631. {
  632. if (DbcContext->BayInformation[bay].BayDescriptor.bPHYPortNumber
  633. == i+1)
  634. {
  635. DbcContext->Bus1394PortInfo[i].BayNumber = bay;
  636. break;
  637. }
  638. }
  639. }
  640. #if DBG
  641. for (i=0; i<DbcContext->NumberOf1394Ports; i++)
  642. {
  643. DBCLASS_KdPrint((2, "'Port [%d] = nodeId (%08X) bay (%08X) flg = (%08X)\n",
  644. i+1,
  645. DbcContext->Bus1394PortInfo[i].NodeId,
  646. DbcContext->Bus1394PortInfo[i].BayNumber,
  647. DbcContext->Bus1394PortInfo[i].Flags));
  648. }
  649. for (i=1; i<= NUMBER_OF_BAYS(DbcContext); i++)
  650. {
  651. DBCLASS_KdPrint((2, "'Port [%d] = bay (%08X)\n",
  652. DbcContext->BayInformation[i].BayDescriptor.bPHYPortNumber,
  653. DbcContext->BayInformation[i].BayDescriptor.bBayNumber
  654. ));
  655. }
  656. #endif
  657. }
  658. else
  659. {
  660. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  661. DBCLASS_KdPrint((0, "No memory for Port Info'\n"));
  662. TRAP();
  663. }
  664. }
  665. if (topologyMap)
  666. {
  667. DbcExFreePool(topologyMap);
  668. }
  669. BayPort_End:
  670. return ntStatus;
  671. }
  672. USHORT
  673. DBCLASS_GetBayFor1394Pdo(
  674. PDEVICE_OBJECT BusFilterMdo,
  675. PDBC_CONTEXT DbcContext,
  676. PDEVICE_OBJECT Pdo1394
  677. )
  678. /*++
  679. Routine Description:
  680. given a 1394 PDO figure out wich bay it is associated with
  681. Arguments:
  682. Return Value:
  683. zero if not a device bay PDO.
  684. --*/
  685. {
  686. PNODE_DEVICE_EXTENSION nodeExtension;
  687. USHORT nodeId;
  688. ULONG i;
  689. NTSTATUS ntStatus;
  690. PBUS1394_PORT_INFO bus1394PortInfo;
  691. PAGED_CODE();
  692. ntStatus = DBCLASS_Get1394BayPortMapping(BusFilterMdo,
  693. DbcContext);
  694. if (NT_SUCCESS(ntStatus))
  695. {
  696. nodeExtension = Pdo1394->DeviceExtension;
  697. // check the node id against the bay port mapping
  698. nodeId = nodeExtension->NodeAddress.NA_Node_Number;
  699. DBCLASS_KdPrint((1, "'>1394 PDO (%08X) has NodeID = (%08X)\n",
  700. Pdo1394, nodeId));
  701. bus1394PortInfo = DbcContext->Bus1394PortInfo;
  702. for (i=0; i< DbcContext->NumberOf1394Ports; i++)
  703. {
  704. if (bus1394PortInfo->NodeId == nodeId)
  705. {
  706. DBCLASS_KdPrint((1, "'>1394 PDO is in bay = %d\n",
  707. bus1394PortInfo->BayNumber));
  708. return bus1394PortInfo->BayNumber;
  709. }
  710. bus1394PortInfo++;
  711. }
  712. }
  713. #if DBG
  714. else
  715. {
  716. DBCLASS_KdPrint((1, "'failed to get 1394 bay->port mapping!\n"));
  717. }
  718. #endif
  719. return 0;
  720. }
  721. NTSTATUS
  722. DBCLASS_DeferIrpCompletion(
  723. IN PDEVICE_OBJECT DeviceObject,
  724. IN PIRP Irp,
  725. IN PVOID Context
  726. )
  727. /*++
  728. Routine Description:
  729. This routine is called when the port driver completes an IRP.
  730. Arguments:
  731. DeviceObject - Pointer to the device object for the class device.
  732. Irp - Irp completed.
  733. Context - Driver defined context.
  734. Return Value:
  735. The function value is the final status from the operation.
  736. --*/
  737. {
  738. PKEVENT event = Context;
  739. KeSetEvent(event,
  740. 1,
  741. FALSE);
  742. DBCLASS_KdPrint((2, "'defer irp %x\n", Irp));
  743. return STATUS_MORE_PROCESSING_REQUIRED;
  744. }
  745. NTSTATUS
  746. DBCLASS_CreateDeviceFilterObject(
  747. IN PDRIVER_OBJECT DriverObject,
  748. IN OUT PDEVICE_OBJECT *DeviceObject,
  749. IN PDEVICE_OBJECT DevicePdo,
  750. IN PDBC_CONTEXT DbcContext,
  751. IN ULONG BusTypeSig
  752. )
  753. /*++
  754. Routine Description:
  755. This routine is called to create a new instance of the DBC
  756. bus filter.
  757. Arguments:
  758. DriverObject - pointer to the driver object for USBD.
  759. *DeviceObject - ptr to DeviceObject ptr to be filled
  760. in with the device object we create.
  761. Return Value:
  762. NT status code
  763. --*/
  764. {
  765. NTSTATUS ntStatus;
  766. PAGED_CODE();
  767. ntStatus = IoCreateDevice(DriverObject,
  768. sizeof (DEVICE_EXTENSION),
  769. NULL,
  770. FILE_DEVICE_CONTROLLER,
  771. 0,
  772. FALSE, //NOT Exclusive
  773. DeviceObject);
  774. if (!NT_SUCCESS(ntStatus) && *DeviceObject)
  775. {
  776. IoDeleteDevice(*DeviceObject);
  777. }
  778. if (NT_SUCCESS(ntStatus))
  779. {
  780. PDEVICE_OBJECT deviceObject = *DeviceObject, stackTopDO;
  781. PDEVICE_EXTENSION deviceExtension;
  782. // initialize the FDO
  783. // and attach it to the PDO
  784. //
  785. // clone some charateristics of the PDO.
  786. //
  787. deviceExtension = deviceObject->DeviceExtension;
  788. deviceExtension->PhysicalDeviceObject = DevicePdo;
  789. stackTopDO =
  790. deviceExtension->TopOfStackDeviceObject =
  791. IoAttachDeviceToDeviceStack(deviceObject, DevicePdo);
  792. //
  793. // Preserve flags in lower device object
  794. //
  795. deviceObject->Flags |= (DevicePdo->Flags &
  796. (DO_POWER_INRUSH | DO_POWER_PAGABLE));
  797. deviceObject->Flags |= (DevicePdo->Flags &
  798. (DO_BUFFERED_IO | DO_DIRECT_IO));
  799. deviceExtension->DbcContext = DbcContext;
  800. deviceExtension->FdoType = BusTypeSig;
  801. // object is ready
  802. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  803. }
  804. return ntStatus;
  805. }
  806. NTSTATUS
  807. DBCLASS_1394QBusRelationsComplete(
  808. IN PDEVICE_OBJECT DeviceObject,
  809. IN PIRP Irp,
  810. IN PVOID Context
  811. )
  812. /*++
  813. Routine Description:
  814. Arguments:
  815. DeviceObject - a pointer to the device object
  816. Irp - a pointer to the irp
  817. Context - NULL ptr
  818. Return Value:
  819. STATUS_SUCCESS
  820. --*/
  821. {
  822. PDEVICE_RELATIONS deviceRelations;
  823. ULONG i;
  824. PDEVICE_OBJECT busFilterMdo = Context;
  825. PDEVICE_EXTENSION deviceExtension;
  826. PDEVICE_OBJECT mdo1394;
  827. deviceExtension = busFilterMdo->DeviceExtension;
  828. deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
  829. LOGENTRY(LOG_MISC, '3QBR', busFilterMdo, 0, deviceRelations);
  830. if ((!NT_SUCCESS(Irp->IoStatus.Status)) || deviceRelations == NULL)
  831. {
  832. LOGENTRY(LOG_MISC, '3QBn', busFilterMdo, 0, deviceRelations);
  833. DBCLASS_KdPrint((0, "'>QBR 1394 Failed\n"));
  834. deviceExtension->QBusRelations1394Success = FALSE;
  835. goto DBCLASS_1394QBR_Done;
  836. }
  837. else
  838. {
  839. DBCLASS_KdPrint((0, "'>QBR 1394 Passed\n"));
  840. deviceExtension->QBusRelations1394Success = TRUE;
  841. }
  842. for (i=0; i< deviceRelations->Count; i++)
  843. {
  844. DBCLASS_KdPrint((1, "'>QBR 1394 PDO[%d] %x \n", i,
  845. deviceRelations->Objects[i]));
  846. LOGENTRY(LOG_MISC, 'QBRd', deviceRelations->Objects[i], i, 0);
  847. // 1394 is returning a PDO, see if we know
  848. // about it
  849. // if this is the PHY/LINK for a DBC link it to the
  850. // DBC context
  851. DBCLASS_CheckPhyLink(deviceRelations->Objects[i]);
  852. mdo1394 = DBCLASS_FindDevicePdo(deviceRelations->Objects[i]);
  853. if (mdo1394)
  854. {
  855. // we know about this one,
  856. PDEVICE_EXTENSION mdo1394DeviceExtension;
  857. PDBC_CONTEXT dbcContext;
  858. mdo1394DeviceExtension = mdo1394->DeviceExtension;
  859. dbcContext = mdo1394DeviceExtension->DbcContext;
  860. }
  861. else
  862. {
  863. PDEVICE_OBJECT deviceFilterObject;
  864. NTSTATUS ntStatus;
  865. PDBC_CONTEXT dbcContext;
  866. PDEVICE_OBJECT devObj;
  867. PNODE_DEVICE_EXTENSION nodeExtension;
  868. devObj = deviceRelations->Objects[i];
  869. nodeExtension = devObj->DeviceExtension;
  870. // if this is a "virtual" device, just skip it
  871. if(nodeExtension->Tag == VIRTUAL_DEVICE_EXTENSION_TAG)
  872. {
  873. DBCLASS_KdPrint((1, "'****> Virtual 1394 Device\n"));
  874. continue;
  875. }
  876. // don't know about it,
  877. // create an MDO for this device
  878. dbcContext = NULL;
  879. ntStatus = DBCLASS_CreateDeviceFilterObject(
  880. deviceExtension->DriverObject,
  881. &deviceFilterObject,
  882. devObj,
  883. dbcContext,
  884. DB_FDO_1394_DEVICE);
  885. if (NT_SUCCESS(ntStatus))
  886. {
  887. DBCLASS_AddDevicePDOToList(deviceFilterObject,
  888. deviceRelations->Objects[i]);
  889. }
  890. DBCLASS_KdPrint((1,
  891. "'(dbfilter)(bus)(1394) Create DO %x for 1394 PDO\n",
  892. deviceFilterObject));
  893. }
  894. }
  895. DBCLASS_1394QBR_Done:
  896. KeSetEvent(&deviceExtension->QBusRelations1394Event,
  897. 1,
  898. FALSE);
  899. return STATUS_MORE_PROCESSING_REQUIRED;
  900. }
  901. ULONG
  902. DBCLASS_CountConnectedPorts(
  903. PTOPOLOGY_MAP TopologyMap,
  904. ULONG Index,
  905. ULONG Connection
  906. )
  907. /*++
  908. Routine Description:
  909. Arguments:
  910. Return Value:
  911. NTSTATUS
  912. --*/
  913. {
  914. SELF_ID selfId;
  915. SELF_ID_MORE selfIdMore;
  916. ULONG count = 0;
  917. selfId = TopologyMap->TOP_Self_ID_Array[Index];
  918. DBCLASS_KdPrint((2, "'TOP_Self_ID = (%08X)\n",
  919. selfId));
  920. DBCLASS_KdPrint((2, "'SID_Phys_ID = (%08X)\n", (ULONG)
  921. selfId.SID_Phys_ID));
  922. DBCLASS_KdPrint((2, "'SID_Port1 = (%08X)\n", (ULONG)
  923. selfId.SID_Port1));
  924. DBCLASS_KdPrint((2, "'SID_Port2 = (%08X)\n", (ULONG)
  925. selfId.SID_Port2));
  926. DBCLASS_KdPrint((2, "'SID_Port3 = (%08X)\n", (ULONG)
  927. selfId.SID_Port3));
  928. DBCLASS_KdPrint((2, "'SID_More_Packets = (%08X)\n", (ULONG)
  929. selfId.SID_More_Packets));
  930. #define COUNT_PORT(s) if ((s) == Connection) { count++;}
  931. COUNT_PORT(selfId.SID_Port1);
  932. COUNT_PORT(selfId.SID_Port2);
  933. COUNT_PORT(selfId.SID_Port3);
  934. if (selfId.SID_More_Packets)
  935. {
  936. do
  937. {
  938. Index++;
  939. RtlCopyMemory(&selfIdMore,
  940. &TopologyMap->TOP_Self_ID_Array[Index],
  941. sizeof(ULONG));
  942. DBCLASS_KdPrint((2, "'SID_Phys_ID = (%08X)\n", (ULONG)
  943. selfIdMore.SID_Phys_ID));
  944. DBCLASS_KdPrint((2, "'SID_PortA = (%08X)\n", (ULONG)
  945. selfIdMore.SID_PortA));
  946. DBCLASS_KdPrint((2, "'SID_PortB = (%08X)\n", (ULONG)
  947. selfIdMore.SID_PortB));
  948. DBCLASS_KdPrint((2, "'SID_PortC = (%08X)\n", (ULONG)
  949. selfIdMore.SID_PortC));
  950. DBCLASS_KdPrint((2, "'SID_PortD = (%08X)\n", (ULONG)
  951. selfIdMore.SID_PortD));
  952. DBCLASS_KdPrint((2, "'SID_PortE = (%08X)\n", (ULONG)
  953. selfIdMore.SID_PortE));
  954. DBCLASS_KdPrint((2, "'SID_PortF = (%08X)\n", (ULONG)
  955. selfIdMore.SID_PortF));
  956. DBCLASS_KdPrint((2, "'SID_PortG = (%08X)\n", (ULONG)
  957. selfIdMore.SID_PortG));
  958. DBCLASS_KdPrint((2, "'SID_PortH = (%08X)\n", (ULONG)
  959. selfIdMore.SID_PortH));
  960. COUNT_PORT(selfIdMore.SID_PortA);
  961. COUNT_PORT(selfIdMore.SID_PortB);
  962. COUNT_PORT(selfIdMore.SID_PortC);
  963. COUNT_PORT(selfIdMore.SID_PortD);
  964. COUNT_PORT(selfIdMore.SID_PortE);
  965. COUNT_PORT(selfIdMore.SID_PortF);
  966. COUNT_PORT(selfIdMore.SID_PortG);
  967. COUNT_PORT(selfIdMore.SID_PortH);
  968. } while (selfIdMore.SID_More_Packets);
  969. }
  970. #undef COUNT_PORT
  971. return count;
  972. }
  973. BOOLEAN
  974. DBCLASS_IsParent(
  975. PTOPOLOGY_MAP TopologyMap,
  976. ULONG SelfIdIndex
  977. )
  978. /*++
  979. Routine Description:
  980. returns true if the node is 'connetected to parent' (2)
  981. Arguments:
  982. Return Value:
  983. NTSTATUS
  984. --*/
  985. {
  986. return TRUE;
  987. }
  988. BOOLEAN
  989. DBCLASS_IsChild(
  990. PTOPOLOGY_MAP TopologyMap,
  991. ULONG SelfIdIndex
  992. )
  993. /*++
  994. Routine Description:
  995. returns true if the node is 'connetected to child' (3)
  996. Arguments:
  997. Return Value:
  998. NTSTATUS
  999. --*/
  1000. {
  1001. ULONG i = SelfIdIndex;
  1002. BOOLEAN isChild = FALSE;
  1003. SELF_ID selfId;
  1004. SELF_ID_MORE selfIdMore;
  1005. selfId = TopologyMap->TOP_Self_ID_Array[i];
  1006. if (selfId.SID_Port1 == SELF_ID_CONNECTED_TO_CHILD)
  1007. {
  1008. isChild = TRUE;
  1009. }
  1010. if (selfId.SID_Port2 == SELF_ID_CONNECTED_TO_CHILD)
  1011. {
  1012. isChild = TRUE;
  1013. }
  1014. if (selfId.SID_Port3 == SELF_ID_CONNECTED_TO_CHILD)
  1015. {
  1016. isChild = TRUE;
  1017. }
  1018. if (selfId.SID_More_Packets)
  1019. {
  1020. do
  1021. {
  1022. i++;
  1023. RtlCopyMemory(&selfIdMore,
  1024. &TopologyMap->TOP_Self_ID_Array[i],
  1025. sizeof(ULONG));
  1026. if (selfIdMore.SID_PortA == SELF_ID_CONNECTED_TO_CHILD)
  1027. {
  1028. isChild = TRUE;
  1029. }
  1030. if (selfIdMore.SID_PortB == SELF_ID_CONNECTED_TO_CHILD)
  1031. {
  1032. isChild = TRUE;
  1033. }
  1034. if (selfIdMore.SID_PortC == SELF_ID_CONNECTED_TO_CHILD)
  1035. {
  1036. isChild = TRUE;
  1037. }
  1038. if (selfIdMore.SID_PortD == SELF_ID_CONNECTED_TO_CHILD)
  1039. {
  1040. isChild = TRUE;
  1041. }
  1042. if (selfIdMore.SID_PortE == SELF_ID_CONNECTED_TO_CHILD)
  1043. {
  1044. isChild = TRUE;
  1045. }
  1046. if (selfIdMore.SID_PortF == SELF_ID_CONNECTED_TO_CHILD)
  1047. {
  1048. isChild = TRUE;
  1049. }
  1050. if (selfIdMore.SID_PortG == SELF_ID_CONNECTED_TO_CHILD)
  1051. {
  1052. isChild = TRUE;
  1053. }
  1054. if (selfIdMore.SID_PortH == SELF_ID_CONNECTED_TO_CHILD)
  1055. {
  1056. isChild = TRUE;
  1057. }
  1058. } while (selfIdMore.SID_More_Packets);
  1059. }
  1060. DBCLASS_KdPrint((2, "'IsChild %d\n", isChild));
  1061. return isChild;
  1062. }
  1063. BOOLEAN
  1064. DBCLASS_IsNodeConnectedToLink(
  1065. PDBC_CONTEXT DbcContext,
  1066. PTOPOLOGY_MAP TopologyMap,
  1067. USHORT CurrentNodeId,
  1068. USHORT LinkNodeId
  1069. )
  1070. /*++
  1071. Routine Description:
  1072. Given the nodeId for a Device and the node Id for the link
  1073. figure out if the node is connected to the link
  1074. return true if it is
  1075. Arguments:
  1076. Return Value:
  1077. NTSTATUS
  1078. --*/
  1079. {
  1080. NTSTATUS ntStatus = STATUS_SUCCESS;
  1081. USHORT nodeCount, selfIdCount;
  1082. BOOLEAN connected = FALSE;
  1083. LONG device_Index = -1;
  1084. ULONG connectCount, i, childCount, parentCount;
  1085. DBCLASS_KdPrint((2, "'TopologyMap = (%08X)\n", TopologyMap));
  1086. DBCLASS_KdPrint((2, "'TOP_Length = (%08X)\n", TopologyMap->TOP_Length));
  1087. DBCLASS_KdPrint((2, "'TOP_CRC = (%08X)\n", TopologyMap->TOP_CRC));
  1088. DBCLASS_KdPrint((2, "'TOP_Generation = (%08X)\n", TopologyMap->TOP_Generation));
  1089. DBCLASS_KdPrint((2, "'TOP_Node_Count = (%08X)\n", TopologyMap->TOP_Node_Count));
  1090. DBCLASS_KdPrint((2, "'TOP_Self_ID_Count = (%08X)\n", TopologyMap->TOP_Self_ID_Count));
  1091. nodeCount = TopologyMap->TOP_Node_Count;
  1092. selfIdCount = TopologyMap->TOP_Self_ID_Count;
  1093. DBCLASS_KdPrint((2, "'nodeCount = (%08X) selfIdCount = (%08X)\n",
  1094. nodeCount, selfIdCount));
  1095. //
  1096. // walk the topology map and find the index of the node for the
  1097. // device
  1098. //
  1099. DBCLASS_KdPrint((2, "'Find Node Index\n"));
  1100. for (i=0; i< nodeCount; i++)
  1101. {
  1102. SELF_ID selfId;
  1103. SELF_ID_MORE selfIdMore;
  1104. selfId = TopologyMap->TOP_Self_ID_Array[i];
  1105. DBCLASS_KdPrint((2, "'[%d] SID_Phys_ID = (%08X)\n", i, (ULONG)
  1106. selfId.SID_Phys_ID));
  1107. if (selfId.SID_Phys_ID == CurrentNodeId)
  1108. {
  1109. // this is the host, count the ports
  1110. device_Index = i;
  1111. }
  1112. if (selfId.SID_More_Packets)
  1113. {
  1114. do
  1115. {
  1116. i++;
  1117. RtlCopyMemory(&selfIdMore,
  1118. &TopologyMap->TOP_Self_ID_Array[i],
  1119. sizeof(ULONG));
  1120. DBCLASS_KdPrint((2, "'[%d].more SID_Phys_ID = (%08X)\n", i, (ULONG)
  1121. selfIdMore.SID_Phys_ID));
  1122. } while (selfIdMore.SID_More_Packets);
  1123. }
  1124. } /* for */
  1125. // did we find the device?
  1126. if (device_Index != -1)
  1127. {
  1128. // yes
  1129. DBCLASS_KdPrint((2, "'-->device_Index found = (%08X)\n",
  1130. device_Index));
  1131. // OK if this is a device bay device then it can
  1132. // have only one connected port
  1133. childCount = DBCLASS_CountConnectedPorts(
  1134. TopologyMap,
  1135. device_Index,
  1136. SELF_ID_CONNECTED_TO_CHILD);
  1137. parentCount = DBCLASS_CountConnectedPorts(
  1138. TopologyMap,
  1139. device_Index,
  1140. SELF_ID_CONNECTED_TO_PARENT);
  1141. connectCount = childCount + parentCount;
  1142. DBCLASS_KdPrint((2, "'parent = %d child %d\n",
  1143. parentCount, childCount));
  1144. DBCLASS_KdPrint((2, "'connectCount = %d \n",
  1145. connectCount));
  1146. if (parentCount == 1)
  1147. {
  1148. // OK possible device bay device
  1149. SELF_ID selfId;
  1150. SELF_ID_MORE selfIdMore;
  1151. i = device_Index;
  1152. // port is 'connected to parent' see if it is
  1153. // the link
  1154. // if it is not the link then this cannot be a DB
  1155. // device
  1156. i++;
  1157. if (i == selfIdCount)
  1158. {
  1159. DBCLASS_KdPrint((2, "'NXT ENTRY wraps\n"));
  1160. i=0;
  1161. }
  1162. while (!DBCLASS_IsChild(TopologyMap, i))
  1163. {
  1164. // advance to the next selfId until we find one
  1165. // that is connected to child(3)
  1166. selfId = TopologyMap->TOP_Self_ID_Array[i];
  1167. // skip 'more packets'
  1168. if (selfId.SID_More_Packets)
  1169. {
  1170. do
  1171. {
  1172. i++;
  1173. RtlCopyMemory(&selfIdMore,
  1174. &TopologyMap->TOP_Self_ID_Array[i],
  1175. sizeof(ULONG));
  1176. DBCLASS_KdPrint((2, "'SID_Phys_ID = (%08X)\n", (ULONG)
  1177. selfIdMore.SID_Phys_ID));
  1178. } while (selfIdMore.SID_More_Packets);
  1179. }
  1180. i++;
  1181. if (i == selfIdCount)
  1182. {
  1183. DBCLASS_KdPrint((2, "'NXT ENTRY wraps\n"));
  1184. i=0;
  1185. }
  1186. }
  1187. // now check the next entry
  1188. selfId = TopologyMap->TOP_Self_ID_Array[i];
  1189. DBCLASS_KdPrint((2, "'NXT ENTRY - SID_Phys_ID = (%08X)\n", (ULONG)
  1190. selfId.SID_Phys_ID));
  1191. if (selfId.SID_Phys_ID == LinkNodeId)
  1192. {
  1193. connected = TRUE;
  1194. }
  1195. }
  1196. else if (childCount == 1)
  1197. {
  1198. // possible DB device
  1199. SELF_ID selfId;
  1200. ULONG physIdPrev, top;
  1201. i = device_Index;
  1202. do
  1203. {
  1204. if (i==0)
  1205. {
  1206. i = nodeCount-1;
  1207. }
  1208. else
  1209. {
  1210. i--;
  1211. }
  1212. selfId = TopologyMap->TOP_Self_ID_Array[i];
  1213. physIdPrev = selfId.SID_Phys_ID;
  1214. do
  1215. {
  1216. top = i;
  1217. if (i==0)
  1218. {
  1219. i = nodeCount-1;
  1220. }
  1221. else
  1222. {
  1223. i--;
  1224. }
  1225. selfId = TopologyMap->TOP_Self_ID_Array[i];
  1226. } while (physIdPrev == selfId.SID_Phys_ID);
  1227. i = top;
  1228. DBCLASS_KdPrint((2, "'PREV - idx = %d\n", i));
  1229. // stop when we find a parent
  1230. } while (!DBCLASS_IsParent(TopologyMap, i)); // entry !=2
  1231. // port is 'connected to parent' see if it is
  1232. // the link
  1233. // advance to the next selfId
  1234. selfId = TopologyMap->TOP_Self_ID_Array[i];
  1235. // note that PhysID is the same even if this is a 'more packets'
  1236. // SID
  1237. DBCLASS_KdPrint((2, "'NXT ENTRY - SID_Phys_ID = (%08X)\n", (ULONG)
  1238. selfId.SID_Phys_ID));
  1239. if (selfId.SID_Phys_ID == LinkNodeId)
  1240. {
  1241. connected = TRUE;
  1242. }
  1243. }
  1244. }
  1245. DBCLASS_KdPrint((2, "'>CurrentNodeId %d, LinkNodeId = %d CONNECTED(%d)\n",
  1246. CurrentNodeId, LinkNodeId, connected));
  1247. BRK_ON_TRAP();
  1248. return connected;
  1249. }
  1250. NTSTATUS
  1251. DBCLASS_Check1394DevicePDO(
  1252. PDEVICE_OBJECT FilterDeviceObject,
  1253. PDBC_CONTEXT DbcContext,
  1254. PDEVICE_OBJECT DevicePDO
  1255. )
  1256. /*++
  1257. Routine Description:
  1258. Arguments:
  1259. Return Value:
  1260. NTSTATUS
  1261. --*/
  1262. {
  1263. NTSTATUS ntStatus;
  1264. PTOPOLOGY_MAP topologyMap = NULL;
  1265. PNODE_DEVICE_EXTENSION nodeExtension;
  1266. PDEVICE_EXTENSION deviceExtension;
  1267. USHORT nodeId, linkNodeId;
  1268. IRB irb;
  1269. // get the node id for the device
  1270. deviceExtension = FilterDeviceObject->DeviceExtension;
  1271. nodeExtension = DevicePDO->DeviceExtension;
  1272. nodeId = nodeExtension->NodeAddress.NA_Node_Number;
  1273. DBCLASS_KdPrint((2, "'1394 PDO (%08X) has NodeID = (%08X)\n",
  1274. DevicePDO, nodeId));
  1275. // get the topology map from the local host
  1276. ntStatus = DBCLASS_GetSpeedAndTopologyMaps(&topologyMap,
  1277. FilterDeviceObject);
  1278. if (DbcContext->ControllerSig == DBC_ACPI_CONTROLLER_SIG && topologyMap)
  1279. {
  1280. // ACPI dbc
  1281. // PDO must be a child or parent of the controller
  1282. irb.u.Get1394AddressFromDeviceObject.fulFlags = 0;
  1283. irb.FunctionNumber = REQUEST_GET_ADDR_FROM_DEVICE_OBJECT;
  1284. ntStatus = DBCLASS_SyncSubmitIrb(deviceExtension->TopOfStackDeviceObject,
  1285. &irb);
  1286. DBCLASS_KdPrint((2, "'GetLocalNodeId() = (%08X)\n", ntStatus));
  1287. linkNodeId =
  1288. irb.u.Get1394AddressFromDeviceObject.NodeAddress.NA_Node_Number;
  1289. if (DBCLASS_IsNodeConnectedToLink(DbcContext,
  1290. topologyMap,
  1291. nodeId,
  1292. linkNodeId))
  1293. {
  1294. ntStatus = STATUS_SUCCESS;
  1295. }
  1296. else
  1297. {
  1298. ntStatus = STATUS_DEVICE_NOT_CONNECTED;
  1299. }
  1300. }
  1301. else
  1302. {
  1303. // USB dbc
  1304. PNODE_DEVICE_EXTENSION linkExtension;
  1305. // USB dbc
  1306. // PDO must be a child or parent of the link
  1307. DBCLASS_ASSERT(DbcContext->LinkDeviceObject);
  1308. linkExtension = DbcContext->LinkDeviceObject->DeviceExtension;
  1309. linkNodeId = linkExtension->NodeAddress.NA_Node_Number;
  1310. DBCLASS_ASSERT(RtlCompareMemory(&DbcContext->SubsystemDescriptor.guid1394Link[0],
  1311. &linkExtension->ConfigRom->CR_Node_UniqueID[0],
  1312. 8) == 8);
  1313. if(topologyMap)
  1314. {
  1315. if (DBCLASS_IsNodeConnectedToLink(DbcContext,
  1316. topologyMap,
  1317. nodeId,
  1318. linkNodeId))
  1319. {
  1320. ntStatus = STATUS_SUCCESS;
  1321. }
  1322. else
  1323. {
  1324. ntStatus = STATUS_DEVICE_NOT_CONNECTED;
  1325. }
  1326. }
  1327. }
  1328. return ntStatus;
  1329. }
  1330. NTSTATUS
  1331. DBCLASS_1394GetBusGuid(
  1332. PDEVICE_OBJECT DeviceObject,
  1333. PUCHAR BusGuid
  1334. )
  1335. /*++
  1336. Routine Description:
  1337. Arguments:
  1338. Return Value:
  1339. NTSTATUS
  1340. --*/
  1341. {
  1342. NTSTATUS ntStatus;
  1343. BOOLEAN waitForIt = FALSE;
  1344. IRB irb;
  1345. irb.u.GetLocalHostInformation.nLevel = GET_HOST_UNIQUE_ID;
  1346. irb.FunctionNumber = REQUEST_GET_LOCAL_HOST_INFO;
  1347. irb.u.GetLocalHostInformation.Information = BusGuid;
  1348. ntStatus = DBCLASS_SyncSubmitIrb(DeviceObject,
  1349. &irb);
  1350. DBCLASS_KdPrint((2, "'GetBusGuid() = (%08X)\n", ntStatus));
  1351. #if DBG
  1352. DBCLASS_KdPrint((1, "'>Local Host GUID\n"));
  1353. DBCLASS_KdPrintGuid(1, BusGuid);
  1354. #endif
  1355. return ntStatus;
  1356. }
  1357. NTSTATUS
  1358. DBCLASS_1394BusFilterDispatch(
  1359. PDEVICE_OBJECT DeviceObject,
  1360. PIRP Irp,
  1361. PBOOLEAN Handled
  1362. )
  1363. /*++
  1364. Routine Description:
  1365. Arguments:
  1366. Return Value:
  1367. NTSTATUS
  1368. --*/
  1369. {
  1370. PIO_STACK_LOCATION irpStack;
  1371. NTSTATUS ntStatus;
  1372. PDEVICE_EXTENSION deviceExtension;
  1373. BOOLEAN waitForIt = FALSE;
  1374. UCHAR busGuid1394[8];
  1375. deviceExtension = DeviceObject->DeviceExtension;
  1376. ntStatus = Irp->IoStatus.Status;
  1377. *Handled = FALSE;
  1378. LOGENTRY(LOG_MISC, '13b>', 0, DeviceObject, Irp);
  1379. ntStatus = Irp->IoStatus.Status;
  1380. irpStack = IoGetCurrentIrpStackLocation (Irp);
  1381. DBCLASS_KdPrint((1, "'(dbfilter)(bus)(1394)IRP_MJ_ (%08X) IRP_MN_ (%08X)\n",
  1382. irpStack->MajorFunction, irpStack->MinorFunction));
  1383. switch (irpStack->MajorFunction)
  1384. {
  1385. case IRP_MJ_PNP:
  1386. switch (irpStack->MinorFunction)
  1387. {
  1388. case IRP_MN_START_DEVICE:
  1389. DBCLASS_KdPrint((1, "'(dbfilter)(bus)(1394)IRP_MN_START_DEVICE\n"));
  1390. break;
  1391. case IRP_MN_STOP_DEVICE:
  1392. DBCLASS_KdPrint((1, "'(dbfilter)(bus)(1394)IRP_MN_STOP_DEVICE\n"));
  1393. break;
  1394. case IRP_MN_REMOVE_DEVICE:
  1395. DBCLASS_KdPrint((1, "'(dbfilter)(bus)(1394)IRP_MN_REMOVE_DEVICE\n"));
  1396. DBCLASS_RemoveBusFilterMDOFromList(DeviceObject);
  1397. IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
  1398. IoDeleteDevice (DeviceObject);
  1399. DBCLASS_KdPrint((1, "'REMOVE DB Filter on 1394 BUS\n"));
  1400. break;
  1401. case IRP_MN_QUERY_DEVICE_RELATIONS:
  1402. DBCLASS_KdPrint((1, "'(dbfilter)(bus)(1394)IRP_MN_QUERY_DEVICE_RELATIONS\n"));
  1403. *Handled = TRUE;
  1404. if (irpStack->Parameters.QueryDeviceRelations.Type == BusRelations)
  1405. {
  1406. DBCLASS_KdPrint((1,"'>>QBR 1394 BUS\n"));
  1407. IoCopyCurrentIrpStackLocationToNext(Irp);
  1408. KeInitializeEvent(&deviceExtension->QBusRelations1394Event,
  1409. NotificationEvent,
  1410. FALSE);
  1411. // Set up a completion routine to handle marking the IRP.
  1412. IoSetCompletionRoutine(Irp,
  1413. DBCLASS_1394QBusRelationsComplete,
  1414. DeviceObject,
  1415. TRUE,
  1416. TRUE,
  1417. TRUE);
  1418. waitForIt = TRUE;
  1419. }
  1420. else
  1421. {
  1422. IoSkipCurrentIrpStackLocation(Irp);
  1423. }
  1424. // Now Pass down the IRP
  1425. deviceExtension->QBusRelations1394Success = FALSE;
  1426. ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  1427. if (waitForIt)
  1428. {
  1429. NTSTATUS status;
  1430. status = KeWaitForSingleObject(&deviceExtension->QBusRelations1394Event,
  1431. Suspended,
  1432. KernelMode,
  1433. FALSE,
  1434. NULL);
  1435. // let's see if the call down the stack failed
  1436. if(!deviceExtension->QBusRelations1394Success)
  1437. {
  1438. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1439. break;
  1440. }
  1441. DBCLASS_KdPrint((1, "'**** Searching for Device Bay PDOs \n"));
  1442. //
  1443. // get the bus guid
  1444. //
  1445. if (NT_SUCCESS(DBCLASS_1394GetBusGuid(
  1446. deviceExtension->TopOfStackDeviceObject,
  1447. &busGuid1394[0])))
  1448. {
  1449. PDEVICE_RELATIONS deviceRelations;
  1450. ULONG i;
  1451. deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
  1452. // loop thru DOs finding a DBC links
  1453. for (i=0; i< deviceRelations->Count; i++)
  1454. {
  1455. PDEVICE_EXTENSION mdo1394DeviceExtension;
  1456. PDEVICE_OBJECT mdo1394;
  1457. // should always be found
  1458. mdo1394 = DBCLASS_FindDevicePdo(deviceRelations->Objects[i]);
  1459. if(!mdo1394)
  1460. continue;
  1461. mdo1394DeviceExtension = mdo1394->DeviceExtension;
  1462. DBCLASS_Find1394DbcLinks(
  1463. mdo1394DeviceExtension->PhysicalDeviceObject);
  1464. }
  1465. // loop through PDO list
  1466. // and try to find the controllers
  1467. DBCLASS_KdPrint((1, "'**>> DevRel Count (%08X)\n", deviceRelations->Count));
  1468. for (i=0; i< deviceRelations->Count; i++)
  1469. {
  1470. PDEVICE_EXTENSION mdo1394DeviceExtension;
  1471. PDEVICE_OBJECT mdo1394;
  1472. PDEVICE_OBJECT DevicePDO;
  1473. PNODE_DEVICE_EXTENSION nodeExtension;
  1474. LOGENTRY(LOG_MISC, 'FCQB', deviceRelations->Objects[i], i, 0);
  1475. // should always be found
  1476. mdo1394 = DBCLASS_FindDevicePdo(deviceRelations->Objects[i]);
  1477. if(!mdo1394)
  1478. continue;
  1479. mdo1394DeviceExtension = mdo1394->DeviceExtension;
  1480. DevicePDO = mdo1394DeviceExtension->PhysicalDeviceObject;
  1481. nodeExtension = DevicePDO->DeviceExtension;
  1482. DBCLASS_KdPrint((1, "'****>> MDO (%08X) DbcContext (%08X) DrvObj (%08X) DevObj (%08X) PhysDevObj (%08X)\n",
  1483. mdo1394, mdo1394DeviceExtension->DbcContext,
  1484. deviceExtension->DriverObject, DeviceObject, mdo1394DeviceExtension->PhysicalDeviceObject));
  1485. // if this is a "virtual" device, just skip it
  1486. if(nodeExtension->Tag == VIRTUAL_DEVICE_EXTENSION_TAG)
  1487. {
  1488. DBCLASS_KdPrint((1, "'****> Virtual 1394 Device\n"));
  1489. continue;
  1490. }
  1491. DBCLASS_KdPrint((1, "'****>> NodeNumber (%08X) BusNumber (%08X) DevObj (%08X) PortDevObj (%08X)\n",
  1492. nodeExtension->NodeAddress.NA_Node_Number,
  1493. nodeExtension->NodeAddress.NA_Bus_Number,
  1494. nodeExtension->DeviceObject,
  1495. nodeExtension->PortDeviceObject));
  1496. if (mdo1394DeviceExtension->DbcContext == NULL)
  1497. {
  1498. mdo1394DeviceExtension->DbcContext =
  1499. DBCLASS_FindController1394DevicePdo(
  1500. deviceExtension->DriverObject,
  1501. DeviceObject,
  1502. mdo1394DeviceExtension->PhysicalDeviceObject,
  1503. &busGuid1394[0]);
  1504. }
  1505. // this PDO is associated with a controller
  1506. // see if is really a device bay device
  1507. DBCLASS_KdPrint((1, "'****> Check 1394 Device\n"));
  1508. if (mdo1394DeviceExtension->DbcContext)
  1509. {
  1510. PDBC_CONTEXT dbcContext;
  1511. USHORT bay = 0;
  1512. DBCLASS_KdPrint((1, "'****>> DBC detected on bus\n"));
  1513. DBCLASS_KdPrint((2, "'DbcContext (%08X) PhyDevObj (%08X)\n", mdo1394DeviceExtension->DbcContext,
  1514. mdo1394DeviceExtension->PhysicalDeviceObject));
  1515. dbcContext = mdo1394DeviceExtension->DbcContext;
  1516. bay = DBCLASS_GetBayFor1394Pdo(
  1517. DeviceObject,
  1518. mdo1394DeviceExtension->DbcContext,
  1519. mdo1394DeviceExtension->PhysicalDeviceObject);
  1520. if (bay)
  1521. {
  1522. // This is device bay device
  1523. dbcContext->BayInformation[bay].DeviceFilterObject =
  1524. mdo1394;
  1525. mdo1394DeviceExtension->Bay = bay;
  1526. DBCLASS_KdPrint((1,
  1527. "'****>>> 1394 PDO(%x) is in BAY[%d]\n",
  1528. mdo1394DeviceExtension->PhysicalDeviceObject,
  1529. bay));
  1530. // Notify PNP that this Device object
  1531. // is tied to the controller PDO
  1532. //TEST_TRAP();
  1533. IoInvalidateDeviceRelations(dbcContext->ControllerPdo,
  1534. RemovalRelations);
  1535. }
  1536. else
  1537. {
  1538. // not a device bay device
  1539. mdo1394DeviceExtension->Bay = 0;
  1540. DBCLASS_KdPrint((1,
  1541. "'****>>> 1394 PDO(%x) is not a DB device\n",
  1542. mdo1394DeviceExtension->PhysicalDeviceObject));
  1543. }
  1544. }
  1545. else
  1546. {
  1547. // no DBC phy link on this bus therefore this is
  1548. // not a device bay device
  1549. DBCLASS_KdPrint(
  1550. (1, "'****>> No DBC detected on bus\n"));
  1551. mdo1394DeviceExtension->Bay = 0;
  1552. DBCLASS_KdPrint((1,
  1553. "'****>>> 1394 PDO(%x) is not a DB device\n",
  1554. mdo1394DeviceExtension->PhysicalDeviceObject));
  1555. }
  1556. #if DBG
  1557. // dump the guid for this PDO
  1558. {
  1559. PNODE_DEVICE_EXTENSION nodeExtension;
  1560. nodeExtension =
  1561. mdo1394DeviceExtension->PhysicalDeviceObject->DeviceExtension;
  1562. DBCLASS_KdPrint((2, "'****>>>> 1394 PDO GUID\n"));
  1563. DBCLASS_KdPrintGuid(2, (PUCHAR)&nodeExtension->ConfigRom->CR_Node_UniqueID[0]);
  1564. }
  1565. #endif
  1566. DBCLASS_KdPrint((2, "'****>>>>> FC-QBR 1394 PDO[%d] %x DbcContext %x\n", i,
  1567. deviceRelations->Objects[i], mdo1394DeviceExtension->DbcContext));
  1568. }
  1569. }
  1570. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1571. }
  1572. break;
  1573. } /* irpStack->MinorFunction */
  1574. break;
  1575. } /* irpStack->MajorFunction */
  1576. LOGENTRY(LOG_MISC, '13b<', 0, DeviceObject, 0);
  1577. return ntStatus;
  1578. }