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.

1592 lines
42 KiB

  1. /*++
  2. Copyright (C) 1997-99 Microsoft Corporation
  3. Module Name:
  4. ide.c
  5. Abstract:
  6. This contain DriverEntry and utilities routines
  7. Author:
  8. Joe Dai (joedai)
  9. Environment:
  10. kernel mode only
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include "ideport.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(INIT, DriverEntry)
  17. #pragma alloc_text(PAGE, IdePortNoSupportIrp)
  18. #pragma alloc_text(PAGE, IdePortPassDownToNextDriver)
  19. #pragma alloc_text(PAGE, IdePortStatusSuccessAndPassDownToNextDriver)
  20. #pragma alloc_text(PAGE, IdePortDispatchPnp)
  21. #pragma alloc_text(PAGE, IdePortDispatchSystemControl)
  22. #pragma alloc_text(PAGE, IdePortOkToDetectLegacy)
  23. #pragma alloc_text(PAGE, IdePortOpenServiceSubKey)
  24. #pragma alloc_text(PAGE, IdePortCloseServiceSubKey)
  25. #pragma alloc_text(PAGE, IdePortParseDeviceParameters)
  26. #pragma alloc_text(PAGE, IdePortGetDeviceTypeString)
  27. #pragma alloc_text(PAGE, IdePortGetCompatibleIdString)
  28. #pragma alloc_text(PAGE, IdePortGetPeripheralIdString)
  29. #pragma alloc_text(PAGE, IdePortUnload)
  30. #pragma alloc_text(PAGE, IdePortSearchDeviceInRegMultiSzList)
  31. #pragma alloc_text(PAGE, IdePortSyncSendIrp)
  32. #pragma alloc_text(PAGE, IdePortInSetup)
  33. #pragma alloc_text(NONPAGE, IdePortDispatchDeviceControl)
  34. #pragma alloc_text(NONPAGE, IdePortAlwaysStatusSuccessIrp)
  35. #pragma alloc_text(NONPAGE, IdePortDispatchPower)
  36. #pragma alloc_text(NONPAGE, IdePortGenericCompletionRoutine)
  37. #endif // ALLOC_PRAGMA
  38. //
  39. // get the share code
  40. //
  41. #include "..\share\util.c"
  42. #if DBG
  43. //
  44. // for performance tuning
  45. //
  46. void _DebugPrintResetTickCount (LARGE_INTEGER * lastTickCount) {
  47. KeQueryTickCount(lastTickCount);
  48. }
  49. void _DebugPrintTickCount (LARGE_INTEGER * lastTickCount, ULONG limit, PUCHAR filename, ULONG lineNumber)
  50. {
  51. LARGE_INTEGER tickCount;
  52. KeQueryTickCount(&tickCount);
  53. if ((tickCount.QuadPart - lastTickCount->QuadPart) >= limit) {
  54. DebugPrint ((1, "File: %s Line %u: CurrentTick = %u (%u ticks since last check)\n", filename, lineNumber, (ULONG) tickCount.QuadPart, (ULONG) (tickCount.QuadPart - lastTickCount->QuadPart)));
  55. }
  56. *lastTickCount = tickCount;
  57. }
  58. #endif //DBG
  59. //
  60. // Po Dispatch Table
  61. //
  62. PDRIVER_DISPATCH FdoPowerDispatchTable[NUM_POWER_MINOR_FUNCTION];
  63. PDRIVER_DISPATCH PdoPowerDispatchTable[NUM_POWER_MINOR_FUNCTION];
  64. NTSTATUS
  65. IdePortNoSupportIrp (
  66. IN PDEVICE_OBJECT DeviceObject,
  67. IN OUT PIRP Irp
  68. )
  69. /*++
  70. Routine Description:
  71. Generic routine to fail unsupported irp
  72. Arguments:
  73. DeviceObject - Pointer to the device object for which this IRP applies.
  74. Irp - Pointer to the IRP to fail.
  75. Return Value:
  76. NT status.
  77. --*/
  78. {
  79. NTSTATUS status = Irp->IoStatus.Status;
  80. PIO_STACK_LOCATION thisIrpSp;
  81. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  82. //
  83. // You should call PoStartNextPowerIrp before completing a power irp
  84. //
  85. if (thisIrpSp->MajorFunction == IRP_MJ_POWER) {
  86. PoStartNextPowerIrp (Irp);
  87. }
  88. DebugPrint ((
  89. DBG_WARNING,
  90. "IdePort: devobj 0x%x failing unsupported Irp (0x%x, 0x%x) with status = %x\n",
  91. DeviceObject,
  92. thisIrpSp->MajorFunction,
  93. thisIrpSp->MinorFunction,
  94. status
  95. ));
  96. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  97. return status;
  98. } // IdePortNoSupportIrp
  99. NTSTATUS
  100. IdePortAlwaysStatusSuccessIrp (
  101. IN PDEVICE_OBJECT DeviceObject,
  102. IN OUT PIRP Irp
  103. /*++
  104. Routine Description:
  105. Generic routine to STATUS_SUCCESS an irp
  106. Arguments:
  107. DeviceObject - Pointer to the device object for which this IRP applies.
  108. Irp - Pointer to the IRP.
  109. Return Value:
  110. NT status.
  111. --*/
  112. )
  113. {
  114. Irp->IoStatus.Status = STATUS_SUCCESS;
  115. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  116. return STATUS_SUCCESS;
  117. } // IdePortAlwaysStatusSuccessIrp
  118. NTSTATUS
  119. IdePortPassDownToNextDriver (
  120. IN PDEVICE_OBJECT DeviceObject,
  121. IN OUT PIRP Irp
  122. )
  123. /*++
  124. Routine Description:
  125. Generic routine to pass an irp down to the lower driver
  126. Arguments:
  127. DeviceObject - Pointer to the device object for which this IRP applies.
  128. Irp - Pointer to the IRP.
  129. Return Value:
  130. NT status.
  131. --*/
  132. {
  133. PDEVICE_EXTENSION_HEADER doExtension;
  134. PIO_STACK_LOCATION thisIrpSp;
  135. NTSTATUS status;
  136. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  137. doExtension = (PDEVICE_EXTENSION_HEADER) DeviceObject->DeviceExtension;
  138. ASSERT (doExtension->AttacheeDeviceObject);
  139. if (thisIrpSp->MajorFunction == IRP_MJ_POWER) {
  140. //
  141. // call PoStartNextPowerIrp before completing a power irp
  142. //
  143. PoStartNextPowerIrp (Irp);
  144. IoSkipCurrentIrpStackLocation (Irp);
  145. status = PoCallDriver (doExtension->AttacheeDeviceObject, Irp);
  146. } else {
  147. //
  148. // Not a power irp
  149. //
  150. IoSkipCurrentIrpStackLocation (Irp);
  151. status = IoCallDriver (doExtension->AttacheeDeviceObject, Irp);
  152. }
  153. return status;
  154. } // IdePortPassDownToNextDriver
  155. NTSTATUS
  156. IdePortStatusSuccessAndPassDownToNextDriver (
  157. IN PDEVICE_OBJECT DeviceObject,
  158. IN OUT PIRP Irp
  159. )
  160. {
  161. PAGED_CODE();
  162. Irp->IoStatus.Status = STATUS_SUCCESS;
  163. return IdePortPassDownToNextDriver(DeviceObject, Irp);
  164. } // IdePortStatusSuccessAndPassDownToNextDriver
  165. NTSTATUS
  166. IdePortDispatchDeviceControl(
  167. IN PDEVICE_OBJECT DeviceObject,
  168. IN OUT PIRP Irp
  169. )
  170. /*++
  171. Routine Description:
  172. Dispatch routine for IRP_MJ_DEVICE_CONTROL
  173. Arguments:
  174. DeviceObject - Pointer to the device object for which this IRP applies.
  175. Irp - Pointer to the IRP.
  176. Return Value:
  177. NT status.
  178. --*/
  179. {
  180. PDEVICE_EXTENSION_HEADER DoExtensionHeader;
  181. NTSTATUS status;
  182. DoExtensionHeader = DeviceObject->DeviceExtension;
  183. if (IS_PDO(DoExtensionHeader)) {
  184. //
  185. // PDO
  186. //
  187. status = DeviceDeviceIoControl (
  188. DeviceObject,
  189. Irp
  190. );
  191. } else {
  192. //
  193. // FDO
  194. //
  195. status = IdePortDeviceControl (
  196. DeviceObject,
  197. Irp
  198. );
  199. }
  200. return status;
  201. } // IdePortDispatchDeviceControl
  202. NTSTATUS
  203. IdePortDispatchPower(
  204. IN PDEVICE_OBJECT DeviceObject,
  205. IN OUT PIRP Irp
  206. )
  207. /*++
  208. Routine Description:
  209. Dispatch routine for IRP_MJ_POWER
  210. Arguments:
  211. DeviceObject - Pointer to the device object for which this IRP applies.
  212. Irp - Pointer to the IRP.
  213. Return Value:
  214. NT status.
  215. --*/
  216. {
  217. PIO_STACK_LOCATION thisIrpSp;
  218. NTSTATUS status;
  219. PDEVICE_EXTENSION_HEADER doExtension;
  220. BOOLEAN pendingIrp;
  221. //
  222. // Get a pointer to our stack location and take appropriate action based
  223. // on the minor function.
  224. //
  225. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  226. doExtension = (PDEVICE_EXTENSION_HEADER) DeviceObject->DeviceExtension;
  227. DebugPrint ((DBG_POWER,
  228. "IdePort: 0x%x %s %d got %s[%d, %d]\n",
  229. doExtension->AttacheeDeviceObject ?
  230. ((PFDO_EXTENSION) doExtension)->IdeResource.TranslatedCommandBaseAddress :
  231. ((PPDO_EXTENSION) doExtension)->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  232. doExtension->AttacheeDeviceObject ? "FDO" : "PDO",
  233. doExtension->AttacheeDeviceObject ? 0 :
  234. ((PPDO_EXTENSION) doExtension)->TargetId,
  235. IdeDebugPowerIrpName[thisIrpSp->MinorFunction],
  236. thisIrpSp->Parameters.Power.Type,
  237. thisIrpSp->Parameters.Power.State
  238. ));
  239. if (thisIrpSp->MinorFunction < NUM_POWER_MINOR_FUNCTION) {
  240. status = doExtension->PowerDispatchTable[thisIrpSp->MinorFunction] (DeviceObject, Irp);
  241. } else {
  242. DebugPrint ((DBG_WARNING,
  243. "ATAPI: Power Dispatch Table too small\n"
  244. ));
  245. status = doExtension->DefaultDispatch(DeviceObject, Irp);
  246. }
  247. return status;
  248. } // IdePortDispatchPower
  249. NTSTATUS
  250. IdePortDispatchPnp(
  251. IN PDEVICE_OBJECT DeviceObject,
  252. IN OUT PIRP Irp
  253. )
  254. /*++
  255. Routine Description:
  256. Dispatch routine for IRP_MJ_PNP_POWER IRPs
  257. Arguments:
  258. DeviceObject - Pointer to the device object for which this IRP applies.
  259. Irp - Pointer to the IRP_MJ_PNP_POWER IRP to dispatch.
  260. Return Value:
  261. NT status.
  262. --*/
  263. {
  264. PIO_STACK_LOCATION thisIrpSp;
  265. NTSTATUS status;
  266. PDEVICE_EXTENSION_HEADER doExtension;
  267. //
  268. // Get a pointer to our stack location and take appropriate action based
  269. // on the minor function.
  270. //
  271. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  272. doExtension = (PDEVICE_EXTENSION_HEADER) DeviceObject->DeviceExtension;
  273. DebugPrint ((DBG_PNP,
  274. "IdePort: 0x%x %s %d got %s\n",
  275. doExtension->AttacheeDeviceObject ?
  276. ((PFDO_EXTENSION) doExtension)->IdeResource.TranslatedCommandBaseAddress :
  277. ((PPDO_EXTENSION) doExtension)->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  278. doExtension->AttacheeDeviceObject ? "FDO" : "PDO",
  279. doExtension->AttacheeDeviceObject ? 0 :
  280. ((PPDO_EXTENSION) doExtension)->TargetId,
  281. IdeDebugPnpIrpName[thisIrpSp->MinorFunction]));
  282. if (thisIrpSp->MinorFunction < NUM_PNP_MINOR_FUNCTION) {
  283. status = doExtension->PnPDispatchTable[thisIrpSp->MinorFunction] (DeviceObject, Irp);
  284. } else {
  285. if (thisIrpSp->MinorFunction != 0xff) {
  286. ASSERT (!"ATAPI: PnP Dispatch Table too small\n");
  287. }
  288. status = doExtension->DefaultDispatch (DeviceObject, Irp);
  289. }
  290. return status;
  291. } // IdePortDispatchPnp
  292. NTSTATUS
  293. IdePortDispatchSystemControl(
  294. IN PDEVICE_OBJECT DeviceObject,
  295. IN OUT PIRP Irp
  296. )
  297. /*++
  298. Routine Description:
  299. Dispatch routine for IRP_MJ_SYSTEM_CONTROL (WMI) IRPs
  300. Arguments:
  301. DeviceObject - Pointer to the device object for which this IRP applies.
  302. Irp - Pointer to the IRP_MJ_PNP_POWER IRP to dispatch.
  303. Return Value:
  304. NT status.
  305. --*/
  306. {
  307. PIO_STACK_LOCATION thisIrpSp;
  308. NTSTATUS status;
  309. PDEVICE_EXTENSION_HEADER doExtension;
  310. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  311. doExtension = (PDEVICE_EXTENSION_HEADER) DeviceObject->DeviceExtension;
  312. DebugPrint ((DBG_WMI,
  313. "IdePort: 0x%x %s %d got %s\n",
  314. doExtension->AttacheeDeviceObject ?
  315. ((PFDO_EXTENSION) doExtension)->IdeResource.TranslatedCommandBaseAddress :
  316. ((PPDO_EXTENSION) doExtension)->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  317. doExtension->AttacheeDeviceObject ? "FDO" : "PDO",
  318. doExtension->AttacheeDeviceObject ? 0 :
  319. ((PPDO_EXTENSION) doExtension)->TargetId,
  320. IdeDebugWmiIrpName[thisIrpSp->MinorFunction]));
  321. if (thisIrpSp->MinorFunction < NUM_WMI_MINOR_FUNCTION) {
  322. status = doExtension->WmiDispatchTable[thisIrpSp->MinorFunction] (DeviceObject, Irp);
  323. } else {
  324. DebugPrint((DBG_WARNING,
  325. "ATAPI: WMI Dispatch Table too small\n"
  326. ));
  327. status = doExtension->DefaultDispatch (DeviceObject, Irp);
  328. }
  329. return status;
  330. } // IdePortDispatchSystemControl
  331. ULONG
  332. DriverEntry(
  333. IN OUT PDRIVER_OBJECT DriverObject,
  334. IN PUNICODE_STRING RegistryPath
  335. )
  336. /*++
  337. Routine Description:
  338. Entry point to this driver
  339. Arguments:
  340. DeviceObject - Pointer to the device object for which this IRP applies.
  341. Irp - Pointer to the IRP.
  342. Return Value:
  343. NT status.
  344. --*/
  345. {
  346. NTSTATUS status;
  347. PIDEDRIVER_EXTENSION ideDriverExtension;
  348. ULONG i;
  349. #if DBG
  350. //
  351. // checking IDE_COMMAND_BLOCK_WRITE_REGISTERS structure and its macros
  352. //
  353. {
  354. IDE_COMMAND_BLOCK_WRITE_REGISTERS baseIoAddress1;
  355. IDE_REGISTERS_2 baseIoAddress2;
  356. ULONG baseIoAddress1Length;
  357. ULONG baseIoAddress2Length;
  358. ULONG maxIdeDevice;
  359. ULONG maxIdeTargetId;
  360. AtapiBuildIoAddress (0,
  361. 0,
  362. (PIDE_REGISTERS_1)&baseIoAddress1,
  363. &baseIoAddress2,
  364. &baseIoAddress1Length,
  365. &baseIoAddress2Length,
  366. &maxIdeDevice,
  367. &maxIdeTargetId);
  368. ASSERT (ATA_DATA16_REG (&baseIoAddress1) == 0);
  369. ASSERT (ATA_ERROR_REG (&baseIoAddress1) == (PUCHAR)1);
  370. ASSERT (ATA_SECTOR_COUNT_REG (&baseIoAddress1) == (PUCHAR)2);
  371. ASSERT (ATA_SECTOR_NUMBER_REG(&baseIoAddress1) == (PUCHAR)3);
  372. ASSERT (ATA_CYLINDER_LOW_REG (&baseIoAddress1) == (PUCHAR)4);
  373. ASSERT (ATA_CYLINDER_HIGH_REG(&baseIoAddress1) == (PUCHAR)5);
  374. ASSERT (ATA_DRIVE_SELECT_REG (&baseIoAddress1) == (PUCHAR)6);
  375. ASSERT (ATA_STATUS_REG (&baseIoAddress1) == (PUCHAR)7);
  376. ASSERT (ATA_FEATURE_REG (&baseIoAddress1) == (PUCHAR)1);
  377. ASSERT (ATA_COMMAND_REG (&baseIoAddress1) == (PUCHAR)7);
  378. ASSERT (ATAPI_DATA16_REG (&baseIoAddress1) == 0);
  379. ASSERT (ATAPI_ERROR_REG (&baseIoAddress1) == (PUCHAR)1);
  380. ASSERT (ATAPI_INTERRUPT_REASON_REG (&baseIoAddress1) == (PUCHAR)2);
  381. ASSERT (ATAPI_BYTECOUNT_LOW_REG (&baseIoAddress1) == (PUCHAR)4);
  382. ASSERT (ATAPI_BYTECOUNT_HIGH_REG (&baseIoAddress1) == (PUCHAR)5);
  383. ASSERT (ATAPI_DRIVE_SELECT_REG (&baseIoAddress1) == (PUCHAR)6);
  384. ASSERT (ATAPI_STATUS_REG (&baseIoAddress1) == (PUCHAR)7);
  385. ASSERT (ATAPI_FEATURE_REG (&baseIoAddress1) == (PUCHAR)1);
  386. ASSERT (ATAPI_COMMAND_REG (&baseIoAddress1) == (PUCHAR)7);
  387. ASSERT (baseIoAddress1Length == 8);
  388. ASSERT (baseIoAddress2Length == 1);
  389. ASSERT (maxIdeDevice == 2);
  390. if (IsNEC_98) {
  391. AtapiBuildIoAddress ((PUCHAR)0x640,
  392. (PUCHAR) 0x74C,
  393. (PIDE_REGISTERS_1)&baseIoAddress1,
  394. &baseIoAddress2,
  395. &baseIoAddress1Length,
  396. &baseIoAddress2Length,
  397. &maxIdeDevice,
  398. &maxIdeTargetId);
  399. ASSERT (ATA_DATA16_REG (&baseIoAddress1) == (PUSHORT)0x640);
  400. ASSERT (ATA_ERROR_REG (&baseIoAddress1) == (PUCHAR)0x642);
  401. ASSERT (ATA_SECTOR_COUNT_REG (&baseIoAddress1) == (PUCHAR)0x644);
  402. ASSERT (ATA_SECTOR_NUMBER_REG(&baseIoAddress1) == (PUCHAR)0x646);
  403. ASSERT (ATA_CYLINDER_LOW_REG (&baseIoAddress1) == (PUCHAR)0x648);
  404. ASSERT (ATA_CYLINDER_HIGH_REG(&baseIoAddress1) == (PUCHAR)0x64a);
  405. ASSERT (ATA_DRIVE_SELECT_REG (&baseIoAddress1) == (PUCHAR)0x64c);
  406. ASSERT (ATA_STATUS_REG (&baseIoAddress1) == (PUCHAR)0x64e);
  407. ASSERT (ATA_FEATURE_REG (&baseIoAddress1) == (PUCHAR)0x642);
  408. ASSERT (ATA_COMMAND_REG (&baseIoAddress1) == (PUCHAR)0x64e);
  409. ASSERT (ATAPI_DATA16_REG (&baseIoAddress1) == (PUSHORT)0x640);
  410. ASSERT (ATAPI_ERROR_REG (&baseIoAddress1) == (PUCHAR)0x642);
  411. ASSERT (ATAPI_INTERRUPT_REASON_REG (&baseIoAddress1) == (PUCHAR)0x644);
  412. ASSERT (ATAPI_BYTECOUNT_LOW_REG (&baseIoAddress1) == (PUCHAR)0x648);
  413. ASSERT (ATAPI_BYTECOUNT_HIGH_REG (&baseIoAddress1) == (PUCHAR)0x64a);
  414. ASSERT (ATAPI_DRIVE_SELECT_REG (&baseIoAddress1) == (PUCHAR)0x64c);
  415. ASSERT (ATAPI_STATUS_REG (&baseIoAddress1) == (PUCHAR)0x64e);
  416. ASSERT (ATAPI_FEATURE_REG (&baseIoAddress1) == (PUCHAR)0x642);
  417. ASSERT (ATAPI_COMMAND_REG (&baseIoAddress1) == (PUCHAR)0x64e);
  418. ASSERT (baseIoAddress1Length == 1);
  419. ASSERT (baseIoAddress2Length == 1);
  420. ASSERT (maxIdeDevice == 4);
  421. }
  422. }
  423. #endif //DBG
  424. if (!DriverObject) {
  425. //
  426. // We are called by crashdump or po
  427. //
  428. return AtapiCrashDumpDriverEntry (RegistryPath);
  429. }
  430. //
  431. // Allocate Driver Object Extension for storing
  432. // the RegistryPath
  433. //
  434. status = IoAllocateDriverObjectExtension(
  435. DriverObject,
  436. DRIVER_OBJECT_EXTENSION_ID,
  437. sizeof (DRIVER_EXTENSION),
  438. &ideDriverExtension
  439. );
  440. if (!NT_SUCCESS(status)) {
  441. DebugPrint ((0, "IdePort: Unable to create driver extension\n"));
  442. return status;
  443. }
  444. ASSERT(ideDriverExtension);
  445. RtlZeroMemory (
  446. ideDriverExtension,
  447. sizeof (DRIVER_EXTENSION)
  448. );
  449. //
  450. // make copy of the RegistryPath
  451. //
  452. ideDriverExtension->RegistryPath.Buffer = ExAllocatePool (NonPagedPool, RegistryPath->Length * sizeof(WCHAR));
  453. if (ideDriverExtension->RegistryPath.Buffer == NULL) {
  454. DebugPrint ((0, "IdePort: Unable to allocate memory for registry path\n"));
  455. return (ULONG) STATUS_INSUFFICIENT_RESOURCES;
  456. }
  457. ideDriverExtension->RegistryPath.Length = 0;
  458. ideDriverExtension->RegistryPath.MaximumLength = RegistryPath->Length;
  459. RtlCopyUnicodeString (&ideDriverExtension->RegistryPath, RegistryPath);
  460. //
  461. // The PnP thing to do
  462. //
  463. DriverObject->DriverExtension->AddDevice = ChannelAddDevice;
  464. //
  465. // Set up the device driver entry points.
  466. //
  467. DriverObject->DriverStartIo = IdePortStartIo;
  468. DriverObject->DriverUnload = IdePortUnload;
  469. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = IdePortDispatch;
  470. DriverObject->MajorFunction[IRP_MJ_SCSI] = IdePortDispatch;
  471. DriverObject->MajorFunction[IRP_MJ_CREATE] = IdePortAlwaysStatusSuccessIrp;
  472. DriverObject->MajorFunction[IRP_MJ_CLOSE] = IdePortAlwaysStatusSuccessIrp;
  473. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IdePortDispatchDeviceControl;
  474. DriverObject->MajorFunction[IRP_MJ_POWER] = IdePortDispatchPower;
  475. DriverObject->MajorFunction[IRP_MJ_PNP] = IdePortDispatchPnp;
  476. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = IdePortDispatchSystemControl;
  477. //
  478. // FDO PnP Dispatch Table
  479. //
  480. for (i=0; i<NUM_PNP_MINOR_FUNCTION; i++) {
  481. FdoPnpDispatchTable[i] = IdePortPassDownToNextDriver;
  482. }
  483. FdoPnpDispatchTable[IRP_MN_START_DEVICE ] = ChannelStartDevice;
  484. FdoPnpDispatchTable[IRP_MN_QUERY_REMOVE_DEVICE ] = IdePortStatusSuccessAndPassDownToNextDriver;
  485. FdoPnpDispatchTable[IRP_MN_CANCEL_REMOVE_DEVICE ] = IdePortStatusSuccessAndPassDownToNextDriver;
  486. FdoPnpDispatchTable[IRP_MN_REMOVE_DEVICE ] = ChannelRemoveDevice;
  487. FdoPnpDispatchTable[IRP_MN_QUERY_STOP_DEVICE ] = IdePortStatusSuccessAndPassDownToNextDriver;
  488. FdoPnpDispatchTable[IRP_MN_CANCEL_STOP_DEVICE ] = IdePortStatusSuccessAndPassDownToNextDriver;
  489. FdoPnpDispatchTable[IRP_MN_STOP_DEVICE ] = ChannelStopDevice;
  490. FdoPnpDispatchTable[IRP_MN_QUERY_DEVICE_RELATIONS ] = ChannelQueryDeviceRelations;
  491. FdoPnpDispatchTable[IRP_MN_QUERY_ID ] = ChannelQueryId;
  492. FdoPnpDispatchTable[IRP_MN_DEVICE_USAGE_NOTIFICATION ] = ChannelUsageNotification;
  493. FdoPnpDispatchTable[IRP_MN_FILTER_RESOURCE_REQUIREMENTS] = ChannelFilterResourceRequirements;
  494. FdoPnpDispatchTable[IRP_MN_QUERY_PNP_DEVICE_STATE ] = ChannelQueryPnPDeviceState;
  495. FdoPnpDispatchTable[IRP_MN_SURPRISE_REMOVAL ] = ChannelSurpriseRemoveDevice;
  496. //
  497. // PDO PnP Dispatch Table
  498. //
  499. for (i=0; i<NUM_PNP_MINOR_FUNCTION; i++) {
  500. PdoPnpDispatchTable[i] = IdePortNoSupportIrp;
  501. }
  502. PdoPnpDispatchTable[IRP_MN_START_DEVICE ] = DeviceStartDevice;
  503. PdoPnpDispatchTable[IRP_MN_QUERY_DEVICE_RELATIONS ] = DeviceQueryDeviceRelations;
  504. PdoPnpDispatchTable[IRP_MN_QUERY_REMOVE_DEVICE ] = DeviceQueryStopRemoveDevice;
  505. PdoPnpDispatchTable[IRP_MN_REMOVE_DEVICE ] = DeviceRemoveDevice;
  506. PdoPnpDispatchTable[IRP_MN_CANCEL_REMOVE_DEVICE ] = IdePortAlwaysStatusSuccessIrp;
  507. PdoPnpDispatchTable[IRP_MN_STOP_DEVICE ] = DeviceStopDevice;
  508. PdoPnpDispatchTable[IRP_MN_QUERY_STOP_DEVICE ] = DeviceQueryStopRemoveDevice;
  509. PdoPnpDispatchTable[IRP_MN_CANCEL_STOP_DEVICE ] = IdePortAlwaysStatusSuccessIrp;
  510. PdoPnpDispatchTable[IRP_MN_QUERY_ID ] = DeviceQueryId;
  511. PdoPnpDispatchTable[IRP_MN_QUERY_CAPABILITIES ] = DeviceQueryCapabilities;
  512. PdoPnpDispatchTable[IRP_MN_QUERY_DEVICE_TEXT ] = DeviceQueryText;
  513. PdoPnpDispatchTable[IRP_MN_DEVICE_USAGE_NOTIFICATION ] = DeviceUsageNotification;
  514. PdoPnpDispatchTable[IRP_MN_QUERY_PNP_DEVICE_STATE ] = DeviceQueryPnPDeviceState;
  515. PdoPnpDispatchTable[IRP_MN_SURPRISE_REMOVAL ] = DeviceRemoveDevice;
  516. //
  517. // FDO Power Dispatch Table
  518. //
  519. for (i=0; i<NUM_POWER_MINOR_FUNCTION; i++) {
  520. FdoPowerDispatchTable[i] = IdePortPassDownToNextDriver;
  521. }
  522. FdoPowerDispatchTable[IRP_MN_SET_POWER] = IdePortSetFdoPowerState;
  523. FdoPowerDispatchTable[IRP_MN_QUERY_POWER] = ChannelQueryPowerState;
  524. //
  525. // PDO Power Dispatch Table
  526. //
  527. for (i=0; i<NUM_POWER_MINOR_FUNCTION; i++) {
  528. PdoPowerDispatchTable[i] = IdePortNoSupportIrp;
  529. }
  530. PdoPowerDispatchTable[IRP_MN_SET_POWER] = IdePortSetPdoPowerState;
  531. PdoPowerDispatchTable[IRP_MN_QUERY_POWER] = DeviceQueryPowerState;
  532. //
  533. // FDO WMI Dispatch Table
  534. //
  535. for (i=0; i<NUM_WMI_MINOR_FUNCTION; i++) {
  536. FdoWmiDispatchTable[i] = IdePortPassDownToNextDriver;
  537. }
  538. //
  539. // PDO WMI Dispatch Table
  540. //
  541. for (i=0; i<NUM_WMI_MINOR_FUNCTION; i++) {
  542. #if defined (IDEPORT_WMI_SUPPORT)
  543. PdoWmiDispatchTable[i] = IdePortWmiSystemControl;
  544. #else
  545. PdoWmiDispatchTable[i] = IdePortNoSupportIrp;
  546. #endif // IDEPORT_WMI_SUPPORT
  547. }
  548. #if defined (IDEPORT_WMI_SUPPORT)
  549. //
  550. // Init WMI related stuff
  551. //
  552. IdePortWmiInit ();
  553. #endif // IDEPORT_WMI_SUPPORT
  554. //
  555. // Create device object name directory
  556. //
  557. IdeCreateIdeDirectory();
  558. //
  559. // Detect legacy (non-enumerable) IDE devices
  560. //
  561. #if !defined(NO_LEGACY_DRIVERS)
  562. IdePortDetectLegacyController (
  563. DriverObject,
  564. RegistryPath
  565. );
  566. #endif // NO_LEGACY_DRIVERS
  567. return STATUS_SUCCESS;
  568. } // DriverEntry
  569. #ifdef DRIVER_PARAMETER_REGISTRY_SUPPORT
  570. HANDLE
  571. IdePortOpenServiceSubKey (
  572. IN PDRIVER_OBJECT DriverObject,
  573. IN PUNICODE_STRING SubKeyPath
  574. )
  575. /*++
  576. Routine Description:
  577. Open a registry key
  578. Arguments:
  579. DriverObject - this driver driver object
  580. SubKeyPath - registry key to open
  581. Return Value:
  582. handle to the registry key
  583. --*/
  584. {
  585. PIDEDRIVER_EXTENSION ideDriverExtension;
  586. OBJECT_ATTRIBUTES objectAttributes;
  587. HANDLE serviceKey;
  588. HANDLE subServiceKey;
  589. NTSTATUS status;
  590. ideDriverExtension = IoGetDriverObjectExtension(
  591. DriverObject,
  592. DRIVER_OBJECT_EXTENSION_ID
  593. );
  594. if (!ideDriverExtension) {
  595. return NULL;
  596. }
  597. InitializeObjectAttributes(&objectAttributes,
  598. &ideDriverExtension->RegistryPath,
  599. OBJ_CASE_INSENSITIVE,
  600. NULL,
  601. (PSECURITY_DESCRIPTOR) NULL);
  602. status = ZwOpenKey(&serviceKey,
  603. KEY_READ,
  604. &objectAttributes);
  605. if (!NT_SUCCESS(status)) {
  606. return NULL;
  607. }
  608. InitializeObjectAttributes(&objectAttributes,
  609. SubKeyPath,
  610. OBJ_CASE_INSENSITIVE,
  611. serviceKey,
  612. (PSECURITY_DESCRIPTOR) NULL);
  613. status = ZwOpenKey(&subServiceKey,
  614. KEY_READ,
  615. &objectAttributes);
  616. ZwClose(serviceKey);
  617. if (NT_SUCCESS(status)) {
  618. return subServiceKey;
  619. } else {
  620. return NULL;
  621. }
  622. } // IdePortOpenServiceSubKey
  623. VOID
  624. IdePortCloseServiceSubKey (
  625. IN HANDLE SubServiceKey
  626. )
  627. /*++
  628. Routine Description:
  629. close a registry key handle
  630. Arguments:
  631. SubServiceKey - registry key to close
  632. Return Value:
  633. None
  634. --*/
  635. {
  636. ZwClose(SubServiceKey);
  637. } // IdePortCloseServiceSubKey
  638. VOID
  639. IdePortParseDeviceParameters(
  640. IN HANDLE SubServiceKey,
  641. IN OUT PCUSTOM_DEVICE_PARAMETER CustomDeviceParameter
  642. )
  643. /*++
  644. Routine Description:
  645. This routine parses a device key node and updates the CustomDeviceParameter
  646. Arguments:
  647. SubServiceKey - Supplies an open key to the device node.
  648. CustomDeviceParameter - Supplies the configuration information to be initialized.
  649. Return Value:
  650. None
  651. --*/
  652. {
  653. UCHAR keyValueInformationBuffer[SP_REG_BUFFER_SIZE];
  654. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  655. ULONG length;
  656. ULONG index;
  657. UNICODE_STRING unicodeString;
  658. ANSI_STRING ansiString;
  659. NTSTATUS status;
  660. //
  661. // Look at each of the values in the device node.
  662. //
  663. index = 0;
  664. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) keyValueInformationBuffer;
  665. while (NT_SUCCESS (ZwEnumerateValueKey(
  666. SubServiceKey,
  667. index,
  668. KeyValueFullInformation,
  669. keyValueInformation,
  670. SP_REG_BUFFER_SIZE,
  671. &length))) {
  672. //
  673. // Update the index for the next time around the loop.
  674. //
  675. index++;
  676. //
  677. // Check that the length is reasonable.
  678. //
  679. if (keyValueInformation->Type == REG_DWORD &&
  680. keyValueInformation->DataLength != sizeof(ULONG)) {
  681. continue;
  682. }
  683. //
  684. // Check for a maximum lu number.
  685. //
  686. if (_wcsnicmp(keyValueInformation->Name, L"ScsiDebug",
  687. keyValueInformation->NameLength/2) == 0) {
  688. if (keyValueInformation->Type != REG_DWORD) {
  689. DebugPrint((1, "IdeParseDevice: Bad data type for ScsiDebug.\n"));
  690. continue;
  691. }
  692. #if DBG
  693. ScsiDebug = *((PULONG) (keyValueInformationBuffer + keyValueInformation->DataOffset));
  694. #endif
  695. }
  696. //
  697. // Check for driver parameters tranfers.
  698. //
  699. if (_wcsnicmp(keyValueInformation->Name, L"DriverParameters",
  700. keyValueInformation->NameLength/2) == 0) {
  701. if (keyValueInformation->DataLength == 0) {
  702. continue;
  703. }
  704. if (keyValueInformation->Type == REG_SZ) {
  705. //
  706. // This is a unicode string. Convert it to a ANSI string.
  707. // Initialize the strings.
  708. //
  709. unicodeString.Buffer = (PWSTR) ((PCCHAR) keyValueInformation +
  710. keyValueInformation->DataOffset);
  711. unicodeString.Length = (USHORT) keyValueInformation->DataLength;
  712. unicodeString.MaximumLength = (USHORT) keyValueInformation->DataLength;
  713. status = RtlUnicodeStringToAnsiString(
  714. &ansiString,
  715. &unicodeString,
  716. TRUE
  717. );
  718. if (NT_SUCCESS(status)) {
  719. CustomDeviceParameter->CommandRegisterBase =
  720. AtapiParseArgumentString(ansiString.Buffer, "BaseAddress");
  721. if (CustomDeviceParameter->CommandRegisterBase) {
  722. CustomDeviceParameter->IrqLevel =
  723. AtapiParseArgumentString(ansiString.Buffer, "Interrupt");
  724. }
  725. RtlFreeAnsiString (&ansiString);
  726. }
  727. }
  728. DebugPrint((2, "IdeParseDeviceParameters: Found driver parameter.\n"));
  729. }
  730. }
  731. return;
  732. } // IdePortParseDeviceParameters
  733. #endif // DRIVER_PARAMETER_REGISTRY_SUPPORT
  734. #pragma data_seg ("PAGEDATA")
  735. //
  736. // device description table
  737. // index by SCSI device type
  738. //
  739. const static IDE_DEVICE_TYPE IdeDeviceType[] = {
  740. {"Disk", "GenDisk", "DiskPeripheral" },
  741. {"Sequential", "GenSequential", "TapePeripheral" },
  742. {"Printer", "GenPrinter", "PrinterPeripheral" },
  743. {"Processor", "GenProcessor", "ProcessorPeripheral" },
  744. {"Worm", "GenWorm", "WormPeripheral" },
  745. {"CdRom", "GenCdRom", "CdRomPeripheral" },
  746. {"Scanner", "GenScanner", "ScannerPeripheral" },
  747. {"Optical", "GenOptical", "OpticalDiskPeripheral" },
  748. {"Changer", "GenChanger", "MediumChangerPeripheral" },
  749. {"Net", "GenNet", "CommunicationPeripheral" }
  750. };
  751. #pragma data_seg ()
  752. PCSTR
  753. IdePortGetDeviceTypeString (
  754. IN ULONG DeviceType
  755. )
  756. /*++
  757. Routine Description:
  758. look up SCSI device type string
  759. Arguments:
  760. DeviceType - SCSI device type
  761. Return Value:
  762. device type string
  763. --*/
  764. {
  765. if (DeviceType < (sizeof (IdeDeviceType) / sizeof (IDE_DEVICE_TYPE))) {
  766. return IdeDeviceType[DeviceType].DeviceTypeString;
  767. } else {
  768. return NULL;
  769. }
  770. } // IdePortGetDeviceTypeString
  771. PCSTR
  772. IdePortGetCompatibleIdString (
  773. IN ULONG DeviceType
  774. )
  775. /*++
  776. Routine Description:
  777. look up compatible ID string
  778. Arguments:
  779. DeviceType - SCSI device type
  780. Return Value:
  781. compatible ID string
  782. --*/
  783. {
  784. if (DeviceType < (sizeof (IdeDeviceType) / sizeof (IDE_DEVICE_TYPE))) {
  785. return IdeDeviceType[DeviceType].CompatibleIdString;
  786. } else {
  787. return NULL;
  788. }
  789. } // IdePortGetCompatibleIdString
  790. PCSTR
  791. IdePortGetPeripheralIdString (
  792. IN ULONG DeviceType
  793. )
  794. /*++
  795. Routine Description:
  796. look up peripheral ID string
  797. Arguments:
  798. DeviceType - SCSI device type
  799. Return Value:
  800. Peripheral ID string
  801. --*/
  802. {
  803. if (DeviceType < (sizeof (IdeDeviceType) / sizeof (IDE_DEVICE_TYPE))) {
  804. return IdeDeviceType[DeviceType].PeripheralIdString;
  805. } else {
  806. return NULL;
  807. }
  808. } // IdePortGetPeripheralIdString
  809. VOID
  810. IdePortUnload(
  811. IN PDRIVER_OBJECT DriverObject
  812. )
  813. /*++
  814. Routine Description:
  815. get ready to be unloaded
  816. Arguments:
  817. DriverObject - the driver being unloaded
  818. Return Value:
  819. none
  820. --*/
  821. {
  822. PIDEDRIVER_EXTENSION ideDriverExtension;
  823. DebugPrint ((1, "IdePort: unloading...\n"));
  824. ASSERT (DriverObject->DeviceObject == NULL);
  825. ideDriverExtension = IoGetDriverObjectExtension(
  826. DriverObject,
  827. DRIVER_OBJECT_EXTENSION_ID
  828. );
  829. if (ideDriverExtension->RegistryPath.Buffer != NULL) {
  830. ExFreePool (ideDriverExtension->RegistryPath.Buffer);
  831. }
  832. return;
  833. } // IdePortUnload
  834. BOOLEAN
  835. IdePortOkToDetectLegacy (
  836. IN PDRIVER_OBJECT DriverObject
  837. )
  838. {
  839. NTSTATUS status;
  840. OBJECT_ATTRIBUTES attributes;
  841. HANDLE regHandle;
  842. UNICODE_STRING pathRoot;
  843. ULONG legacyDetection;
  844. RTL_QUERY_REGISTRY_TABLE queryTable[2];
  845. RtlInitUnicodeString (&pathRoot, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Pnp");
  846. InitializeObjectAttributes(&attributes,
  847. &pathRoot,
  848. OBJ_CASE_INSENSITIVE,
  849. NULL,
  850. (PSECURITY_DESCRIPTOR)NULL
  851. );
  852. status = ZwOpenKey(&regHandle,
  853. KEY_READ,
  854. &attributes
  855. );
  856. if (NT_SUCCESS(status)) {
  857. ULONG parameterValue = 0;
  858. RtlZeroMemory(&queryTable, sizeof(queryTable));
  859. queryTable->QueryRoutine = NULL;
  860. queryTable->Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND | RTL_QUERY_REGISTRY_DIRECT;
  861. queryTable->Name = L"DisableFirmwareMapper";
  862. queryTable->EntryContext = &parameterValue;
  863. queryTable->DefaultType = REG_DWORD;
  864. queryTable->DefaultData = &parameterValue;
  865. queryTable->DefaultLength = sizeof (parameterValue);
  866. status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  867. (PWSTR) regHandle,
  868. queryTable,
  869. NULL,
  870. NULL);
  871. ZwClose (regHandle);
  872. if (parameterValue) {
  873. //
  874. // Cool. no need to detect legacy controller
  875. //
  876. return FALSE;
  877. }
  878. }
  879. status = IdePortGetParameterFromServiceSubKey (
  880. DriverObject,
  881. LEGACY_DETECTION,
  882. REG_DWORD,
  883. TRUE,
  884. (PVOID) &legacyDetection,
  885. 0
  886. );
  887. if (NT_SUCCESS(status)) {
  888. if (legacyDetection) {
  889. legacyDetection = 0;
  890. //
  891. // disable legacy detection for next boot
  892. //
  893. IdePortGetParameterFromServiceSubKey (
  894. DriverObject,
  895. LEGACY_DETECTION,
  896. REG_DWORD,
  897. FALSE,
  898. (PVOID) &legacyDetection,
  899. sizeof (legacyDetection)
  900. );
  901. return TRUE;
  902. } else {
  903. return FALSE;
  904. }
  905. }
  906. return TRUE;
  907. }
  908. BOOLEAN
  909. IdePortSearchDeviceInRegMultiSzList (
  910. IN PFDO_EXTENSION FdoExtension,
  911. IN PIDENTIFY_DATA IdentifyData,
  912. IN PWSTR RegKeyValue
  913. )
  914. {
  915. PWSTR string;
  916. UNICODE_STRING unicodeString;
  917. BOOLEAN foundIt;
  918. NTSTATUS status;
  919. PWSTR regDeviceList;
  920. ANSI_STRING ansiTargetDeviceId;
  921. UNICODE_STRING unicodeTargetDeviceId;
  922. PUCHAR targetDeviceId;
  923. ULONG i;
  924. ULONG j;
  925. PAGED_CODE();
  926. ASSERT (IdentifyData);
  927. ASSERT (RegKeyValue);
  928. foundIt = FALSE;
  929. status = IdePortGetParameterFromServiceSubKey (
  930. FdoExtension->DriverObject,
  931. RegKeyValue,
  932. REG_MULTI_SZ,
  933. TRUE,
  934. &regDeviceList,
  935. 0
  936. );
  937. if (NT_SUCCESS(status) && regDeviceList) {
  938. targetDeviceId = ExAllocatePool (
  939. PagedPool,
  940. sizeof(IdentifyData->ModelNumber) +
  941. sizeof(IdentifyData->FirmwareRevision) +
  942. sizeof('\0')
  943. );
  944. if (targetDeviceId) {
  945. for (i=0; i<sizeof(IdentifyData->ModelNumber); i+=2) {
  946. targetDeviceId[i + 0] = IdentifyData->ModelNumber[i + 1];
  947. targetDeviceId[i + 1] = IdentifyData->ModelNumber[i + 0];
  948. if (targetDeviceId[i + 0] == '\0') {
  949. targetDeviceId[i + 0] = ' ';
  950. }
  951. if (targetDeviceId[i + 1] == '\0') {
  952. targetDeviceId[i + 1] = ' ';
  953. }
  954. }
  955. for (j=0; j<sizeof(IdentifyData->FirmwareRevision); j+=2) {
  956. targetDeviceId[i + j + 0] = IdentifyData->FirmwareRevision[j + 1];
  957. targetDeviceId[i + j + 1] = IdentifyData->FirmwareRevision[j + 0];
  958. if (targetDeviceId[i + j + 0] == '\0') {
  959. targetDeviceId[i + j + 0] = ' ';
  960. }
  961. if (targetDeviceId[i + j + 1] == '\0') {
  962. targetDeviceId[i + j + 1] = ' ';
  963. }
  964. }
  965. targetDeviceId[i + j] = 0;
  966. RtlInitAnsiString(
  967. &ansiTargetDeviceId,
  968. targetDeviceId
  969. );
  970. status = RtlAnsiStringToUnicodeString(
  971. &unicodeTargetDeviceId,
  972. &ansiTargetDeviceId,
  973. TRUE
  974. );
  975. if (NT_SUCCESS(status)) {
  976. string = regDeviceList;
  977. DebugPrint ((DBG_REG_SEARCH, "IdePort: searching for %s in list\n", targetDeviceId));
  978. while (string[0]) {
  979. ULONG length;
  980. DebugPrint ((DBG_REG_SEARCH, "IdePort: device list: %ws\n", string));
  981. RtlInitUnicodeString(
  982. &unicodeString,
  983. string
  984. );
  985. //
  986. // compare up to the length of the shorter string
  987. //
  988. if (unicodeTargetDeviceId.Length < unicodeString.Length) {
  989. length = unicodeTargetDeviceId.Length;
  990. } else {
  991. length = unicodeString.Length;
  992. }
  993. if (length == RtlCompareMemory(unicodeTargetDeviceId.Buffer, unicodeString.Buffer, length)) {
  994. DebugPrint ((DBG_REG_SEARCH, "IdePort: Found a target device on the device list. %ws\n", string));
  995. foundIt = TRUE;
  996. break;
  997. } else {
  998. string += (unicodeString.Length / sizeof(WCHAR)) + 1;
  999. }
  1000. }
  1001. RtlFreeUnicodeString (
  1002. &unicodeTargetDeviceId
  1003. );
  1004. } else {
  1005. ASSERT (FALSE);
  1006. }
  1007. ExFreePool(targetDeviceId);
  1008. }
  1009. ExFreePool(regDeviceList);
  1010. }
  1011. return foundIt;
  1012. }
  1013. NTSTATUS
  1014. IdePortSyncSendIrp (
  1015. IN PDEVICE_OBJECT TargetDeviceObject,
  1016. IN PIO_STACK_LOCATION IrpSp,
  1017. IN OUT OPTIONAL PIO_STATUS_BLOCK IoStatus
  1018. )
  1019. {
  1020. PIO_STACK_LOCATION newIrpSp;
  1021. PIRP newIrp;
  1022. KEVENT event;
  1023. NTSTATUS status;
  1024. ASSERT (TargetDeviceObject);
  1025. ASSERT (IrpSp);
  1026. //
  1027. // Allocate an IRP for below
  1028. //
  1029. newIrp = IoAllocateIrp (TargetDeviceObject->StackSize, FALSE); // Get stack size from PDO
  1030. if (newIrp == NULL) {
  1031. DebugPrint ((DBG_ALWAYS, "IdePortSyncSendIrp: Unable to get allocate an irp"));
  1032. return STATUS_NO_MEMORY;
  1033. }
  1034. newIrpSp = IoGetNextIrpStackLocation(newIrp);
  1035. RtlMoveMemory (newIrpSp, IrpSp, sizeof (*IrpSp));
  1036. if (IoStatus) {
  1037. newIrp->IoStatus.Status = IoStatus->Status;
  1038. } else {
  1039. newIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  1040. }
  1041. KeInitializeEvent(&event,
  1042. NotificationEvent,
  1043. FALSE);
  1044. IoSetCompletionRoutine (
  1045. newIrp,
  1046. IdePortGenericCompletionRoutine,
  1047. &event,
  1048. TRUE,
  1049. TRUE,
  1050. TRUE);
  1051. status = IoCallDriver (TargetDeviceObject, newIrp);
  1052. if (status == STATUS_PENDING) {
  1053. status = KeWaitForSingleObject(&event,
  1054. Executive,
  1055. KernelMode,
  1056. FALSE,
  1057. NULL);
  1058. }
  1059. status = newIrp->IoStatus.Status;
  1060. if (IoStatus) {
  1061. *IoStatus = newIrp->IoStatus;
  1062. }
  1063. IoFreeIrp (newIrp);
  1064. return status;
  1065. }
  1066. NTSTATUS
  1067. IdePortGenericCompletionRoutine (
  1068. IN PDEVICE_OBJECT DeviceObject,
  1069. IN PIRP Irp,
  1070. IN PVOID Context
  1071. )
  1072. {
  1073. PKEVENT event = Context;
  1074. KeSetEvent(
  1075. event,
  1076. EVENT_INCREMENT,
  1077. FALSE
  1078. );
  1079. return STATUS_MORE_PROCESSING_REQUIRED;
  1080. } // IdePortSyncSendIrpCompletionRoutine
  1081. ULONG
  1082. IdePortSimpleCheckSum (
  1083. IN ULONG PartialSum,
  1084. IN PVOID SourceVa,
  1085. IN ULONG Length
  1086. )
  1087. /*++
  1088. Routine Description:
  1089. Computes a checksum for the supplied virtual address and length
  1090. This function comes from Dr. Dobbs Journal, May 1992
  1091. Arguments:
  1092. PartialSum - The previous partial checksum
  1093. SourceVa - Starting address
  1094. Length - Length, in bytes, of the range
  1095. Return Value:
  1096. The checksum value
  1097. --*/
  1098. {
  1099. PUSHORT Source;
  1100. Source = (PUSHORT) SourceVa;
  1101. Length = Length / 2;
  1102. while (Length--) {
  1103. PartialSum += *Source++;
  1104. PartialSum = (PartialSum >> 16) + (PartialSum & 0xFFFF);
  1105. }
  1106. return PartialSum;
  1107. }
  1108. BOOLEAN
  1109. IdePortInSetup(
  1110. IN PFDO_EXTENSION FdoExtension
  1111. )
  1112. /*++
  1113. --*/
  1114. {
  1115. OBJECT_ATTRIBUTES objectAttributes;
  1116. UNICODE_STRING keyName;
  1117. HANDLE hKey;
  1118. ULONG systemSetupInProgress = 0;
  1119. NTSTATUS status;
  1120. BOOLEAN textmodeSetup = TRUE;
  1121. PAGED_CODE();
  1122. RtlInitUnicodeString(&keyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\setupdd");
  1123. InitializeObjectAttributes(&objectAttributes,
  1124. &keyName,
  1125. OBJ_CASE_INSENSITIVE,
  1126. NULL,
  1127. (PSECURITY_DESCRIPTOR) NULL);
  1128. status = ZwOpenKey(&hKey,
  1129. KEY_READ,
  1130. &objectAttributes);
  1131. if (!NT_SUCCESS(status)) {
  1132. textmodeSetup = FALSE;
  1133. } else {
  1134. ZwClose(hKey);
  1135. }
  1136. RtlInitUnicodeString(&keyName,L"\\Registry\\Machine\\System\\setup");
  1137. InitializeObjectAttributes(&objectAttributes,
  1138. &keyName,
  1139. OBJ_CASE_INSENSITIVE,
  1140. NULL,
  1141. (PSECURITY_DESCRIPTOR) NULL);
  1142. status = ZwOpenKey(&hKey,
  1143. KEY_READ,
  1144. &objectAttributes);
  1145. if (NT_SUCCESS(status)) {
  1146. //
  1147. // Query the data for the key value.
  1148. //
  1149. RTL_QUERY_REGISTRY_TABLE queryTable[2];
  1150. systemSetupInProgress = 0;
  1151. RtlZeroMemory(&queryTable, sizeof(queryTable));
  1152. queryTable->QueryRoutine = NULL;
  1153. queryTable->Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND | RTL_QUERY_REGISTRY_DIRECT;
  1154. queryTable->Name = L"SystemSetupInProgress";
  1155. queryTable->EntryContext = &systemSetupInProgress;
  1156. queryTable->DefaultType = REG_DWORD;
  1157. queryTable->DefaultData = &systemSetupInProgress;
  1158. queryTable->DefaultLength = sizeof (systemSetupInProgress);
  1159. status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  1160. (PWSTR) hKey,
  1161. queryTable,
  1162. NULL,
  1163. NULL);
  1164. ZwClose (hKey);
  1165. }
  1166. return (textmodeSetup || systemSetupInProgress);
  1167. }