Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1005 lines
36 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1992 - 1999
  3. Module Name:
  4. atapikd.c
  5. Abstract:
  6. Debugger Extension Api for interpretting atapi structures
  7. Author:
  8. Environment:
  9. User Mode.
  10. Revision History:
  11. --*/
  12. #include "pch.h"
  13. #include "math.h"
  14. #include "ideport.h"
  15. const LARGE_INTEGER Magic10000 = {0xe219652c, 0xd1b71758};
  16. #define SHIFT10000 13
  17. #define Convert100nsToMilliseconds(LARGE_INTEGER) ( \
  18. RtlExtendedMagicDivide( (LARGE_INTEGER), Magic10000, SHIFT10000 ) \
  19. )
  20. VOID
  21. AtapiDumpPdoExtension(
  22. IN ULONG64 PdoExtAddr,
  23. IN ULONG Detail,
  24. IN ULONG Depth
  25. );
  26. VOID
  27. AtapiDumpFdoExtension(
  28. IN ULONG64 FdoExtAddr,
  29. IN ULONG Detail,
  30. IN ULONG Depth
  31. );
  32. VOID
  33. DumpPdoState(
  34. IN ULONG Depth,
  35. IN ULONG State
  36. );
  37. VOID
  38. DumpFdoState(
  39. IN ULONG Depth,
  40. IN ULONG State
  41. );
  42. #ifdef ENABLE_COMMAND_LOG
  43. VOID
  44. DumpCommandLog(
  45. IN ULONG Depth,
  46. IN ULONG64 SrbDataAddr
  47. );
  48. #else
  49. #define DumpCommandLog(a, b)
  50. #endif
  51. VOID
  52. DumpIdentifyData(
  53. IN ULONG Depth,
  54. IN PIDENTIFY_DATA IdData
  55. );
  56. PUCHAR DMR_Reason[] = {
  57. "",
  58. "Enum Failed",
  59. "Reported Missing",
  60. "Too Many Timeout",
  61. "Killed PDO",
  62. "Replaced By User"
  63. };
  64. PUCHAR DeviceType[] = {
  65. "DIRECT_ACCESS_DEVICE",
  66. "SEQUENTIAL_ACCESS_DEVICE",
  67. "PRINTER_DEVICE",
  68. "PROCESSOR_DEVICE",
  69. "WRITE_ONCE_READ_MULTIPLE_DEVICE",
  70. "READ_ONLY_DIRECT_ACCESS_DEVICE",
  71. "SCANNER_DEVICE",
  72. "OPTICAL_DEVICE",
  73. "MEDIUM_CHANGER",
  74. "COMMUNICATION_DEVICE"
  75. };
  76. PUCHAR PdoState[] = {
  77. "PDOS_DEVICE_CLAIMED",
  78. "PDOS_LEGACY_ATTACHER",
  79. "PDOS_STARTED",
  80. "PDOS_STOPPED",
  81. "PDOS_SURPRISE_REMOVED",
  82. "PDOS_REMOVED",
  83. "PDOS_DEADMEAT",
  84. "PDOS_NO_POWER_DOWN",
  85. "PDOS_QUEUE_FROZEN_BY_POWER_DOWN",
  86. "PDOS_QUEUE_FROZEN_BY_SLEEPING_SYSTEM",
  87. "PDOS_QUEUE_FROZEN_BY_STOP_DEVICE",
  88. "PDOS_QUEUE_FROZEN_BY_PARENT",
  89. "PDOS_QUEUE_FROZEN_BY_START",
  90. "PDOS_DISABLED_BY_USER",
  91. "PDOS_NEED_RESCAN",
  92. "PDOS_REPORTED_TO_PNP",
  93. "PDOS_INITIALIZED"
  94. };
  95. PUCHAR FdoState[] = {
  96. "FDOS_DEADMEAT",
  97. "FDOS_STARTED",
  98. "FDOS_STOPPED"
  99. };
  100. #define MAX_PDO_STATES 16
  101. #define MAX_FDO_STATES 3
  102. DECLARE_API(pdoext)
  103. /*++
  104. Routine Description:
  105. Dumps the pdo extension for a given device object, or dumps the
  106. given pdo extension
  107. Arguments:
  108. args - string containing the address of the device object or device
  109. extension
  110. Return Value:
  111. none
  112. --*/
  113. {
  114. ULONG64 devObjAddr = 0;
  115. ULONG64 detail = 0;
  116. ReloadSymbols("atapi.sys");
  117. if (GetExpressionEx(args, &devObjAddr, &args))
  118. {
  119. GetExpressionEx(args, &detail, &args);
  120. }
  121. if (devObjAddr){
  122. CSHORT objType = GetUSHORTField(devObjAddr, "nt!_DEVICE_OBJECT", "Type");
  123. if (objType == IO_TYPE_DEVICE){
  124. ULONG64 pdoExtAddr;
  125. pdoExtAddr = GetULONGField(devObjAddr, "nt!_DEVICE_OBJECT", "DeviceExtension");
  126. if (pdoExtAddr != BAD_VALUE){
  127. AtapiDumpPdoExtension(pdoExtAddr, (ULONG)detail, 0);
  128. }
  129. }
  130. else {
  131. dprintf("Error: 0x%08p is not a device object\n", devObjAddr);
  132. }
  133. }
  134. else {
  135. dprintf("\n usage: !atapikd.pdoext <atapi pdo> \n\n");
  136. }
  137. return S_OK;
  138. }
  139. VOID
  140. AtapiDumpPdoExtension(
  141. IN ULONG64 PdoExtAddr,
  142. IN ULONG Detail,
  143. IN ULONG Depth
  144. )
  145. {
  146. UCHAR scsiDeviceType;
  147. ULONG pdoState;
  148. ULONG luFlags;
  149. ULONG64 attacheePdo;
  150. ULONG64 idleCounterAddr;
  151. ULONG64 srbDataAddr;
  152. ULONG devicePowerState, systemPowerState;
  153. xdprintf(Depth, ""), dprintf("\nATAPI physical device extension at address 0x%08p\n\n", PdoExtAddr);
  154. Depth++;
  155. scsiDeviceType = GetUCHARField(PdoExtAddr, "atapi!_PDO_EXTENSION", "ScsiDeviceType");
  156. pdoState = (ULONG)GetULONGField(PdoExtAddr, "atapi!_PDO_EXTENSION", "PdoState");
  157. luFlags = (ULONG)GetULONGField(PdoExtAddr, "atapi!_PDO_EXTENSION", "LuFlags");
  158. attacheePdo = GetULONGField(PdoExtAddr, "atapi!_PDO_EXTENSION", "AttacheePdo");
  159. idleCounterAddr = GetULONGField(PdoExtAddr, "atapi!_PDO_EXTENSION", "IdleCounter");
  160. srbDataAddr = GetFieldAddr(PdoExtAddr, "atapi!_PDO_EXTENSION", "SrbData");
  161. devicePowerState = (ULONG)GetULONGField(PdoExtAddr, "atapi!_PDO_EXTENSION", "DevicePowerState");
  162. systemPowerState = (ULONG)GetULONGField(PdoExtAddr, "atapi!_PDO_EXTENSION", "SystemPowerState");
  163. if ((scsiDeviceType != BAD_VALUE) && (pdoState != BAD_VALUE) && (luFlags != BAD_VALUE) &&
  164. (attacheePdo != BAD_VALUE) && (idleCounterAddr != BAD_VALUE) && (srbDataAddr != BAD_VALUE) &&
  165. (devicePowerState != BAD_VALUE) && (systemPowerState != BAD_VALUE)){
  166. ULONG idlecount;
  167. if ((scsiDeviceType >= 0) && (scsiDeviceType <= 9)) {
  168. xdprintf(Depth, ""), dprintf("SCSI Device Type : %s\n", DeviceType[scsiDeviceType]);
  169. }
  170. else {
  171. xdprintf(Depth, ""), dprintf("Connected to Unknown Device\n");
  172. }
  173. DumpPdoState(Depth, pdoState);
  174. dprintf("\n");
  175. DumpFlags(Depth, "LU Flags", luFlags, LuFlags);
  176. xdprintf(Depth, ""), dprintf("PowerState (D%d, S%d)\n", devicePowerState-1, systemPowerState-1);
  177. if (idleCounterAddr){
  178. ULONG resultLen = 0;
  179. ReadMemory(idleCounterAddr, &idlecount, sizeof(ULONG), &resultLen);
  180. if (resultLen != sizeof(ULONG)){
  181. idlecount = 0;
  182. }
  183. }
  184. else {
  185. idlecount = 0;
  186. }
  187. xdprintf(Depth, ""), dprintf("IdleCounter 0x%08x\n", idlecount);
  188. xdprintf(Depth, ""), dprintf("SrbData: (use ' dt atapi!_SRB_DATA %08p ')\n", srbDataAddr);
  189. dprintf("\n");
  190. xdprintf(Depth, ""), dprintf("(for more info, use ' dt atapi!_PDO_EXTENSION %08p ')\n", PdoExtAddr);
  191. #ifdef LOG_DEADMEAT_EVENT
  192. {
  193. ULONG deadmeatReason;
  194. deadmeatReason = (ULONG)GetULONGField(PdoExtAddr, "atapi!_PDO_EXTENSION", "DeadmeatRecord.Reason");
  195. if ((deadmeatReason != BAD_VALUE) && (deadmeatReason > 0) && (deadmeatReason < sizeof(DMR_Reason)/sizeof(PUCHAR))){
  196. dprintf("\n");
  197. xdprintf(Depth, "Deadmeat Record: \n");
  198. xdprintf(Depth+1, "Reason : %s\n", DMR_Reason[deadmeatReason]);
  199. xdprintf(Depth+1, ""), dprintf("(for more info, use ' dt -r atapi!_PDO_EXTENSION %08p ')\n", PdoExtAddr);
  200. }
  201. }
  202. #endif
  203. #ifdef ENABLE_COMMAND_LOG
  204. DumpCommandLog(Depth, srbDataAddr);
  205. #endif
  206. }
  207. dprintf("\n");
  208. }
  209. VOID DumpPdoState(IN ULONG Depth, IN ULONG State)
  210. {
  211. int inx, statebit, count;
  212. count = 0;
  213. xdprintf(Depth, ""), dprintf("PDO State (0x%08x): \n", State);
  214. if (State & 0x80000000) {
  215. xdprintf(Depth+1, "Initialized ");
  216. count++;
  217. }
  218. for (inx = 0; inx < MAX_PDO_STATES; inx++) {
  219. statebit = (1 << inx);
  220. if (State & statebit) {
  221. xdprintf(Depth+1, "%s ", PdoState[inx]);
  222. count++;
  223. if ((count % 2) == 0) {
  224. dprintf("\n");
  225. }
  226. }
  227. }
  228. dprintf("\n");
  229. }
  230. DECLARE_API(fdoext)
  231. /*++
  232. Routine Description:
  233. Dumps the fdo extension for a given device object, or dumps the
  234. given fdo extension
  235. Arguments:
  236. args - string containing the address of the device object or device
  237. extension
  238. Return Value:
  239. none
  240. --*/
  241. {
  242. ULONG64 devObjAddr = 0;
  243. ULONG64 detail = 0;
  244. ReloadSymbols("atapi.sys");
  245. if (GetExpressionEx(args, &devObjAddr, &args))
  246. {
  247. GetExpressionEx(args, &detail, &args);
  248. }
  249. if (devObjAddr){
  250. CSHORT objType = GetUSHORTField(devObjAddr, "nt!_DEVICE_OBJECT", "Type");
  251. if (objType == IO_TYPE_DEVICE){
  252. ULONG64 fdoExtAddr;
  253. fdoExtAddr = GetULONGField(devObjAddr, "nt!_DEVICE_OBJECT", "DeviceExtension");
  254. if (fdoExtAddr != BAD_VALUE){
  255. AtapiDumpFdoExtension(fdoExtAddr, (ULONG)detail, 0);
  256. }
  257. }
  258. else {
  259. dprintf("Error: 0x%08p is not a device object\n", devObjAddr);
  260. }
  261. }
  262. else {
  263. dprintf("\n usage: !atapikd.pdoext <atapi pdo> \n\n");
  264. }
  265. return S_OK;
  266. }
  267. DECLARE_API(miniext)
  268. /*++
  269. Routine Description:
  270. Dumps the Miniport device extension at the given address
  271. Arguments:
  272. args - string containing the address of the miniport extension
  273. Return Value:
  274. none
  275. --*/
  276. {
  277. ULONG64 hwDevExtAddr;
  278. ULONG Depth = 1;
  279. ReloadSymbols("atapi.sys");
  280. GetExpressionEx(args, &hwDevExtAddr, &args);
  281. if (hwDevExtAddr){
  282. ULONG64 deviceFlagsArrayAddr;
  283. ULONG64 lastLunArrayAddr;
  284. ULONG64 timeoutCountArrayAddr;
  285. ULONG64 numberOfCylindersArrayAddr;
  286. ULONG64 numberOHeadsArrayAddr;
  287. ULONG64 sectorsPerTrackArrayAddr;
  288. ULONG64 maxBlockTransferArrayAddr;
  289. ULONG64 identifyDataArrayAddr;
  290. deviceFlagsArrayAddr = GetFieldAddr(hwDevExtAddr, "atapi!_HW_DEVICE_EXTENSION", "DeviceFlags");
  291. lastLunArrayAddr = GetFieldAddr(hwDevExtAddr, "atapi!_HW_DEVICE_EXTENSION", "LastLun");
  292. timeoutCountArrayAddr = GetFieldAddr(hwDevExtAddr, "atapi!_HW_DEVICE_EXTENSION", "TimeoutCount");
  293. numberOfCylindersArrayAddr = GetFieldAddr(hwDevExtAddr, "atapi!_HW_DEVICE_EXTENSION", "NumberOfCylinders");
  294. numberOHeadsArrayAddr = GetFieldAddr(hwDevExtAddr, "atapi!_HW_DEVICE_EXTENSION", "NumberOfHeads");
  295. sectorsPerTrackArrayAddr = GetFieldAddr(hwDevExtAddr, "atapi!_HW_DEVICE_EXTENSION", "SectorsPerTrack");
  296. maxBlockTransferArrayAddr = GetFieldAddr(hwDevExtAddr, "atapi!_HW_DEVICE_EXTENSION", "MaximumBlockXfer");
  297. identifyDataArrayAddr = GetFieldAddr(hwDevExtAddr, "atapi!_HW_DEVICE_EXTENSION", "IdentifyData");
  298. if ((deviceFlagsArrayAddr != BAD_VALUE) && (lastLunArrayAddr != BAD_VALUE) &&
  299. (timeoutCountArrayAddr != BAD_VALUE) && (numberOfCylindersArrayAddr != BAD_VALUE) &&
  300. (numberOHeadsArrayAddr != BAD_VALUE) && (sectorsPerTrackArrayAddr != BAD_VALUE) &&
  301. (maxBlockTransferArrayAddr != BAD_VALUE) && (identifyDataArrayAddr != BAD_VALUE)){
  302. ULONG deviceFlagsArray[MAX_IDE_DEVICE * MAX_IDE_LINE];
  303. ULONG lastLunArray[MAX_IDE_DEVICE * MAX_IDE_LINE];
  304. ULONG timeoutCountArray[MAX_IDE_DEVICE * MAX_IDE_LINE];
  305. ULONG numberOfCylindersArray[MAX_IDE_DEVICE * MAX_IDE_LINE];
  306. ULONG numberOfHeadsArray[MAX_IDE_DEVICE * MAX_IDE_LINE];
  307. ULONG sectorsPerTrackArray[MAX_IDE_DEVICE * MAX_IDE_LINE];
  308. UCHAR maxBlockTransferArray[MAX_IDE_DEVICE * MAX_IDE_LINE];
  309. IDENTIFY_DATA identifyDataArray[MAX_IDE_DEVICE * MAX_IDE_LINE];
  310. ULONG resultLen;
  311. BOOLEAN ok;
  312. xdprintf(Depth, ""), dprintf("\nATAPI Miniport Device Extension at address 0x%08p\n\n", hwDevExtAddr);
  313. /*
  314. * Read in arrays of info for child LUNs
  315. */
  316. ok = TRUE;
  317. if (ok) ok = (BOOLEAN)ReadMemory(deviceFlagsArrayAddr, (PVOID)deviceFlagsArray, sizeof(deviceFlagsArray), &resultLen);
  318. if (ok) ok = (BOOLEAN)ReadMemory(lastLunArrayAddr, (PVOID)lastLunArray, sizeof(lastLunArray), &resultLen);
  319. if (ok) ok = (BOOLEAN)ReadMemory(timeoutCountArrayAddr, (PVOID)timeoutCountArray, sizeof(timeoutCountArray), &resultLen);
  320. if (ok) ok = (BOOLEAN)ReadMemory(numberOfCylindersArrayAddr, (PVOID)numberOfCylindersArray, sizeof(numberOfCylindersArray), &resultLen);
  321. if (ok) ok = (BOOLEAN)ReadMemory(numberOHeadsArrayAddr, (PVOID)numberOfHeadsArray, sizeof(numberOfHeadsArray), &resultLen);
  322. if (ok) ok = (BOOLEAN)ReadMemory(sectorsPerTrackArrayAddr, (PVOID)sectorsPerTrackArray, sizeof(sectorsPerTrackArray), &resultLen);
  323. if (ok) ok = (BOOLEAN)ReadMemory(maxBlockTransferArrayAddr, (PVOID)maxBlockTransferArray, sizeof(maxBlockTransferArray), &resultLen);
  324. if (ok) ok = (BOOLEAN)ReadMemory(identifyDataArrayAddr, (PVOID)identifyDataArray, sizeof(identifyDataArray), &resultLen);
  325. if (ok){
  326. ULONG i;
  327. /*
  328. * Display details for each device
  329. */
  330. dprintf("\n");
  331. for (i = 0; i < (MAX_IDE_DEVICE * MAX_IDE_LINE); i++) {
  332. if (deviceFlagsArray[i] & DFLAGS_DEVICE_PRESENT){
  333. xdprintf(Depth, "Device %d Details:\n", i);
  334. DumpFlags(Depth+1, "Device Flags", deviceFlagsArray[i], DevFlags);
  335. xdprintf(Depth+1, "TimeoutCount %u, LastLun %u, MaxBlockXfer 0x%02x\n",
  336. timeoutCountArray[i], lastLunArray[i], maxBlockTransferArray[i]);
  337. xdprintf(Depth+1, "NumCylinders 0x%08x, NumHeads 0x%08x, SectorsPerTrack 0x%08x\n",
  338. numberOfCylindersArray[i], numberOfHeadsArray[i], sectorsPerTrackArray[i]);
  339. /*
  340. * Display DeviceParameters info
  341. */
  342. dprintf("\n");
  343. if (IsPtr64()){
  344. xdprintf(Depth+1, "(cannot display DeviceParameters[] info for 64-bit)\n");
  345. }
  346. else {
  347. /*
  348. * DeviceParameters[] is an array of embedded structs.
  349. * Reading this in an architecture-agnostic way would be tricky,
  350. * so we punt and only do it for 32-bit target and 32-bit debug extension.
  351. */
  352. #ifdef _X86_
  353. HW_DEVICE_EXTENSION hwDevExt;
  354. ok = (BOOLEAN)ReadMemory(hwDevExtAddr, (PVOID)&hwDevExt, sizeof(hwDevExt), &resultLen);
  355. if (ok){
  356. #define IsInitXferMode(a) ((a == 0x7fffffff) ? -1 : a)
  357. xdprintf(Depth+1, "Device Parameters Summary :\n");
  358. xdprintf(Depth+2, "PioReadCommand 0x%02x, PioWriteCommand 0x%02x\n",
  359. hwDevExt.DeviceParameters[i].IdePioReadCommand,
  360. hwDevExt.DeviceParameters[i].IdePioWriteCommand);
  361. xdprintf(Depth+2, "IdeFlushCommand 0x%02x, MaxBytePerPioInterrupt %u\n",
  362. hwDevExt.DeviceParameters[i].IdeFlushCommand,
  363. hwDevExt.DeviceParameters[i].MaxBytePerPioInterrupt);
  364. xdprintf(Depth+2, "BestPioMode %d, BestSwDMAMode %d\n",
  365. IsInitXferMode(hwDevExt.DeviceParameters[i].BestPioMode),
  366. IsInitXferMode(hwDevExt.DeviceParameters[i].BestSwDmaMode));
  367. xdprintf(Depth+2, "BestMwDMAMode %d, BestUDMAMode %d\n",
  368. IsInitXferMode(hwDevExt.DeviceParameters[i].BestMwDmaMode),
  369. IsInitXferMode(hwDevExt.DeviceParameters[i].BestUDmaMode));
  370. xdprintf(Depth+2, "TMSupported 0x%08x, TMCurrent 0x%08x\n",
  371. hwDevExt.DeviceParameters[i].TransferModeSupported,
  372. hwDevExt.DeviceParameters[i].TransferModeCurrent);
  373. xdprintf(Depth+2, "TMMask 0x%08x, TMSelected 0x%08x\n",
  374. hwDevExt.DeviceParameters[i].TransferModeMask,
  375. hwDevExt.DeviceParameters[i].TransferModeSelected);
  376. }
  377. else {
  378. dprintf("\n failed to read HW_DEVICE_EXTENSION at 0x%08p\n", hwDevExtAddr);
  379. }
  380. #else
  381. xdprintf(Depth+1, "(64-bit debug extension cannot display DeviceParameters[] info)\n");
  382. #endif
  383. }
  384. /*
  385. * Display Identify Data
  386. */
  387. dprintf("\n");
  388. xdprintf(Depth+1, ""), dprintf("Identify Data Summary :\n");
  389. xdprintf(Depth+2, ""), dprintf("Word 1,3,6 (C-0x%04x, H-0x%04x, S-0x%04x) \n",
  390. identifyDataArray[i].NumCylinders,
  391. identifyDataArray[i].NumHeads,
  392. identifyDataArray[i].NumSectorsPerTrack);
  393. xdprintf(Depth+2, ""), dprintf("Word 54,55,56 (C-0x%04x, H-0x%04x, S-0x%04x) \n",
  394. identifyDataArray[i].NumberOfCurrentCylinders,
  395. identifyDataArray[i].NumberOfCurrentHeads,
  396. identifyDataArray[i].CurrentSectorsPerTrack);
  397. xdprintf(Depth+2, ""), dprintf("CurrentSectorCapacity 0x%08x, UserAddressableSectors 0x%08x\n",
  398. identifyDataArray[i].CurrentSectorCapacity,
  399. identifyDataArray[i].UserAddressableSectors);
  400. xdprintf(Depth+2, ""), dprintf("Capabilities(word 49) 0x%04x, UDMASup 0x%02x, UDMAActive 0x%02x\n",
  401. identifyDataArray[i].Capabilities,
  402. identifyDataArray[i].UltraDMASupport,
  403. identifyDataArray[i].UltraDMAActive);
  404. dprintf("\n");
  405. }
  406. else {
  407. xdprintf(Depth, "Device %d not present\n", i);
  408. }
  409. }
  410. }
  411. else {
  412. dprintf("\n ReadMemory failed to read one of the arrays from HW_DEVICE_EXTENSION @ 0x%08p\n", hwDevExtAddr);
  413. }
  414. }
  415. dprintf("\n");
  416. xdprintf(Depth+1, ""), dprintf("(for more info, use ' dt atapi!_HW_DEVICE_EXTENSION %08p ')\n", hwDevExtAddr);
  417. }
  418. else {
  419. dprintf("\n usage: !atapikd.miniext <PHW_DEVICE_EXTENSION> \n\n");
  420. }
  421. dprintf("\n");
  422. return S_OK;
  423. }
  424. VOID AtapiDumpFdoExtension(IN ULONG64 FdoExtAddr, IN ULONG Detail, IN ULONG Depth)
  425. {
  426. ULONG devicePowerState, systemPowerState;
  427. ULONG flags, srbFlags, fdoState;
  428. ULONG64 interruptDataAddr;
  429. ULONG64 ideResourceAddr;
  430. xdprintf(Depth, ""), dprintf("\nATAPI Functional Device Extension @ 0x%08p\n\n", FdoExtAddr);
  431. devicePowerState = (ULONG)GetULONGField(FdoExtAddr, "atapi!_FDO_EXTENSION", "DevicePowerState");
  432. systemPowerState = (ULONG)GetULONGField(FdoExtAddr, "atapi!_FDO_EXTENSION", "SystemPowerState");
  433. flags = (ULONG)GetULONGField(FdoExtAddr, "atapi!_FDO_EXTENSION", "Flags");
  434. srbFlags = (ULONG)GetULONGField(FdoExtAddr, "atapi!_FDO_EXTENSION", "SrbFlags");
  435. fdoState = (ULONG)GetULONGField(FdoExtAddr, "atapi!_FDO_EXTENSION", "FdoState");
  436. interruptDataAddr = GetFieldAddr(FdoExtAddr, "atapi!_FDO_EXTENSION", "InterruptData");
  437. ideResourceAddr = GetFieldAddr(FdoExtAddr, "atapi!_FDO_EXTENSION", "IdeResource");
  438. if ((devicePowerState != BAD_VALUE) && (systemPowerState != BAD_VALUE) &&
  439. (flags != BAD_VALUE) && (srbFlags != BAD_VALUE) && (fdoState != BAD_VALUE) &&
  440. (interruptDataAddr != BAD_VALUE) && (ideResourceAddr != BAD_VALUE)){
  441. ULONG interruptFlags, interruptMode, interruptLevel;
  442. BOOLEAN primaryDiskClaimed, secondaryDiskClaimed;
  443. xdprintf(Depth+1, "Power State (D%d, S%d)\n", devicePowerState-1, systemPowerState-1);
  444. DumpFlags(Depth+1, "Port Flags", flags, PortFlags);
  445. DumpFlags(Depth+1, "SRB Flags", srbFlags, SrbFlags);
  446. DumpFdoState(Depth+1, fdoState);
  447. /*
  448. * Display interrupt data
  449. */
  450. dprintf("\n");
  451. xdprintf(Depth+1, "Interrupt Data: \n");
  452. interruptFlags = (ULONG)GetULONGField(interruptDataAddr, "atapi!_INTERRUPT_DATA", "InterruptFlags");
  453. if (interruptFlags != BAD_VALUE){
  454. DumpFlags(Depth+2, "Port Flags", interruptFlags, PortFlags);
  455. }
  456. xdprintf(Depth+2, ""), dprintf("(for more info, use ' dt atapi!_INTERRUPT_DATA %08p ')\n", interruptDataAddr);
  457. /*
  458. * Display IDE_RESOURCE info
  459. */
  460. dprintf("\n");
  461. xdprintf(Depth+1, " IDE Resources: \n");
  462. interruptMode = (ULONG)GetULONGField(ideResourceAddr, "atapi!_IDE_RESOURCE", "InterruptMode");
  463. interruptLevel = (ULONG)GetULONGField(ideResourceAddr, "atapi!_IDE_RESOURCE", "InterruptLevel");
  464. primaryDiskClaimed = (BOOLEAN)GetUCHARField(ideResourceAddr, "atapi!_IDE_RESOURCE", "AtdiskPrimaryClaimed");
  465. secondaryDiskClaimed = (BOOLEAN)GetUCHARField(ideResourceAddr, "atapi!_IDE_RESOURCE", "AtdiskSecondaryClaimed");
  466. if ((interruptMode != BAD_VALUE) && (interruptLevel != BAD_VALUE) &&
  467. (primaryDiskClaimed != BAD_VALUE) && (secondaryDiskClaimed != BAD_VALUE)){
  468. xdprintf(Depth+2, "Interrupt Mode : %s \n", interruptMode ? "Latched" : "Level Sensitive");
  469. xdprintf(Depth+2, "Interrupt Level 0x%x\n", interruptLevel);
  470. xdprintf(Depth+2, "Primary Disk %s.\n", primaryDiskClaimed ? "Claimed" : "Not Claimed");
  471. xdprintf(Depth+2, "Secondary Disk %s.\n", secondaryDiskClaimed ? "Claimed" : "Not Claimed");
  472. }
  473. xdprintf(Depth+2, ""), dprintf("(for more info use ' dt atapi!_IDE_RESOURCE %08p ')\n", ideResourceAddr);
  474. }
  475. dprintf("\n");
  476. xdprintf(Depth+1, ""), dprintf("(for more info, use ' dt atapi!_FDO_EXTENSION %08p ')\n", FdoExtAddr);
  477. dprintf("\n");
  478. }
  479. VOID DumpFdoState(IN ULONG Depth, IN ULONG State)
  480. {
  481. int inx, count;
  482. count = 0;
  483. xdprintf(Depth, ""), dprintf("FDO State (0x%08x): \n", State);
  484. for (inx = 0; inx < MAX_FDO_STATES; inx++) {
  485. if (State & (1<<inx)) {
  486. xdprintf(Depth+1, "%s ", FdoState[inx]);
  487. }
  488. }
  489. dprintf("\n");
  490. }
  491. #ifdef ENABLE_COMMAND_LOG
  492. /*
  493. VOID ShowCommandLog(ULONG Depth, PCOMMAND_LOG CmdLogEntry, ULONG LogNumber)
  494. {
  495. if ((CmdLogEntry->FinalTaskFile.bCommandReg & IDE_STATUS_ERROR) || (CmdLogEntry->Cdb[0] == SCSIOP_REQUEST_SENSE)){
  496. xdprintf(Depth, "Log[%03d]: Cmd(%02x), SrbSts(%02x), Sts(%02x), BmStat(%02x), Sense(%02x/%02x/%02x)",
  497. LogNumber, CmdLogEntry->Cdb[0], CmdLogEntry->SrbStatus, CmdLogEntry->FinalTaskFile.bCommandReg, CmdLogEntry->BmStatus,
  498. CmdLogEntry->SenseData[0], CmdLogEntry->SenseData[1], CmdLogEntry->SenseData[2]);
  499. }
  500. else {
  501. xdprintf(Depth, "Log[%03d]: Cmd(%02x), SrbSts(%02x), Sts(%02x), BmStat(%02x)",
  502. LogNumber, CmdLogEntry->Cdb[0], CmdLogEntry->SrbStatus, CmdLogEntry->FinalTaskFile.bCommandReg, CmdLogEntry->BmStatus);
  503. }
  504. //
  505. // For pass through commands print out the command register
  506. //
  507. if (CmdLogEntry->Cdb[0] == 0xc8){
  508. xdprintf(Depth, "CmdR(%02x)", CmdLogEntry->Cdb[7]);
  509. }
  510. dprintf("\n");
  511. }
  512. */
  513. VOID
  514. FileTimeToString(
  515. IN LARGE_INTEGER Time,
  516. OUT PCHAR Buffer
  517. )
  518. {
  519. TIME_FIELDS TimeFields;
  520. TIME_ZONE_INFORMATION TimeZoneInfo;
  521. PWCHAR pszTz;
  522. ULONGLONG TzBias;
  523. DWORD Result;
  524. //
  525. // Get the local (to the debugger) timezone bias
  526. //
  527. Result = GetTimeZoneInformation(&TimeZoneInfo);
  528. if (Result == 0xffffffff) {
  529. pszTz = L"UTC";
  530. } else {
  531. //
  532. // Bias is in minutes, convert to 100ns units
  533. //
  534. TzBias = (ULONGLONG)TimeZoneInfo.Bias * 60 * 10000000;
  535. switch (Result) {
  536. case TIME_ZONE_ID_UNKNOWN:
  537. pszTz = L"unknown";
  538. break;
  539. case TIME_ZONE_ID_STANDARD:
  540. pszTz = TimeZoneInfo.StandardName;
  541. break;
  542. case TIME_ZONE_ID_DAYLIGHT:
  543. pszTz = TimeZoneInfo.DaylightName;
  544. break;
  545. }
  546. Time.QuadPart -= TzBias;
  547. }
  548. RtlTimeToTimeFields(&Time, &TimeFields);
  549. sprintf(Buffer, "%02d:%02d:%02d.%03d",
  550. TimeFields.Hour,
  551. TimeFields.Minute,
  552. TimeFields.Second,
  553. TimeFields.Milliseconds);
  554. }
  555. VOID
  556. ShowCommandLog(
  557. ULONG Depth,
  558. PCOMMAND_LOG CmdLogEntry,
  559. ULONG LogNumber
  560. )
  561. {
  562. LARGE_INTEGER timeDiff;
  563. CHAR startTime[256] = {0};
  564. ULONG sector;
  565. sector = (CmdLogEntry->Cdb[5] |
  566. CmdLogEntry->Cdb[4] << 8 |
  567. CmdLogEntry->Cdb[3] << 16 |
  568. CmdLogEntry->Cdb[2] << 24);
  569. FileTimeToString(CmdLogEntry->StartTime, startTime);
  570. dprintf ("%02x %02x %02x %08x %s ",
  571. CmdLogEntry->Cdb[0],
  572. CmdLogEntry->SrbStatus,
  573. CmdLogEntry->FinalTaskFile.bCommandReg,
  574. sector,
  575. startTime
  576. );
  577. if (CmdLogEntry->EndTime.QuadPart >= CmdLogEntry->StartTime.QuadPart) {
  578. timeDiff.QuadPart = CmdLogEntry->EndTime.QuadPart - CmdLogEntry->StartTime.QuadPart;
  579. timeDiff = Convert100nsToMilliseconds( timeDiff);
  580. dprintf ("(%4d ms)",
  581. timeDiff.LowPart
  582. );
  583. }
  584. dprintf("\n");
  585. }
  586. VOID DumpCommandLog(IN ULONG Depth, IN ULONG64 SrbDataAddr)
  587. {
  588. ULONG64 cmdLogAddr;
  589. ULONG cmdLogIndex;
  590. dprintf("\n");
  591. cmdLogAddr = GetULONGField(SrbDataAddr, "atapi!_SRB_DATA", "IdeCommandLog");
  592. cmdLogIndex = (ULONG)GetULONGField(SrbDataAddr, "atapi!_SRB_DATA", "IdeCommandLogIndex");
  593. if ((cmdLogAddr != BAD_VALUE) && (cmdLogIndex != BAD_VALUE)){
  594. UCHAR cmdLogBlock[MAX_COMMAND_LOG_ENTRIES*sizeof(COMMAND_LOG)];
  595. ULONG resultLen;
  596. BOOLEAN ok;
  597. xdprintf(Depth, ""), dprintf("Command Log Summary at %p\n\n", cmdLogAddr);
  598. ok = (BOOLEAN)ReadMemory(cmdLogAddr, (PVOID)cmdLogBlock, sizeof(cmdLogBlock), &resultLen);
  599. if (ok){
  600. PCOMMAND_LOG cmdLog = (PCOMMAND_LOG)cmdLogBlock;
  601. ULONG logIndex, logNumber;
  602. /*
  603. * Print the log in temporal order, starting at the correct point in the circular log buffer.
  604. */
  605. xdprintf(Depth+1, "Log Srb Ata \n");
  606. xdprintf(Depth+1, "Offset Cmd Status Status Lba Time Stamp\n");
  607. xdprintf(Depth+1, "------ --- ------ ------ --- ---- -----\n");
  608. logNumber = 0;
  609. for (logIndex=cmdLogIndex+1; logIndex< MAX_COMMAND_LOG_ENTRIES; logIndex++, logNumber++) {
  610. xdprintf(Depth+1,"+%04x : ",
  611. logIndex*GetTypeSize("atapi!_COMMAND_LOG")
  612. );
  613. ShowCommandLog(Depth+1, &cmdLog[logIndex], logNumber);
  614. }
  615. for (logIndex=0; logIndex <= cmdLogIndex; logIndex++, logNumber++) {
  616. xdprintf(Depth+1,"+%04x : ",
  617. logIndex*GetTypeSize("atapi!_COMMAND_LOG")
  618. );
  619. ShowCommandLog(Depth+1, &cmdLog[logIndex], logNumber);
  620. }
  621. }
  622. else {
  623. dprintf("\n Error reading command log at address 0x%08p\n", cmdLogAddr);
  624. }
  625. }
  626. }
  627. #endif
  628. /*
  629. *
  630. * USAGE: !atapikd.findirp {pdo|fdo} [specificIrp]
  631. */
  632. DECLARE_API(findirp)
  633. {
  634. ULONG64 devObjAddr = 0;
  635. ULONG64 specificIrpAddr = 0;
  636. ReloadSymbols("atapi.sys");
  637. /*
  638. * Make sure that the output buffers don't overflow by limiting the length of the input buffer that we process.
  639. */
  640. if (GetExpressionEx(args, &devObjAddr, &args))
  641. {
  642. GetExpressionEx(args, &specificIrpAddr, &args);
  643. }
  644. if (devObjAddr){
  645. if (IsAtapiPdo(devObjAddr)){
  646. /*
  647. * Find the Irp or dump all Irps
  648. * If specificIrpAddr is NULL, FindIrpInPdo will dump all Irps.
  649. */
  650. FindIrpInPdo(1, devObjAddr, specificIrpAddr, TRUE);
  651. }
  652. else if (IsAtapiFdo(devObjAddr)){
  653. /*
  654. * Find the Irp or dump all Irps
  655. * If specificIrpAddr is NULL, FindIrpInFdo will dump all Irps.
  656. */
  657. FindIrpInFdo(1, devObjAddr, specificIrpAddr);
  658. }
  659. else {
  660. dprintf("\n error: %08p is not an ATAPI Fdo or Pdo\n");
  661. }
  662. }
  663. else {
  664. dprintf("\n USAGE: !atapikd.findirp <pdo|fdo> [irp]\n");
  665. }
  666. return S_OK;
  667. }
  668. BOOLEAN IsAtapiPdo(ULONG64 DevObjAddr)
  669. {
  670. ULONG64 devExtAddr;
  671. BOOLEAN isPdo = FALSE;
  672. devExtAddr = GetULONGField(DevObjAddr, "nt!_DEVICE_OBJECT", "DeviceExtension");
  673. if (devExtAddr != BAD_VALUE){
  674. ULONG64 attacheeDevObj = GetULONGField(devExtAddr, "atapi!_PDO_EXTENSION", "AttacheeDeviceObject");
  675. if (attacheeDevObj == (ULONG64)NULL){
  676. // BUGBUG FINISH
  677. isPdo = TRUE;
  678. }
  679. }
  680. return isPdo;
  681. }
  682. BOOLEAN IsAtapiFdo(ULONG64 DevObjAddr)
  683. {
  684. ULONG64 devExtAddr;
  685. BOOLEAN isFdo = FALSE;
  686. devExtAddr = GetULONGField(DevObjAddr, "nt!_DEVICE_OBJECT", "DeviceExtension");
  687. if (devExtAddr != BAD_VALUE){
  688. ULONG64 attacheeDevObj = GetULONGField(devExtAddr, "atapi!_FDO_EXTENSION", "AttacheeDeviceObject");
  689. if (attacheeDevObj){
  690. // BUGBUG FINISH
  691. isFdo = TRUE;
  692. }
  693. }
  694. return isFdo;
  695. }
  696. /*
  697. * FindIrpInPdo
  698. *
  699. * If IrpAddr is NULL, dump all IRPs. Otherwise, find only the given Irp.
  700. */
  701. BOOLEAN FindIrpInPdo(ULONG Depth, ULONG64 PdoAddr, ULONG64 IrpAddr, BOOLEAN SearchParent)
  702. {
  703. ULONG64 currentIrp;
  704. ULONG64 pdoExtAddr;
  705. ULONG64 deviceQueueAddr;
  706. BOOLEAN found = FALSE;
  707. xdprintf(Depth, ""), dprintf("Searching Atapi Pdo %08p ...\n", PdoAddr);
  708. currentIrp = GetULONGField(PdoAddr, "nt!_DEVICE_OBJECT", "CurrentIrp");
  709. if (currentIrp && (!IrpAddr || (currentIrp == IrpAddr))){
  710. xdprintf(Depth+1, ""), dprintf("- CurrentIrp of Pdo %08p = %08p\n", PdoAddr, currentIrp);
  711. }
  712. deviceQueueAddr = GetFieldAddr(PdoAddr, "nt!_DEVICE_OBJECT", "DeviceQueue");
  713. if (deviceQueueAddr != BAD_VALUE){
  714. ULONG64 devQueueListHeadAddr = GetFieldAddr(deviceQueueAddr, "nt!_KDEVICE_QUEUE", "DeviceListHead");
  715. if (devQueueListHeadAddr != BAD_VALUE){
  716. if (IrpAddr){
  717. if (FindIrpInDeviceQueue(devQueueListHeadAddr, IrpAddr)){
  718. xdprintf(Depth+1, ""), dprintf("- Irp %08p is in DeviceQueue of Pdo %08p\n", IrpAddr, PdoAddr);
  719. }
  720. }
  721. else {
  722. DumpIrpDeviceQueue(Depth+1, "Pdo Irp Queue", devQueueListHeadAddr);
  723. }
  724. }
  725. }
  726. pdoExtAddr = GetULONGField(PdoAddr, "nt!_DEVICE_OBJECT", "DeviceExtension");
  727. if (pdoExtAddr != BAD_VALUE){
  728. ULONG64 pendingIrp = GetULONGField(pdoExtAddr, "atapi!_PDO_EXTENSION", "PendingRequest");
  729. ULONG64 busyIrp = GetULONGField(pdoExtAddr, "atapi!_PDO_EXTENSION", "BusyRequest");
  730. ULONG64 abortSrbAddr = GetULONGField(pdoExtAddr, "atapi!_PDO_EXTENSION", "AbortSrb");
  731. if (pendingIrp && (!IrpAddr || (pendingIrp == IrpAddr))){
  732. xdprintf(Depth+1, ""), dprintf("- PendingRequest of Pdo %08p = %08p\n", PdoAddr, pendingIrp);
  733. found = TRUE;
  734. }
  735. if (busyIrp && (!IrpAddr || (busyIrp == IrpAddr))){
  736. xdprintf(Depth+1, ""), dprintf("- BusyRequest of Pdo %08p = %08p\n", PdoAddr, busyIrp);
  737. found = TRUE;
  738. }
  739. if (abortSrbAddr && (abortSrbAddr != BAD_VALUE)){
  740. ULONG64 origRequestIrpAddr = GetULONGField(abortSrbAddr, "atapi!_SCSI_REQUEST_BLOCK", "OriginalRequest");
  741. if (origRequestIrpAddr && (!IrpAddr || (origRequestIrpAddr == IrpAddr))){
  742. xdprintf(Depth+1, ""), dprintf("- AbortSrb %08p of Pdo %08p has OriginalRequest Irp %08p\n", abortSrbAddr, PdoAddr, origRequestIrpAddr);
  743. }
  744. }
  745. if (SearchParent){
  746. ULONG64 fdoExtAddr = GetULONGField(pdoExtAddr, "atapi!_PDO_EXTENSION", "ParentDeviceExtension");
  747. if (fdoExtAddr != BAD_VALUE){
  748. ULONG64 fdoAddr = GetULONGField(fdoExtAddr, "atapi!_FDO_EXTENSION", "DeviceObject");
  749. if (FindIrpInFdo(Depth+1, fdoAddr, IrpAddr)){
  750. found = TRUE;
  751. }
  752. }
  753. }
  754. }
  755. return found;
  756. }
  757. /*
  758. * FindIrpInFdo
  759. *
  760. * If IrpAddr is NULL, dump all IRPs. Otherwise, find only the given Irp.
  761. */
  762. BOOLEAN FindIrpInFdo(ULONG Depth, ULONG64 FdoAddr, ULONG64 IrpAddr)
  763. {
  764. ULONG64 fdoExtAddr;
  765. ULONG64 currentIrp;
  766. ULONG64 deviceQueueAddr;
  767. BOOLEAN found = FALSE;
  768. xdprintf(Depth, ""), dprintf("Searching Atapi Fdo %08p ...\n", FdoAddr);
  769. deviceQueueAddr = GetFieldAddr(FdoAddr, "nt!_DEVICE_OBJECT", "DeviceQueue");
  770. if (deviceQueueAddr != BAD_VALUE){
  771. ULONG64 devQueueListHeadAddr = GetFieldAddr(deviceQueueAddr, "nt!_KDEVICE_QUEUE", "DeviceListHead");
  772. if (devQueueListHeadAddr != BAD_VALUE){
  773. if (IrpAddr){
  774. if (FindIrpInDeviceQueue(devQueueListHeadAddr, IrpAddr)){
  775. xdprintf(Depth+1, ""), dprintf("- Irp %08p is in DeviceQueue of Fdo %08p\n", IrpAddr, FdoAddr);
  776. }
  777. }
  778. else {
  779. DumpIrpDeviceQueue(Depth+1, "Fdo Irp Queue", devQueueListHeadAddr);
  780. }
  781. }
  782. }
  783. currentIrp = GetULONGField(FdoAddr, "nt!_DEVICE_OBJECT", "CurrentIrp");
  784. if (currentIrp && (!IrpAddr || (currentIrp == IrpAddr))){
  785. xdprintf(Depth+1, ""), dprintf("- CurrentIrp of Fdo %08p = %08p\n", FdoAddr, currentIrp);
  786. }
  787. fdoExtAddr = GetULONGField(FdoAddr, "nt!_DEVICE_OBJECT", "DeviceExtension");
  788. if (fdoExtAddr != BAD_VALUE){
  789. ULONG64 resetSrbAddr = GetULONGField(fdoExtAddr, "atapi!_FDO_EXTENSION", "ResetSrb");
  790. if (resetSrbAddr && (resetSrbAddr != BAD_VALUE)){
  791. ULONG64 origRequestIrpAddr = GetULONGField(resetSrbAddr, "atapi!_SCSI_REQUEST_BLOCK", "OriginalRequest");
  792. if (origRequestIrpAddr && (!IrpAddr || (origRequestIrpAddr == IrpAddr))){
  793. xdprintf(Depth+1, ""), dprintf("- ResetSrb %08p of Fdo %08p has OriginalRequest Irp %08p\n", resetSrbAddr, FdoAddr, origRequestIrpAddr);
  794. found = TRUE;
  795. }
  796. }
  797. }
  798. return found;
  799. }