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.

621 lines
17 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 2000
  3. Module Name:
  4. pdo.c
  5. Abstract:
  6. This file contains PDO routines
  7. Environment:
  8. kernel mode only
  9. Revision History:
  10. --*/
  11. #include "port.h"
  12. NTSTATUS
  13. iScsiPortPdoDeviceControl(
  14. IN PDEVICE_OBJECT Pdo,
  15. IN PIRP Irp
  16. )
  17. {
  18. PISCSI_PDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
  19. PCOMMON_EXTENSION commonExtension = Pdo->DeviceExtension;
  20. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  21. ULONG ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  22. NTSTATUS status;
  23. ULONG isRemoved;
  24. isRemoved = iSpAcquireRemoveLock(Pdo, Irp);
  25. if(isRemoved) {
  26. iSpReleaseRemoveLock(Pdo, Irp);
  27. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  28. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  29. return STATUS_DEVICE_DOES_NOT_EXIST;
  30. }
  31. DebugPrint((3, "PDO DeviceControl - IO Control Code : 0x%08x\n",
  32. ioControlCode));
  33. switch (ioControlCode) {
  34. case IOCTL_STORAGE_QUERY_PROPERTY: {
  35. //
  36. // Validate the query
  37. //
  38. PSTORAGE_PROPERTY_QUERY query = Irp->AssociatedIrp.SystemBuffer;
  39. if(irpStack->Parameters.DeviceIoControl.InputBufferLength <
  40. sizeof(STORAGE_PROPERTY_QUERY)) {
  41. status = STATUS_INVALID_PARAMETER;
  42. break;
  43. }
  44. status = iScsiPortQueryProperty(Pdo, Irp);
  45. return status;
  46. break;
  47. }
  48. case IOCTL_SCSI_GET_IP_ADDRESS: {
  49. PISCSI_IP_ADDRESS iScsiAddress = Irp->AssociatedIrp.SystemBuffer;
  50. if(irpStack->Parameters.DeviceIoControl.OutputBufferLength <
  51. sizeof(ISCSI_IP_ADDRESS)) {
  52. status = STATUS_BUFFER_TOO_SMALL;
  53. break;
  54. }
  55. iScsiAddress->IPAddress = pdoExtension->TargetIPAddress;
  56. iScsiAddress->PortNumber = pdoExtension->TargetPortNumber;
  57. Irp->IoStatus.Information = sizeof(ISCSI_IP_ADDRESS);
  58. status = STATUS_SUCCESS;
  59. break;
  60. }
  61. case IOCTL_SCSI_GET_ADDRESS: {
  62. PSCSI_ADDRESS scsiAddress = Irp->AssociatedIrp.SystemBuffer;
  63. if(irpStack->Parameters.DeviceIoControl.OutputBufferLength <
  64. sizeof(SCSI_ADDRESS)) {
  65. status = STATUS_BUFFER_TOO_SMALL;
  66. break;
  67. }
  68. scsiAddress->Length = sizeof(PSCSI_ADDRESS);
  69. scsiAddress->PortNumber = (UCHAR) pdoExtension->PortNumber;
  70. scsiAddress->PathId = pdoExtension->PathId;
  71. scsiAddress->TargetId = pdoExtension->TargetId;
  72. scsiAddress->Lun = pdoExtension->Lun;
  73. Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
  74. status = STATUS_SUCCESS;
  75. break;
  76. }
  77. default: {
  78. IoSkipCurrentIrpStackLocation(Irp);
  79. iSpReleaseRemoveLock(Pdo, Irp);
  80. return IoCallDriver(commonExtension->LowerDeviceObject, Irp);
  81. }
  82. } // switch (ioControlCode)
  83. iSpReleaseRemoveLock(Pdo, Irp);
  84. Irp->IoStatus.Status = status;
  85. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  86. return status;
  87. }
  88. NTSTATUS
  89. iScsiPortPdoPnp(
  90. IN PDEVICE_OBJECT LogicalUnit,
  91. IN PIRP Irp
  92. )
  93. {
  94. PISCSI_PDO_EXTENSION pdoExtension = LogicalUnit->DeviceExtension;
  95. PCOMMON_EXTENSION commonExtension = LogicalUnit->DeviceExtension;
  96. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  97. NTSTATUS status = STATUS_SUCCESS;
  98. ULONG isRemoved;
  99. isRemoved = iSpAcquireRemoveLock(LogicalUnit, Irp);
  100. if(isRemoved) {
  101. iSpReleaseRemoveLock(LogicalUnit, Irp);
  102. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  103. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  104. return STATUS_DEVICE_DOES_NOT_EXIST;
  105. }
  106. DebugPrint((1, "PDO PnP - Minorfunction Code : 0x%x\n",
  107. irpStack->MinorFunction));
  108. switch (irpStack->MinorFunction) {
  109. case IRP_MN_START_DEVICE: {
  110. commonExtension->CurrentPnpState = IRP_MN_START_DEVICE;
  111. commonExtension->PreviousPnpState = 0xff;
  112. commonExtension->IsInitialized = TRUE;
  113. //
  114. // Make up numbers here
  115. //
  116. pdoExtension->PortNumber = 5;
  117. pdoExtension->PathId = 0;
  118. //
  119. // N.B. TargetId is set in iSpInitializeLocalNodes
  120. // routine when the PDO is created.
  121. //
  122. pdoExtension->Lun = 0;
  123. Irp->IoStatus.Status = STATUS_SUCCESS;
  124. break;
  125. }
  126. case IRP_MN_QUERY_DEVICE_RELATIONS: {
  127. PDEVICE_RELATIONS deviceRelations;
  128. if(irpStack->Parameters.QueryDeviceRelations.Type !=
  129. TargetDeviceRelation) {
  130. DebugPrint((1, "Not TargetDevicesRelations for PDO\n"));
  131. break;
  132. }
  133. //
  134. // DEVICE_RELATIONS definition contains one object pointer.
  135. //
  136. deviceRelations = iSpAllocatePool(PagedPool,
  137. sizeof(DEVICE_RELATIONS),
  138. ISCSI_TAG_DEVICE_RELATIONS);
  139. if(deviceRelations == NULL) {
  140. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  141. break;
  142. }
  143. RtlZeroMemory(deviceRelations, sizeof(DEVICE_RELATIONS));
  144. deviceRelations->Count = 1;
  145. deviceRelations->Objects[0] = LogicalUnit;
  146. ObReferenceObject(deviceRelations->Objects[0]);
  147. Irp->IoStatus.Status = STATUS_SUCCESS;
  148. Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  149. DebugPrint((1, "Completing QDR for PDO successfully\n"));
  150. break;
  151. }
  152. case IRP_MN_QUERY_PNP_DEVICE_STATE: {
  153. Irp->IoStatus.Status = STATUS_SUCCESS;
  154. break;
  155. }
  156. case IRP_MN_QUERY_DEVICE_TEXT: {
  157. Irp->IoStatus.Status =
  158. iSpQueryDeviceText(
  159. LogicalUnit,
  160. irpStack->Parameters.QueryDeviceText.DeviceTextType,
  161. irpStack->Parameters.QueryDeviceText.LocaleId,
  162. (PWSTR *) &Irp->IoStatus.Information
  163. );
  164. break;
  165. }
  166. case IRP_MN_QUERY_ID: {
  167. UCHAR rawIdString[64] = "UNKNOWN ID TYPE";
  168. ANSI_STRING ansiIdString;
  169. UNICODE_STRING unicodeIdString;
  170. BOOLEAN multiStrings;
  171. PINQUIRYDATA inquiryData = &(pdoExtension->InquiryData);
  172. if ((pdoExtension->InquiryDataInitialized) == FALSE) {
  173. DebugPrint((3, "PdoPnp : Will obtain inquiry data\n"));
  174. status = IssueInquiry(LogicalUnit);
  175. if (!NT_SUCCESS(status)) {
  176. DebugPrint((1,
  177. "Failed to get inquiry data. Status : %x\n",
  178. status));
  179. Irp->IoStatus.Status = status;
  180. iSpReleaseRemoveLock(LogicalUnit, Irp);
  181. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  182. return status;
  183. } else {
  184. DebugPrint((3, "PdoPnp : Obtained Inquiry data.\n"));
  185. }
  186. }
  187. //
  188. // We've been asked for the id of one of the physical device objects
  189. //
  190. DebugPrint((3, "PDO PnP: Got IRP_MN_QUERY_ID\n"));
  191. RtlInitUnicodeString(&unicodeIdString, NULL);
  192. RtlInitAnsiString(&ansiIdString, NULL);
  193. switch(irpStack->Parameters.QueryId.IdType) {
  194. case BusQueryDeviceID: {
  195. DebugPrint((3, "BusQueryDeviceID\n"));
  196. status = iScsiPortGetDeviceId(LogicalUnit,
  197. &unicodeIdString);
  198. multiStrings = FALSE;
  199. break;
  200. }
  201. case BusQueryInstanceID: {
  202. DebugPrint((3, "BusQueryInstanceID\n"));
  203. status = iScsiPortGetInstanceId(LogicalUnit,
  204. &unicodeIdString);
  205. multiStrings = FALSE;
  206. break;
  207. }
  208. case BusQueryHardwareIDs: {
  209. DebugPrint((3, "BusQueryHardwareIDs\n"));
  210. status = iScsiPortGetHardwareIds(
  211. LogicalUnit->DriverObject,
  212. &(pdoExtension->InquiryData),
  213. &unicodeIdString);
  214. multiStrings = TRUE;
  215. break;
  216. }
  217. case BusQueryCompatibleIDs: {
  218. DebugPrint((3, "BusQueryCompatibleIDs\n"));
  219. status = iScsiPortGetCompatibleIds(
  220. LogicalUnit->DriverObject,
  221. &(pdoExtension->InquiryData),
  222. &unicodeIdString);
  223. multiStrings = TRUE;
  224. break;
  225. }
  226. default: {
  227. status = Irp->IoStatus.Status;
  228. Irp->IoStatus.Information = 0;
  229. break;
  230. }
  231. }
  232. Irp->IoStatus.Status = status;
  233. if(NT_SUCCESS(status)) {
  234. PWCHAR idString;
  235. DebugPrint((3, "Query ID successful\n"));
  236. //
  237. // fix up all invalid characters
  238. //
  239. idString = unicodeIdString.Buffer;
  240. while (*idString) {
  241. if ((*idString <= L' ') ||
  242. (*idString > (WCHAR)0x7F) ||
  243. (*idString == L',')) {
  244. *idString = L'_';
  245. }
  246. idString++;
  247. if ((*idString == L'\0') && multiStrings) {
  248. idString++;
  249. }
  250. }
  251. Irp->IoStatus.Information = (ULONG_PTR) unicodeIdString.Buffer;
  252. } else {
  253. DebugPrint((1, "Query ID failed\n"));
  254. Irp->IoStatus.Information = (ULONG_PTR) NULL;
  255. }
  256. iSpReleaseRemoveLock(LogicalUnit, Irp);
  257. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  258. return status;
  259. break;
  260. }
  261. case IRP_MN_QUERY_RESOURCES:
  262. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: {
  263. status = STATUS_SUCCESS;
  264. Irp->IoStatus.Information = (ULONG_PTR) NULL;
  265. break;
  266. }
  267. case IRP_MN_REMOVE_DEVICE: {
  268. PISCSI_FDO_EXTENSION fdoExtension;
  269. ULONG inx;
  270. BOOLEAN foundPDO = FALSE;
  271. iSpReleaseRemoveLock(LogicalUnit, Irp);
  272. //
  273. // Remove this PDO from FDO's PDO List
  274. //
  275. fdoExtension = pdoExtension->ParentFDOExtension;
  276. inx = 0;
  277. while (inx < (fdoExtension->NumberOfTargets)) {
  278. if (fdoExtension->PDOList[inx] == LogicalUnit) {
  279. foundPDO = TRUE;
  280. break;
  281. }
  282. inx++;
  283. }
  284. if (foundPDO == TRUE) {
  285. DebugPrint((1, "Found the PDO : 0x%x\n",
  286. LogicalUnit));
  287. pdoExtension->IsClaimed = FALSE;
  288. commonExtension->IsRemoved = REMOVE_PENDING;
  289. if ((pdoExtension->IsMissing == TRUE) &&
  290. (pdoExtension->IsEnumerated == FALSE)) {
  291. (fdoExtension->NumberOfTargets)--;
  292. DebugPrint((0, "Will remove the PDO\n"));
  293. commonExtension->IsRemoved = REMOVE_COMPLETE;
  294. pdoExtension->PathId = 0xff;
  295. pdoExtension->TargetId = 0xff;
  296. pdoExtension->Lun = 0xff;
  297. DebugPrint((0, "Query remove received for the PDO\n"));
  298. iSpStopNetwork(LogicalUnit);
  299. IoDeleteDevice(LogicalUnit);
  300. } else {
  301. DebugPrint((0, "Will not delete the PDO\n"));
  302. commonExtension->IsRemoved = NO_REMOVE;
  303. }
  304. status = STATUS_SUCCESS;
  305. } else {
  306. DebugPrint((0, "Did not find the PDO\n"));
  307. status = STATUS_NO_SUCH_DEVICE;
  308. }
  309. Irp->IoStatus.Status = status;
  310. Irp->IoStatus.Information = (ULONG_PTR) NULL;
  311. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  312. return status;
  313. }
  314. case IRP_MN_QUERY_REMOVE_DEVICE:
  315. case IRP_MN_QUERY_STOP_DEVICE: {
  316. DebugPrint((0, "Query remove or query stop received\n"));
  317. Irp->IoStatus.Status = STATUS_SUCCESS;
  318. break;
  319. }
  320. default: {
  321. DebugPrint((1,
  322. "Not handling PDO MN Code - 0x%x. Status - 0x%08x\n",
  323. (irpStack->MinorFunction),
  324. (Irp->IoStatus.Status)));
  325. }
  326. }
  327. iSpReleaseRemoveLock(LogicalUnit, Irp);
  328. status = Irp->IoStatus.Status;
  329. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  330. return status;
  331. }
  332. NTSTATUS
  333. iScsiPortPdoDispatch(
  334. IN PDEVICE_OBJECT LogicalUnit,
  335. IN PIRP Irp
  336. )
  337. {
  338. PISCSI_PDO_EXTENSION pdoExtension = LogicalUnit->DeviceExtension;
  339. PCOMMON_EXTENSION commonExtension = LogicalUnit->DeviceExtension;
  340. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  341. PSCSI_REQUEST_BLOCK srb = irpStack->Parameters.Scsi.Srb;
  342. NTSTATUS status;
  343. ULONG isRemoved;
  344. BOOLEAN sendCommandToServer = FALSE;
  345. DebugPrint((3, "PdoDispatch - SRB Function : 0x%x\n",
  346. srb->Function));
  347. isRemoved = iSpAcquireRemoveLock(LogicalUnit, Irp);
  348. if (isRemoved &&
  349. !IS_CLEANUP_REQUEST(irpStack) &&
  350. (srb->Function != SRB_FUNCTION_CLAIM_DEVICE)) {
  351. iSpReleaseRemoveLock(LogicalUnit, Irp);
  352. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  353. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  354. return STATUS_DEVICE_DOES_NOT_EXIST;
  355. }
  356. switch(srb->Function) {
  357. case SRB_FUNCTION_ABORT_COMMAND: {
  358. DebugPrint((1, "Not handling abort command\n"));
  359. status = STATUS_NOT_SUPPORTED;
  360. break;
  361. }
  362. case SRB_FUNCTION_CLAIM_DEVICE:
  363. case SRB_FUNCTION_REMOVE_DEVICE: {
  364. status = iSpClaimLogicalUnit(
  365. pdoExtension->CommonExtension.LowerDeviceObject->DeviceExtension,
  366. pdoExtension,
  367. Irp);
  368. break;
  369. }
  370. case SRB_FUNCTION_RELEASE_QUEUE:
  371. case SRB_FUNCTION_FLUSH_QUEUE:
  372. case SRB_FUNCTION_SHUTDOWN:
  373. case SRB_FUNCTION_FLUSH:
  374. case SRB_FUNCTION_LOCK_QUEUE:
  375. case SRB_FUNCTION_UNLOCK_QUEUE:
  376. case SRB_FUNCTION_IO_CONTROL:
  377. case SRB_FUNCTION_RESET_BUS:
  378. case SRB_FUNCTION_WMI: {
  379. //
  380. // We won't handle these functions on the client
  381. // side for the timebeing.
  382. //
  383. status = STATUS_SUCCESS;
  384. srb->SrbStatus = SRB_STATUS_SUCCESS;
  385. break;
  386. }
  387. case SRB_FUNCTION_EXECUTE_SCSI: {
  388. //
  389. // Mark Irp status pending.
  390. //
  391. IoMarkIrpPending(Irp);
  392. sendCommandToServer = TRUE;
  393. status = STATUS_PENDING;
  394. break;
  395. }
  396. default: {
  397. //
  398. // Unsupported SRB function.
  399. //
  400. DebugPrint((0,
  401. "PdoDispatch: Unsupported function, SRB %p\n",
  402. srb));
  403. srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  404. status = STATUS_INVALID_DEVICE_REQUEST;
  405. break;
  406. }
  407. }
  408. if (sendCommandToServer == FALSE) {
  409. DebugPrint((1, "Not sending the command to the server\n"));
  410. iSpReleaseRemoveLock(LogicalUnit, Irp);
  411. Irp->IoStatus.Status = status;
  412. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  413. return status;
  414. }
  415. DebugPrint((3, "Will send the command to the server\n"));
  416. status = iSpSendScsiCommand(LogicalUnit, Irp);
  417. if (NT_SUCCESS(status)) {
  418. DebugPrint((3, "Command successfully sent to the server.\n"));
  419. status = STATUS_PENDING;
  420. } else {
  421. //
  422. // In case of error, the lock will be released and the irp will
  423. // be completed in iSpSendScsiCommand routine.
  424. //
  425. DebugPrint((1, "Failed to send the command. Status : %x\n",
  426. status));
  427. }
  428. return status;
  429. }
  430. NTSTATUS
  431. iScsiPortPdoCreateClose(
  432. IN PDEVICE_OBJECT DeviceObject,
  433. IN PIRP Irp
  434. )
  435. {
  436. ULONG isRemoved;
  437. NTSTATUS status = STATUS_SUCCESS;
  438. isRemoved = iSpAcquireRemoveLock(DeviceObject, Irp);
  439. if(IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_CREATE) {
  440. if(isRemoved) {
  441. status = STATUS_DEVICE_DOES_NOT_EXIST;
  442. }
  443. }
  444. Irp->IoStatus.Status = status;
  445. iSpReleaseRemoveLock(DeviceObject, Irp);
  446. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  447. return status;
  448. }