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.

806 lines
32 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1991 - 1999
  3. Module Name:
  4. debug.c
  5. Abstract:
  6. CLASSPNP debug code and data
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. Revision History:
  11. --*/
  12. #include "classp.h"
  13. #include "debug.h"
  14. #if DBG
  15. //
  16. // default to not breaking in for lost irps, five minutes before we even
  17. // bother checking for lost irps, using standard debug print macros, and
  18. // using a 64k debug print buffer
  19. //
  20. #ifndef CLASS_GLOBAL_BREAK_ON_LOST_IRPS
  21. #error "CLASS_GLOBAL_BREAK_ON_LOST_IRPS undefined"
  22. #define CLASS_GLOBAL_BREAK_ON_LOST_IRPS 0
  23. #endif // CLASS_GLOBAL_BREAK_ON_LOST_IRPS
  24. #ifndef CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB
  25. #error "CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB undefined"
  26. #define CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB 300
  27. #endif // CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB
  28. #ifndef CLASS_GLOBAL_BUFFERED_DEBUG_PRINT
  29. #error "CLASS_GLOBAL_BUFFERED_DEBUG_PRINT undefined"
  30. #define CLASS_GLOBAL_BUFFERED_DEBUG_PRINT 0
  31. #endif // CLASS_GLOBAL_BUFFERED_DEBUG_PRINT
  32. #ifndef CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE
  33. #error "CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE undefined"
  34. #define CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE 512
  35. #endif // CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE
  36. #ifndef CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS
  37. #error "CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS undefined"
  38. #define CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS 512
  39. #endif // CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS
  40. #pragma data_seg("NONPAGE")
  41. CLASSPNP_GLOBALS ClasspnpGlobals;
  42. //
  43. // the low sixteen bits are used to see if the debug level is high enough
  44. // the high sixteen bits are used to singly enable debug levels 1-16
  45. //
  46. LONG ClassDebug = 0x00000000;
  47. BOOLEAN DebugTrapOnWarn = FALSE;
  48. VOID ClasspInitializeDebugGlobals()
  49. {
  50. KIRQL irql;
  51. if (InterlockedCompareExchange(&ClasspnpGlobals.Initializing, 1, 0) == 0) {
  52. KeInitializeSpinLock(&ClasspnpGlobals.SpinLock);
  53. KeAcquireSpinLock(&ClasspnpGlobals.SpinLock, &irql);
  54. DebugPrint((1, "CLASSPNP.SYS => Initializing ClasspnpGlobals...\n"));
  55. ClasspnpGlobals.Buffer = NULL;
  56. ClasspnpGlobals.Index = -1;
  57. ClasspnpGlobals.BreakOnLostIrps = CLASS_GLOBAL_BREAK_ON_LOST_IRPS;
  58. ClasspnpGlobals.EachBufferSize = CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE;
  59. ClasspnpGlobals.NumberOfBuffers = CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS;
  60. ClasspnpGlobals.SecondsToWaitForIrps = CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB;
  61. //
  62. // this should be the last item set
  63. //
  64. ClasspnpGlobals.UseBufferedDebugPrint = CLASS_GLOBAL_BUFFERED_DEBUG_PRINT;
  65. KeReleaseSpinLock(&ClasspnpGlobals.SpinLock, irql);
  66. InterlockedExchange(&ClasspnpGlobals.Initialized, 1);
  67. }
  68. }
  69. /*++////////////////////////////////////////////////////////////////////////////
  70. ClassDebugPrint()
  71. Routine Description:
  72. Debug print for all class drivers, NOOP on FRE versions.
  73. Allows printing to a debug buffer (with auto fallback to kdprint) by
  74. properly setting the Globals in classpnp on CHK versions.
  75. Arguments:
  76. Debug print level, or from 0 to 3 for legacy drivers.
  77. Return Value:
  78. None
  79. --*/
  80. VOID ClassDebugPrint(CLASS_DEBUG_LEVEL DebugPrintLevel, PCCHAR DebugMessage, ...)
  81. {
  82. va_list ap;
  83. va_start(ap, DebugMessage);
  84. if ((DebugPrintLevel <= (ClassDebug & 0x0000ffff)) ||
  85. ((1 << (DebugPrintLevel + 15)) & ClassDebug)) {
  86. if (ClasspnpGlobals.UseBufferedDebugPrint &&
  87. ClasspnpGlobals.Buffer == NULL) {
  88. //
  89. // this double-check prevents always taking
  90. // a spinlock just to ensure we have a buffer
  91. //
  92. KIRQL irql;
  93. KeAcquireSpinLock(&ClasspnpGlobals.SpinLock, &irql);
  94. if (ClasspnpGlobals.Buffer == NULL) {
  95. SIZE_T bufferSize;
  96. bufferSize = ClasspnpGlobals.NumberOfBuffers *
  97. ClasspnpGlobals.EachBufferSize;
  98. DbgPrintEx(DPFLTR_CLASSPNP_ID, DPFLTR_ERROR_LEVEL,
  99. "ClassDebugPrint: Allocating %x bytes for "
  100. "classdebugprint buffer\n", bufferSize);
  101. ClasspnpGlobals.Index = -1;
  102. ClasspnpGlobals.Buffer =
  103. ExAllocatePoolWithTag(NonPagedPool, bufferSize, 'bDcS');
  104. DbgPrintEx(DPFLTR_CLASSPNP_ID, DPFLTR_ERROR_LEVEL,
  105. "ClassDebugPrint: Allocated buffer at %p\n",
  106. ClasspnpGlobals.Buffer);
  107. }
  108. KeReleaseSpinLock(&ClasspnpGlobals.SpinLock, irql);
  109. }
  110. if (ClasspnpGlobals.UseBufferedDebugPrint &&
  111. ClasspnpGlobals.Buffer != NULL) {
  112. //
  113. // we never free the buffer, so once it exists,
  114. // we can just print to it with immunity
  115. //
  116. ULONG index;
  117. PUCHAR buffer;
  118. index = InterlockedIncrement(&ClasspnpGlobals.Index);
  119. index %= ClasspnpGlobals.NumberOfBuffers;
  120. index *= (ULONG)ClasspnpGlobals.EachBufferSize;
  121. buffer = ClasspnpGlobals.Buffer;
  122. buffer += index;
  123. _vsnprintf(buffer, ClasspnpGlobals.EachBufferSize, DebugMessage, ap);
  124. } else {
  125. //
  126. // either we could not allocate a buffer for debug prints
  127. // or buffered debug prints are disabled
  128. //
  129. vDbgPrintEx(DPFLTR_CLASSPNP_ID, DPFLTR_INFO_LEVEL, DebugMessage, ap);
  130. }
  131. }
  132. va_end(ap);
  133. }
  134. char *DbgGetIoctlStr(ULONG ioctl)
  135. {
  136. char *ioctlStr = "?";
  137. switch (ioctl){
  138. #undef MAKE_CASE
  139. #define MAKE_CASE(ioctlCode) case ioctlCode: ioctlStr = #ioctlCode; break;
  140. MAKE_CASE(IOCTL_STORAGE_CHECK_VERIFY)
  141. MAKE_CASE(IOCTL_STORAGE_CHECK_VERIFY2)
  142. MAKE_CASE(IOCTL_STORAGE_MEDIA_REMOVAL)
  143. MAKE_CASE(IOCTL_STORAGE_EJECT_MEDIA)
  144. MAKE_CASE(IOCTL_STORAGE_LOAD_MEDIA)
  145. MAKE_CASE(IOCTL_STORAGE_LOAD_MEDIA2)
  146. MAKE_CASE(IOCTL_STORAGE_RESERVE)
  147. MAKE_CASE(IOCTL_STORAGE_RELEASE)
  148. MAKE_CASE(IOCTL_STORAGE_FIND_NEW_DEVICES)
  149. MAKE_CASE(IOCTL_STORAGE_EJECTION_CONTROL)
  150. MAKE_CASE(IOCTL_STORAGE_MCN_CONTROL)
  151. MAKE_CASE(IOCTL_STORAGE_GET_MEDIA_TYPES)
  152. MAKE_CASE(IOCTL_STORAGE_GET_MEDIA_TYPES_EX)
  153. MAKE_CASE(IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER)
  154. MAKE_CASE(IOCTL_STORAGE_GET_HOTPLUG_INFO)
  155. MAKE_CASE(IOCTL_STORAGE_RESET_BUS)
  156. MAKE_CASE(IOCTL_STORAGE_RESET_DEVICE)
  157. MAKE_CASE(IOCTL_STORAGE_GET_DEVICE_NUMBER)
  158. MAKE_CASE(IOCTL_STORAGE_PREDICT_FAILURE)
  159. MAKE_CASE(IOCTL_STORAGE_QUERY_PROPERTY)
  160. MAKE_CASE(OBSOLETE_IOCTL_STORAGE_RESET_BUS)
  161. MAKE_CASE(OBSOLETE_IOCTL_STORAGE_RESET_DEVICE)
  162. }
  163. return ioctlStr;
  164. }
  165. char *DbgGetScsiOpStr(PSCSI_REQUEST_BLOCK Srb)
  166. {
  167. PCDB pCdb = (PCDB)Srb->Cdb;
  168. UCHAR scsiOp = pCdb->CDB6GENERIC.OperationCode;
  169. char *scsiOpStr = "?";
  170. switch (scsiOp){
  171. #undef MAKE_CASE
  172. #define MAKE_CASE(scsiOpCode) case scsiOpCode: scsiOpStr = #scsiOpCode; break;
  173. MAKE_CASE(SCSIOP_TEST_UNIT_READY)
  174. MAKE_CASE(SCSIOP_REWIND) // aka SCSIOP_REZERO_UNIT
  175. MAKE_CASE(SCSIOP_REQUEST_BLOCK_ADDR)
  176. MAKE_CASE(SCSIOP_REQUEST_SENSE)
  177. MAKE_CASE(SCSIOP_FORMAT_UNIT)
  178. MAKE_CASE(SCSIOP_READ_BLOCK_LIMITS)
  179. MAKE_CASE(SCSIOP_INIT_ELEMENT_STATUS) // aka SCSIOP_REASSIGN_BLOCKS
  180. MAKE_CASE(SCSIOP_RECEIVE) // aka SCSIOP_READ6
  181. MAKE_CASE(SCSIOP_SEND) // aka SCSIOP_WRITE6, SCSIOP_PRINT
  182. MAKE_CASE(SCSIOP_SLEW_PRINT) // aka SCSIOP_SEEK6, SCSIOP_TRACK_SELECT
  183. MAKE_CASE(SCSIOP_SEEK_BLOCK)
  184. MAKE_CASE(SCSIOP_PARTITION)
  185. MAKE_CASE(SCSIOP_READ_REVERSE)
  186. MAKE_CASE(SCSIOP_FLUSH_BUFFER) // aka SCSIOP_WRITE_FILEMARKS
  187. MAKE_CASE(SCSIOP_SPACE)
  188. MAKE_CASE(SCSIOP_INQUIRY)
  189. MAKE_CASE(SCSIOP_VERIFY6)
  190. MAKE_CASE(SCSIOP_RECOVER_BUF_DATA)
  191. MAKE_CASE(SCSIOP_MODE_SELECT)
  192. MAKE_CASE(SCSIOP_RESERVE_UNIT)
  193. MAKE_CASE(SCSIOP_RELEASE_UNIT)
  194. MAKE_CASE(SCSIOP_COPY)
  195. MAKE_CASE(SCSIOP_ERASE)
  196. MAKE_CASE(SCSIOP_MODE_SENSE)
  197. MAKE_CASE(SCSIOP_START_STOP_UNIT) // aka SCSIOP_STOP_PRINT, SCSIOP_LOAD_UNLOAD
  198. MAKE_CASE(SCSIOP_RECEIVE_DIAGNOSTIC)
  199. MAKE_CASE(SCSIOP_SEND_DIAGNOSTIC)
  200. MAKE_CASE(SCSIOP_MEDIUM_REMOVAL)
  201. MAKE_CASE(SCSIOP_READ_FORMATTED_CAPACITY)
  202. MAKE_CASE(SCSIOP_READ_CAPACITY)
  203. MAKE_CASE(SCSIOP_READ)
  204. MAKE_CASE(SCSIOP_WRITE)
  205. MAKE_CASE(SCSIOP_SEEK) // aka SCSIOP_LOCATE, SCSIOP_POSITION_TO_ELEMENT
  206. MAKE_CASE(SCSIOP_WRITE_VERIFY)
  207. MAKE_CASE(SCSIOP_VERIFY)
  208. MAKE_CASE(SCSIOP_SEARCH_DATA_HIGH)
  209. MAKE_CASE(SCSIOP_SEARCH_DATA_EQUAL)
  210. MAKE_CASE(SCSIOP_SEARCH_DATA_LOW)
  211. MAKE_CASE(SCSIOP_SET_LIMITS)
  212. MAKE_CASE(SCSIOP_READ_POSITION)
  213. MAKE_CASE(SCSIOP_SYNCHRONIZE_CACHE)
  214. MAKE_CASE(SCSIOP_COMPARE)
  215. MAKE_CASE(SCSIOP_COPY_COMPARE)
  216. MAKE_CASE(SCSIOP_WRITE_DATA_BUFF)
  217. MAKE_CASE(SCSIOP_READ_DATA_BUFF)
  218. MAKE_CASE(SCSIOP_CHANGE_DEFINITION)
  219. MAKE_CASE(SCSIOP_READ_SUB_CHANNEL)
  220. MAKE_CASE(SCSIOP_READ_TOC)
  221. MAKE_CASE(SCSIOP_READ_HEADER)
  222. MAKE_CASE(SCSIOP_PLAY_AUDIO)
  223. MAKE_CASE(SCSIOP_GET_CONFIGURATION)
  224. MAKE_CASE(SCSIOP_PLAY_AUDIO_MSF)
  225. MAKE_CASE(SCSIOP_PLAY_TRACK_INDEX)
  226. MAKE_CASE(SCSIOP_PLAY_TRACK_RELATIVE)
  227. MAKE_CASE(SCSIOP_GET_EVENT_STATUS)
  228. MAKE_CASE(SCSIOP_PAUSE_RESUME)
  229. MAKE_CASE(SCSIOP_LOG_SELECT)
  230. MAKE_CASE(SCSIOP_LOG_SENSE)
  231. MAKE_CASE(SCSIOP_STOP_PLAY_SCAN)
  232. MAKE_CASE(SCSIOP_READ_DISK_INFORMATION)
  233. MAKE_CASE(SCSIOP_READ_TRACK_INFORMATION)
  234. MAKE_CASE(SCSIOP_RESERVE_TRACK_RZONE)
  235. MAKE_CASE(SCSIOP_SEND_OPC_INFORMATION)
  236. MAKE_CASE(SCSIOP_MODE_SELECT10)
  237. MAKE_CASE(SCSIOP_MODE_SENSE10)
  238. MAKE_CASE(SCSIOP_CLOSE_TRACK_SESSION)
  239. MAKE_CASE(SCSIOP_READ_BUFFER_CAPACITY)
  240. MAKE_CASE(SCSIOP_SEND_CUE_SHEET)
  241. MAKE_CASE(SCSIOP_PERSISTENT_RESERVE_IN)
  242. MAKE_CASE(SCSIOP_PERSISTENT_RESERVE_OUT)
  243. MAKE_CASE(SCSIOP_REPORT_LUNS)
  244. MAKE_CASE(SCSIOP_BLANK)
  245. MAKE_CASE(SCSIOP_SEND_KEY)
  246. MAKE_CASE(SCSIOP_REPORT_KEY)
  247. MAKE_CASE(SCSIOP_MOVE_MEDIUM)
  248. MAKE_CASE(SCSIOP_LOAD_UNLOAD_SLOT) // aka SCSIOP_EXCHANGE_MEDIUM
  249. MAKE_CASE(SCSIOP_SET_READ_AHEAD)
  250. MAKE_CASE(SCSIOP_READ_DVD_STRUCTURE)
  251. MAKE_CASE(SCSIOP_REQUEST_VOL_ELEMENT)
  252. MAKE_CASE(SCSIOP_SEND_VOLUME_TAG)
  253. MAKE_CASE(SCSIOP_READ_ELEMENT_STATUS)
  254. MAKE_CASE(SCSIOP_READ_CD_MSF)
  255. MAKE_CASE(SCSIOP_SCAN_CD)
  256. MAKE_CASE(SCSIOP_SET_CD_SPEED)
  257. MAKE_CASE(SCSIOP_PLAY_CD)
  258. MAKE_CASE(SCSIOP_MECHANISM_STATUS)
  259. MAKE_CASE(SCSIOP_READ_CD)
  260. MAKE_CASE(SCSIOP_SEND_DVD_STRUCTURE)
  261. MAKE_CASE(SCSIOP_INIT_ELEMENT_RANGE)
  262. }
  263. return scsiOpStr;
  264. }
  265. char *DbgGetSrbStatusStr(PSCSI_REQUEST_BLOCK Srb)
  266. {
  267. char *srbStatStr = "?";
  268. switch (Srb->SrbStatus){
  269. #undef MAKE_CASE
  270. #define MAKE_CASE(srbStat) \
  271. case srbStat: \
  272. srbStatStr = #srbStat; \
  273. break; \
  274. case srbStat|SRB_STATUS_QUEUE_FROZEN: \
  275. srbStatStr = #srbStat "|SRB_STATUS_QUEUE_FROZEN"; \
  276. break; \
  277. case srbStat|SRB_STATUS_AUTOSENSE_VALID: \
  278. srbStatStr = #srbStat "|SRB_STATUS_AUTOSENSE_VALID"; \
  279. break; \
  280. case srbStat|SRB_STATUS_QUEUE_FROZEN|SRB_STATUS_AUTOSENSE_VALID: \
  281. srbStatStr = #srbStat "|SRB_STATUS_QUEUE_FROZEN|SRB_STATUS_AUTOSENSE_VALID"; \
  282. break;
  283. MAKE_CASE(SRB_STATUS_PENDING)
  284. MAKE_CASE(SRB_STATUS_SUCCESS)
  285. MAKE_CASE(SRB_STATUS_ABORTED)
  286. MAKE_CASE(SRB_STATUS_ABORT_FAILED)
  287. MAKE_CASE(SRB_STATUS_ERROR)
  288. MAKE_CASE(SRB_STATUS_BUSY)
  289. MAKE_CASE(SRB_STATUS_INVALID_REQUEST)
  290. MAKE_CASE(SRB_STATUS_INVALID_PATH_ID)
  291. MAKE_CASE(SRB_STATUS_NO_DEVICE)
  292. MAKE_CASE(SRB_STATUS_TIMEOUT)
  293. MAKE_CASE(SRB_STATUS_SELECTION_TIMEOUT)
  294. MAKE_CASE(SRB_STATUS_COMMAND_TIMEOUT)
  295. MAKE_CASE(SRB_STATUS_MESSAGE_REJECTED)
  296. MAKE_CASE(SRB_STATUS_BUS_RESET)
  297. MAKE_CASE(SRB_STATUS_PARITY_ERROR)
  298. MAKE_CASE(SRB_STATUS_REQUEST_SENSE_FAILED)
  299. MAKE_CASE(SRB_STATUS_NO_HBA)
  300. MAKE_CASE(SRB_STATUS_DATA_OVERRUN)
  301. MAKE_CASE(SRB_STATUS_UNEXPECTED_BUS_FREE)
  302. MAKE_CASE(SRB_STATUS_PHASE_SEQUENCE_FAILURE)
  303. MAKE_CASE(SRB_STATUS_BAD_SRB_BLOCK_LENGTH)
  304. MAKE_CASE(SRB_STATUS_REQUEST_FLUSHED)
  305. MAKE_CASE(SRB_STATUS_INVALID_LUN)
  306. MAKE_CASE(SRB_STATUS_INVALID_TARGET_ID)
  307. MAKE_CASE(SRB_STATUS_BAD_FUNCTION)
  308. MAKE_CASE(SRB_STATUS_ERROR_RECOVERY)
  309. MAKE_CASE(SRB_STATUS_NOT_POWERED)
  310. MAKE_CASE(SRB_STATUS_INTERNAL_ERROR)
  311. }
  312. return srbStatStr;
  313. }
  314. char *DbgGetSenseCodeStr(PSCSI_REQUEST_BLOCK Srb)
  315. {
  316. char *senseCodeStr = "?";
  317. if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID){
  318. PSENSE_DATA senseData;
  319. UCHAR senseCode;
  320. ASSERT(Srb->SenseInfoBuffer);
  321. senseData = Srb->SenseInfoBuffer;
  322. senseCode = senseData->SenseKey & 0xf;
  323. switch (senseCode){
  324. #undef MAKE_CASE
  325. #define MAKE_CASE(snsCod) case snsCod: senseCodeStr = #snsCod; break;
  326. MAKE_CASE(SCSI_SENSE_NO_SENSE)
  327. MAKE_CASE(SCSI_SENSE_RECOVERED_ERROR)
  328. MAKE_CASE(SCSI_SENSE_NOT_READY)
  329. MAKE_CASE(SCSI_SENSE_MEDIUM_ERROR)
  330. MAKE_CASE(SCSI_SENSE_HARDWARE_ERROR)
  331. MAKE_CASE(SCSI_SENSE_ILLEGAL_REQUEST)
  332. MAKE_CASE(SCSI_SENSE_UNIT_ATTENTION)
  333. MAKE_CASE(SCSI_SENSE_DATA_PROTECT)
  334. MAKE_CASE(SCSI_SENSE_BLANK_CHECK)
  335. MAKE_CASE(SCSI_SENSE_UNIQUE)
  336. MAKE_CASE(SCSI_SENSE_COPY_ABORTED)
  337. MAKE_CASE(SCSI_SENSE_ABORTED_COMMAND)
  338. MAKE_CASE(SCSI_SENSE_EQUAL)
  339. MAKE_CASE(SCSI_SENSE_VOL_OVERFLOW)
  340. MAKE_CASE(SCSI_SENSE_MISCOMPARE)
  341. MAKE_CASE(SCSI_SENSE_RESERVED)
  342. }
  343. }
  344. return senseCodeStr;
  345. }
  346. char *DbgGetAdditionalSenseCodeStr(PSCSI_REQUEST_BLOCK Srb)
  347. {
  348. char *adSenseCodeStr = "?";
  349. if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID){
  350. PSENSE_DATA senseData;
  351. UCHAR adSenseCode;
  352. ASSERT(Srb->SenseInfoBuffer);
  353. senseData = Srb->SenseInfoBuffer;
  354. adSenseCode = senseData->AdditionalSenseCode;
  355. switch (adSenseCode){
  356. #undef MAKE_CASE
  357. #define MAKE_CASE(adSnsCod) case adSnsCod: adSenseCodeStr = #adSnsCod; break;
  358. MAKE_CASE(SCSI_ADSENSE_NO_SENSE)
  359. MAKE_CASE(SCSI_ADSENSE_LUN_NOT_READY)
  360. MAKE_CASE(SCSI_ADSENSE_TRACK_ERROR)
  361. MAKE_CASE(SCSI_ADSENSE_SEEK_ERROR)
  362. MAKE_CASE(SCSI_ADSENSE_REC_DATA_NOECC)
  363. MAKE_CASE(SCSI_ADSENSE_REC_DATA_ECC)
  364. MAKE_CASE(SCSI_ADSENSE_ILLEGAL_COMMAND)
  365. MAKE_CASE(SCSI_ADSENSE_ILLEGAL_BLOCK)
  366. MAKE_CASE(SCSI_ADSENSE_INVALID_CDB)
  367. MAKE_CASE(SCSI_ADSENSE_INVALID_LUN)
  368. MAKE_CASE(SCSI_ADSENSE_WRITE_PROTECT) // aka SCSI_ADWRITE_PROTECT
  369. MAKE_CASE(SCSI_ADSENSE_MEDIUM_CHANGED)
  370. MAKE_CASE(SCSI_ADSENSE_BUS_RESET)
  371. MAKE_CASE(SCSI_ADSENSE_INVALID_MEDIA)
  372. MAKE_CASE(SCSI_ADSENSE_NO_MEDIA_IN_DEVICE)
  373. MAKE_CASE(SCSI_ADSENSE_POSITION_ERROR)
  374. MAKE_CASE(SCSI_ADSENSE_OPERATOR_REQUEST)
  375. MAKE_CASE(SCSI_ADSENSE_FAILURE_PREDICTION_THRESHOLD_EXCEEDED)
  376. MAKE_CASE(SCSI_ADSENSE_COPY_PROTECTION_FAILURE)
  377. MAKE_CASE(SCSI_ADSENSE_VENDOR_UNIQUE)
  378. MAKE_CASE(SCSI_ADSENSE_MUSIC_AREA)
  379. MAKE_CASE(SCSI_ADSENSE_DATA_AREA)
  380. MAKE_CASE(SCSI_ADSENSE_VOLUME_OVERFLOW)
  381. }
  382. }
  383. return adSenseCodeStr;
  384. }
  385. char *DbgGetAdditionalSenseCodeQualifierStr(PSCSI_REQUEST_BLOCK Srb)
  386. {
  387. char *adSenseCodeQualStr = "?";
  388. if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID){
  389. PSENSE_DATA senseData;
  390. UCHAR adSenseCode;
  391. UCHAR adSenseCodeQual;
  392. ASSERT(Srb->SenseInfoBuffer);
  393. senseData = Srb->SenseInfoBuffer;
  394. adSenseCode = senseData->AdditionalSenseCode;
  395. adSenseCodeQual = senseData->AdditionalSenseCodeQualifier;
  396. switch (adSenseCode){
  397. #undef MAKE_CASE
  398. #define MAKE_CASE(adSnsCodQual) case adSnsCodQual: adSenseCodeQualStr = #adSnsCodQual; break;
  399. case SCSI_ADSENSE_LUN_NOT_READY:
  400. switch (adSenseCodeQual){
  401. MAKE_CASE(SCSI_SENSEQ_CAUSE_NOT_REPORTABLE)
  402. MAKE_CASE(SCSI_SENSEQ_BECOMING_READY)
  403. MAKE_CASE(SCSI_SENSEQ_INIT_COMMAND_REQUIRED)
  404. MAKE_CASE(SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED)
  405. MAKE_CASE(SCSI_SENSEQ_FORMAT_IN_PROGRESS)
  406. MAKE_CASE(SCSI_SENSEQ_REBUILD_IN_PROGRESS)
  407. MAKE_CASE(SCSI_SENSEQ_RECALCULATION_IN_PROGRESS)
  408. MAKE_CASE(SCSI_SENSEQ_OPERATION_IN_PROGRESS)
  409. MAKE_CASE(SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS)
  410. }
  411. break;
  412. case SCSI_ADSENSE_NO_SENSE:
  413. switch (adSenseCodeQual){
  414. MAKE_CASE(SCSI_SENSEQ_FILEMARK_DETECTED)
  415. MAKE_CASE(SCSI_SENSEQ_END_OF_MEDIA_DETECTED)
  416. MAKE_CASE(SCSI_SENSEQ_SETMARK_DETECTED)
  417. MAKE_CASE(SCSI_SENSEQ_BEGINNING_OF_MEDIA_DETECTED)
  418. }
  419. break;
  420. case SCSI_ADSENSE_ILLEGAL_BLOCK:
  421. switch (adSenseCodeQual){
  422. MAKE_CASE(SCSI_SENSEQ_ILLEGAL_ELEMENT_ADDR)
  423. }
  424. break;
  425. case SCSI_ADSENSE_POSITION_ERROR:
  426. switch (adSenseCodeQual){
  427. MAKE_CASE(SCSI_SENSEQ_DESTINATION_FULL)
  428. MAKE_CASE(SCSI_SENSEQ_SOURCE_EMPTY)
  429. }
  430. break;
  431. case SCSI_ADSENSE_INVALID_MEDIA:
  432. switch (adSenseCodeQual){
  433. MAKE_CASE(SCSI_SENSEQ_INCOMPATIBLE_MEDIA_INSTALLED)
  434. MAKE_CASE(SCSI_SENSEQ_UNKNOWN_FORMAT)
  435. MAKE_CASE(SCSI_SENSEQ_INCOMPATIBLE_FORMAT)
  436. MAKE_CASE(SCSI_SENSEQ_CLEANING_CARTRIDGE_INSTALLED)
  437. }
  438. break;
  439. case SCSI_ADSENSE_OPERATOR_REQUEST:
  440. switch (adSenseCodeQual){
  441. MAKE_CASE(SCSI_SENSEQ_STATE_CHANGE_INPUT)
  442. MAKE_CASE(SCSI_SENSEQ_MEDIUM_REMOVAL)
  443. MAKE_CASE(SCSI_SENSEQ_WRITE_PROTECT_ENABLE)
  444. MAKE_CASE(SCSI_SENSEQ_WRITE_PROTECT_DISABLE)
  445. }
  446. break;
  447. case SCSI_ADSENSE_COPY_PROTECTION_FAILURE:
  448. switch (adSenseCodeQual){
  449. MAKE_CASE(SCSI_SENSEQ_AUTHENTICATION_FAILURE)
  450. MAKE_CASE(SCSI_SENSEQ_KEY_NOT_PRESENT)
  451. MAKE_CASE(SCSI_SENSEQ_KEY_NOT_ESTABLISHED)
  452. MAKE_CASE(SCSI_SENSEQ_READ_OF_SCRAMBLED_SECTOR_WITHOUT_AUTHENTICATION)
  453. MAKE_CASE(SCSI_SENSEQ_MEDIA_CODE_MISMATCHED_TO_LOGICAL_UNIT)
  454. MAKE_CASE(SCSI_SENSEQ_LOGICAL_UNIT_RESET_COUNT_ERROR)
  455. }
  456. break;
  457. }
  458. }
  459. return adSenseCodeQualStr;
  460. }
  461. /*
  462. * DbgCheckReturnedPkt
  463. *
  464. * Check a completed TRANSFER_PACKET for all sorts of error conditions
  465. * and warn/trap appropriately.
  466. */
  467. VOID DbgCheckReturnedPkt(TRANSFER_PACKET *Pkt)
  468. {
  469. PCDB pCdb = (PCDB)Pkt->Srb.Cdb;
  470. ASSERT(Pkt->Srb.OriginalRequest == Pkt->Irp);
  471. ASSERT(Pkt->Srb.DataBuffer == Pkt->BufPtrCopy);
  472. ASSERT(Pkt->Srb.DataTransferLength <= Pkt->BufLenCopy);
  473. ASSERT(!Pkt->Irp->CancelRoutine);
  474. if (SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_PENDING){
  475. DBGERR(("SRB completed with status PENDING in packet %ph: (op=%s srbstat=%s(%xh), irpstat=%xh)",
  476. Pkt,
  477. DBGGETSCSIOPSTR(&Pkt->Srb),
  478. DBGGETSRBSTATUSSTR(&Pkt->Srb),
  479. (ULONG)Pkt->Srb.SrbStatus,
  480. Pkt->Irp->IoStatus.Status));
  481. }
  482. else if (SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_SUCCESS){
  483. /*
  484. * Make sure SRB and IRP status match.
  485. */
  486. if (!NT_SUCCESS(Pkt->Irp->IoStatus.Status)){
  487. DBGWARN(("SRB and IRP status don't match in packet %ph: (op=%s srbstat=%s(%xh), irpstat=%xh)",
  488. Pkt,
  489. DBGGETSCSIOPSTR(&Pkt->Srb),
  490. DBGGETSRBSTATUSSTR(&Pkt->Srb),
  491. (ULONG)Pkt->Srb.SrbStatus,
  492. Pkt->Irp->IoStatus.Status));
  493. }
  494. if (Pkt->Irp->IoStatus.Information != Pkt->Srb.DataTransferLength){
  495. DBGERR(("SRB and IRP result transfer lengths don't match in succeeded packet %ph: (op=%s, SrbStatus=%s, Srb.DataTransferLength=%xh, Irp->IoStatus.Information=%xh).",
  496. Pkt,
  497. DBGGETSCSIOPSTR(&Pkt->Srb),
  498. DBGGETSRBSTATUSSTR(&Pkt->Srb),
  499. Pkt->Srb.DataTransferLength,
  500. Pkt->Irp->IoStatus.Information));
  501. }
  502. }
  503. else {
  504. if (NT_SUCCESS(Pkt->Irp->IoStatus.Status)){
  505. DBGWARN(("SRB and IRP status don't match in packet %ph: (op=%s srbstat=%s(%xh), irpstat=%xh)",
  506. Pkt,
  507. DBGGETSCSIOPSTR(&Pkt->Srb),
  508. DBGGETSRBSTATUSSTR(&Pkt->Srb),
  509. (ULONG)Pkt->Srb.SrbStatus,
  510. Pkt->Irp->IoStatus.Status));
  511. }
  512. DBGTRACE(ClassDebugWarning, ("Packet %ph failed (op=%s srbstat=%s(%xh), irpstat=%xh, sense=%s/%s/%s)",
  513. Pkt,
  514. DBGGETSCSIOPSTR(&Pkt->Srb),
  515. DBGGETSRBSTATUSSTR(&Pkt->Srb),
  516. (ULONG)Pkt->Srb.SrbStatus,
  517. Pkt->Irp->IoStatus.Status,
  518. DBGGETSENSECODESTR(&Pkt->Srb),
  519. DBGGETADSENSECODESTR(&Pkt->Srb),
  520. DBGGETADSENSEQUALIFIERSTR(&Pkt->Srb)));
  521. /*
  522. * If the SRB failed with underrun or overrun, then the actual
  523. * transferred length should be returned in both SRB and IRP.
  524. * (SRB's only have an error status for overrun, so it's overloaded).
  525. */
  526. if ((SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) &&
  527. (Pkt->Irp->IoStatus.Information != Pkt->Srb.DataTransferLength)){
  528. DBGERR(("SRB and IRP result transfer lengths don't match in failed packet %ph: (op=%s, SrbStatus=%s, Srb.DataTransferLength=%xh, Irp->IoStatus.Information=%xh).",
  529. Pkt,
  530. DBGGETSCSIOPSTR(&Pkt->Srb),
  531. DBGGETSRBSTATUSSTR(&Pkt->Srb),
  532. Pkt->Srb.DataTransferLength,
  533. Pkt->Irp->IoStatus.Information));
  534. }
  535. }
  536. /*
  537. * If the port driver returned STATUS_INSUFFICIENT_RESOURCES,
  538. * make sure this is also the InternalStatus in the SRB so that we process it correctly.
  539. */
  540. if (Pkt->Irp->IoStatus.Status == STATUS_INSUFFICIENT_RESOURCES){
  541. ASSERT(SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_INTERNAL_ERROR);
  542. ASSERT(Pkt->Srb.InternalStatus == STATUS_INSUFFICIENT_RESOURCES);
  543. }
  544. /*
  545. * Some miniport drivers have been caught changing the SCSI operation
  546. * code in the SRB. This is absolutely disallowed as it breaks our error handling.
  547. */
  548. switch (pCdb->CDB10.OperationCode){
  549. case SCSIOP_MEDIUM_REMOVAL:
  550. case SCSIOP_MODE_SENSE:
  551. case SCSIOP_READ_CAPACITY:
  552. case SCSIOP_READ:
  553. case SCSIOP_WRITE:
  554. case SCSIOP_START_STOP_UNIT:
  555. break;
  556. default:
  557. DBGERR(("Miniport illegally changed Srb.Cdb.OperationCode in packet %ph failed (op=%s srbstat=%s(%xh), irpstat=%xh, sense=%s/%s/%s)",
  558. Pkt,
  559. DBGGETSCSIOPSTR(&Pkt->Srb),
  560. DBGGETSRBSTATUSSTR(&Pkt->Srb),
  561. (ULONG)Pkt->Srb.SrbStatus,
  562. Pkt->Irp->IoStatus.Status,
  563. DBGGETSENSECODESTR(&Pkt->Srb),
  564. DBGGETADSENSECODESTR(&Pkt->Srb),
  565. DBGGETADSENSEQUALIFIERSTR(&Pkt->Srb)));
  566. break;
  567. }
  568. }
  569. VOID DbgLogSendPacket(TRANSFER_PACKET *Pkt)
  570. {
  571. PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
  572. PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
  573. KIRQL oldIrql;
  574. if (Pkt->OriginalIrp){
  575. Pkt->DbgOriginalIrpCopy = *Pkt->OriginalIrp;
  576. if (Pkt->OriginalIrp->MdlAddress){
  577. Pkt->DbgMdlCopy = *Pkt->OriginalIrp->MdlAddress;
  578. }
  579. }
  580. KeQueryTickCount(&Pkt->DbgTimeSent);
  581. Pkt->DbgTimeReturned.QuadPart = 0L;
  582. KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
  583. fdoData->DbgPacketLogs[fdoData->DbgPacketLogNextIndex] = *Pkt;
  584. fdoData->DbgPacketLogNextIndex++;
  585. fdoData->DbgPacketLogNextIndex %= DBG_NUM_PACKET_LOG_ENTRIES;
  586. KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
  587. }
  588. VOID DbgLogReturnPacket(TRANSFER_PACKET *Pkt)
  589. {
  590. PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
  591. PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
  592. KIRQL oldIrql;
  593. KeQueryTickCount(&Pkt->DbgTimeReturned);
  594. #if 0
  595. // ISSUE: there are some problems with this check (e.g. multiproc), so don't include it yet
  596. if (Pkt->OriginalIrp){
  597. /*
  598. * No one should have touched the original irp while the packet was outstanding,
  599. * except for a couple fields that we ourselves update during the transfer
  600. * or that are allowed to change;
  601. * make those couple fields the same and then to a bytewise compare
  602. */
  603. ULONG lenSame;
  604. Pkt->DbgOriginalIrpCopy.IoStatus.Status = Pkt->OriginalIrp->IoStatus.Status;
  605. Pkt->DbgOriginalIrpCopy.IoStatus.Information = Pkt->OriginalIrp->IoStatus.Information;
  606. Pkt->DbgOriginalIrpCopy.Tail.Overlay.DriverContext[0] = Pkt->OriginalIrp->Tail.Overlay.DriverContext[0];
  607. Pkt->DbgOriginalIrpCopy.ThreadListEntry = Pkt->OriginalIrp->ThreadListEntry;
  608. Pkt->DbgOriginalIrpCopy.Cancel = Pkt->OriginalIrp->Cancel;
  609. lenSame = (ULONG)RtlCompareMemory(Pkt->OriginalIrp, &Pkt->DbgOriginalIrpCopy, sizeof(IRP));
  610. ASSERT(lenSame == sizeof(IRP));
  611. }
  612. #endif
  613. KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
  614. fdoData->DbgPacketLogs[fdoData->DbgPacketLogNextIndex] = *Pkt;
  615. fdoData->DbgPacketLogNextIndex++;
  616. fdoData->DbgPacketLogNextIndex %= DBG_NUM_PACKET_LOG_ENTRIES;
  617. KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
  618. }
  619. VOID DbgLogFlushInfo(PCLASS_PRIVATE_FDO_DATA FdoData, BOOLEAN IsIO, BOOLEAN IsFUA, BOOLEAN IsFlush)
  620. {
  621. /*
  622. * Reset all FUA/Flush logging fields.
  623. */
  624. if (FdoData->DbgInitFlushLogging){
  625. FdoData->DbgNumIORequests = 0;
  626. FdoData->DbgNumFUAs = 0;
  627. FdoData->DbgNumFlushes = 0;
  628. FdoData->DbgIOsSinceFUA = 0;
  629. FdoData->DbgIOsSinceFlush = 0;
  630. FdoData->DbgAveIOsToFUA = 0;
  631. FdoData->DbgAveIOsToFlush = 0;
  632. FdoData->DbgMaxIOsToFUA = 0;
  633. FdoData->DbgMaxIOsToFlush = 0;
  634. FdoData->DbgMinIOsToFUA = 0xffffffff;
  635. FdoData->DbgMinIOsToFlush = 0xffffffff;
  636. FdoData->DbgInitFlushLogging = FALSE;
  637. }
  638. if (IsIO){
  639. FdoData->DbgNumIORequests++;
  640. FdoData->DbgIOsSinceFlush++;
  641. if (IsFUA){
  642. if (FdoData->DbgNumFUAs > 0){
  643. FdoData->DbgMinIOsToFUA = min(FdoData->DbgMinIOsToFUA, FdoData->DbgIOsSinceFUA);
  644. }
  645. FdoData->DbgNumFUAs++;
  646. FdoData->DbgAveIOsToFUA = FdoData->DbgNumIORequests/FdoData->DbgNumFUAs;
  647. FdoData->DbgIOsSinceFUA = 0;
  648. }
  649. else {
  650. FdoData->DbgIOsSinceFUA++;
  651. FdoData->DbgMaxIOsToFUA = max(FdoData->DbgMaxIOsToFUA, FdoData->DbgIOsSinceFUA);
  652. }
  653. FdoData->DbgMaxIOsToFlush = max(FdoData->DbgMaxIOsToFlush, FdoData->DbgIOsSinceFlush);
  654. }
  655. else if (IsFlush){
  656. if (FdoData->DbgNumFlushes > 0){
  657. FdoData->DbgMinIOsToFlush = min(FdoData->DbgMinIOsToFlush, FdoData->DbgIOsSinceFlush);
  658. }
  659. FdoData->DbgNumFlushes++;
  660. FdoData->DbgAveIOsToFlush = FdoData->DbgNumIORequests/FdoData->DbgNumFlushes;
  661. FdoData->DbgIOsSinceFlush = 0;
  662. }
  663. }
  664. #else
  665. // We have to keep this in the retail build for legacy.
  666. VOID ClassDebugPrint(CLASS_DEBUG_LEVEL DebugPrintLevel, PCCHAR DebugMessage, ...)
  667. {
  668. }
  669. #endif