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.

1161 lines
26 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. scsi.c
  5. Abstract:
  6. This file contains RAM disk driver code for processing SCSI commands.
  7. Author:
  8. Chuck Lenzmeier (ChuckL) 2001
  9. Environment:
  10. Kernel mode only.
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. //
  17. // Local functions.
  18. //
  19. NTSTATUS
  20. Do6ByteCdbCommand (
  21. IN PDEVICE_OBJECT DeviceObject,
  22. IN OUT PSCSI_REQUEST_BLOCK Srb
  23. );
  24. NTSTATUS
  25. Do10ByteCdbCommand (
  26. IN PDEVICE_OBJECT DeviceObject,
  27. IN OUT PIRP Irp,
  28. IN OUT PSCSI_REQUEST_BLOCK Srb
  29. );
  30. NTSTATUS
  31. Do12ByteCdbCommand (
  32. IN PDEVICE_OBJECT DeviceObject,
  33. IN OUT PSCSI_REQUEST_BLOCK Srb
  34. );
  35. NTSTATUS
  36. BuildInquiryData (
  37. IN PDEVICE_OBJECT DeviceObject,
  38. IN OUT PSCSI_REQUEST_BLOCK Srb
  39. );
  40. NTSTATUS
  41. BuildModeSenseInfo (
  42. IN PDEVICE_OBJECT DeviceObject,
  43. IN OUT PSCSI_REQUEST_BLOCK Srb
  44. );
  45. //
  46. // Declare pageable routines.
  47. //
  48. #ifdef ALLOC_PRAGMA
  49. #pragma alloc_text( PAGE, RamdiskScsiExecuteNone )
  50. #pragma alloc_text( PAGE, RamdiskScsiExecuteIo )
  51. #pragma alloc_text( PAGE, Do6ByteCdbCommand )
  52. #pragma alloc_text( PAGE, Do10ByteCdbCommand )
  53. #pragma alloc_text( PAGE, Do12ByteCdbCommand )
  54. #pragma alloc_text( PAGE, BuildInquiryData )
  55. #pragma alloc_text( PAGE, BuildModeSenseInfo )
  56. #endif // ALLOC_PRAGMA
  57. NTSTATUS
  58. RamdiskScsi (
  59. IN PDEVICE_OBJECT DeviceObject,
  60. IN PIRP Irp
  61. )
  62. /*++
  63. Routine Description:
  64. This routine is called by the I/O system to process a SCSI IRP.
  65. Arguments:
  66. DeviceObject - a pointer to the object that represents the device on which
  67. I/O is to be performed
  68. Irp - a pointer to the I/O Request Packet for this request
  69. Return Value:
  70. NTSTATUS - the status of the operation
  71. --*/
  72. {
  73. NTSTATUS status;
  74. PDISK_EXTENSION diskExtension;
  75. diskExtension = DeviceObject->DeviceExtension;
  76. //
  77. // ISSUE: Can't be paged because ClassCheckMediaState calls it from timer
  78. // routine. (For removable disks.) Therefore we can't acquire the device
  79. // mutex here.
  80. //
  81. //
  82. // Check to see if the device is being removed.
  83. //
  84. if ( diskExtension->DeviceState > RamdiskDeviceStatePendingRemove ) {
  85. status = STATUS_DEVICE_DOES_NOT_EXIST;
  86. COMPLETE_REQUEST( status, 0, Irp );
  87. return status;
  88. }
  89. //
  90. // Acquire the remove lock for the device.
  91. //
  92. status = IoAcquireRemoveLock( &diskExtension->RemoveLock, Irp );
  93. if ( !NT_SUCCESS(status) ) {
  94. DBGPRINT( DBG_PNP, DBG_ERROR, ("%s", "RamdiskScsi: acquire RemoveLock failed\n") );
  95. COMPLETE_REQUEST( status, 0, Irp );
  96. return status;
  97. }
  98. //
  99. // This IRP must be processed in thread context.
  100. //
  101. status = SendIrpToThread( DeviceObject, Irp );
  102. if ( status != STATUS_PENDING ) {
  103. DBGPRINT( DBG_PNP, DBG_ERROR, ("%s", "RamdiskScsi: SendIrpToThread failed\n") );
  104. COMPLETE_REQUEST( status, 0, Irp );
  105. return status;
  106. }
  107. //
  108. // Release the remove lock.
  109. //
  110. IoReleaseRemoveLock(&diskExtension->RemoveLock, Irp );
  111. return STATUS_PENDING;
  112. } // RamdiskScsi
  113. NTSTATUS
  114. RamdiskScsiExecuteNone (
  115. PDEVICE_OBJECT DeviceObject,
  116. PIRP Irp,
  117. PSCSI_REQUEST_BLOCK Srb,
  118. ULONG ControlCode
  119. )
  120. /*++
  121. Routine Description:
  122. This routine is called by the I/O system to process a SCSI IRP that
  123. does not involve I/O.
  124. Arguments:
  125. DeviceObject - a pointer to the object that represents the device on which
  126. I/O is to be performed
  127. Irp - a pointer to the I/O Request Packet for this request
  128. Srb - the SRB associated with the IRP
  129. ControlCode - the control code from the SRB
  130. Return Value:
  131. NTSTATUS - the status of the operation
  132. --*/
  133. {
  134. NTSTATUS status;
  135. UCHAR function;
  136. PDISK_EXTENSION diskExtension;
  137. PAGED_CODE();
  138. diskExtension = DeviceObject->DeviceExtension;
  139. //
  140. // Dispatch based on the SRB function.
  141. //
  142. function = Srb->Function;
  143. switch( function ) {
  144. case SRB_FUNCTION_ATTACH_DEVICE:
  145. case SRB_FUNCTION_CLAIM_DEVICE:
  146. DBGPRINT( DBG_SRB, DBG_VERBOSE, ("%s", "SRB_FUNCTION_CLAIM_DEVICE\n") );
  147. //
  148. // If the device has not already been claimed, mark it so now.
  149. // Otherwise, indicate to the caller that the device is busy.
  150. //
  151. if ( (diskExtension->Status & RAMDISK_STATUS_CLAIMED) == 0 ) {
  152. diskExtension->DeviceState = RamdiskDeviceStateWorking;
  153. diskExtension->Status |= RAMDISK_STATUS_CLAIMED;
  154. Srb->DataBuffer = DeviceObject;
  155. status = STATUS_SUCCESS;
  156. Srb->ScsiStatus = SCSISTAT_GOOD;
  157. Srb->SrbStatus = SRB_STATUS_SUCCESS;
  158. } else {
  159. status = STATUS_DEVICE_BUSY;
  160. Srb->ScsiStatus = SCSISTAT_BUSY;
  161. Srb->SrbStatus = SRB_STATUS_BUSY;
  162. }
  163. break;
  164. case SRB_FUNCTION_RELEASE_DEVICE:
  165. case SRB_FUNCTION_REMOVE_DEVICE:
  166. DBGPRINT( DBG_SRB, DBG_VERBOSE, ("%s", "SRB_FUNCTION_RELEASE_DEVICE\n") );
  167. //
  168. // Indicate that the device is no longer claimed.
  169. //
  170. diskExtension->Status &= ~RAMDISK_STATUS_CLAIMED;
  171. status = STATUS_SUCCESS;
  172. Srb->ScsiStatus = SCSISTAT_GOOD;
  173. Srb->SrbStatus = SRB_STATUS_SUCCESS;
  174. break;
  175. default:
  176. //
  177. // Unrecognized non-I/O function. Try the I/O path.
  178. //
  179. status = RamdiskScsiExecuteIo( DeviceObject, Irp, Srb, ControlCode );
  180. break;
  181. }
  182. return status;
  183. } // RamdiskScsiExecuteNone
  184. NTSTATUS
  185. RamdiskScsiExecuteIo (
  186. PDEVICE_OBJECT DeviceObject,
  187. PIRP Irp,
  188. PSCSI_REQUEST_BLOCK Srb,
  189. ULONG ControlCode
  190. )
  191. /*++
  192. Routine Description:
  193. This routine is called by the I/O system to process a SCSI IRP that
  194. involves I/O.
  195. Arguments:
  196. DeviceObject - a pointer to the object that represents the device on which
  197. I/O is to be performed
  198. Irp - a pointer to the I/O Request Packet for this request
  199. Srb - the SRB associated with the IRP
  200. ControlCode - the control code from the SRB
  201. Return Value:
  202. NTSTATUS - the status of the operation
  203. --*/
  204. {
  205. NTSTATUS status;
  206. UCHAR function;
  207. PDISK_EXTENSION diskExtension;
  208. PAGED_CODE();
  209. diskExtension = DeviceObject->DeviceExtension;
  210. //
  211. // Dispatch based on the SRB function.
  212. //
  213. function = Srb->Function;
  214. switch( function ) {
  215. case SRB_FUNCTION_EXECUTE_SCSI:
  216. Srb->SrbStatus = SRB_STATUS_SUCCESS;
  217. //
  218. // Dispatch based on the CDB length.
  219. //
  220. switch( Srb->CdbLength ) {
  221. case 6:
  222. status = Do6ByteCdbCommand( DeviceObject, Srb );
  223. break;
  224. case 10:
  225. status = Do10ByteCdbCommand( DeviceObject, Irp, Srb );
  226. break;
  227. case 12:
  228. status = Do12ByteCdbCommand( DeviceObject, Srb );
  229. break;
  230. default:
  231. DBGPRINT( DBG_SRB, DBG_ERROR,
  232. ("Unknown CDB length 0x%x for function 0x%x, IOCTL 0x%x\n",
  233. Srb->CdbLength, function, ControlCode) );
  234. UNRECOGNIZED_IOCTL_BREAK;
  235. status = STATUS_INVALID_DEVICE_REQUEST;
  236. Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  237. break;
  238. }
  239. break;
  240. case SRB_FUNCTION_FLUSH:
  241. case SRB_FUNCTION_SHUTDOWN:
  242. //
  243. // For flush and shutdown on a file-backed RAM disk, we need to flush
  244. // the mapped data back to the file.
  245. //
  246. status = RamdiskFlushBuffersReal( diskExtension );
  247. Srb->SrbStatus = SRB_STATUS_SUCCESS;
  248. break;
  249. case SRB_FUNCTION_IO_CONTROL:
  250. //
  251. // We don't handle this function, but we don't want to complain
  252. // when we get it.
  253. //
  254. status = STATUS_INVALID_DEVICE_REQUEST;
  255. Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  256. break;
  257. default:
  258. DBGPRINT( DBG_SRB, DBG_ERROR,
  259. ("Unknown SRB Function 0x%x for IOCTL 0x%x\n", function, ControlCode) );
  260. UNRECOGNIZED_IOCTL_BREAK;
  261. status = STATUS_INTERNAL_ERROR;
  262. }
  263. return status;
  264. } // RamdiskScsiExecuteIo
  265. NTSTATUS
  266. Do6ByteCdbCommand (
  267. IN PDEVICE_OBJECT DeviceObject,
  268. IN OUT PSCSI_REQUEST_BLOCK Srb
  269. )
  270. /*++
  271. Routine Description:
  272. This routine handles 6-byte CDBs.
  273. Arguments:
  274. DeviceObject - a pointer to the object that represents the device on which
  275. I/O is to be performed
  276. Srb - the SRB associated with the I/O request
  277. Return Value:
  278. NTSTATUS - the status of the operation
  279. --*/
  280. {
  281. NTSTATUS status;
  282. PDISK_EXTENSION diskExtension;
  283. PCDB cdb;
  284. PAGED_CODE();
  285. //
  286. // Get pointers to the device extension and to the CDB.
  287. //
  288. diskExtension = DeviceObject->DeviceExtension;
  289. cdb = (PCDB)Srb->Cdb;
  290. //
  291. // Assume success.
  292. //
  293. status = STATUS_SUCCESS;
  294. Srb->SrbStatus = SRB_STATUS_SUCCESS;
  295. Srb->ScsiStatus = SCSISTAT_GOOD;
  296. ASSERT( Srb->CdbLength == 6 );
  297. ASSERT( cdb != NULL );
  298. DBGPRINT( DBG_SRB, DBG_VERBOSE,
  299. ("Do6ByteCdbCommand Called OpCode 0x%x\n", cdb->CDB6GENERIC.OperationCode) );
  300. //
  301. // Dispatch based on the operation code.
  302. //
  303. switch ( cdb->CDB6GENERIC.OperationCode ) {
  304. case SCSIOP_TEST_UNIT_READY:
  305. //
  306. // RAM disks are always ready.
  307. //
  308. break;
  309. case SCSIOP_REQUEST_SENSE:
  310. //
  311. // We don't handle request sense.
  312. //
  313. Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  314. status = STATUS_INVALID_DEVICE_REQUEST;
  315. break;
  316. case SCSIOP_FORMAT_UNIT:
  317. // ISSUE: Need to do something here, like zero the image?
  318. break;
  319. case SCSIOP_INQUIRY:
  320. //
  321. // If the buffer is big enough, build the inquiry data.
  322. //
  323. if ( Srb->DataTransferLength >= INQUIRYDATABUFFERSIZE ) {
  324. status = BuildInquiryData( DeviceObject, Srb );
  325. } else {
  326. Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  327. status = STATUS_INVALID_DEVICE_REQUEST;
  328. }
  329. break;
  330. case SCSIOP_MODE_SENSE:
  331. //
  332. // Build the mode sense information.
  333. //
  334. status = BuildModeSenseInfo( DeviceObject, Srb );
  335. break;
  336. case SCSIOP_MEDIUM_REMOVAL:
  337. //
  338. // Remember whether media removal is allowed.
  339. //
  340. if (cdb->MEDIA_REMOVAL.Prevent == TRUE) {
  341. diskExtension->Status |= RAMDISK_STATUS_PREVENT_REMOVE;
  342. } else {
  343. diskExtension->Status &= ~RAMDISK_STATUS_PREVENT_REMOVE;
  344. }
  345. break;
  346. //case SCSIOP_READ6:
  347. //case SCSIOP_WRITE6:
  348. //case SCSIOP_REZERO_UNIT:
  349. //case SCSIOP_REQUEST_BLOCK_ADDR:
  350. //case SCSIOP_READ_BLOCK_LIMITS:
  351. //case SCSIOP_REASSIGN_BLOCKS:
  352. //case SCSIOP_SEEK6:
  353. //case SCSIOP_SEEK_BLOCK:
  354. //case SCSIOP_PARTITION:
  355. //case SCSIOP_READ_REVERSE:
  356. //case SCSIOP_WRITE_FILEMARKS:
  357. //case SCSIOP_SPACE:
  358. //case SCSIOP_VERIFY6:
  359. //case SCSIOP_RECOVER_BUF_DATA:
  360. //case SCSIOP_MODE_SELECT:
  361. //case SCSIOP_RESERVE_UNIT:
  362. //case SCSIOP_RELEASE_UNIT:
  363. //case SCSIOP_COPY:
  364. //case SCSIOP_ERASE:
  365. //case SCSIOP_START_STOP_UNIT:
  366. //case SCSIOP_RECEIVE_DIAGNOSTIC:
  367. //case SCSIOP_SEND_DIAGNOSTIC:
  368. default:
  369. DBGPRINT( DBG_SRB, DBG_ERROR,
  370. ("Unknown CDB Function 0x%x\n", cdb->CDB6GENERIC.OperationCode) );
  371. UNRECOGNIZED_IOCTL_BREAK;
  372. status = STATUS_INVALID_DEVICE_REQUEST;
  373. Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  374. }
  375. DBGPRINT( DBG_SRB, DBG_VERBOSE, ("Do6ByteCdbCommand Done status 0x%x\n", status) );
  376. return status;
  377. } // Do6ByteCdbCommand
  378. NTSTATUS
  379. Do10ByteCdbCommand (
  380. IN PDEVICE_OBJECT DeviceObject,
  381. IN OUT PIRP Irp,
  382. IN OUT PSCSI_REQUEST_BLOCK Srb
  383. )
  384. /*++
  385. Routine Description:
  386. This routine handles 10-byte CDBs.
  387. Arguments:
  388. DeviceObject - a pointer to the object that represents the device on which
  389. I/O is to be performed
  390. Irp - a pointer to the I/O Request Packet for this request
  391. Srb - the SRB associated with the IRP
  392. Return Value:
  393. NTSTATUS - the status of the operation
  394. --*/
  395. {
  396. NTSTATUS status;
  397. PDISK_EXTENSION diskExtension;
  398. PCDB cdb;
  399. PREAD_CAPACITY_DATA readCapacityData;
  400. ULONGLONG diskSize;
  401. ULONG lastBlock;
  402. FOUR_BYTE startingBlockNumber;
  403. TWO_BYTE count;
  404. ULONG_PTR offset;
  405. ULONG dataSize;
  406. PUCHAR diskByteAddress;
  407. PUCHAR dataBuffer;
  408. ULONG mappedLength;
  409. PAGED_CODE();
  410. //
  411. // Get pointers to the device extension and to the CDB.
  412. //
  413. diskExtension = DeviceObject->DeviceExtension;
  414. cdb = (PCDB)Srb->Cdb;
  415. //
  416. // Assume success.
  417. //
  418. status = STATUS_SUCCESS;
  419. Srb->SrbStatus = SRB_STATUS_SUCCESS;
  420. Srb->ScsiStatus = SCSISTAT_GOOD;
  421. ASSERT( Srb->CdbLength == 10 );
  422. ASSERT( cdb != NULL );
  423. DBGPRINT( DBG_SRB, DBG_VERBOSE,
  424. ("Do10ByteCdbCommand Called OpCode 0x%x\n", cdb->CDB10.OperationCode) );
  425. //
  426. // Dispatch based on the operation code.
  427. //
  428. switch ( cdb->CDB10.OperationCode ) {
  429. case SCSIOP_READ_CAPACITY:
  430. //
  431. // Return the disk's block size and last block number (big-endian).
  432. //
  433. readCapacityData = Srb->DataBuffer;
  434. diskSize = diskExtension->DiskLength;
  435. lastBlock = (ULONG)(diskSize / diskExtension->BytesPerSector) - 1;
  436. readCapacityData->BytesPerBlock = _byteswap_ulong( diskExtension->BytesPerSector );
  437. readCapacityData->LogicalBlockAddress = _byteswap_ulong( lastBlock );
  438. break;
  439. case SCSIOP_READ:
  440. case SCSIOP_WRITE:
  441. //
  442. // Read from or write to the disk.
  443. //
  444. //
  445. // Convert the transfer length, in blocks, from big-endian. Convert
  446. // that to bytes.
  447. //
  448. count.Byte0 = cdb->CDB10.TransferBlocksLsb;
  449. count.Byte1 = cdb->CDB10.TransferBlocksMsb;
  450. dataSize = count.AsUShort * diskExtension->BytesPerSector;
  451. //
  452. // If the CDB length is greater than the SRB length, use the SRB
  453. // length.
  454. //
  455. if ( dataSize > Srb->DataTransferLength ) {
  456. dataSize = Srb->DataTransferLength;
  457. }
  458. //
  459. // Convert the starting block number from big-endian.
  460. //
  461. startingBlockNumber.Byte0 = cdb->CDB10.LogicalBlockByte3;
  462. startingBlockNumber.Byte1 = cdb->CDB10.LogicalBlockByte2;
  463. startingBlockNumber.Byte2 = cdb->CDB10.LogicalBlockByte1;
  464. startingBlockNumber.Byte3 = cdb->CDB10.LogicalBlockByte0;
  465. //
  466. // We don't handle RelativeAddress requests.
  467. //
  468. if ( cdb->CDB10.RelativeAddress ) {
  469. Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  470. status = STATUS_INVALID_DEVICE_REQUEST;
  471. break;
  472. }
  473. //
  474. // Get the offset within the disk to the start of the operation.
  475. //
  476. offset = (startingBlockNumber.AsULong * diskExtension->BytesPerSector);
  477. //
  478. // If the transfer length causes the offset to wrap, or if the request
  479. // goes beyond the end of the disk, reject the request.
  480. //
  481. if ( ((offset + dataSize) < offset) ||
  482. ((offset + dataSize) > diskExtension->DiskLength) ) {
  483. Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  484. status = STATUS_INVALID_DEVICE_REQUEST;
  485. break;
  486. }
  487. //
  488. // For a zero-length transfer, we don't have to do anything.
  489. //
  490. DBGPRINT( DBG_READWRITE, DBG_VERBOSE,
  491. ("%s: Starting Block 0x%x, Length 0x%x at Offset 0x%I64x SrbBuffer=0x%p "
  492. "SrbLength=0x%x, MdlLength=0x%x\n",
  493. cdb->CDB10.OperationCode == SCSIOP_READ ? "Read" : "Write",
  494. startingBlockNumber.AsULong, count.AsUShort, offset,
  495. Srb->DataBuffer,
  496. Srb->DataTransferLength,
  497. Irp->MdlAddress->ByteCount) );
  498. dataBuffer = Srb->DataBuffer;
  499. while ( dataSize != 0 ) {
  500. //
  501. // Map the target section of the disk into memory. Then copy the
  502. // data in the appropriate direction.
  503. //
  504. diskByteAddress = RamdiskMapPages( diskExtension, offset, dataSize, &mappedLength );
  505. if ( diskByteAddress != NULL ) {
  506. if ( cdb->CDB10.OperationCode == SCSIOP_READ ) {
  507. memcpy( dataBuffer, diskByteAddress, mappedLength );
  508. } else {
  509. memcpy( diskByteAddress, dataBuffer, mappedLength );
  510. }
  511. RamdiskUnmapPages( diskExtension, diskByteAddress, offset, mappedLength );
  512. dataSize -= mappedLength;
  513. offset += mappedLength;
  514. dataBuffer += mappedLength;
  515. } else {
  516. dataSize = 0;
  517. Srb->SrbStatus = SRB_STATUS_ERROR;
  518. status = STATUS_INSUFFICIENT_RESOURCES;
  519. }
  520. }
  521. break;
  522. case SCSIOP_VERIFY:
  523. //
  524. // Verify always succeeds.
  525. //
  526. break;
  527. case SCSIOP_MODE_SENSE10:
  528. //
  529. // Build the mode sense information.
  530. //
  531. status = BuildModeSenseInfo( DeviceObject, Srb );
  532. break;
  533. //case SCSIOP_SEEK:
  534. //case SCSIOP_WRITE_VERIFY:
  535. //case SCSIOP_READ_FORMATTED_CAPACITY:
  536. //case SCSIOP_SEARCH_DATA_HIGH:
  537. //case SCSIOP_SEARCH_DATA_EQUAL:
  538. //case SCSIOP_SEARCH_DATA_LOW:
  539. //case SCSIOP_SET_LIMITS:
  540. //case SCSIOP_READ_POSITION:
  541. //case SCSIOP_SYNCHRONIZE_CACHE:
  542. //case SCSIOP_COMPARE:
  543. //case SCSIOP_COPY_COMPARE:
  544. //case SCSIOP_WRITE_DATA_BUFF:
  545. //case SCSIOP_READ_DATA_BUFF:
  546. //case SCSIOP_CHANGE_DEFINITION:
  547. //case SCSIOP_READ_SUB_CHANNEL:
  548. //case SCSIOP_READ_TOC:
  549. //case SCSIOP_READ_HEADER:
  550. //case SCSIOP_PLAY_AUDIO:
  551. //case SCSIOP_GET_CONFIGURATION:
  552. //case SCSIOP_PLAY_AUDIO_MSF:
  553. //case SCSIOP_PLAY_TRACK_INDEX:
  554. //case SCSIOP_PLAY_TRACK_RELATIVE:
  555. //case SCSIOP_GET_EVENT_STATUS:
  556. //case SCSIOP_PAUSE_RESUME:
  557. //case SCSIOP_LOG_SELECT:
  558. //case SCSIOP_LOG_SENSE:
  559. //case SCSIOP_STOP_PLAY_SCAN:
  560. //case SCSIOP_READ_DISK_INFORMATION:
  561. //case SCSIOP_READ_TRACK_INFORMATION:
  562. //case SCSIOP_RESERVE_TRACK_RZONE:
  563. //case SCSIOP_SEND_OPC_INFORMATION:
  564. //case SCSIOP_MODE_SELECT10:
  565. //case SCSIOP_CLOSE_TRACK_SESSION:
  566. //case SCSIOP_READ_BUFFER_CAPACITY:
  567. //case SCSIOP_SEND_CUE_SHEET:
  568. //case SCSIOP_PERSISTENT_RESERVE_IN:
  569. //case SCSIOP_PERSISTENT_RESERVE_OUT:
  570. default:
  571. DBGPRINT( DBG_SRB, DBG_ERROR,
  572. ("Unknown CDB Function 0x%x\n", cdb->CDB10.OperationCode) );
  573. UNRECOGNIZED_IOCTL_BREAK;
  574. status = STATUS_INVALID_DEVICE_REQUEST;
  575. Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  576. }
  577. DBGPRINT( DBG_SRB, DBG_VERBOSE, ("Do10ByteCdbCommand Done status 0x%x\n", status) );
  578. return status;
  579. } // Do10ByteCdbCommand
  580. NTSTATUS
  581. Do12ByteCdbCommand (
  582. IN PDEVICE_OBJECT DeviceObject,
  583. IN OUT PSCSI_REQUEST_BLOCK Srb
  584. )
  585. /*++
  586. Routine Description:
  587. This routine handles 12-byte CDBs.
  588. Arguments:
  589. DeviceObject - a pointer to the object that represents the device on which
  590. I/O is to be performed
  591. Srb - the SRB associated with the IRP
  592. Return Value:
  593. NTSTATUS - the status of the operation
  594. --*/
  595. {
  596. NTSTATUS status;
  597. PDISK_EXTENSION diskExtension;
  598. PCDB cdb;
  599. PAGED_CODE();
  600. //
  601. // Get pointers to the device extension and to the CDB.
  602. //
  603. diskExtension = DeviceObject->DeviceExtension;
  604. cdb = (PCDB)Srb->Cdb;
  605. //
  606. // Assume success.
  607. //
  608. status = STATUS_SUCCESS;
  609. Srb->SrbStatus = SRB_STATUS_SUCCESS;
  610. Srb->ScsiStatus = SCSISTAT_GOOD;
  611. ASSERT( Srb->CdbLength == 12 );
  612. ASSERT( cdb != NULL );
  613. DBGPRINT( DBG_SRB, DBG_VERBOSE,
  614. ("Do12ByteCdbCommand Called OpCode 0x%x\n", cdb->CDB12.OperationCode) );
  615. //
  616. // Dispatch based on the operation code.
  617. //
  618. switch ( cdb->CDB12.OperationCode ) {
  619. //case SCSIOP_REPORT_LUNS:
  620. //case SCSIOP_BLANK:
  621. //case SCSIOP_SEND_KEY:
  622. //case SCSIOP_REPORT_KEY:
  623. //case SCSIOP_MOVE_MEDIUM:
  624. //case SCSIOP_LOAD_UNLOAD_SLOT:
  625. //case SCSIOP_SET_READ_AHEAD:
  626. //case SCSIOP_READ_DVD_STRUCTURE:
  627. //case SCSIOP_REQUEST_VOL_ELEMENT:
  628. //case SCSIOP_SEND_VOLUME_TAG:
  629. //case SCSIOP_READ_ELEMENT_STATUS:
  630. //case SCSIOP_READ_CD_MSF:
  631. //case SCSIOP_SCAN_CD:
  632. //case SCSIOP_SET_CD_SPEED:
  633. //case SCSIOP_PLAY_CD:
  634. //case SCSIOP_MECHANISM_STATUS:
  635. //case SCSIOP_READ_CD:
  636. //case SCSIOP_SEND_DVD_STRUCTURE:
  637. //case SCSIOP_INIT_ELEMENT_RANGE:
  638. default:
  639. DBGPRINT( DBG_SRB, DBG_ERROR,
  640. ("Unknown CDB Function 0x%x\n", cdb->CDB12.OperationCode) );
  641. UNRECOGNIZED_IOCTL_BREAK;
  642. status = STATUS_INVALID_DEVICE_REQUEST;
  643. Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  644. }
  645. DBGPRINT( DBG_SRB, DBG_VERBOSE, ("Do12ByteCdbCommand Done status 0x%x\n", status) );
  646. return status;
  647. } // Do12ByteCdbCommand
  648. NTSTATUS
  649. BuildInquiryData (
  650. IN PDEVICE_OBJECT DeviceObject,
  651. IN OUT PSCSI_REQUEST_BLOCK Srb
  652. )
  653. /*++
  654. Routine Description:
  655. This routine builds inquiry data.
  656. Arguments:
  657. DeviceObject - a pointer to the object that represents the device on which
  658. I/O is to be performed
  659. Srb - the SRB associated with the I/O request
  660. Return Value:
  661. NTSTATUS - the status of the operation
  662. --*/
  663. {
  664. PDISK_EXTENSION diskExtension;
  665. PINQUIRYDATA inquiryData;
  666. STRING vendor;
  667. STRING product;
  668. STRING revLevel;
  669. PAGED_CODE();
  670. //
  671. // Get pointers to the device extension and to the inquiry data buffer.
  672. //
  673. diskExtension = DeviceObject->DeviceExtension;
  674. inquiryData = (PINQUIRYDATA)Srb->DataBuffer;
  675. //
  676. // Build the inquiry data.
  677. //
  678. RtlInitString( &vendor, "Microsoft" );
  679. RtlInitString( &product, "Ramdisk" );
  680. RtlInitString( &revLevel, "1.0" );
  681. RtlZeroMemory( inquiryData, INQUIRYDATABUFFERSIZE );
  682. inquiryData->DeviceType = DIRECT_ACCESS_DEVICE;
  683. inquiryData->RemovableMedia = (diskExtension->Options.Fixed ? FALSE : TRUE);
  684. inquiryData->ANSIVersion = 2;
  685. inquiryData->ResponseDataFormat = 2;
  686. inquiryData->AdditionalLength = INQUIRYDATABUFFERSIZE - 4;
  687. RtlCopyMemory(
  688. inquiryData->VendorId,
  689. vendor.Buffer,
  690. min( vendor.Length, sizeof(inquiryData->VendorId) )
  691. );
  692. RtlCopyMemory(
  693. inquiryData->ProductId,
  694. product.Buffer,
  695. min( product.Length, sizeof(inquiryData->ProductId) )
  696. );
  697. RtlCopyMemory(
  698. inquiryData->ProductRevisionLevel,
  699. revLevel.Buffer,
  700. min( revLevel.Length, sizeof(inquiryData->ProductRevisionLevel) )
  701. );
  702. return STATUS_SUCCESS;
  703. } // BuildInquiryData
  704. NTSTATUS
  705. BuildModeSenseInfo (
  706. IN PDEVICE_OBJECT DeviceObject,
  707. IN OUT PSCSI_REQUEST_BLOCK Srb
  708. )
  709. /*++
  710. Routine Description:
  711. This routine builds mode sense information.
  712. Arguments:
  713. DeviceObject - a pointer to the object that represents the device on which
  714. I/O is to be performed
  715. Srb - the SRB associated with the I/O request
  716. Return Value:
  717. NTSTATUS - the status of the operation
  718. --*/
  719. {
  720. PDISK_EXTENSION diskExtension;
  721. MODE_PARAMETER_HEADER modeHeader = {0};
  722. MODE_PARAMETER_HEADER10 modeHeader10 = {0};
  723. PVOID header = NULL;
  724. PVOID data = NULL;
  725. unsigned char headerSize;
  726. unsigned dataSize = 0;
  727. PCDB cdb;
  728. unsigned cdbLength;
  729. unsigned dataBufferLength;
  730. unsigned char valueType;
  731. unsigned dataLength;
  732. PAGED_CODE();
  733. //
  734. // Get pointers to the device extension and to the inquiry data buffer.
  735. //
  736. diskExtension = DeviceObject->DeviceExtension;
  737. cdb = (PCDB)Srb->Cdb;
  738. cdbLength = Srb->CdbLength;
  739. //
  740. // Dispatch based on the CDB length.
  741. //
  742. switch ( cdbLength ) {
  743. case 6:
  744. dataBufferLength = cdb->MODE_SENSE.AllocationLength;
  745. valueType = cdb->MODE_SENSE.Pc;
  746. headerSize = sizeof(MODE_PARAMETER_HEADER);
  747. if ( valueType != 0 ) {
  748. //
  749. // We only support current value retrieval.
  750. //
  751. Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  752. return STATUS_INVALID_DEVICE_REQUEST;
  753. }
  754. if ( dataBufferLength > headerSize ) {
  755. header = &modeHeader;
  756. data = (char*)header + headerSize;
  757. dataLength = headerSize - FIELD_OFFSET( MODE_PARAMETER_HEADER, MediumType );
  758. modeHeader.ModeDataLength = (UCHAR)dataLength;
  759. modeHeader.MediumType = 0x00;
  760. modeHeader.DeviceSpecificParameter = 0x00;
  761. modeHeader.BlockDescriptorLength = 0x00;
  762. }
  763. break;
  764. case 10:
  765. dataBufferLength = *(USHORT *)cdb->MODE_SENSE10.AllocationLength;
  766. valueType = cdb->MODE_SENSE10.Pc;
  767. headerSize = sizeof(MODE_PARAMETER_HEADER10);
  768. if ( dataBufferLength > headerSize ) {
  769. header = &modeHeader10;
  770. data = (char*)header + headerSize;
  771. dataLength = headerSize - FIELD_OFFSET( MODE_PARAMETER_HEADER10, MediumType );
  772. RtlCopyMemory(
  773. modeHeader10.ModeDataLength,
  774. &dataLength,
  775. sizeof(modeHeader10.ModeDataLength)
  776. );
  777. modeHeader10.MediumType = 0x00;
  778. modeHeader10.DeviceSpecificParameter = 0x00;
  779. modeHeader10.BlockDescriptorLength[0] = 0;
  780. modeHeader10.BlockDescriptorLength[1] = 0;
  781. }
  782. break;
  783. default:
  784. //
  785. // Can't get here.
  786. //
  787. ASSERT( FALSE );
  788. Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  789. return STATUS_INVALID_DEVICE_REQUEST;
  790. }
  791. if ( header != NULL ) {
  792. RtlCopyMemory( Srb->DataBuffer, header, headerSize );
  793. dataBufferLength -= headerSize;
  794. }
  795. if ( (data != NULL) && (dataBufferLength != 0) ) {
  796. RtlCopyMemory(
  797. (PUCHAR)Srb->DataBuffer + headerSize,
  798. data,
  799. min( dataBufferLength, dataSize )
  800. );
  801. }
  802. return STATUS_SUCCESS;
  803. } // BuildModeSenseInfo