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.

250 lines
6.0 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. extern PEPROCESS iScsiSystemProcess;
  17. NTSTATUS
  18. iScsiPortFdoDeviceControl(
  19. IN PDEVICE_OBJECT DeviceObject,
  20. IN PIRP Irp
  21. )
  22. {
  23. PISCSI_FDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  24. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  25. PIO_STACK_LOCATION irpStack;
  26. NTSTATUS status = STATUS_SUCCESS;
  27. ULONG controlCode;
  28. ULONG isRemoved;
  29. PAGED_CODE();
  30. irpStack = IoGetCurrentIrpStackLocation(Irp);
  31. controlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  32. DebugPrint((3,
  33. "iSpFdoDeviceControl : DeviceObject %x, ControlCode 0x%08x\n",
  34. DeviceObject, controlCode));
  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 (controlCode) {
  43. case IOCTL_ISCSI_SETUP_SERVER: {
  44. if (commonExtension->IsServerNodeSetup) {
  45. DebugPrint((1, "Server node already setup\n"));
  46. status = STATUS_SUCCESS;
  47. } else {
  48. iSpAttachProcess(iScsiSystemProcess);
  49. status = iSpStartNetwork(DeviceObject);
  50. if (NT_SUCCESS(status)) {
  51. commonExtension->IsServerNodeSetup = TRUE;
  52. }
  53. iSpDetachProcess();
  54. }
  55. break;
  56. }
  57. case IOCTL_ISCSI_CLOSE_SERVER: {
  58. if ((commonExtension->IsServerNodeSetup) == FALSE) {
  59. DebugPrint((1, "Server node not setup\n"));
  60. status = STATUS_INVALID_DEVICE_REQUEST;
  61. } else {
  62. iSpAttachProcess(iScsiSystemProcess);
  63. status = iSpStopNetwork(DeviceObject);
  64. if (NT_SUCCESS(status)) {
  65. commonExtension->IsServerNodeSetup = FALSE;
  66. }
  67. iSpDetachProcess();
  68. }
  69. break;
  70. }
  71. default: {
  72. //
  73. // Control code that we don't understand. Just pass
  74. // it to the lower driver
  75. //
  76. IoCopyCurrentIrpStackLocationToNext(Irp);
  77. iSpReleaseRemoveLock(DeviceObject, Irp);
  78. status = IoCallDriver(commonExtension->LowerDeviceObject,
  79. Irp);
  80. return status;
  81. break;
  82. }
  83. } // switch (controlCode)
  84. iSpReleaseRemoveLock(DeviceObject, Irp);
  85. Irp->IoStatus.Status = status;
  86. Irp->IoStatus.Information = 0L;
  87. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  88. return status;
  89. }
  90. NTSTATUS
  91. iScsiPortFdoCreateClose(
  92. IN PDEVICE_OBJECT DeviceObject,
  93. IN PIRP Irp
  94. )
  95. {
  96. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  97. DebugPrint((3, "iScsiPortFdoCreateClose : %s - DeviceObject %x, Irp %x\n",
  98. ((irpStack->MajorFunction) == IRP_MJ_CREATE) ? "Create" : "Close",
  99. DeviceObject, Irp));
  100. Irp->IoStatus.Status = STATUS_SUCCESS;
  101. Irp->IoStatus.Information = 0L;
  102. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  103. return STATUS_SUCCESS;
  104. }
  105. NTSTATUS
  106. iSpSetEvent(
  107. IN PDEVICE_OBJECT DeviceObject,
  108. IN PIRP Irp,
  109. IN PVOID Context
  110. )
  111. {
  112. KeSetEvent((PKEVENT)Context, 0, FALSE);
  113. return STATUS_MORE_PROCESSING_REQUIRED;
  114. }
  115. NTSTATUS
  116. iScsiPortClaimDevice(
  117. IN PDEVICE_OBJECT LowerDeviceObject,
  118. IN BOOLEAN Release
  119. )
  120. {
  121. IO_STATUS_BLOCK ioStatus;
  122. PIRP irp;
  123. PIO_STACK_LOCATION irpStack;
  124. KEVENT event;
  125. NTSTATUS status;
  126. SCSI_REQUEST_BLOCK srb;
  127. PAGED_CODE();
  128. //
  129. // Clear the SRB fields.
  130. //
  131. RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
  132. //
  133. // Write length to SRB.
  134. //
  135. srb.Length = SCSI_REQUEST_BLOCK_SIZE;
  136. srb.Function = Release ? SRB_FUNCTION_RELEASE_DEVICE :
  137. SRB_FUNCTION_CLAIM_DEVICE;
  138. //
  139. // Set the event object to the unsignaled state.
  140. // It will be used to signal request completion
  141. //
  142. KeInitializeEvent(&event, SynchronizationEvent, FALSE);
  143. //
  144. // Build synchronous request with no transfer.
  145. //
  146. irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_NONE,
  147. LowerDeviceObject,
  148. NULL,
  149. 0,
  150. NULL,
  151. 0,
  152. TRUE,
  153. &event,
  154. &ioStatus);
  155. if (irp == NULL) {
  156. DebugPrint((1, "ClassClaimDevice: Can't allocate Irp\n"));
  157. return STATUS_INSUFFICIENT_RESOURCES;
  158. }
  159. irpStack = IoGetNextIrpStackLocation(irp);
  160. //
  161. // Save SRB address in next stack for port driver.
  162. //
  163. irpStack->Parameters.Scsi.Srb = &srb;
  164. //
  165. // Set up IRP Address.
  166. //
  167. srb.OriginalRequest = irp;
  168. //
  169. // Call the port driver with the request and wait for it to complete.
  170. //
  171. status = IoCallDriver(LowerDeviceObject, irp);
  172. if (status == STATUS_PENDING) {
  173. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  174. status = ioStatus.Status;
  175. }
  176. //
  177. // If this is a release request, then just decrement the reference count
  178. // and return. The status does not matter.
  179. //
  180. if (Release) {
  181. // ObDereferenceObject(LowerDeviceObject);
  182. return STATUS_SUCCESS;
  183. }
  184. if (!NT_SUCCESS(status)) {
  185. return status;
  186. }
  187. ASSERT(srb.DataBuffer != NULL);
  188. return status;
  189. } // end ClassClaimDevice()