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.

540 lines
13 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 2000
  3. Module Name:
  4. internal.c
  5. Abstract:
  6. This file contains internal routines
  7. Environment:
  8. kernel mode only
  9. Revision History:
  10. --*/
  11. #include "port.h"
  12. #ifdef ALLOC_PRAGMA
  13. #pragma alloc_text(PAGE, iScsiPortFdoDeviceControl)
  14. #pragma alloc_text(PAGE, iScsiPortFdoCreateClose)
  15. #endif // ALLOC_PRAGMA
  16. /*
  17. PISCSI_PDO_EXTENSION
  18. GetPdoExtension(
  19. IN PISCSI_FDO_EXTENSION fdoExtension
  20. );
  21. */
  22. NTSTATUS
  23. iScsiPortFdoDeviceControl(
  24. IN PDEVICE_OBJECT DeviceObject,
  25. IN PIRP Irp
  26. )
  27. {
  28. PISCSI_FDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  29. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  30. NTSTATUS status;
  31. ULONG isRemoved;
  32. ULONG ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  33. DebugPrint((1, "FDO DeviceControl - IO control code : 0x%08x\n",
  34. ioControlCode));
  35. isRemoved = iSpAcquireRemoveLock(DeviceObject, Irp);
  36. if(isRemoved) {
  37. iSpReleaseRemoveLock(DeviceObject, Irp);
  38. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  39. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  40. return STATUS_DEVICE_DOES_NOT_EXIST;
  41. }
  42. switch (ioControlCode) {
  43. case IOCTL_STORAGE_QUERY_PROPERTY: {
  44. PSTORAGE_PROPERTY_QUERY query = Irp->AssociatedIrp.SystemBuffer;
  45. if(irpStack->Parameters.DeviceIoControl.InputBufferLength <
  46. sizeof(STORAGE_PROPERTY_QUERY)) {
  47. status = STATUS_INVALID_PARAMETER;
  48. break;
  49. }
  50. //
  51. // This routine will release the lock and complete the irp.
  52. //
  53. status = iScsiPortQueryProperty(DeviceObject, Irp);
  54. return status;
  55. break;
  56. }
  57. //
  58. // Get adapter capabilities.
  59. //
  60. case IOCTL_SCSI_GET_CAPABILITIES: {
  61. //
  62. // If the output buffer is equal to the size of the a PVOID then just
  63. // return a pointer to the buffer.
  64. //
  65. if (irpStack->Parameters.DeviceIoControl.OutputBufferLength
  66. == sizeof(PVOID)) {
  67. *((PVOID *)Irp->AssociatedIrp.SystemBuffer)
  68. = &fdoExtension->IoScsiCapabilities;
  69. Irp->IoStatus.Information = sizeof(PVOID);
  70. status = STATUS_SUCCESS;
  71. break;
  72. }
  73. if (irpStack->Parameters.DeviceIoControl.OutputBufferLength
  74. < sizeof(IO_SCSI_CAPABILITIES)) {
  75. status = STATUS_BUFFER_TOO_SMALL;
  76. break;
  77. }
  78. RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
  79. &fdoExtension->IoScsiCapabilities,
  80. sizeof(IO_SCSI_CAPABILITIES));
  81. Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
  82. status = STATUS_SUCCESS;
  83. break;
  84. }
  85. case IOCTL_SCSI_PASS_THROUGH:
  86. case IOCTL_SCSI_PASS_THROUGH_DIRECT: {
  87. status = STATUS_NOT_SUPPORTED;
  88. break;
  89. }
  90. case IOCTL_SCSI_MINIPORT: {
  91. status = STATUS_NOT_SUPPORTED;
  92. break;
  93. }
  94. case IOCTL_SCSI_GET_DUMP_POINTERS: {
  95. status = STATUS_NOT_SUPPORTED;
  96. break;
  97. }
  98. case IOCTL_SCSI_RESCAN_BUS:
  99. case IOCTL_SCSI_GET_INQUIRY_DATA: {
  100. status = STATUS_NOT_SUPPORTED;
  101. break;
  102. }
  103. default: {
  104. DebugPrint((1,
  105. "iScsiPortFdoDeviceControl: Unsupported IOCTL (%x)\n",
  106. ioControlCode));
  107. status = STATUS_INVALID_DEVICE_REQUEST;
  108. break;
  109. }
  110. }
  111. //
  112. // Set status in Irp.
  113. //
  114. Irp->IoStatus.Status = status;
  115. iSpReleaseRemoveLock(DeviceObject, Irp);
  116. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  117. return status;
  118. }
  119. NTSTATUS
  120. iScsiPortFdoDispatch(
  121. IN PDEVICE_OBJECT DeviceObject,
  122. IN PIRP Irp
  123. )
  124. {
  125. PISCSI_FDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  126. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  127. PSCSI_REQUEST_BLOCK srb = irpStack->Parameters.Scsi.Srb;
  128. PISCSI_PDO_EXTENSION pdoExtension;
  129. NTSTATUS status;
  130. ULONG isRemoved;
  131. BOOLEAN sendCommandToServer = FALSE;
  132. //
  133. // Should never get here. All SCSI requests are handled
  134. // by the PDO Dispatch routine
  135. //
  136. DebugPrint((0, "SRB function sent to FDO Dispatch\n"));
  137. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  138. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  139. return STATUS_INVALID_DEVICE_REQUEST;
  140. /*
  141. isRemoved = iSpAcquireRemoveLock(DeviceObject, Irp);
  142. if (isRemoved && !IS_CLEANUP_REQUEST(irpStack)) {
  143. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  144. iSpReleaseRemoveLock(DeviceObject, Irp);
  145. IoCompleteRequest(Irp,
  146. IO_NO_INCREMENT);
  147. return STATUS_DEVICE_DOES_NOT_EXIST;
  148. }
  149. if ((srb->Function) != SRB_FUNCTION_EXECUTE_SCSI) {
  150. DebugPrint((1, "FdoDispatch - SRB Function : 0x%x\n",
  151. srb->Function));
  152. }
  153. pdoExtension = GetPdoExtension(fdoExtension);
  154. ASSERT(pdoExtension != NULL);
  155. switch (srb->Function) {
  156. case SRB_FUNCTION_SHUTDOWN:
  157. case SRB_FUNCTION_FLUSH:
  158. case SRB_FUNCTION_LOCK_QUEUE:
  159. case SRB_FUNCTION_UNLOCK_QUEUE:
  160. case SRB_FUNCTION_IO_CONTROL:
  161. case SRB_FUNCTION_WMI: {
  162. //
  163. // We won't handle these functions on the client
  164. // side for the timebeing.
  165. //
  166. status = STATUS_SUCCESS;
  167. srb->SrbStatus = SRB_STATUS_SUCCESS;
  168. break;
  169. }
  170. case SRB_FUNCTION_SHUTDOWN:
  171. case SRB_FUNCTION_FLUSH: {
  172. //
  173. // Send SCSIOP_SYNCHRONIZE_CACHE command
  174. // to flush the queue
  175. //
  176. srb->CdbLength = 10;
  177. srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE;
  178. IoMarkIrpPending(Irp);
  179. sendCommandToServer = TRUE;
  180. status = STATUS_PENDING;
  181. break;
  182. }
  183. case SRB_FUNCTION_EXECUTE_SCSI: {
  184. //
  185. // Mark Irp status pending.
  186. //
  187. IoMarkIrpPending(Irp);
  188. sendCommandToServer = TRUE;
  189. status = STATUS_PENDING;
  190. }
  191. case SRB_FUNCTION_RELEASE_QUEUE:
  192. case SRB_FUNCTION_FLUSH_QUEUE: {
  193. //
  194. // These will be handled on the server
  195. // side. Here, just return STATUS_SUCCESS
  196. //
  197. status = STATUS_SUCCESS;
  198. srb->SrbStatus = SRB_STATUS_SUCCESS;
  199. break;
  200. }
  201. case SRB_FUNCTION_RESET_BUS: {
  202. DebugPrint((1, "FdoDospatch : Received reset request\n"));
  203. srb->SrbStatus = SRB_STATUS_SUCCESS;
  204. status = STATUS_SUCCESS;
  205. break;
  206. }
  207. case SRB_FUNCTION_ABORT_COMMAND: {
  208. DebugPrint((1, "FdoDispatch: SCSI Abort command\n"));
  209. srb->SrbStatus = SRB_STATUS_SUCCESS;
  210. status = STATUS_SUCCESS;
  211. break;
  212. }
  213. case SRB_FUNCTION_ATTACH_DEVICE:
  214. case SRB_FUNCTION_CLAIM_DEVICE:
  215. case SRB_FUNCTION_RELEASE_DEVICE: {
  216. iSpAcquireRemoveLock((pdoExtension->CommonExtension.DeviceObject),
  217. Irp);
  218. status = iSpClaimLogicalUnit(fdoExtension,
  219. pdoExtension,
  220. Irp);
  221. iSpReleaseRemoveLock((pdoExtension->CommonExtension.DeviceObject),
  222. Irp);
  223. break;
  224. }
  225. default: {
  226. //
  227. // Found unsupported SRB function.
  228. //
  229. DebugPrint((1,
  230. "FdoDispatch: Unsupported function, SRB %p\n",
  231. srb));
  232. srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  233. status = STATUS_INVALID_DEVICE_REQUEST;
  234. break;
  235. }
  236. }
  237. if (sendCommandToServer == FALSE) {
  238. iSpReleaseRemoveLock(DeviceObject, Irp);
  239. Irp->IoStatus.Status = status;
  240. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  241. return status;
  242. }
  243. DebugPrint((3, "FdoDispatch : Will send the command to the server\n"));
  244. status = iSpSendScsiCommand(DeviceObject, Irp);
  245. //
  246. // The lock will be released and IRP will be completed in
  247. // iSpSendScsiCommand.
  248. //
  249. if (NT_SUCCESS(status)) {
  250. DebugPrint((3,
  251. "FdoDispatch : Command sent to the server.\n"));
  252. status = STATUS_PENDING;
  253. } else {
  254. DebugPrint((1,
  255. "FdoDispatch : Failed to send the command. Status : %x\n",
  256. status));
  257. }
  258. return status;
  259. */
  260. }
  261. NTSTATUS
  262. iScsiPortFdoCreateClose(
  263. IN PDEVICE_OBJECT DeviceObject,
  264. IN PIRP Irp
  265. )
  266. {
  267. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  268. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  269. NTSTATUS status = STATUS_SUCCESS;
  270. ULONG isRemoved;
  271. isRemoved = iSpAcquireRemoveLock(DeviceObject, Irp);
  272. if(irpStack->MajorFunction == IRP_MJ_CREATE) {
  273. if(isRemoved != NO_REMOVE) {
  274. status = STATUS_DEVICE_DOES_NOT_EXIST;
  275. } else if(commonExtension->CurrentPnpState != IRP_MN_START_DEVICE) {
  276. status = STATUS_DEVICE_NOT_READY;
  277. }
  278. }
  279. iSpReleaseRemoveLock(DeviceObject, Irp);
  280. status = STATUS_SUCCESS;
  281. Irp->IoStatus.Status = status;
  282. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  283. return status;
  284. }
  285. NTSTATUS
  286. iSpSetEvent(
  287. IN PDEVICE_OBJECT DeviceObject,
  288. IN PIRP Irp,
  289. IN PVOID Context
  290. )
  291. {
  292. KeSetEvent((PKEVENT)Context, 0, FALSE);
  293. return STATUS_MORE_PROCESSING_REQUIRED;
  294. }
  295. NTSTATUS
  296. iSpClaimLogicalUnit(
  297. IN PISCSI_FDO_EXTENSION FdoExtension,
  298. IN PISCSI_PDO_EXTENSION PdoExtension,
  299. IN PIRP Irp
  300. )
  301. {
  302. PIO_STACK_LOCATION irpStack;
  303. PSCSI_REQUEST_BLOCK srb;
  304. PDEVICE_OBJECT saveDevice;
  305. NTSTATUS status;
  306. PAGED_CODE();
  307. DebugPrint((3, "Entering iSpClaimLogicalUnit\n"));
  308. //
  309. // Get SRB address from current IRP stack.
  310. //
  311. irpStack = IoGetCurrentIrpStackLocation(Irp);
  312. srb = (PSCSI_REQUEST_BLOCK) irpStack->Parameters.Others.Argument1;
  313. if (srb->Function == SRB_FUNCTION_RELEASE_DEVICE) {
  314. PdoExtension->IsClaimed = FALSE;
  315. srb->SrbStatus = SRB_STATUS_SUCCESS;
  316. return(STATUS_SUCCESS);
  317. }
  318. //
  319. // Check for a claimed device.
  320. //
  321. if (PdoExtension->IsClaimed) {
  322. DebugPrint((0, "Device already claimed\n"));
  323. srb->SrbStatus = SRB_STATUS_BUSY;
  324. return(STATUS_DEVICE_BUSY);
  325. }
  326. //
  327. // Save the current device object.
  328. //
  329. saveDevice = PdoExtension->CommonExtension.DeviceObject;
  330. //
  331. // Update the lun information based on the operation type.
  332. //
  333. if (srb->Function == SRB_FUNCTION_CLAIM_DEVICE) {
  334. PdoExtension->IsClaimed = TRUE;
  335. }
  336. if (srb->Function == SRB_FUNCTION_ATTACH_DEVICE) {
  337. ASSERT(FALSE);
  338. PdoExtension->CommonExtension.DeviceObject = srb->DataBuffer;
  339. }
  340. srb->DataBuffer = saveDevice;
  341. srb->SrbStatus = SRB_STATUS_SUCCESS;
  342. DebugPrint((3, "Successfully claimed the device\n"));
  343. return(STATUS_SUCCESS);
  344. }
  345. /*
  346. PISCSI_PDO_EXTENSION
  347. GetPdoExtension(
  348. IN PISCSI_FDO_EXTENSION fdoExtension
  349. )
  350. {
  351. return ((fdoExtension->UpperPDO)->DeviceExtension);
  352. }
  353. */
  354. NTSTATUS
  355. iSpProcessScsiRequest(
  356. IN PDEVICE_OBJECT LogicalUnit,
  357. IN PSCSI_REQUEST_BLOCK Srb
  358. )
  359. {
  360. PISCSI_PDO_EXTENSION pdoExtension = LogicalUnit->DeviceExtension;
  361. PIRP irp;
  362. ULONG bytesReturned;
  363. NTSTATUS status;
  364. PAGED_CODE();
  365. irp = IoAllocateIrp((LogicalUnit->StackSize) + 1, FALSE);
  366. if (irp == NULL) {
  367. DebugPrint((1, "IssueInquiry : Failed to allocate IRP.\n"));
  368. return STATUS_INSUFFICIENT_RESOURCES;
  369. }
  370. IoInitializeIrp(irp,
  371. IoSizeOfIrp((LogicalUnit->StackSize) + 1),
  372. ((LogicalUnit->StackSize) + 1));
  373. status = iSpSendSrbSynchronous(LogicalUnit,
  374. Srb,
  375. irp,
  376. Srb->DataBuffer,
  377. Srb->DataTransferLength,
  378. Srb->SenseInfoBuffer,
  379. Srb->SenseInfoBufferLength,
  380. &bytesReturned
  381. );
  382. ASSERT(bytesReturned <= (Srb->DataTransferLength));
  383. if(!NT_SUCCESS(status)) {
  384. DebugPrint((1, "Failed to process SRB. Status : %x\n",
  385. status));
  386. }
  387. IoFreeIrp(irp);
  388. return status;
  389. }