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.

1068 lines
32 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. class.c
  5. Abstract:
  6. Contains a subset of routines in classpnp.sys.
  7. Author:
  8. Ray Patrick (raypat)
  9. Environment:
  10. kernel mode only
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include <stdio.h>
  15. #include "stddef.h"
  16. #include "wdm.h"
  17. #include "scsi.h"
  18. #include "ntddstor.h"
  19. #include "ntddscsi.h"
  20. #include "scsiscan.h"
  21. #include "private.h"
  22. #include "debug.h"
  23. #ifdef ALLOC_PRAGMA
  24. #pragma alloc_text(PAGE, ClassGetDescriptor)
  25. #pragma alloc_text(PAGE, ClassGetInfo)
  26. #endif
  27. NTSTATUS
  28. ClassGetDescriptor(
  29. IN PDEVICE_OBJECT pDeviceObject,
  30. IN PSTORAGE_PROPERTY_ID pPropertyId,
  31. OUT PSTORAGE_DESCRIPTOR_HEADER *pDescriptor
  32. )
  33. /*++
  34. Routine Description:
  35. This routine will perform a query for the specified property id and will
  36. allocate a non-paged buffer to store the data in. It is the responsibility
  37. of the caller to ensure that this buffer is freed.
  38. This routine must be run at IRQL_PASSIVE_LEVEL
  39. Arguments:
  40. pDeviceObject - the device to query
  41. pDescriptor - a location to store a pointer to the buffer we allocate
  42. Return Value:
  43. Status
  44. if status is unsuccessful *DeviceInfo will be set to 0
  45. --*/
  46. {
  47. PIRP pIrp;
  48. PKEVENT pEvent = NULL;
  49. STORAGE_PROPERTY_QUERY Query;
  50. ULONG Buffer[2];
  51. PSTORAGE_DESCRIPTOR_HEADER pLocalDescriptor = NULL;
  52. ULONG Length;
  53. IO_STATUS_BLOCK StatusBlock;
  54. NTSTATUS Status;
  55. UCHAR Pass;
  56. //
  57. // Set the descriptor pointer to NULL and
  58. // Initialize the event we're going to wait on.
  59. //
  60. *pDescriptor = NULL;
  61. pEvent = MyAllocatePool(NonPagedPool, sizeof(KEVENT));
  62. if(pEvent == NULL) {
  63. DebugTrace(MAX_TRACE,("ClassGetDescriptor: Unable to allocate event\n"));
  64. Status = STATUS_INSUFFICIENT_RESOURCES;
  65. return Status;
  66. }
  67. KeInitializeEvent(pEvent, SynchronizationEvent, FALSE);
  68. Pass = 0;
  69. __try {
  70. //
  71. // Retrieve the property page
  72. //
  73. do {
  74. RtlZeroMemory(&Query, sizeof(STORAGE_PROPERTY_QUERY));
  75. Query.PropertyId = *pPropertyId;
  76. Query.QueryType = PropertyStandardQuery;
  77. switch( Pass ) {
  78. case 0:
  79. //
  80. // On the first pass we just want to get the first few
  81. // bytes of the descriptor so we can read it's size
  82. //
  83. pLocalDescriptor = (PVOID) &Buffer[0];
  84. Length = sizeof(ULONG) * 2;
  85. break;
  86. case 1:
  87. //
  88. // This time we know how much data there is so we can
  89. // allocate a buffer of the correct size
  90. //
  91. Length = ((PSTORAGE_DESCRIPTOR_HEADER) pLocalDescriptor)->Size;
  92. pLocalDescriptor = MyAllocatePool(NonPagedPool, Length);
  93. if (pLocalDescriptor == NULL) {
  94. Status = STATUS_INSUFFICIENT_RESOURCES;
  95. DebugTrace(MAX_TRACE,
  96. ("ClassGetDescriptor: unable to get memory for descriptor (%d bytes)\n",
  97. Length));
  98. __leave;
  99. }
  100. break;
  101. }
  102. //
  103. // Build the query irp and wait for it to complete (if necessary)
  104. //
  105. pIrp = IoBuildDeviceIoControlRequest(
  106. IOCTL_STORAGE_QUERY_PROPERTY,
  107. pDeviceObject,
  108. &Query,
  109. sizeof(STORAGE_PROPERTY_QUERY),
  110. pLocalDescriptor,
  111. Length,
  112. FALSE,
  113. pEvent,
  114. &StatusBlock);
  115. if (pIrp == NULL) {
  116. DebugTrace(MAX_TRACE,("ClassGetDescriptor: unable to allocate irp\n"));
  117. Status = STATUS_INSUFFICIENT_RESOURCES;
  118. __leave;
  119. }
  120. Status = IoCallDriver(pDeviceObject, pIrp);
  121. if (Status == STATUS_PENDING) {
  122. KeWaitForSingleObject(pEvent,
  123. Executive,
  124. KernelMode,
  125. FALSE,
  126. NULL);
  127. Status = StatusBlock.Status;
  128. }
  129. if (!NT_SUCCESS(Status)) {
  130. DebugTrace(MAX_TRACE,
  131. ("ClassGetDescriptor: error %#08lx trying to query properties\n",
  132. Status));
  133. __leave;
  134. }
  135. } while (Pass++ != 1);
  136. } __finally {
  137. MyFreePool(pEvent);
  138. if(NT_SUCCESS(Status)){
  139. *pDescriptor = pLocalDescriptor;
  140. } else {
  141. if( (Pass != 0)
  142. && (NULL != pLocalDescriptor) )
  143. {
  144. MyFreePool(pLocalDescriptor);
  145. pLocalDescriptor = NULL;
  146. }
  147. } // if(NT_SUCCESS(Status))
  148. }
  149. return Status;
  150. }
  151. BOOLEAN
  152. ClassInterpretSenseInfo(
  153. IN PDEVICE_OBJECT pDeviceObject,
  154. IN PSRB pSrb,
  155. IN UCHAR MajorFunctionCode,
  156. IN ULONG IoDeviceCode,
  157. IN ULONG RetryCount,
  158. OUT NTSTATUS *Status
  159. )
  160. /*++
  161. Routine Description:
  162. This routine interprets the data returned from the SCSI
  163. request sense. It determines the status to return in the
  164. IRP and whether this request can be retried.
  165. Arguments:
  166. pDeviceObject - Supplies the device object associated with this request.
  167. pSrb - Supplies the scsi request block which failed.
  168. MajorFunctionCode - Supplies the function code to be used for logging.
  169. IoDeviceCode - Supplies the device code to be used for logging.
  170. Status - Returns the status for the request.
  171. Return Value:
  172. BOOLEAN TRUE: Drivers should retry this request.
  173. FALSE: Drivers should not retry this request.
  174. --*/
  175. {
  176. PSCSISCAN_DEVICE_EXTENSION pde;
  177. PSENSE_DATA pSenseBuffer;
  178. BOOLEAN Retry;
  179. BOOLEAN LogError;
  180. ULONG BadSector;
  181. ULONG UniqueId;
  182. NTSTATUS LogStatus;
  183. ULONG ReadSector;
  184. ULONG Index;
  185. PIO_ERROR_LOG_PACKET pErrorLogEntry;
  186. pde = (PSCSISCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  187. pSenseBuffer = pSrb -> SenseInfoBuffer;
  188. Retry = TRUE;
  189. LogError = FALSE;
  190. BadSector = 0;
  191. //
  192. // Check that request sense buffer is valid.
  193. //
  194. if (pSrb -> SrbStatus & SRB_STATUS_AUTOSENSE_VALID &&
  195. pSrb -> SenseInfoBufferLength >= offsetof(SENSE_DATA, CommandSpecificInformation)) {
  196. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Error code is %x\n",
  197. pSenseBuffer -> ErrorCode));
  198. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Sense key is %x\n",
  199. pSenseBuffer -> SenseKey));
  200. DebugTrace(MAX_TRACE,( "ScsiScannerInterpretSenseInfo: Additional sense code is %x\n",
  201. pSenseBuffer -> AdditionalSenseCode));
  202. DebugTrace(MAX_TRACE,( "ScsiScannerInterpretSenseInfo: Additional sense code qualifier is %x\n",
  203. pSenseBuffer -> AdditionalSenseCodeQualifier));
  204. //
  205. // Zero the additional sense code and additional sense code qualifier
  206. // if they were not returned by the device.
  207. //
  208. ReadSector = pSenseBuffer -> AdditionalSenseLength +
  209. offsetof(SENSE_DATA, AdditionalSenseLength);
  210. if (ReadSector > pSrb -> SenseInfoBufferLength) {
  211. ReadSector = pSrb -> SenseInfoBufferLength;
  212. }
  213. if (ReadSector <= offsetof(SENSE_DATA, AdditionalSenseCode)) {
  214. pSenseBuffer -> AdditionalSenseCode = 0;
  215. }
  216. if (ReadSector <= offsetof(SENSE_DATA, AdditionalSenseCodeQualifier)) {
  217. pSenseBuffer -> AdditionalSenseCodeQualifier = 0;
  218. }
  219. switch (pSenseBuffer -> SenseKey & 0xf) {
  220. case SCSI_SENSE_NOT_READY:
  221. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Device not ready\n"));
  222. *Status = STATUS_DEVICE_NOT_READY;
  223. switch (pSenseBuffer -> AdditionalSenseCode) {
  224. case SCSI_ADSENSE_LUN_NOT_READY:
  225. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Lun not ready\n"));
  226. switch (pSenseBuffer -> AdditionalSenseCodeQualifier) {
  227. case SCSI_SENSEQ_BECOMING_READY:
  228. DebugTrace(MAX_TRACE,( "ScsiScannerInterpretSenseInfo:"
  229. " In process of becoming ready\n"));
  230. break;
  231. case SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED:
  232. DebugTrace(MAX_TRACE,( "ScsiScannerInterpretSenseInfo:"
  233. " Manual intervention required\n"));
  234. *Status = STATUS_NO_MEDIA_IN_DEVICE;
  235. Retry = FALSE;
  236. break;
  237. case SCSI_SENSEQ_FORMAT_IN_PROGRESS:
  238. DebugTrace(MAX_TRACE,( "ScsiScannerInterpretSenseInfo: Format in progress\n"));
  239. Retry = FALSE;
  240. break;
  241. case SCSI_SENSEQ_INIT_COMMAND_REQUIRED:
  242. default:
  243. DebugTrace(MAX_TRACE,( "ScsiScannerInterpretSenseInfo:"
  244. " Initializing command required\n"));
  245. break;
  246. } // end switch (pSenseBuffer -> AdditionalSenseCodeQualifier)
  247. break;
  248. case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE:
  249. DebugTrace(MAX_TRACE,(
  250. "ScsiScannerInterpretSenseInfo:"
  251. " No Media in device.\n"));
  252. *Status = STATUS_NO_MEDIA_IN_DEVICE;
  253. Retry = FALSE;
  254. break;
  255. } // end switch (pSenseBuffer -> AdditionalSenseCode)
  256. break;
  257. case SCSI_SENSE_DATA_PROTECT:
  258. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Media write protected\n"));
  259. *Status = STATUS_MEDIA_WRITE_PROTECTED;
  260. Retry = FALSE;
  261. break;
  262. case SCSI_SENSE_MEDIUM_ERROR:
  263. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Bad media\n"));
  264. *Status = STATUS_DEVICE_DATA_ERROR;
  265. Retry = FALSE;
  266. LogError = TRUE;
  267. UniqueId = 256;
  268. LogStatus = IO_ERR_BAD_BLOCK;
  269. break;
  270. case SCSI_SENSE_HARDWARE_ERROR:
  271. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Hardware error\n"));
  272. *Status = STATUS_IO_DEVICE_ERROR;
  273. LogError = TRUE;
  274. UniqueId = 257;
  275. LogStatus = IO_ERR_CONTROLLER_ERROR;
  276. break;
  277. case SCSI_SENSE_ILLEGAL_REQUEST:
  278. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Illegal SCSI request\n"));
  279. *Status = STATUS_INVALID_DEVICE_REQUEST;
  280. switch (pSenseBuffer -> AdditionalSenseCode) {
  281. case SCSI_ADSENSE_ILLEGAL_COMMAND:
  282. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Illegal command\n"));
  283. Retry = FALSE;
  284. break;
  285. case SCSI_ADSENSE_ILLEGAL_BLOCK:
  286. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Illegal block address\n"));
  287. *Status = STATUS_NONEXISTENT_SECTOR;
  288. Retry = FALSE;
  289. break;
  290. case SCSI_ADSENSE_INVALID_LUN:
  291. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Invalid LUN\n"));
  292. *Status = STATUS_NO_SUCH_DEVICE;
  293. Retry = FALSE;
  294. break;
  295. case SCSI_ADSENSE_MUSIC_AREA:
  296. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Music area\n"));
  297. Retry = FALSE;
  298. break;
  299. case SCSI_ADSENSE_DATA_AREA:
  300. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Data area\n"));
  301. Retry = FALSE;
  302. break;
  303. case SCSI_ADSENSE_VOLUME_OVERFLOW:
  304. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Volume overflow\n"));
  305. Retry = FALSE;
  306. break;
  307. case SCSI_ADSENSE_INVALID_CDB:
  308. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Invalid CDB\n"));
  309. Retry = FALSE;
  310. break;
  311. } // end switch (pSenseBuffer -> AdditionalSenseCode)
  312. break;
  313. case SCSI_SENSE_UNIT_ATTENTION:
  314. switch (pSenseBuffer -> AdditionalSenseCode) {
  315. case SCSI_ADSENSE_MEDIUM_CHANGED:
  316. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Media changed\n"));
  317. break;
  318. case SCSI_ADSENSE_BUS_RESET:
  319. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Bus reset\n"));
  320. break;
  321. default:
  322. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Unit attention\n"));
  323. break;
  324. } // end switch (pSenseBuffer -> AdditionalSenseCode)
  325. *Status = STATUS_IO_DEVICE_ERROR;
  326. break;
  327. case SCSI_SENSE_ABORTED_COMMAND:
  328. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Command aborted\n"));
  329. *Status = STATUS_IO_DEVICE_ERROR;
  330. break;
  331. case SCSI_SENSE_RECOVERED_ERROR:
  332. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Recovered error\n"));
  333. *Status = STATUS_SUCCESS;
  334. Retry = FALSE;
  335. LogError = TRUE;
  336. UniqueId = 258;
  337. switch(pSenseBuffer -> AdditionalSenseCode) {
  338. case SCSI_ADSENSE_SEEK_ERROR:
  339. case SCSI_ADSENSE_TRACK_ERROR:
  340. LogStatus = IO_ERR_SEEK_ERROR;
  341. break;
  342. case SCSI_ADSENSE_REC_DATA_NOECC:
  343. case SCSI_ADSENSE_REC_DATA_ECC:
  344. LogStatus = IO_RECOVERED_VIA_ECC;
  345. break;
  346. default:
  347. LogStatus = IO_ERR_CONTROLLER_ERROR;
  348. break;
  349. } // end switch(pSenseBuffer -> AdditionalSenseCode)
  350. if (pSenseBuffer -> IncorrectLength) {
  351. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Incorrect length detected.\n"));
  352. *Status = STATUS_INVALID_BLOCK_LENGTH ;
  353. }
  354. break;
  355. case SCSI_SENSE_NO_SENSE:
  356. //
  357. // Check other indicators.
  358. //
  359. if (pSenseBuffer -> IncorrectLength) {
  360. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Incorrect length detected.\n"));
  361. *Status = STATUS_INVALID_BLOCK_LENGTH ;
  362. Retry = FALSE;
  363. } else {
  364. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: No specific sense key\n"));
  365. *Status = STATUS_IO_DEVICE_ERROR;
  366. Retry = TRUE;
  367. }
  368. break;
  369. default:
  370. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Unrecognized sense code\n"));
  371. *Status = STATUS_IO_DEVICE_ERROR;
  372. break;
  373. } // end switch (pSenseBuffer -> SenseKey & 0xf)
  374. //
  375. // Try to determine the bad sector from the inquiry data.
  376. //
  377. if ((((PCDB)pSrb -> Cdb) -> CDB10.OperationCode == SCSIOP_READ ||
  378. ((PCDB)pSrb -> Cdb) -> CDB10.OperationCode == SCSIOP_VERIFY ||
  379. ((PCDB)pSrb -> Cdb) -> CDB10.OperationCode == SCSIOP_WRITE)) {
  380. for (Index = 0; Index < 4; Index++) {
  381. BadSector = (BadSector << 8) | pSenseBuffer -> Information[Index];
  382. }
  383. ReadSector = 0;
  384. for (Index = 0; Index < 4; Index++) {
  385. ReadSector = (ReadSector << 8) | pSrb -> Cdb[Index+2];
  386. }
  387. Index = (((PCDB)pSrb -> Cdb) -> CDB10.TransferBlocksMsb << 8) |
  388. ((PCDB)pSrb -> Cdb) -> CDB10.TransferBlocksLsb;
  389. //
  390. // Make sure the bad sector is within the read sectors.
  391. //
  392. if (!(BadSector >= ReadSector && BadSector < ReadSector + Index)) {
  393. BadSector = ReadSector;
  394. }
  395. }
  396. } else {
  397. //
  398. // Request sense buffer not valid. No sense information
  399. // to pinpoint the error. Return general request fail.
  400. //
  401. DebugTrace(MAX_TRACE,("ScsiScannerInterpretSenseInfo: Request sense info not valid. SrbStatus %2x\n",
  402. SRB_STATUS(pSrb -> SrbStatus)));
  403. Retry = TRUE;
  404. switch (SRB_STATUS(pSrb -> SrbStatus)) {
  405. case SRB_STATUS_INVALID_LUN:
  406. case SRB_STATUS_INVALID_TARGET_ID:
  407. case SRB_STATUS_NO_DEVICE:
  408. case SRB_STATUS_NO_HBA:
  409. case SRB_STATUS_INVALID_PATH_ID:
  410. *Status = STATUS_NO_SUCH_DEVICE;
  411. Retry = FALSE;
  412. break;
  413. case SRB_STATUS_COMMAND_TIMEOUT:
  414. case SRB_STATUS_ABORTED:
  415. case SRB_STATUS_TIMEOUT:
  416. //
  417. // Update the error count for the device.
  418. //
  419. pde -> ErrorCount++;
  420. *Status = STATUS_IO_TIMEOUT;
  421. break;
  422. case SRB_STATUS_SELECTION_TIMEOUT:
  423. //
  424. // Avoid reporting too much if device seems to be not connected
  425. //
  426. if (pde->LastSrbError != SRB_STATUS_SELECTION_TIMEOUT) {
  427. LogError = TRUE;
  428. }
  429. LogStatus = IO_ERR_NOT_READY;
  430. UniqueId = 260;
  431. *Status = STATUS_DEVICE_NOT_CONNECTED;
  432. Retry = FALSE;
  433. break;
  434. case SRB_STATUS_DATA_OVERRUN:
  435. *Status = STATUS_DATA_OVERRUN;
  436. Retry = FALSE;
  437. break;
  438. case SRB_STATUS_PHASE_SEQUENCE_FAILURE:
  439. //
  440. // Update the error count for the device.
  441. //
  442. pde -> ErrorCount++;
  443. *Status = STATUS_IO_DEVICE_ERROR;
  444. //
  445. // If there was phase sequence error then limit the number of
  446. // retries.
  447. //
  448. if (RetryCount > 1 ) {
  449. Retry = FALSE;
  450. }
  451. break;
  452. case SRB_STATUS_REQUEST_FLUSHED:
  453. *Status = STATUS_IO_DEVICE_ERROR;
  454. break;
  455. case SRB_STATUS_INVALID_REQUEST:
  456. //
  457. // An invalid request was attempted.
  458. //
  459. *Status = STATUS_INVALID_DEVICE_REQUEST;
  460. Retry = FALSE;
  461. break;
  462. case SRB_STATUS_UNEXPECTED_BUS_FREE:
  463. case SRB_STATUS_PARITY_ERROR:
  464. //
  465. // Update the error count for the device.
  466. //
  467. pde -> ErrorCount++;
  468. //
  469. // Fall through to below.
  470. //
  471. case SRB_STATUS_BUS_RESET:
  472. *Status = STATUS_IO_DEVICE_ERROR;
  473. break;
  474. case SRB_STATUS_ERROR:
  475. *Status = STATUS_IO_DEVICE_ERROR;
  476. if (pSrb -> ScsiStatus == 0) {
  477. //
  478. // This is some strange return code. Update the error
  479. // count for the device.
  480. //
  481. pde -> ErrorCount++;
  482. }
  483. if (pSrb -> ScsiStatus == SCSISTAT_BUSY) {
  484. *Status = STATUS_DEVICE_NOT_READY;
  485. }
  486. if (pSrb -> ScsiStatus == SCSISTAT_RESERVATION_CONFLICT) {
  487. *Status = STATUS_DEVICE_BUSY;
  488. Retry = FALSE;
  489. }
  490. break;
  491. default:
  492. LogError = TRUE;
  493. LogStatus = IO_ERR_CONTROLLER_ERROR;
  494. UniqueId = 259;
  495. *Status = STATUS_IO_DEVICE_ERROR;
  496. break;
  497. }
  498. //
  499. // If the error count has exceeded the error limit, then disable
  500. // any tagged queuing, multiple requests per lu queueing
  501. // and sychronous data transfers.
  502. //
  503. if (pde -> ErrorCount == 4) {
  504. //
  505. // Clearing the no queue freeze flag prevents the port driver
  506. // from sending multiple requests per logical unit.
  507. //
  508. pde -> SrbFlags &= ~(SRB_FLAGS_QUEUE_ACTION_ENABLE |
  509. SRB_FLAGS_NO_QUEUE_FREEZE);
  510. pde -> SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
  511. DebugTrace(MAX_TRACE,( "ScsiScannerInterpretSenseInfo: Too many errors disabling tagged queuing and synchronous data tranfers.\n"));
  512. } else if (pde -> ErrorCount == 8) {
  513. //
  514. // If a second threshold is reached, disable disconnects.
  515. //
  516. //pde -> SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT;
  517. DebugTrace(MAX_TRACE,( "ScsiScannerInterpretSenseInfo: Too many errors disabling disconnects.\n"));
  518. }
  519. }
  520. //
  521. // Log an error if necessary.
  522. //
  523. pde->LastSrbError = SRB_STATUS(pSrb -> SrbStatus);
  524. if (LogError) {
  525. pErrorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
  526. pDeviceObject,
  527. sizeof(IO_ERROR_LOG_PACKET) + 5 * sizeof(ULONG));
  528. if (NULL == pErrorLogEntry) {
  529. //
  530. // Return if no packet could be allocated.
  531. //
  532. return Retry;
  533. }
  534. if (Retry && RetryCount < MAXIMUM_RETRIES) {
  535. pErrorLogEntry -> FinalStatus = STATUS_SUCCESS;
  536. } else {
  537. pErrorLogEntry -> FinalStatus = *Status;
  538. }
  539. //
  540. // Calculate the device offset if there is a geometry.
  541. //
  542. pErrorLogEntry -> ErrorCode = LogStatus;
  543. pErrorLogEntry -> SequenceNumber = 0;
  544. pErrorLogEntry -> MajorFunctionCode = MajorFunctionCode;
  545. pErrorLogEntry -> IoControlCode = IoDeviceCode;
  546. pErrorLogEntry -> RetryCount = (UCHAR) RetryCount;
  547. pErrorLogEntry -> UniqueErrorValue = UniqueId;
  548. pErrorLogEntry -> DumpDataSize = 6 * sizeof(ULONG);
  549. pErrorLogEntry -> DumpData[0] = pSrb -> PathId;
  550. pErrorLogEntry -> DumpData[1] = pSrb -> TargetId;
  551. pErrorLogEntry -> DumpData[2] = pSrb -> Lun;
  552. pErrorLogEntry -> DumpData[3] = 0;
  553. pErrorLogEntry -> DumpData[4] = pSrb -> SrbStatus << 8 | pSrb -> ScsiStatus;
  554. if (pSenseBuffer != NULL) {
  555. pErrorLogEntry -> DumpData[5] = pSenseBuffer -> SenseKey << 16 |
  556. pSenseBuffer -> AdditionalSenseCode << 8 |
  557. pSenseBuffer -> AdditionalSenseCodeQualifier;
  558. }
  559. //
  560. // Write the error log packet.
  561. //
  562. IoWriteErrorLogEntry(pErrorLogEntry);
  563. }
  564. return Retry;
  565. } // end ScsiScannerInterpretSenseInfo()
  566. VOID
  567. ClassReleaseQueue(
  568. IN PDEVICE_OBJECT pDeviceObject
  569. )
  570. /*++
  571. Routine Description:
  572. This routine issues an internal device control command
  573. to the port driver to release a frozen queue. The call
  574. is issued asynchronously as ClassReleaseQueue will be invoked
  575. from the IO completion DPC (and will have no context to
  576. wait for a synchronous call to complete).
  577. Arguments:
  578. pDeviceObject - The functional device object for the device with the frozen queue.
  579. Return Value:
  580. None.
  581. --*/
  582. {
  583. PIO_STACK_LOCATION pIrpStack;
  584. PIRP pIrp;
  585. PSCSISCAN_DEVICE_EXTENSION pde;
  586. PCOMPLETION_CONTEXT pContext;
  587. PSCSI_REQUEST_BLOCK pSrb;
  588. KIRQL CurrentIrql;
  589. DebugTrace(MAX_TRACE,("Release Queue \n"));
  590. //
  591. // Get our device extension.
  592. //
  593. pde = (PSCSISCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  594. //
  595. // Allocate context from nonpaged pool.
  596. //
  597. pContext = MyAllocatePool(NonPagedPool,
  598. sizeof(COMPLETION_CONTEXT));
  599. if(NULL == pContext){
  600. DebugTrace(MAX_TRACE,("ClassReleaseQueue: ERROR!! Couldn't allocate context memory.\n"));
  601. goto ClassReleaseQueue_return;
  602. } // if(NULL == pContext)
  603. pContext -> Signature = 'pmoC';
  604. //
  605. // Save the device object in the context for use by the completion
  606. // routine.
  607. //
  608. pContext->pDeviceObject = pDeviceObject;
  609. pSrb = &(pContext->Srb);
  610. //
  611. // Zero out srb.
  612. //
  613. RtlZeroMemory(pSrb, SCSI_REQUEST_BLOCK_SIZE);
  614. //
  615. // Write length to SRB.
  616. //
  617. pSrb->Length = SCSI_REQUEST_BLOCK_SIZE;
  618. //
  619. // specify release queue command.
  620. //
  621. pSrb->Function = SRB_FUNCTION_RELEASE_QUEUE;
  622. //
  623. // Build the asynchronous request to be sent to the port driver.
  624. //
  625. pIrp = IoAllocateIrp(pDeviceObject->StackSize, FALSE);
  626. if (pIrp != NULL ) {
  627. IoSetCompletionRoutine(pIrp,
  628. (PIO_COMPLETION_ROUTINE)ClassAsynchronousCompletion,
  629. pContext,
  630. TRUE,
  631. TRUE,
  632. TRUE);
  633. pIrpStack = IoGetNextIrpStackLocation(pIrp);
  634. pIrpStack->MajorFunction = IRP_MJ_SCSI;
  635. pSrb->OriginalRequest = pIrp;
  636. //
  637. // Store the SRB address in next stack for port driver.
  638. //
  639. pIrpStack->Parameters.Scsi.Srb = pSrb;
  640. //
  641. // Since this routine can cause outstanding requests to be completed, and
  642. // calling a completion routine at < DISPATCH_LEVEL is dangerous (if they
  643. // call IoStartNextPacket we will bugcheck) raise up to dispatch level before
  644. // issuing the request
  645. //
  646. CurrentIrql = KeGetCurrentIrql();
  647. if(CurrentIrql < DISPATCH_LEVEL) {
  648. KeRaiseIrql(DISPATCH_LEVEL, &CurrentIrql);
  649. IoCallDriver(pde->pStackDeviceObject, pIrp);
  650. KeLowerIrql(CurrentIrql);
  651. } else {
  652. IoCallDriver(pde->pStackDeviceObject, pIrp);
  653. }
  654. }
  655. else {
  656. DebugTrace(MAX_TRACE,("ScsiScanner Couldn't allocate IRP \n"));
  657. //
  658. // Free context if we are bailing out
  659. //
  660. if (pContext) {
  661. MyFreePool(pContext);
  662. pContext = NULL;
  663. }
  664. // return STATUS_INSUFFICIENT_RESOURCES;
  665. }
  666. ClassReleaseQueue_return:
  667. return;
  668. } // end ClassReleaseQueue()
  669. NTSTATUS
  670. ClassAsynchronousCompletion(
  671. PDEVICE_OBJECT pDeviceObject,
  672. PIRP pIrp,
  673. PCOMPLETION_CONTEXT pContext
  674. )
  675. /*++
  676. Routine Description:
  677. This routine is called when an asynchronous I/O request
  678. which was issused by the class driver completes. Examples of such requests
  679. are release queue or START UNIT. This routine releases the queue if
  680. necessary. It then frees the context and the IRP.
  681. Arguments:
  682. pDeviceObject - The device object for the logical unit; however since this
  683. is the top stack location the value is NULL.
  684. pIrp - Supplies a pointer to the Irp to be processed.
  685. pContext - Supplies the context to be used to process this request.
  686. Return Value:
  687. None.
  688. --*/
  689. {
  690. PSCSI_REQUEST_BLOCK pSrb;
  691. pSrb = &(pContext->Srb);
  692. //
  693. // If this is an execute srb, then check the return status and make sure.
  694. // the queue is not frozen.
  695. //
  696. if (pSrb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
  697. //
  698. // Check for a frozen queue.
  699. //
  700. if (pSrb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
  701. //
  702. // Unfreeze the queue getting the device object from the context.
  703. //
  704. ClassReleaseQueue(pContext->pDeviceObject);
  705. }
  706. }
  707. //
  708. // Free the context and the Irp.
  709. //
  710. if (pIrp->MdlAddress != NULL) {
  711. MmUnlockPages(pIrp->MdlAddress);
  712. IoFreeMdl(pIrp->MdlAddress);
  713. pIrp->MdlAddress = NULL;
  714. }
  715. if (pContext) {
  716. MyFreePool(pContext);
  717. }
  718. IoFreeIrp(pIrp);
  719. //
  720. // Indicate the I/O system should stop processing the Irp completion.
  721. //
  722. return STATUS_MORE_PROCESSING_REQUIRED;
  723. } // ClassAsynchronousCompletion()
  724. NTSTATUS
  725. ClassGetInfo(
  726. IN PDEVICE_OBJECT pDeviceObject,
  727. OUT PSCSISCAN_INFO pTargetInfo
  728. )
  729. /*++
  730. Routine Description:
  731. This routine will get target device information such as SCSI ID, LUN, and
  732. PortNumber. It calls portdriver with IOCTL_SCSI_GET_ADDRESS to retrieve
  733. required data. Caller has to have allocated the data buffer beforehand.
  734. This routine must be run at IRQL_PASSIVE_LEVEL
  735. Arguments:
  736. pDeviceObject - the device to query
  737. pTargetInfo - a location to store the data of target SCSI device
  738. Return Value:
  739. Status
  740. --*/
  741. {
  742. PIRP pIrp = NULL;
  743. PKEVENT pEvent = NULL;
  744. PSCSI_ADDRESS pLocalInfo = NULL;
  745. IO_STATUS_BLOCK StatusBlock;
  746. NTSTATUS Status ;
  747. //
  748. // Set the descriptor pointer to NULL and
  749. // Initialize the event we're going to wait on.
  750. //
  751. pEvent = NULL;
  752. pLocalInfo = NULL;
  753. pEvent = MyAllocatePool(NonPagedPool, sizeof(KEVENT));
  754. if(pEvent == NULL) {
  755. DebugTrace(MAX_TRACE,("ClassGetInfo: Unable to allocate event\n"));
  756. Status = STATUS_INSUFFICIENT_RESOURCES;
  757. goto Cleanup;
  758. }
  759. pLocalInfo = MyAllocatePool(NonPagedPool, sizeof(SCSI_ADDRESS));
  760. if(pLocalInfo == NULL) {
  761. DebugTrace(MAX_TRACE,("ClassGetInfo: Unable to allocate local buffer\n"));
  762. Status = STATUS_INSUFFICIENT_RESOURCES;
  763. goto Cleanup;
  764. }
  765. KeInitializeEvent(pEvent, SynchronizationEvent, FALSE);
  766. __try {
  767. //
  768. // Build irp and wait for it to complete (if necessary)
  769. //
  770. pIrp = IoBuildDeviceIoControlRequest(
  771. IOCTL_SCSI_GET_ADDRESS, // IOCTL code
  772. pDeviceObject, // DeviceObject to be called
  773. NULL, // input buffer
  774. 0, // size of input buffer
  775. pLocalInfo, // output buffer
  776. sizeof(SCSI_ADDRESS), // size of output buffer
  777. FALSE, // IRP_MJ_DEVICE_CONTROL
  778. pEvent, // event is called when completion
  779. &StatusBlock); // IO status block
  780. if (pIrp == NULL) {
  781. DebugTrace(MAX_TRACE,("ClassGetInfo: unable to allocate irp\n"));
  782. Status = STATUS_INSUFFICIENT_RESOURCES;
  783. __leave;
  784. }
  785. Status = IoCallDriver(pDeviceObject, pIrp);
  786. if (Status == STATUS_PENDING) {
  787. KeWaitForSingleObject(pEvent,
  788. Executive,
  789. KernelMode,
  790. FALSE,
  791. NULL);
  792. Status = StatusBlock.Status;
  793. }
  794. if (!NT_SUCCESS(Status)) {
  795. DebugTrace(MAX_TRACE,
  796. ("ClassGetInfo: error %#08lx\n",
  797. Status));
  798. __leave;
  799. }
  800. } __finally {
  801. if(NT_SUCCESS(Status)) {
  802. pTargetInfo->PortNumber = pLocalInfo->PortNumber;
  803. pTargetInfo->PathId = pLocalInfo->PathId;
  804. pTargetInfo->TargetId = pLocalInfo->TargetId;
  805. pTargetInfo->Lun = pLocalInfo->Lun;
  806. }
  807. }
  808. Cleanup:
  809. //
  810. // Release resources
  811. //
  812. if (pEvent) {
  813. MyFreePool(pEvent);
  814. pEvent = NULL;
  815. }
  816. if (pLocalInfo) {
  817. MyFreePool(pLocalInfo);
  818. pLocalInfo = NULL;
  819. }
  820. return Status;
  821. }