Leaked source code of windows server 2003
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.

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