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.

401 lines
11 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 2000
  3. Module Name:
  4. pnp.c
  5. Abstract:
  6. This file contains plug and play code for the NT iSCSI port driver.
  7. Environment:
  8. kernel mode only
  9. Revision History:
  10. --*/
  11. #include "port.h"
  12. #ifdef ALLOC_PRAGMA
  13. #pragma alloc_text(PAGE, iScsiPortAddDevice)
  14. #pragma alloc_text(PAGE, iScsiPortUnload)
  15. #endif // ALLOC_PRAGMA
  16. GUID iScsiServerGuid = iSCSI_SERVER_GUID;
  17. NTSTATUS
  18. iScsiPortAddDevice(
  19. IN PDRIVER_OBJECT DriverObject,
  20. IN PDEVICE_OBJECT PhysicalDeviceObject
  21. )
  22. /*+++
  23. Routine Description:
  24. This routine handles add-device requests for the iSCSI port driver
  25. Arguments:
  26. DriverObject - a pointer to the driver object for this device
  27. PhysicalDeviceObject - a pointer to the PDO we are being added to
  28. Return Value:
  29. STATUS_SUCCESS if successful
  30. Appropriate NTStatus code on error
  31. --*/
  32. {
  33. PDEVICE_OBJECT deviceObject;
  34. PDEVICE_OBJECT newDeviceObject;
  35. PDEVICE_OBJECT lowerDevice;
  36. PISCSI_FDO_EXTENSION fdoExtension;
  37. PCOMMON_EXTENSION commonExtension;
  38. NTSTATUS status;
  39. UNICODE_STRING deviceName;
  40. UNICODE_STRING dosUnicodeString;
  41. //
  42. // Claim the device
  43. //
  44. lowerDevice = IoGetAttachedDeviceReference(PhysicalDeviceObject);
  45. status = iScsiPortClaimDevice(lowerDevice, FALSE);
  46. if (!NT_SUCCESS(status)) {
  47. DebugPrint((0, "Failed to claim the device. Status : %x\n",
  48. status));
  49. ObDereferenceObject(lowerDevice);
  50. return status;
  51. }
  52. RtlInitUnicodeString(&deviceName, ISCSI_DEVICE_NAME);
  53. status = IoCreateDevice(DriverObject,
  54. sizeof(ISCSI_FDO_EXTENSION),
  55. &deviceName,
  56. FILE_DEVICE_NETWORK,
  57. 0,
  58. FALSE,
  59. &deviceObject);
  60. if (!NT_SUCCESS(status)) {
  61. DebugPrint((0, "iScsiPortAddDevice failed. Status %lx\n",
  62. status));
  63. ObDereferenceObject(lowerDevice);
  64. return status;
  65. }
  66. newDeviceObject = IoAttachDeviceToDeviceStack(deviceObject,
  67. PhysicalDeviceObject);
  68. if (newDeviceObject == NULL) {
  69. DebugPrint((0,
  70. "IoAttachDeviceToDeviceStack failed in iScsiAddDevice\n"));
  71. IoDeleteDevice(deviceObject);
  72. ObDereferenceObject(lowerDevice);
  73. return STATUS_UNSUCCESSFUL;
  74. }
  75. deviceObject->Flags |= DO_DIRECT_IO;
  76. fdoExtension = deviceObject->DeviceExtension;
  77. commonExtension = &(fdoExtension->CommonExtension);
  78. RtlZeroMemory(fdoExtension, sizeof(ISCSI_FDO_EXTENSION));
  79. fdoExtension->LowerPdo = PhysicalDeviceObject;
  80. commonExtension->LowerDeviceObject = newDeviceObject;
  81. commonExtension->DeviceObject = deviceObject;
  82. commonExtension->IsPdo = FALSE;
  83. commonExtension->CurrentPnpState = 0xff;
  84. commonExtension->PreviousPnpState = 0xff;
  85. commonExtension->IsServerNodeSetup = FALSE;
  86. commonExtension->IsRemoved = NO_REMOVE;
  87. commonExtension->RemoveLock = 0;
  88. KeInitializeEvent(&(commonExtension->RemoveEvent),
  89. SynchronizationEvent,
  90. FALSE);
  91. //
  92. // Create the dos device name.
  93. //
  94. if ((commonExtension->DosNameCreated) == FALSE) {
  95. RtlInitUnicodeString(&dosUnicodeString,
  96. ISCSI_DOS_DEVICE_NAME);
  97. //
  98. // Recreate the deviceName
  99. //
  100. RtlInitUnicodeString(&deviceName,
  101. ISCSI_DEVICE_NAME);
  102. status = IoAssignArcName(&dosUnicodeString,
  103. &deviceName);
  104. if (NT_SUCCESS(status)) {
  105. commonExtension->DosNameCreated = TRUE;
  106. } else {
  107. commonExtension->DosNameCreated = FALSE;
  108. }
  109. }
  110. //
  111. // Initialize the entry points for this device
  112. //
  113. iScsiPortInitializeDispatchTables();
  114. commonExtension->MajorFunction = FdoMajorFunctionTable;
  115. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  116. ObDereferenceObject(lowerDevice);
  117. DebugPrint((3, "Add Device was successful\n"));
  118. return STATUS_SUCCESS;
  119. }
  120. VOID
  121. iScsiPortUnload(
  122. IN PDRIVER_OBJECT DriverObject
  123. )
  124. {
  125. PISCSIPORT_DRIVER_EXTENSION driverExtension;
  126. driverExtension = IoGetDriverObjectExtension( DriverObject,
  127. (PVOID)ISCSI_TAG_DRIVER_EXTENSION);
  128. if (driverExtension != NULL) {
  129. ExFreePool(driverExtension->RegistryPath.Buffer);
  130. driverExtension->RegistryPath.Buffer = NULL;
  131. driverExtension->RegistryPath.Length = 0;
  132. driverExtension->RegistryPath.MaximumLength = 0;
  133. }
  134. return;
  135. }
  136. NTSTATUS
  137. iScsiPortFdoPnp(
  138. IN PDEVICE_OBJECT DeviceObject,
  139. IN PIRP Irp
  140. )
  141. {
  142. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  143. PISCSI_FDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  144. PIO_STACK_LOCATION irpStack;
  145. NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
  146. ULONG isRemoved;
  147. BOOLEAN forwardIrp = FALSE;
  148. PAGED_CODE();
  149. irpStack = IoGetCurrentIrpStackLocation(Irp);
  150. DebugPrint((3, "FdoPnp for DeviceObject %x, Irp %x, MinorFunction %x\n",
  151. DeviceObject, Irp, (irpStack->MinorFunction)));
  152. isRemoved = iSpAcquireRemoveLock(DeviceObject, Irp);
  153. if (isRemoved) {
  154. iSpReleaseRemoveLock(DeviceObject, Irp);
  155. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  156. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  157. return STATUS_DEVICE_DOES_NOT_EXIST;
  158. }
  159. switch (irpStack->MinorFunction) {
  160. case IRP_MN_START_DEVICE: {
  161. status = iSpSendIrpSynchronous(commonExtension->LowerDeviceObject,
  162. Irp);
  163. RtlInitUnicodeString(&(fdoExtension->IScsiInterfaceName), NULL);
  164. status = IoRegisterDeviceInterface(fdoExtension->LowerPdo,
  165. (LPGUID) &iScsiServerGuid,
  166. NULL,
  167. &(fdoExtension->IScsiInterfaceName));
  168. if (!NT_SUCCESS(status)) {
  169. RtlInitUnicodeString(&(fdoExtension->IScsiInterfaceName), NULL);
  170. } else {
  171. status = IoSetDeviceInterfaceState(&(fdoExtension->IScsiInterfaceName),
  172. TRUE);
  173. }
  174. DebugPrint((3, "Status from StartDevice : %x\n",
  175. status));
  176. break;
  177. }
  178. case IRP_MN_QUERY_STOP_DEVICE: {
  179. status = STATUS_SUCCESS;
  180. Irp->IoStatus.Status = status;
  181. forwardIrp = TRUE;
  182. break;
  183. }
  184. case IRP_MN_CANCEL_STOP_DEVICE: {
  185. status = STATUS_SUCCESS;
  186. Irp->IoStatus.Status = status;
  187. forwardIrp = TRUE;
  188. break;
  189. }
  190. case IRP_MN_STOP_DEVICE: {
  191. //
  192. // Should stop the network and set state here
  193. //
  194. status = STATUS_SUCCESS;
  195. if (commonExtension->IsServerNodeSetup) {
  196. status = iSpStopNetwork(DeviceObject);
  197. commonExtension->IsServerNodeSetup = FALSE;
  198. }
  199. status = iSpSendIrpSynchronous(commonExtension->LowerDeviceObject,
  200. Irp);
  201. Irp->IoStatus.Status = status;
  202. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  203. break;
  204. }
  205. case IRP_MN_QUERY_REMOVE_DEVICE: {
  206. status = STATUS_SUCCESS;
  207. Irp->IoStatus.Status = status;
  208. forwardIrp = TRUE;
  209. break;
  210. }
  211. case IRP_MN_CANCEL_REMOVE_DEVICE: {
  212. status = STATUS_SUCCESS;
  213. Irp->IoStatus.Status = status;
  214. forwardIrp = TRUE;
  215. break;
  216. }
  217. case IRP_MN_REMOVE_DEVICE: {
  218. //
  219. // If network node hasn't been released yet,
  220. // release it now
  221. //
  222. if (commonExtension->IsServerNodeSetup) {
  223. iSpStopNetwork(DeviceObject);
  224. commonExtension->IsServerNodeSetup = FALSE;
  225. }
  226. iSpReleaseRemoveLock(DeviceObject, Irp);
  227. commonExtension->IsRemoved = REMOVE_PENDING;
  228. DebugPrint((0, "Waiting for remove event.\n"));
  229. KeWaitForSingleObject(&(commonExtension->RemoveEvent),
  230. Executive,
  231. KernelMode,
  232. FALSE,
  233. NULL);
  234. DebugPrint((0, "Will process remove now.\n"));
  235. status = iSpSendIrpSynchronous(commonExtension->LowerDeviceObject,
  236. Irp);
  237. if ((fdoExtension->IScsiInterfaceName.Buffer) != NULL) {
  238. IoSetDeviceInterfaceState(&(fdoExtension->IScsiInterfaceName),
  239. FALSE);
  240. RtlFreeUnicodeString(&(fdoExtension->IScsiInterfaceName));
  241. RtlInitUnicodeString(&(fdoExtension->IScsiInterfaceName), NULL);
  242. }
  243. if (fdoExtension->ServerNodeInfo) {
  244. ExFreePool(fdoExtension->ServerNodeInfo);
  245. fdoExtension->ServerNodeInfo = NULL;
  246. }
  247. if (commonExtension->DosNameCreated) {
  248. UNICODE_STRING dosDeviceName;
  249. RtlInitUnicodeString(&dosDeviceName,
  250. ISCSI_DOS_DEVICE_NAME);
  251. IoDeleteSymbolicLink(&dosDeviceName);
  252. commonExtension->DosNameCreated = FALSE;
  253. }
  254. IoDetachDevice(commonExtension->LowerDeviceObject);
  255. IoDeleteDevice(commonExtension->DeviceObject);
  256. Irp->IoStatus.Status = status;
  257. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  258. return status;
  259. break;
  260. }
  261. default: {
  262. forwardIrp = TRUE;
  263. break;
  264. }
  265. } // switch (irpStack->MinorFunction)
  266. iSpReleaseRemoveLock(DeviceObject, Irp);
  267. if (forwardIrp == TRUE) {
  268. IoSkipCurrentIrpStackLocation(Irp);
  269. return IoCallDriver(commonExtension->LowerDeviceObject,
  270. Irp);
  271. } else {
  272. Irp->IoStatus.Status = status;
  273. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  274. }
  275. return status;
  276. }
  277. NTSTATUS
  278. iSpSendIrpSynchronous(
  279. IN PDEVICE_OBJECT DeviceObject,
  280. IN PIRP Irp
  281. )
  282. {
  283. NTSTATUS status;
  284. KEVENT event;
  285. PAGED_CODE();
  286. if (DeviceObject == NULL) {
  287. DebugPrint((0, "DeviceObject NULL. Irp %x\n",
  288. Irp));
  289. return Irp->IoStatus.Status;
  290. }
  291. KeInitializeEvent(&event, NotificationEvent, FALSE);
  292. IoCopyCurrentIrpStackLocationToNext(Irp);
  293. IoSetCompletionRoutine(Irp,
  294. iSpSetEvent,
  295. &event,
  296. TRUE,
  297. TRUE,
  298. TRUE);
  299. status = IoCallDriver(DeviceObject, Irp);
  300. if (status == STATUS_PENDING) {
  301. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  302. status = Irp->IoStatus.Status;
  303. }
  304. return status;
  305. }