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.

1317 lines
46 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1992 - 1999
  3. Module Name:
  4. classkd.c
  5. Abstract:
  6. Debugger Extension Api for interpretting scsiport structures
  7. Author:
  8. Peter Wieland (peterwie) 16-Oct-1995
  9. johnstra
  10. ervinp
  11. Environment:
  12. User Mode.
  13. Revision History:
  14. --*/
  15. #include "pch.h"
  16. #include "classpnp.h" // #defines ALLOCATE_SRB_FROM_POOL as needed
  17. #include "classp.h" // Classpnp's private definitions
  18. #include "cdrom.h"
  19. #include "classkd.h" // routines that are useful for all class drivers
  20. typedef struct _REMOVE_TRACKING_BLOCK
  21. REMOVE_TRACKING_BLOCK,
  22. *PREMOVE_TRACKING_BLOCK;
  23. struct _REMOVE_TRACKING_BLOCK {
  24. PREMOVE_TRACKING_BLOCK NextBlock;
  25. PVOID Tag;
  26. LARGE_INTEGER TimeLocked;
  27. PCSTR File;
  28. ULONG Line;
  29. };
  30. FLAG_NAME FdoFlags[] = {
  31. FLAG_NAME(DEV_WRITE_CACHE), // 0x00000001
  32. FLAG_NAME(DEV_USE_SCSI1), // 0x00000002
  33. FLAG_NAME(DEV_SAFE_START_UNIT), // 0x00000004
  34. FLAG_NAME(DEV_NO_12BYTE_CDB), // 0x00000008
  35. {0,0}
  36. };
  37. DECLARE_API(classext)
  38. /*++
  39. Routine Description:
  40. Dumps the device extension for a given device object, or dumps the
  41. given device extension
  42. Arguments:
  43. args - string containing the address of the device object or device
  44. extension
  45. Return Value:
  46. none
  47. --*/
  48. {
  49. ULONG64 devObjAddr = 0;
  50. ULONG detail = 0;
  51. GetAddressAndDetailLevel64(args, &devObjAddr, &detail);
  52. /*
  53. * Read the device object and extension into the debugger's address space.
  54. */
  55. if (devObjAddr == 0){
  56. xdprintf(0, "\n usage: !classext <class fdo> <level [0-2]>\n\n");
  57. }
  58. else {
  59. CSHORT objType = GetUSHORTField(devObjAddr, "nt!_DEVICE_OBJECT", "Type");
  60. if (objType == IO_TYPE_DEVICE){
  61. ULONG64 devExtAddr;
  62. devExtAddr = GetULONGField(devObjAddr, "nt!_DEVICE_OBJECT", "DeviceExtension");
  63. if (devExtAddr != BAD_VALUE){
  64. ULONG64 commonExtAddr = devExtAddr;
  65. ULONG64 tmpDevObjAddr;
  66. BOOLEAN isFdo;
  67. /*
  68. * To sanity-check our device context, check that the 'DeviceObject' field matches our device object.
  69. */
  70. tmpDevObjAddr = GetULONGField(devExtAddr, "classpnp!_FUNCTIONAL_DEVICE_EXTENSION", "DeviceObject");
  71. isFdo = GetUCHARField(commonExtAddr, "classpnp!_COMMON_DEVICE_EXTENSION", "IsFdo");
  72. if ((tmpDevObjAddr == devObjAddr) && isFdo && (isFdo != BAD_VALUE)){
  73. ULONG64 fdoDataAddr;
  74. fdoDataAddr = GetULONGField(devExtAddr, "classpnp!_FUNCTIONAL_DEVICE_EXTENSION", "PrivateFdoData");
  75. if (fdoDataAddr != BAD_VALUE){
  76. ClassDumpFdoExtensionInternal(fdoDataAddr, detail, 0);
  77. ClassDumpFdoExtensionExternal(devExtAddr, detail, 0);
  78. // this hasn't worked in some time
  79. // ClassDumpCommonExtension(devObjAddr, detail, 0);
  80. }
  81. }
  82. else {
  83. dprintf("%08p is not a storage class FDO (for PDO information, use !classext on the parent FDO) \n", devObjAddr);
  84. dprintf(g_genericErrorHelpStr);
  85. }
  86. }
  87. }
  88. else {
  89. dprintf("Error: 0x%08p is not a device object\n", devObjAddr);
  90. dprintf(g_genericErrorHelpStr);
  91. }
  92. }
  93. return S_OK;
  94. }
  95. VOID
  96. ClassDumpCommonExtension(
  97. IN ULONG64 Address,
  98. IN ULONG Detail,
  99. IN ULONG Depth
  100. )
  101. {
  102. ULONG result;
  103. ULONG offset;
  104. ULONG tmp;
  105. BOOLEAN IsFdo;
  106. BOOLEAN IsInitialized;
  107. ULONG IsRemoved;
  108. ULONG64 DeviceObject;
  109. ULONG64 LowerDeviceObject;
  110. UCHAR CurrentState;
  111. UCHAR PreviousState;
  112. ULONG64 DriverData;
  113. ULONG PagingPathCount;
  114. ULONG DumpPathCount;
  115. ULONG HibernationPathCount;
  116. FIELD_INFO deviceFields[] = {
  117. {"IsFdo", NULL, 0, COPY, 0, (PVOID) &IsFdo},
  118. {"IsInitialized", NULL, 0, COPY, 0, (PVOID) &IsInitialized},
  119. {"IsRemoved", NULL, 0, COPY, 0, (PVOID) &IsRemoved},
  120. {"DeviceObject", NULL, 0, COPY, 0, (PVOID) &DeviceObject},
  121. {"LowerDeviceObject", NULL, 0, COPY, 0, (PVOID) &LowerDeviceObject},
  122. {"CurrentState", NULL, 0, COPY, 0, (PVOID) &CurrentState},
  123. {"PreviousState", NULL, 0, COPY, 0, (PVOID) &PreviousState},
  124. {"DriverData", NULL, 0, COPY, 0, (PVOID) &DriverData},
  125. {"PagingPathCount", NULL, 0, COPY, 0, (PVOID) &PagingPathCount},
  126. {"DumpPathCount", NULL, 0, COPY, 0, (PVOID) &DumpPathCount},
  127. {"HibernationPathCount", NULL, 0, COPY, 0, (PVOID) &HibernationPathCount},
  128. };
  129. SYM_DUMP_PARAM DevSym = {
  130. sizeof (SYM_DUMP_PARAM),
  131. "classpnp!_COMMON_DEVICE_EXTENSION",
  132. DBG_DUMP_NO_PRINT,
  133. Address,
  134. NULL, NULL, NULL,
  135. sizeof (deviceFields) / sizeof (FIELD_INFO),
  136. &deviceFields[0]
  137. };
  138. result = Ioctl(IG_DUMP_SYMBOL_INFO, &DevSym, DevSym.size);
  139. if (result) {
  140. SCSIKD_PRINT_ERROR(result);
  141. return;
  142. }
  143. xdprintfEx(Depth, ("Classpnp %s device extension at address %p\n",
  144. (!IsFdo ? "physical" : "functional"),
  145. Address));
  146. xdprintfEx(Depth, ("Common Extension:\n"));
  147. Depth += 1;
  148. tmp = Depth;
  149. if(IsInitialized) {
  150. xdprintfEx(tmp, ("Initialized " ));
  151. tmp = 0;
  152. }
  153. switch(IsRemoved) {
  154. case REMOVE_PENDING: {
  155. xdprintfEx(tmp, ("RemovePending"));
  156. tmp = 0;
  157. break;
  158. }
  159. case REMOVE_COMPLETE: {
  160. xdprintfEx(tmp, ("RemoveComplete"));
  161. tmp = 0;
  162. break;
  163. }
  164. }
  165. if(tmp == 0) {
  166. dprintf("\n");
  167. }
  168. tmp = 0;
  169. //
  170. // Calculate the runtime address of the first field to follow the common
  171. // device extension. To do this, we query the type info for the offset
  172. // of the last field, then increment it by the appropriate amount.
  173. //
  174. result = GetFieldOffset("classpnp!_COMMON_DEVICE_EXTENSION",
  175. "Reserved4",
  176. &offset);
  177. if (result) {
  178. SCSIKD_PRINT_ERROR(result);
  179. return;
  180. }
  181. offset += IsPtr64() ? sizeof(ULONG64) : sizeof(ULONG32);
  182. xdprintfEx(Depth, ("DO 0x%p LowerObject 0x%p Other Extension 0x%p\n",
  183. DeviceObject,
  184. LowerDeviceObject,
  185. Address + offset
  186. ));
  187. xdprintfEx(Depth, ("Current PnP state 0x%x Previous state 0x%x\n",
  188. CurrentState,
  189. PreviousState));
  190. xdprintfEx(Depth, ("DriverData 0x%p UsePathCounts (P%d, C%d, H%d)\n",
  191. DriverData,
  192. PagingPathCount,
  193. DumpPathCount,
  194. HibernationPathCount
  195. ));
  196. if(!IsFdo) {
  197. xdprintfEx(Depth - 1, ("PhysicalExtension:\n"));
  198. ClassDumpPdo(Address,
  199. Detail,
  200. Depth);
  201. } else {
  202. xdprintfEx(Depth - 1, ("FunctionalExtension:\n"));
  203. ClassDumpFdo(Address,
  204. Detail,
  205. Depth);
  206. }
  207. ClassDumpLocks(Address, Depth - 1);
  208. return;
  209. }
  210. VOID
  211. ClassDumpFdoExtensionExternal(
  212. IN ULONG64 FdoExtAddr,
  213. IN ULONG Detail,
  214. IN ULONG Depth
  215. )
  216. {
  217. ULONG64 commonExtAddr = FdoExtAddr;
  218. ULONG64 mediaChangeInfoAddr;
  219. ULONG64 childPdoExtAddr;
  220. ULONG isRemoved;
  221. UCHAR isInitialized;
  222. ULONG removeLock;
  223. UCHAR currentState, previousState;
  224. ULONG64 lowerDevObjAddr;
  225. xdprintf(Depth, "\n");
  226. xdprintf(Depth, "Classpnp _EXTERNAL_ data:\n\n");
  227. /*
  228. * Print the media change information (which only exists for removable media like cdrom)
  229. */
  230. mediaChangeInfoAddr = GetULONGField(FdoExtAddr, "classpnp!_FUNCTIONAL_DEVICE_EXTENSION", "MediaChangeDetectionInfo");
  231. if (mediaChangeInfoAddr != BAD_VALUE){
  232. if (mediaChangeInfoAddr){
  233. ULONG64 mediaChangeIrpAddr = GetULONGField(mediaChangeInfoAddr, "classpnp!_MEDIA_CHANGE_DETECTION_INFO", "MediaChangeIrp");
  234. UCHAR gesnSupported = GetUCHARField(mediaChangeInfoAddr, "classpnp!_MEDIA_CHANGE_DETECTION_INFO", "Gesn.Supported");
  235. xdprintf(Depth+1, ""), dprintf("MEDIA_CHANGE_DETECTION_INFO @ %08p:\n", mediaChangeInfoAddr);
  236. if (gesnSupported){
  237. xdprintf(Depth+2, "GESN is supported\n");
  238. }
  239. else {
  240. xdprintf(Depth+2, "GESN is NOT supported\n");
  241. }
  242. xdprintf(Depth+2, ""), dprintf("MediaChangeIrp = %08p\n", mediaChangeIrpAddr);
  243. xdprintf(Depth+2, ""), dprintf("(for more info, use 'dt classpnp!_MEDIA_CHANGE_DETECTION_INFO %08p')\n", mediaChangeInfoAddr);
  244. dprintf("\n");
  245. }
  246. else {
  247. xdprintf(Depth+1, "MediaChangeDetectionInfo is NULL\n");
  248. }
  249. }
  250. /*
  251. * Print the media type and geometry information
  252. */
  253. {
  254. ULONG64 geometryInfoAddr = GetFieldAddr(FdoExtAddr, "classpnp!_FUNCTIONAL_DEVICE_EXTENSION", "DiskGeometry");
  255. if (geometryInfoAddr != BAD_VALUE){
  256. ULONG64 numCylinders = GetULONGField(geometryInfoAddr, "classpnp!_DISK_GEOMETRY", "Cylinders");
  257. ULONG mediaType = (ULONG)GetULONGField(geometryInfoAddr, "classpnp!_DISK_GEOMETRY", "MediaType");
  258. ULONG64 tracksPerCylinder = GetULONGField(geometryInfoAddr, "classpnp!_DISK_GEOMETRY", "TracksPerCylinder");
  259. ULONG64 sectorsPerTrack = GetULONGField(geometryInfoAddr, "classpnp!_DISK_GEOMETRY", "SectorsPerTrack");
  260. ULONG64 bytesPerSector = GetULONGField(geometryInfoAddr, "classpnp!_DISK_GEOMETRY", "BytesPerSector");
  261. if ((numCylinders != BAD_VALUE) && (mediaType != BAD_VALUE) && (tracksPerCylinder != BAD_VALUE) && (sectorsPerTrack != BAD_VALUE) && (bytesPerSector != BAD_VALUE)){
  262. ULONG64 totalVolume = numCylinders*tracksPerCylinder*sectorsPerTrack*bytesPerSector;
  263. xdprintf(Depth+1, ""), dprintf("Media type: %s(%xh)\n", DbgGetMediaTypeStr(mediaType), mediaType);
  264. xdprintf(Depth+1, ""), dprintf("Geometry: %d(%xh)cyl x %d(%xh)tracks x %d(%xh)sectors x %d(%xh)bytes\n",
  265. (ULONG)numCylinders, (ULONG)numCylinders,
  266. (ULONG)tracksPerCylinder, (ULONG)tracksPerCylinder,
  267. (ULONG)sectorsPerTrack, (ULONG)sectorsPerTrack,
  268. (ULONG)bytesPerSector, (ULONG)bytesPerSector);
  269. xdprintf(Depth+1+4, ""), dprintf("= %x'%xh", (ULONG)(totalVolume>>32), (ULONG)totalVolume);
  270. if (totalVolume > (ULONG64)(1 << 30)){
  271. dprintf(" = ~%d GB\n", (ULONG)(totalVolume >> 30));
  272. }
  273. else {
  274. dprintf(" = ~%d MB\n", (ULONG)(totalVolume >> 20));
  275. }
  276. }
  277. }
  278. }
  279. /*
  280. * Print 'IsInitialized' state.
  281. */
  282. isInitialized = GetUCHARField(commonExtAddr, "classpnp!_COMMON_DEVICE_EXTENSION", "IsInitialized");
  283. xdprintf(Depth+1, "IsInitialized = %d\n", isInitialized);
  284. /*
  285. * Print the 'IsRemoved' state.
  286. */
  287. isRemoved = (ULONG)GetULONGField(commonExtAddr, "classpnp!_COMMON_DEVICE_EXTENSION", "IsRemoved");
  288. removeLock = (ULONG)GetULONGField(commonExtAddr, "classpnp!_COMMON_DEVICE_EXTENSION", "RemoveLock");
  289. xdprintf(Depth+1, "Remove lock count = %d\n", removeLock);
  290. switch (isRemoved){
  291. #undef MAKE_CASE
  292. #define MAKE_CASE(remCase) case remCase: xdprintf(Depth+1, "IsRemoved = " #remCase "(%d)\n", isRemoved); break;
  293. MAKE_CASE(NO_REMOVE)
  294. MAKE_CASE(REMOVE_PENDING)
  295. MAKE_CASE(REMOVE_COMPLETE)
  296. }
  297. /*
  298. * Print the PnP state.
  299. */
  300. currentState = GetUCHARField(commonExtAddr, "classpnp!_COMMON_DEVICE_EXTENSION", "CurrentState");
  301. previousState = GetUCHARField(commonExtAddr, "classpnp!_COMMON_DEVICE_EXTENSION", "PreviousState");
  302. xdprintf(Depth+1, "PnP state: CurrentState:");
  303. switch (currentState){
  304. #undef MAKE_CASE
  305. #define MAKE_CASE(pnpCase) case pnpCase: xdprintf(0, #pnpCase "(%xh)", pnpCase); break;
  306. MAKE_CASE(IRP_MN_START_DEVICE)
  307. MAKE_CASE(IRP_MN_STOP_DEVICE)
  308. MAKE_CASE(IRP_MN_REMOVE_DEVICE)
  309. MAKE_CASE(IRP_MN_QUERY_STOP_DEVICE)
  310. MAKE_CASE(IRP_MN_QUERY_REMOVE_DEVICE)
  311. MAKE_CASE(IRP_MN_CANCEL_STOP_DEVICE)
  312. MAKE_CASE(IRP_MN_CANCEL_REMOVE_DEVICE)
  313. default: xdprintf(0, "???(%xh)", currentState); break;
  314. }
  315. xdprintf(0, " PreviousState:");
  316. switch (previousState){
  317. #undef MAKE_CASE
  318. #define MAKE_CASE(pnpCase) case pnpCase: xdprintf(0, #pnpCase "(%xh)", pnpCase); break;
  319. MAKE_CASE(IRP_MN_START_DEVICE)
  320. MAKE_CASE(IRP_MN_STOP_DEVICE)
  321. MAKE_CASE(IRP_MN_REMOVE_DEVICE)
  322. MAKE_CASE(IRP_MN_QUERY_STOP_DEVICE)
  323. MAKE_CASE(IRP_MN_QUERY_REMOVE_DEVICE)
  324. MAKE_CASE(IRP_MN_CANCEL_STOP_DEVICE)
  325. MAKE_CASE(IRP_MN_CANCEL_REMOVE_DEVICE)
  326. case 0x0FF: xdprintf(0, "(None)"); break;
  327. default: xdprintf(0, "???(%xh)", previousState); break;
  328. }
  329. xdprintf(0, "\n");
  330. /*
  331. * Print target device
  332. */
  333. lowerDevObjAddr = GetULONGField(commonExtAddr, "classpnp!_COMMON_DEVICE_EXTENSION", "LowerDeviceObject");
  334. xdprintf(Depth+1, ""), dprintf("Target device=%08p\n", lowerDevObjAddr);
  335. /*
  336. * Dump child PDO list
  337. */
  338. xdprintf(Depth+1, "Child PDOs:\n");
  339. childPdoExtAddr = GetULONGField(commonExtAddr, "classpnp!_COMMON_DEVICE_EXTENSION", "ChildList");
  340. while (childPdoExtAddr && (childPdoExtAddr != BAD_VALUE)){
  341. ULONG64 pdoAddr = GetULONGField(childPdoExtAddr, "classpnp!_PHYSICAL_DEVICE_EXTENSION", "DeviceObject");
  342. UCHAR isEnumerated = GetUCHARField(childPdoExtAddr, "classpnp!_PHYSICAL_DEVICE_EXTENSION", "IsEnumerated");
  343. UCHAR isMissing = GetUCHARField(childPdoExtAddr, "classpnp!_PHYSICAL_DEVICE_EXTENSION", "IsMissing");
  344. xdprintf(Depth+2, ""), dprintf("PDO=%08p IsEnumerated=%d IsMissing=%d\n", pdoAddr, isEnumerated, isMissing);
  345. childPdoExtAddr = GetULONGField(childPdoExtAddr, "classpnp!_PHYSICAL_DEVICE_EXTENSION", "CommonExtension.ChildList");
  346. }
  347. dprintf("\n");
  348. dprintf("\n");
  349. xdprintf(Depth+2, ""), dprintf("(for more info use 'dt classpnp!_FUNCTIONAL_DEVICE_EXTENSION %08p')\n", FdoExtAddr);
  350. xdprintf(0, "\n");
  351. }
  352. VOID
  353. ClassDumpFdoExtensionInternal(
  354. IN ULONG64 FdoDataAddr,
  355. IN ULONG Detail,
  356. IN ULONG Depth
  357. )
  358. {
  359. ULONG64 keTickCountAddr;
  360. ULONG keTickCount;
  361. ULONG len;
  362. dprintf("\n");
  363. xdprintf(Depth, ""), dprintf("Classpnp _INTERNAL_ data (%08p):\n", FdoDataAddr);
  364. /*
  365. * Dump TRANSFER_PACKET lists
  366. */
  367. ClassDumpTransferPacketLists(FdoDataAddr, Detail, Depth+1);
  368. /*
  369. * Dump private error logs
  370. */
  371. ClassDumpPrivateErrorLogs(FdoDataAddr, Detail, Depth+1);
  372. /*
  373. * Show time at trap (for comparison with error log timestamps)
  374. */
  375. keTickCountAddr = GetExpression("nt!KeTickCount");
  376. if (ReadMemory(keTickCountAddr, &keTickCount, sizeof(ULONG), &len)){
  377. dprintf("\n");
  378. xdprintf(Depth, ""), dprintf("KeTickCount trap time: %08xh = %d.%d\n", keTickCount, (ULONG)(keTickCount/1000), (ULONG)(keTickCount%1000));
  379. }
  380. dprintf("\n");
  381. xdprintf(Depth+2, ""), dprintf("(for more info use 'dt classpnp!_CLASS_PRIVATE_FDO_DATA %08p')\n", FdoDataAddr);
  382. }
  383. VOID ClassDumpTransferPacketLists(ULONG64 FdoDataAddr, ULONG Detail, ULONG Depth)
  384. {
  385. ULONG64 allxferPktsListAddr;
  386. /*
  387. * Print transfer packet lists
  388. */
  389. allxferPktsListAddr = GetFieldAddr(FdoDataAddr, "classpnp!_CLASS_PRIVATE_FDO_DATA", "AllTransferPacketsList");
  390. if (allxferPktsListAddr != BAD_VALUE){
  391. ULONG64 listEntryAddr;
  392. ULONG numTotalXferPkts = (ULONG)GetULONGField(FdoDataAddr, "classpnp!_CLASS_PRIVATE_FDO_DATA", "NumTotalTransferPackets");
  393. ULONG numFreeXferPkts = (ULONG)GetULONGField(FdoDataAddr, "classpnp!_CLASS_PRIVATE_FDO_DATA", "NumFreeTransferPackets");
  394. ULONG numPackets;
  395. char *extraSpaces = IsPtr64() ? " " : "";
  396. /*
  397. * Walk AllTransferPacketsList and print only the outstanding packets with full SRB info.
  398. */
  399. xdprintf(Depth, "\n");
  400. xdprintf(Depth, "Outstanding transfer packets: (out of %d total)\n", numTotalXferPkts);
  401. xdprintf(Depth, "\n");
  402. xdprintf(Depth+1, " packet %s irp %s srb %s sense %s status \n", extraSpaces, extraSpaces, extraSpaces, extraSpaces);
  403. xdprintf(Depth+1, "--------%s --------%s --------%s --------%s -------- \n", extraSpaces, extraSpaces, extraSpaces, extraSpaces);
  404. numPackets = 0;
  405. listEntryAddr = GetULONGField(allxferPktsListAddr, "nt!_LIST_ENTRY", "Flink");
  406. while ((listEntryAddr != allxferPktsListAddr) && (listEntryAddr != BAD_VALUE)){
  407. ULONG64 pktAddr;
  408. pktAddr = GetContainingRecord(listEntryAddr, "classpnp!_TRANSFER_PACKET", "AllPktsListEntry");
  409. if (pktAddr == BAD_VALUE){
  410. break;
  411. }
  412. else {
  413. ClassDumpTransferPacket(pktAddr, TRUE, FALSE, TRUE, Depth+1);
  414. numPackets++;
  415. listEntryAddr = GetULONGField(listEntryAddr, "nt!_LIST_ENTRY", "Flink");
  416. }
  417. }
  418. if (numPackets != numTotalXferPkts){
  419. xdprintf(Depth, "*** Warning: NumTotalTransferPackets(%d) doesn't match length of queue(%d) ***\n", numTotalXferPkts, numPackets);
  420. }
  421. if (Detail > 0){
  422. ULONG64 slistEntryAddr;
  423. /*
  424. * Print all transfer packets
  425. */
  426. xdprintf(Depth, "\n");
  427. xdprintf(Depth, "All transfer packets: (%d total, %d free)\n", numTotalXferPkts, numFreeXferPkts);
  428. xdprintf(Depth, "\n");
  429. xdprintf(Depth+1, " packet %s irp %s srb %s sense %s status \n", extraSpaces, extraSpaces, extraSpaces, extraSpaces);
  430. xdprintf(Depth+1, "--------%s --------%s --------%s --------%s -------- \n", extraSpaces, extraSpaces, extraSpaces, extraSpaces);
  431. numPackets = 0;
  432. listEntryAddr = GetULONGField(allxferPktsListAddr, "nt!_LIST_ENTRY", "Flink");
  433. while ((listEntryAddr != allxferPktsListAddr) && (listEntryAddr != BAD_VALUE)){
  434. ULONG64 pktAddr;
  435. pktAddr = GetContainingRecord(listEntryAddr, "classpnp!_TRANSFER_PACKET", "AllPktsListEntry");
  436. if (pktAddr == BAD_VALUE){
  437. break;
  438. }
  439. else {
  440. ClassDumpTransferPacket(pktAddr, TRUE, TRUE, FALSE, Depth+1);
  441. listEntryAddr = GetULONGField(listEntryAddr, "nt!_LIST_ENTRY", "Flink");
  442. }
  443. }
  444. /*
  445. * Print free packets sList
  446. */
  447. xdprintf(Depth, "\n");
  448. xdprintf(Depth, "Free transfer packets in fast SLIST: (%d free)\n", numFreeXferPkts);
  449. if (IsPtr64()){
  450. xdprintf(Depth, "(Cannot display fast SLIST on 64-bit system)\n");
  451. }
  452. else {
  453. xdprintf(Depth+1, " packet %s irp %s srb %s sense %s status \n", extraSpaces, extraSpaces, extraSpaces, extraSpaces);
  454. xdprintf(Depth+1, "--------%s --------%s --------%s --------%s -------- \n", extraSpaces, extraSpaces, extraSpaces, extraSpaces);
  455. numPackets = 0;
  456. slistEntryAddr = GetULONGField(FdoDataAddr, "classpnp!_CLASS_PRIVATE_FDO_DATA", "FreeTransferPacketsList.Next.Next");
  457. while (slistEntryAddr && (slistEntryAddr != BAD_VALUE)){
  458. ULONG64 pktAddr;
  459. pktAddr = GetContainingRecord(slistEntryAddr, "classpnp!_TRANSFER_PACKET", "SlistEntry");
  460. if (pktAddr == BAD_VALUE){
  461. break;
  462. }
  463. else {
  464. ClassDumpTransferPacket(pktAddr, TRUE, TRUE, FALSE, Depth+1);
  465. numPackets++;
  466. slistEntryAddr = GetULONGField(pktAddr, "classpnp!_TRANSFER_PACKET", "SlistEntry.Next");
  467. }
  468. }
  469. if (numPackets != numFreeXferPkts){
  470. xdprintf(Depth, "*** Warning: NumFreeTransferPackets(%d) doesn't match length of queue(%d) ***\n", numFreeXferPkts, numPackets);
  471. }
  472. }
  473. }
  474. }
  475. }
  476. /*
  477. * ClassDumpTransferPacket
  478. *
  479. * Dump TRANSFER_PACKET contents under the following heading:
  480. *
  481. * " packet irp srb sense status "
  482. * " -------- -------- -------- -------- -------- "
  483. *
  484. */
  485. VOID ClassDumpTransferPacket(
  486. ULONG64 PktAddr,
  487. BOOLEAN DumpPendingPkts,
  488. BOOLEAN DumpFreePkts,
  489. BOOLEAN DumpFullInfo,
  490. ULONG Depth)
  491. {
  492. ULONG64 irpAddr = GetULONGField(PktAddr, "classpnp!_TRANSFER_PACKET", "Irp");
  493. ULONG64 srbAddr = GetFieldAddr(PktAddr, "classpnp!_TRANSFER_PACKET", "Srb");
  494. ULONG64 senseAddr = GetFieldAddr(PktAddr, "classpnp!_TRANSFER_PACKET", "SrbErrorSenseData");
  495. if ((irpAddr == BAD_VALUE) || (srbAddr == BAD_VALUE) || (senseAddr == BAD_VALUE)){
  496. dprintf("\n ClassDumpTransferPacket: error retrieving contents of packet %08p.\n", PktAddr);
  497. }
  498. else {
  499. UCHAR currentStackLoc = GetUCHARField(irpAddr, "nt!_IRP", "CurrentLocation");
  500. UCHAR stackCount = GetUCHARField(irpAddr, "nt!_IRP", "StackCount");
  501. BOOLEAN isPending;
  502. isPending = (currentStackLoc != stackCount+1);
  503. if ((isPending && DumpPendingPkts) || (!isPending && DumpFreePkts)){
  504. /*
  505. * Print the transfer packet description line
  506. */
  507. xdprintf(Depth, "");
  508. dprintf("%08p", PktAddr);
  509. dprintf(" %08p", irpAddr);
  510. dprintf(" %08p", srbAddr);
  511. dprintf(" %08p", senseAddr);
  512. if (isPending){
  513. xdprintf(0, " pending*");
  514. }
  515. else {
  516. xdprintf(0, " (free)");
  517. }
  518. xdprintf(0, "\n");
  519. if (DumpFullInfo){
  520. ULONG64 bufLen = GetULONGField(srbAddr, "classpnp!_SCSI_REQUEST_BLOCK", "DataTransferLength");
  521. ULONG64 cdbAddr = GetFieldAddr(srbAddr, "classpnp!_SCSI_REQUEST_BLOCK", "Cdb");
  522. ULONG64 origIrpAddr = GetULONGField(PktAddr, "classpnp!_TRANSFER_PACKET", "OriginalIrp");
  523. ULONG64 mdlAddr = GetULONGField(origIrpAddr, "nt!_IRP", "MdlAddress");
  524. UCHAR scsiOp = GetUCHARField(cdbAddr, "classpnp!_CDB", "CDB6GENERIC.OperationCode");
  525. UCHAR srbStat = GetUCHARField(srbAddr, "classpnp!_SCSI_REQUEST_BLOCK", "SrbStatus");
  526. ULONG64 bufAddr;
  527. /*
  528. * The the buffer address from the MDL if possible;
  529. * else from the SRB (which may not be valid).
  530. */
  531. bufAddr = GetULONGField(srbAddr, "classpnp!_SCSI_REQUEST_BLOCK", "DataBuffer");
  532. if (mdlAddr && (mdlAddr != BAD_VALUE)){
  533. ULONG mdlFlags = (ULONG)GetULONGField(mdlAddr, "nt!_MDL", "MdlFlags");
  534. if ((mdlFlags != BAD_VALUE) && (mdlFlags & MDL_PAGES_LOCKED)){
  535. bufAddr = GetULONGField(mdlAddr, "nt!_MDL", "MappedSystemVa");
  536. }
  537. }
  538. else {
  539. /*
  540. * There's no MDL, so bufAddr should be the actual kernel-space pointer.
  541. * Sanity-check it.
  542. */
  543. if (!IsPtr64() && !(bufAddr & 0x80000000)){
  544. bufAddr = BAD_VALUE;
  545. }
  546. }
  547. /*
  548. * Print the SRB description line
  549. */
  550. xdprintf(Depth+1, "(");
  551. dprintf("%s ", DbgGetScsiOpStr(scsiOp));
  552. dprintf("status=%s ", DbgGetSrbStatusStr(srbStat));
  553. if (mdlAddr && (mdlAddr != BAD_VALUE)){
  554. if (bufAddr == BAD_VALUE){
  555. dprintf("mdl=%08p ", mdlAddr);
  556. }
  557. else {
  558. dprintf("mdl+%08p ", bufAddr);
  559. }
  560. }
  561. else if (bufAddr == BAD_VALUE){
  562. dprintf("buf=??? ");
  563. }
  564. else {
  565. dprintf("buf=%08p ", bufAddr);
  566. }
  567. dprintf("len=%08lx", bufLen);
  568. dprintf(")\n");
  569. /*
  570. * Print a line with original irp if appropriate
  571. */
  572. if (cdbAddr != BAD_VALUE){
  573. UCHAR scsiOp = GetUCHARField(cdbAddr, "classpnp!_CDB", "CDB6GENERIC.OperationCode");
  574. if ((scsiOp == SCSIOP_READ) || (scsiOp == SCSIOP_WRITE)){
  575. xdprintf(Depth+1, ""), dprintf("(OriginalIrp=%08p)\n", origIrpAddr);
  576. }
  577. }
  578. }
  579. }
  580. }
  581. }
  582. VOID ClassDumpPrivateErrorLogs(ULONG64 FdoDataAddr, ULONG Detail, ULONG Depth)
  583. {
  584. ULONG64 errLogsAddr;
  585. errLogsAddr = GetFieldAddr(FdoDataAddr, "classpnp!_CLASS_PRIVATE_FDO_DATA", "ErrorLogs");
  586. if (errLogsAddr != BAD_VALUE){
  587. ULONG errLogSize = GetTypeSize("classpnp!_CLASS_ERROR_LOG_DATA");
  588. if (errLogSize != BAD_VALUE){
  589. ULONG nextErrLogIndex, firstErrLogIndex, lastErrLogIndex;
  590. /*
  591. * Find what should be the index of the last error log (if there were any error logs)
  592. * See if it is valid by checking for a non-zero timestamp.
  593. */
  594. nextErrLogIndex = (ULONG)GetULONGField(FdoDataAddr, "classpnp!_CLASS_PRIVATE_FDO_DATA", "ErrorLogNextIndex");
  595. if (nextErrLogIndex != BAD_VALUE){
  596. ULONG64 tickCount;
  597. lastErrLogIndex = (nextErrLogIndex+NUM_ERROR_LOG_ENTRIES-1) % NUM_ERROR_LOG_ENTRIES;
  598. tickCount = GetULONGField(errLogsAddr+lastErrLogIndex*errLogSize, "classpnp!_CLASS_ERROR_LOG_DATA", "TickCount");
  599. if (tickCount == BAD_VALUE){
  600. }
  601. else if (tickCount == 0){
  602. /*
  603. * The "latest" error log is not initialized, so there are no error logs
  604. */
  605. dprintf("\n"), xdprintf(Depth, "No Error Logs:\n");
  606. }
  607. else {
  608. /*
  609. * Search forward through the circular list for the first valid error log.
  610. */
  611. for (firstErrLogIndex = (lastErrLogIndex+1)%NUM_ERROR_LOG_ENTRIES;
  612. firstErrLogIndex != lastErrLogIndex;
  613. firstErrLogIndex = (firstErrLogIndex+1)%NUM_ERROR_LOG_ENTRIES){
  614. ULONG64 thisErrLogAddr = errLogsAddr+firstErrLogIndex*errLogSize;
  615. tickCount = GetULONGField(thisErrLogAddr, "classpnp!_CLASS_ERROR_LOG_DATA", "TickCount");
  616. if (tickCount == BAD_VALUE){
  617. /*
  618. * something's screwed up; abort
  619. */
  620. break;
  621. }
  622. else if (tickCount != 0){
  623. /*
  624. * found the earliest of the recorded error logs, break
  625. */
  626. break;
  627. }
  628. }
  629. if (tickCount != BAD_VALUE){
  630. /*
  631. * Now that we've found the valid range of error logs, print them out.
  632. */
  633. ULONG numErrLogs = (lastErrLogIndex >= firstErrLogIndex) ?
  634. lastErrLogIndex-firstErrLogIndex+1 :
  635. lastErrLogIndex+NUM_ERROR_LOG_ENTRIES-firstErrLogIndex+1;
  636. dprintf("\n\n"), xdprintf(Depth, "ERROR LOGS (%d):\n", numErrLogs);
  637. xdprintf(Depth, "---------------------------------------------------\n");
  638. do {
  639. ULONG64 thisErrLogAddr = errLogsAddr+firstErrLogIndex*errLogSize;
  640. ULONG64 tickCount = GetFieldAddr(thisErrLogAddr, "classpnp!_CLASS_ERROR_LOG_DATA", "TickCount");
  641. ULONG64 senseDataAddr = GetFieldAddr(thisErrLogAddr, "classpnp!_CLASS_ERROR_LOG_DATA", "SenseData");
  642. ULONG64 srbAddr = GetFieldAddr(thisErrLogAddr, "classpnp!_CLASS_ERROR_LOG_DATA", "Srb");
  643. ULONG64 cdbAddr;
  644. // GetFieldOffset of an embedded struct gets the wrong address for some reason,
  645. // so do this manually.
  646. #if 0
  647. cdbAddr = GetFieldAddr(thisErrLogAddr, "classpnp!_SCSI_REQUEST_BLOCK", "Cdb");
  648. #else
  649. cdbAddr = (srbAddr == BAD_VALUE) ? BAD_VALUE :
  650. IsPtr64() ? srbAddr + 0x48 :
  651. srbAddr + 0x30;
  652. #endif
  653. if ((thisErrLogAddr != BAD_VALUE) && (srbAddr != BAD_VALUE) && (senseDataAddr != BAD_VALUE) && (cdbAddr != BAD_VALUE)){
  654. UCHAR scsiOp = GetUCHARField(cdbAddr, "classpnp!_CDB", "CDB6GENERIC.OperationCode");
  655. UCHAR srbStat = GetUCHARField(srbAddr, "classpnp!_SCSI_REQUEST_BLOCK", "SrbStatus");
  656. UCHAR scsiStat = GetUCHARField(srbAddr, "classpnp!_SCSI_REQUEST_BLOCK", "ScsiStatus");
  657. UCHAR isPaging = GetUCHARField(thisErrLogAddr, "classpnp!_CLASS_ERROR_LOG_DATA", "ErrorPaging");
  658. UCHAR isRetried = GetUCHARField(thisErrLogAddr, "classpnp!_CLASS_ERROR_LOG_DATA", "ErrorRetried");
  659. UCHAR isUnhandled = GetUCHARField(thisErrLogAddr, "classpnp!_CLASS_ERROR_LOG_DATA", "ErrorUnhandled");
  660. tickCount = GetULONGField(thisErrLogAddr, "classpnp!_CLASS_ERROR_LOG_DATA", "TickCount");
  661. if ((scsiOp != BAD_VALUE) && (tickCount != BAD_VALUE)){
  662. xdprintf(Depth+1, "");
  663. dprintf("<tick %d.%d>: ", (ULONG)(tickCount/1000), (ULONG)(tickCount%1000));
  664. dprintf("%s(%xh)\n",
  665. DbgGetScsiOpStr(scsiOp),
  666. (ULONG)scsiOp);
  667. xdprintf(Depth+2, "");
  668. dprintf("srbStat=%s(%xh) scsiStat=%xh \n",
  669. DbgGetSrbStatusStr(srbStat),
  670. (ULONG)srbStat,
  671. (ULONG)scsiStat
  672. );
  673. xdprintf(Depth+2, "");
  674. dprintf("SenseData = %s/%s/%s \n",
  675. DbgGetSenseCodeStr(srbStat, senseDataAddr),
  676. DbgGetAdditionalSenseCodeStr(srbStat, senseDataAddr),
  677. DbgGetAdditionalSenseCodeQualifierStr(srbStat, senseDataAddr));
  678. xdprintf(Depth+2, "");
  679. if (isPaging) dprintf("Paging; "); else dprintf("(not paging); ");
  680. if (isRetried) dprintf("Retried; "); else dprintf("(not retried); ");
  681. if (isUnhandled) dprintf("Unhandled; ");
  682. dprintf("\n");
  683. xdprintf(Depth+2, "");
  684. dprintf("(for more info, use 'dt classpnp!_CLASS_ERROR_LOG_DATA %08p'\n\n", thisErrLogAddr);
  685. firstErrLogIndex = (firstErrLogIndex+1)%NUM_ERROR_LOG_ENTRIES;
  686. }
  687. else {
  688. break;
  689. }
  690. }
  691. else {
  692. break;
  693. }
  694. } while (firstErrLogIndex != (lastErrLogIndex+1)%NUM_ERROR_LOG_ENTRIES);
  695. xdprintf(Depth, "---------------------------------------------------\n");
  696. }
  697. }
  698. }
  699. }
  700. }
  701. }
  702. VOID
  703. ClassDumpMediaChangeInfo(
  704. ULONG64 Address,
  705. ULONG Detail,
  706. ULONG Depth
  707. )
  708. {
  709. PUCHAR states[] = {"Unknown", "Present", "Not Present"};
  710. ULONG result;
  711. ULONG64 MediaChangeDetectionInfo;
  712. ULONG offset;
  713. LONG MediaChangeDetectionDisableCount;
  714. ULONG MediaChangeDetectionState;
  715. BOOLEAN MediaChangeIrpLost;
  716. LONG MediaChangeIrpTimeInUse;
  717. ULONG64 MediaChangeIrp;
  718. ULONG64 SenseBuffer;
  719. result = GetFieldData(Address,
  720. "classpnp!_FUNCTIONAL_DEVICE_EXTENSION",
  721. "MediaChangeDetectionInfo",
  722. sizeof(ULONG64),
  723. &MediaChangeDetectionInfo);
  724. if (result) {
  725. SCSIKD_PRINT_ERROR(result);
  726. return;
  727. }
  728. xdprintfEx(Depth, ("MediaChangeNotification:\n"));
  729. Depth++;
  730. if (MediaChangeDetectionInfo == 0) {
  731. xdprintfEx(Depth, ("MCN is not enabled for this device\n"));
  732. return;
  733. }
  734. InitTypeRead(MediaChangeDetectionInfo,
  735. classpnp!_MEDIA_CHANGE_DETECTION_INFO);
  736. MediaChangeDetectionDisableCount = (LONG) ReadField(MediaChangeDetectionDisableCount);
  737. MediaChangeDetectionState = (ULONG) ReadField(MediaChangeDetectionState);
  738. MediaChangeIrpLost = (BOOLEAN) ReadField(MediaChangeIrpLost);
  739. MediaChangeIrpTimeInUse = (LONG) ReadField(MediaChangeIrpTimeInUse);
  740. MediaChangeIrp = ReadField(MediaChangeIrp);
  741. SenseBuffer = ReadField(SenseBuffer);
  742. result = GetFieldOffset("classpnp!_MEDIA_CHANGE_DETECTION_INFO",
  743. "MediaChangeSrb",
  744. &offset);
  745. if (result) {
  746. SCSIKD_PRINT_ERROR(result);
  747. return;
  748. }
  749. xdprintfEx(Depth, ("MCN is ")); // indent
  750. if (MediaChangeDetectionDisableCount == 0) {
  751. dprintf("Enabled ");
  752. } else {
  753. dprintf("Disabled ");
  754. }
  755. dprintf("Current State %s", states[MediaChangeDetectionState] );
  756. if (MediaChangeIrpLost != 0) {
  757. dprintf(" *** MCN Irp Lost for %x ticks *** ",
  758. MediaChangeIrpTimeInUse);
  759. }
  760. dprintf("\n"); // end indent
  761. xdprintfEx(Depth, ("Irp %p Srb %p SenseBuffer %p\n",
  762. MediaChangeIrp,
  763. MediaChangeDetectionInfo + offset,
  764. SenseBuffer
  765. ));
  766. return;
  767. }
  768. VOID
  769. ClassDumpFdo(
  770. ULONG64 Address,
  771. ULONG Detail,
  772. ULONG Depth
  773. )
  774. {
  775. ULONG result;
  776. ULONG offset;
  777. ULONG tmp;
  778. ULONG64 LowerPdo;
  779. ULONG64 DeviceDescriptor;
  780. ULONG64 AdapterDescriptor;
  781. ULONG DevicePowerState;
  782. ULONG ErrorCount;
  783. BOOLEAN DMActive;
  784. ULONG DMByteSkew;
  785. ULONG DMSkew;
  786. ULONG64 SenseData;
  787. ULONG TimeOutValue;
  788. ULONG DeviceNumber;
  789. ULONG FSrbFlags;
  790. USHORT DeviceFlags;
  791. ULONG64 DiskGeometryCylinders;
  792. ULONG DiskGeometryMediaType;
  793. ULONG DiskGeometryTracksPerCylinder;
  794. ULONG DiskGeometrySectorsPerTrack;
  795. ULONG DiskGeometryBytesPerSector;
  796. LONG LockCount;
  797. LONG ProtectedLockCount;
  798. LONG InternalLockCount;
  799. ULONG MediaChangeCount;
  800. ULONG64 ChildLockOwner;
  801. ULONG ChildLockAcquisitionCount;
  802. FIELD_INFO deviceFields[] = {
  803. {"LowerPdo", NULL, 0, COPY, 0, (PVOID) &LowerPdo},
  804. {"DeviceDescriptor", NULL, 0, COPY, 0, (PVOID) &DeviceDescriptor},
  805. {"AdapterDescriptor", NULL, 0, COPY, 0, (PVOID) &AdapterDescriptor},
  806. {"DevicePowerState", NULL, 0, COPY, 0, (PVOID) &DevicePowerState},
  807. {"ErrorCount", NULL, 0, COPY, 0, (PVOID) &ErrorCount},
  808. {"DMActive", NULL, 0, COPY, 0, (PVOID) &DMActive},
  809. {"DMByteSkew", NULL, 0, COPY, 0, (PVOID) &DMByteSkew},
  810. {"DMSkew", NULL, 0, COPY, 0, (PVOID) &DMSkew},
  811. {"SenseData", NULL, 0, COPY, 0, (PVOID) &SenseData},
  812. {"TimeOutValue", NULL, 0, COPY, 0, (PVOID) &TimeOutValue},
  813. {"DeviceNumber", NULL, 0, COPY, 0, (PVOID) &DeviceNumber},
  814. {"SrbFlags", NULL, 0, COPY, 0, (PVOID) &FSrbFlags},
  815. {"DeviceFlags", NULL, 0, COPY, 0, (PVOID) &DeviceFlags},
  816. {"DiskGeometry.Cylinders", NULL, 0, COPY, 0, (PVOID) &DiskGeometryCylinders},
  817. {"DiskGeometry.MediaType", NULL, 0, COPY, 0, (PVOID) &DiskGeometryMediaType},
  818. {"DiskGeometry.TracksPerCylinder", NULL, 0, COPY, 0, (PVOID) &DiskGeometryTracksPerCylinder},
  819. {"DiskGeometry.SectorsPerTrack", NULL, 0, COPY, 0, (PVOID) &DiskGeometrySectorsPerTrack},
  820. {"DiskGeometry.BytesPerSector", NULL, 0, COPY, 0, (PVOID) &DiskGeometryBytesPerSector},
  821. {"LockCount", NULL, 0, COPY, 0, (PVOID) &LockCount},
  822. {"ProtectedLockCount", NULL, 0, COPY, 0, (PVOID) &ProtectedLockCount},
  823. {"InternalLockCount", NULL, 0, COPY, 0, (PVOID) &InternalLockCount},
  824. {"MediaChangeCount", NULL, 0, COPY, 0, (PVOID) &MediaChangeCount},
  825. {"ChildLockOwner", NULL, 0, COPY, 0, (PVOID) &ChildLockOwner},
  826. {"ChildLockAcquisitionCount", NULL, 0, COPY, 0, (PVOID) &ChildLockAcquisitionCount},
  827. };
  828. SYM_DUMP_PARAM DevSym = {
  829. sizeof (SYM_DUMP_PARAM),
  830. "classpnp!_FUNCTIONAL_DEVICE_EXTENSION",
  831. DBG_DUMP_NO_PRINT,
  832. Address,
  833. NULL, NULL, NULL,
  834. sizeof (deviceFields) / sizeof (FIELD_INFO),
  835. &deviceFields[0]
  836. };
  837. result = Ioctl(IG_DUMP_SYMBOL_INFO, &DevSym, DevSym.size);
  838. if (result) {
  839. SCSIKD_PRINT_ERROR(result);
  840. return;
  841. }
  842. tmp = Depth;
  843. xdprintfEx(Depth, ("LowerPdo 0x%p DeviceDesc 0x%p AdapterDesc 0x%p\n",
  844. LowerPdo,
  845. DeviceDescriptor,
  846. AdapterDescriptor));
  847. xdprintfEx(Depth, ("DevicePowerState %d ErrorCount %#x\n",
  848. DevicePowerState,
  849. ErrorCount
  850. ));
  851. if(DMActive) {
  852. xdprintfEx(Depth, ("DMByteSkew 0x%08lx DmSkew 0x%08lx\n",
  853. DMByteSkew,
  854. DMSkew));
  855. } else {
  856. xdprintfEx(Depth, ("DM Not Found\n"));
  857. }
  858. xdprintfEx(Depth, ("Sense Data 0x%p Timeout %d DeviceNumber %d\n",
  859. SenseData,
  860. TimeOutValue,
  861. DeviceNumber));
  862. DumpFlags(Depth, "Srb Flags", FSrbFlags, SrbFlags);
  863. DumpFlags(Depth, "Device Flags", DeviceFlags, FdoFlags);
  864. xdprintfEx(Depth, ("DiskGeometry:\n"));
  865. {
  866. Depth++;
  867. xdprintfEx(Depth, ("Cylinders %#I64x MediaType %#x\n",
  868. DiskGeometryCylinders,
  869. DiskGeometryMediaType
  870. ));
  871. xdprintfEx(Depth, ("Tracks %#x Sectors %#x Bytes %#x\n",
  872. DiskGeometryTracksPerCylinder,
  873. DiskGeometrySectorsPerTrack,
  874. DiskGeometryBytesPerSector));
  875. Depth--;
  876. }
  877. xdprintfEx(Depth, ("Lock Counts: Normal %#x Protected %#x Internal %#x\n",
  878. LockCount,
  879. ProtectedLockCount,
  880. InternalLockCount));
  881. ClassDumpMediaChangeInfo(Address, Detail, Depth);
  882. xdprintfEx(Depth, ("Media Change Count %#x\n", MediaChangeCount));
  883. result = GetFieldOffset("classpnp!_FUNCTIONAL_DEVICE_EXTENSION",
  884. "ChildLock",
  885. &offset);
  886. if (result) {
  887. SCSIKD_PRINT_ERROR(result);
  888. return;
  889. }
  890. xdprintfEx(Depth, ("ChildLock: Event %08p, Owner %08p, Count %#x\n",
  891. Address + offset,
  892. ChildLockOwner,
  893. ChildLockAcquisitionCount
  894. ));
  895. ClassDumpChildren(Address, Detail, Depth);
  896. return;
  897. }
  898. VOID
  899. ClassDumpChildren(
  900. IN ULONG64 Fdo,
  901. IN ULONG Detail,
  902. IN ULONG Depth
  903. )
  904. {
  905. ULONG i;
  906. ULONG64 ChildList;
  907. ULONG result;
  908. xdprintfEx(Depth, ("Children: \n"));
  909. Depth++;
  910. result = GetFieldData(Fdo,
  911. "classpnp!_COMMON_DEVICE_EXTENSION",
  912. "ChildList",
  913. sizeof(ULONG64),
  914. &ChildList);
  915. if (result) {
  916. SCSIKD_PRINT_ERROR(result);
  917. return;
  918. }
  919. if (ChildList == 0) {
  920. xdprintfEx(Depth, ("No Children\n"));
  921. }
  922. while((ChildList != 0) && (!CheckControlC())) {
  923. ULONG64 DeviceObject;
  924. xdprintfEx(Depth, ("Child 0x%p ", ChildList));
  925. /*
  926. result = GetFieldData(ChildList,
  927. "classpnp!_PHYSICAL_DEVICE_EXTENSION",
  928. "DeviceObject",
  929. sizeof(ULONG64),
  930. &DeviceObject);
  931. if (result) {
  932. SCSIKD_PRINT_ERROR(result);
  933. break;
  934. }
  935. */
  936. if(Detail > 1) {
  937. dprintf("\n");
  938. ClassDumpCommonExtension(ChildList,
  939. Detail,
  940. Depth + 1);
  941. } else {
  942. dprintf("DevObj 0x%p\n", ChildList);
  943. }
  944. //
  945. // Get the next child.
  946. //
  947. result = GetFieldData(ChildList,
  948. "classpnp!_COMMON_DEVICE_EXTENSION",
  949. "ChildList",
  950. sizeof(ULONG64),
  951. &ChildList);
  952. if (result) {
  953. SCSIKD_PRINT_ERROR(result);
  954. break;
  955. }
  956. }
  957. return;
  958. }
  959. VOID
  960. ClassDumpPdo(
  961. ULONG64 Address,
  962. ULONG Detail,
  963. ULONG Depth
  964. )
  965. {
  966. ULONG tmp;
  967. BOOLEAN IsMissing;
  968. BOOLEAN IsEnumerated;
  969. tmp = Depth;
  970. InitTypeRead(Address, classpnp!_PHYSICAL_DEVICE_EXTENSION);
  971. IsMissing = (BOOLEAN)ReadField(IsMissing);
  972. IsEnumerated = (BOOLEAN)ReadField(IsEnumerated);
  973. if(IsMissing) {
  974. xdprintfEx(tmp, ("Missing " ));
  975. tmp = 0;
  976. }
  977. if(IsEnumerated) {
  978. xdprintfEx(tmp, ("Enumerated"));
  979. tmp = 0;
  980. }
  981. if(tmp == 0) {
  982. dprintf("\n");
  983. }
  984. tmp = 0;
  985. return;
  986. }
  987. BOOLEAN
  988. ClassIsCheckedVersion(
  989. ULONG64 RemoveTrackingSpinlock
  990. )
  991. {
  992. if ((PVOID)RemoveTrackingSpinlock == (PVOID)-1) {
  993. //
  994. // negative one is an invalid value for a spinlock,
  995. // therefore this is a FRE build
  996. //
  997. return FALSE;
  998. } else {
  999. return TRUE;
  1000. }
  1001. }
  1002. VOID
  1003. ClassDumpLocks(
  1004. ULONG64 CommonExtension,
  1005. ULONG Depth
  1006. )
  1007. /*++
  1008. Routine Description:
  1009. dumps the remove locks for a given device object
  1010. Arguments:
  1011. CommonExtension - a pointer to the local copy of the device object
  1012. common extension
  1013. Return Value:
  1014. None
  1015. --*/
  1016. {
  1017. ULONG result;
  1018. ULONG64 lockEntryAddress;
  1019. ULONG64 RemoveLock;
  1020. ULONG64 RemoveTrackingSpinlock;
  1021. ULONG64 RemoveTrackingList;
  1022. InitTypeRead(CommonExtension, classpnp!_COMMON_DEVICE_EXTENSION);
  1023. RemoveLock = ReadField(RemoveLock);
  1024. RemoveTrackingSpinlock = ReadField(RemoveTrackingSpinlock);
  1025. xdprintfEx(Depth, ("RemoveLock count is %d", RemoveLock));
  1026. //
  1027. // seeing if RemoveTrackingSpinLock is -1 is our check for the
  1028. // FRE version, which does not contain useful data.
  1029. //
  1030. if(!ClassIsCheckedVersion(RemoveTrackingSpinlock)) {
  1031. dprintf(" (not tracked on free build)\n");
  1032. return;
  1033. }
  1034. RemoveTrackingList = ReadField(RemoveTrackingList);
  1035. lockEntryAddress = RemoveTrackingList;
  1036. dprintf(":\n");
  1037. Depth++;
  1038. if(RemoveTrackingSpinlock != 0) {
  1039. xdprintfEx(Depth, ("RemoveTrackingList at %p is in intermediate state\n",
  1040. RemoveTrackingList));
  1041. return;
  1042. }
  1043. while((lockEntryAddress != 0L) && !CheckControlC()) {
  1044. UCHAR buffer[512];
  1045. ULONG64 Tag;
  1046. ULONG64 File;
  1047. ULONG64 Line;
  1048. ULONG64 NextBlock;
  1049. InitTypeRead(lockEntryAddress, classpnp!_REMOVE_TRACKING_BLOCK);
  1050. Tag = ReadField(Tag);
  1051. File = ReadField(File);
  1052. Line = ReadField(Line);
  1053. NextBlock = ReadField(NextBlock);
  1054. result = sizeof(buffer)-sizeof(UCHAR);
  1055. if(!GetAnsiString(File,
  1056. buffer,
  1057. &result)) {
  1058. xdprintfEx(Depth, ("Tag 0x%p File 0x%p Line %d\n",
  1059. Tag,
  1060. File,
  1061. Line));
  1062. } else {
  1063. PUCHAR name;
  1064. name = &buffer[result];
  1065. while((result > 0) &&
  1066. (*(name - 1) != '\\') &&
  1067. (*(name - 1) != '/') &&
  1068. (!CheckControlC())) {
  1069. name--;
  1070. result--;
  1071. }
  1072. xdprintfEx(Depth, ("Tag 0x%p File %8s Line %d\n",
  1073. Tag,
  1074. name,
  1075. Line));
  1076. }
  1077. lockEntryAddress = NextBlock;
  1078. }
  1079. return;
  1080. }