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.

1184 lines
30 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: pciidex.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "pciidex.h"
  11. #ifdef ALLOC_PRAGMA
  12. #pragma alloc_text(PAGE, DriverEntry)
  13. #pragma alloc_text(PAGE, PciIdeXInitialize)
  14. #pragma alloc_text(PAGE, PciIdeXAlwaysStatusSuccessIrp)
  15. #pragma alloc_text(PAGE, DispatchPnp)
  16. #pragma alloc_text(PAGE, DispatchWmi)
  17. #pragma alloc_text(PAGE, PassDownToNextDriver)
  18. #pragma alloc_text(PAGE, PciIdeInternalDeviceIoControl)
  19. #pragma alloc_text(PAGE, PciIdeXGetDeviceParameter)
  20. #pragma alloc_text(PAGE, PciIdeXGetDeviceParameterEx)
  21. #pragma alloc_text(PAGE, PciIdeXRegQueryRoutine)
  22. #pragma alloc_text(PAGE, PciIdeUnload)
  23. #pragma alloc_text(PAGE, PciIdeXSyncSendIrp)
  24. #pragma alloc_text(NONPAGE, PciIdeXGetBusData)
  25. #pragma alloc_text(NONPAGE, PciIdeXSetBusData)
  26. #pragma alloc_text(NONPAGE, DispatchPower)
  27. #pragma alloc_text(NONPAGE, NoSupportIrp)
  28. #pragma alloc_text(NONPAGE, PciIdeBusData)
  29. #pragma alloc_text(NONPAGE, PciIdeBusDataCompletionRoutine)
  30. #pragma alloc_text(NONPAGE, PciIdeXSyncSendIrpCompletionRoutine)
  31. #if DBG
  32. #pragma alloc_text(PAGE, PciIdeXSaveDeviceParameter)
  33. #endif // DBG
  34. #endif // ALLOC_PRAGMA
  35. //
  36. // get the share code
  37. //
  38. #include "..\share\util.c"
  39. #if DBG
  40. ULONG PciIdeDebug = 0;
  41. UCHAR DebugBuffer[128 * 6];
  42. VOID
  43. PciIdeDebugPrint(
  44. ULONG DebugPrintLevel,
  45. PCCHAR DebugMessage,
  46. ...
  47. )
  48. /*++
  49. Routine Description:
  50. Debug print for all SCSI drivers
  51. Arguments:
  52. Debug print level between 0 and 3, with 3 being the most verbose.
  53. Return Value:
  54. None
  55. --*/
  56. {
  57. va_list ap;
  58. va_start(ap, DebugMessage);
  59. if (DebugPrintLevel <= PciIdeDebug) {
  60. vsprintf(DebugBuffer, DebugMessage, ap);
  61. //DbgPrint(DebugBuffer);
  62. #if 1
  63. DbgPrintEx(DPFLTR_PCIIDE_ID,
  64. DPFLTR_INFO_LEVEL,
  65. DebugBuffer
  66. );
  67. #endif
  68. }
  69. va_end(ap);
  70. } // end DebugPrint()
  71. #else
  72. VOID
  73. PciIdeDebugPrint(
  74. ULONG DebugPrintLevel,
  75. PCCHAR DebugMessage,
  76. ...
  77. )
  78. {
  79. return;
  80. }
  81. #endif
  82. //
  83. // PnP Dispatch Table
  84. //
  85. PDRIVER_DISPATCH FdoPnpDispatchTable[NUM_PNP_MINOR_FUNCTION];
  86. PDRIVER_DISPATCH PdoPnpDispatchTable[NUM_PNP_MINOR_FUNCTION];
  87. //
  88. // Po Dispatch Table
  89. //
  90. PDRIVER_DISPATCH FdoPowerDispatchTable[NUM_POWER_MINOR_FUNCTION];
  91. PDRIVER_DISPATCH PdoPowerDispatchTable[NUM_POWER_MINOR_FUNCTION];
  92. //
  93. // Wmi Dispatch Table
  94. //
  95. PDRIVER_DISPATCH FdoWmiDispatchTable[NUM_WMI_MINOR_FUNCTION];
  96. PDRIVER_DISPATCH PdoWmiDispatchTable[NUM_WMI_MINOR_FUNCTION];
  97. NTSTATUS
  98. DriverEntry(
  99. IN PDRIVER_OBJECT DriverObject,
  100. IN PUNICODE_STRING RegistryPath
  101. )
  102. {
  103. PAGED_CODE();
  104. return STATUS_SUCCESS;
  105. } // DriverEntry
  106. NTSTATUS
  107. PciIdeXInitialize(
  108. IN PDRIVER_OBJECT DriverObject,
  109. IN PUNICODE_STRING RegistryPath,
  110. IN PCONTROLLER_PROPERTIES PciIdeGetControllerProperties,
  111. IN ULONG ExtensionSize
  112. )
  113. {
  114. NTSTATUS status;
  115. PDRIVER_EXTENSION driverExtension;
  116. PDRIVER_OBJECT_EXTENSION driverObjectExtension;
  117. ULONG i;
  118. PAGED_CODE();
  119. status = IoAllocateDriverObjectExtension(
  120. DriverObject,
  121. DRIVER_OBJECT_EXTENSION_ID,
  122. sizeof (DRIVER_OBJECT_EXTENSION),
  123. &driverObjectExtension
  124. );
  125. if (!NT_SUCCESS(status)) {
  126. DebugPrint ((0, "PciIde: Unable to create driver extension\n"));
  127. return status;
  128. }
  129. ASSERT (driverObjectExtension);
  130. driverObjectExtension->PciIdeGetControllerProperties = PciIdeGetControllerProperties;
  131. driverObjectExtension->ExtensionSize = ExtensionSize;
  132. //
  133. // some entry point init.
  134. //
  135. DriverObject->DriverUnload = PciIdeUnload;
  136. DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
  137. DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
  138. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = PciIdeInternalDeviceIoControl;
  139. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchWmi;
  140. driverExtension = DriverObject->DriverExtension;
  141. driverExtension->AddDevice = ControllerAddDevice;
  142. //
  143. // FDO PnP Dispatch Table
  144. //
  145. for (i=0; i<NUM_PNP_MINOR_FUNCTION; i++) {
  146. FdoPnpDispatchTable[i] = PassDownToNextDriver;
  147. }
  148. FdoPnpDispatchTable[IRP_MN_START_DEVICE ] = ControllerStartDevice;
  149. FdoPnpDispatchTable[IRP_MN_QUERY_REMOVE_DEVICE ] = StatusSuccessAndPassDownToNextDriver;
  150. FdoPnpDispatchTable[IRP_MN_CANCEL_REMOVE_DEVICE ] = StatusSuccessAndPassDownToNextDriver;
  151. FdoPnpDispatchTable[IRP_MN_STOP_DEVICE ] = ControllerStopDevice;
  152. FdoPnpDispatchTable[IRP_MN_QUERY_STOP_DEVICE ] = StatusSuccessAndPassDownToNextDriver;
  153. FdoPnpDispatchTable[IRP_MN_CANCEL_STOP_DEVICE ] = StatusSuccessAndPassDownToNextDriver;
  154. FdoPnpDispatchTable[IRP_MN_REMOVE_DEVICE ] = ControllerRemoveDevice;
  155. FdoPnpDispatchTable[IRP_MN_QUERY_DEVICE_RELATIONS ] = ControllerQueryDeviceRelations;
  156. FdoPnpDispatchTable[IRP_MN_QUERY_INTERFACE ] = ControllerQueryInterface;
  157. FdoPnpDispatchTable[IRP_MN_DEVICE_USAGE_NOTIFICATION] = ControllerUsageNotification;
  158. FdoPnpDispatchTable[IRP_MN_QUERY_PNP_DEVICE_STATE ] = ControllerQueryPnPDeviceState;
  159. FdoPnpDispatchTable[IRP_MN_SURPRISE_REMOVAL ] = ControllerSurpriseRemoveDevice;
  160. //
  161. // PDO PnP Dispatch Table
  162. //
  163. for (i=0; i<NUM_PNP_MINOR_FUNCTION; i++) {
  164. PdoPnpDispatchTable[i] = NoSupportIrp;
  165. }
  166. PdoPnpDispatchTable[IRP_MN_START_DEVICE ] = ChannelStartDevice;
  167. PdoPnpDispatchTable[IRP_MN_QUERY_REMOVE_DEVICE ] = ChannelQueryStopRemoveDevice;
  168. PdoPnpDispatchTable[IRP_MN_REMOVE_DEVICE ] = ChannelRemoveDevice;
  169. PdoPnpDispatchTable[IRP_MN_CANCEL_REMOVE_DEVICE ] = PciIdeXAlwaysStatusSuccessIrp;
  170. PdoPnpDispatchTable[IRP_MN_STOP_DEVICE ] = ChannelStopDevice;
  171. PdoPnpDispatchTable[IRP_MN_QUERY_STOP_DEVICE ] = ChannelQueryStopRemoveDevice;
  172. PdoPnpDispatchTable[IRP_MN_CANCEL_STOP_DEVICE ] = PciIdeXAlwaysStatusSuccessIrp;
  173. PdoPnpDispatchTable[IRP_MN_QUERY_CAPABILITIES ] = ChannelQueryCapabitilies;
  174. PdoPnpDispatchTable[IRP_MN_QUERY_RESOURCES ] = ChannelQueryResources;
  175. PdoPnpDispatchTable[IRP_MN_QUERY_RESOURCE_REQUIREMENTS] = ChannelQueryResourceRequirements;
  176. PdoPnpDispatchTable[IRP_MN_QUERY_DEVICE_TEXT ] = ChannelQueryText;
  177. PdoPnpDispatchTable[IRP_MN_QUERY_ID ] = ChannelQueryId;
  178. PdoPnpDispatchTable[IRP_MN_QUERY_DEVICE_RELATIONS ] = ChannelQueryDeviceRelations;
  179. PdoPnpDispatchTable[IRP_MN_QUERY_INTERFACE ] = PciIdeChannelQueryInterface;
  180. PdoPnpDispatchTable[IRP_MN_DEVICE_USAGE_NOTIFICATION ] = ChannelUsageNotification;
  181. PdoPnpDispatchTable[IRP_MN_QUERY_PNP_DEVICE_STATE ] = ChannelQueryPnPDeviceState;
  182. PdoPnpDispatchTable[IRP_MN_SURPRISE_REMOVAL ] = ChannelRemoveDevice;
  183. PdoPnpDispatchTable[IRP_MN_FILTER_RESOURCE_REQUIREMENTS] = ChannelFilterResourceRequirements;
  184. //
  185. // FDO Power Dispatch Table
  186. //
  187. for (i=0; i<NUM_POWER_MINOR_FUNCTION; i++) {
  188. FdoPowerDispatchTable[i] = PassDownToNextDriver;
  189. }
  190. FdoPowerDispatchTable[IRP_MN_SET_POWER] = PciIdeSetFdoPowerState;
  191. FdoPowerDispatchTable[IRP_MN_QUERY_POWER] = PciIdeXQueryPowerState;
  192. //
  193. // PDO Power Dispatch Table
  194. //
  195. for (i=0; i<NUM_POWER_MINOR_FUNCTION; i++) {
  196. PdoPowerDispatchTable[i] = NoSupportIrp;
  197. }
  198. PdoPowerDispatchTable[IRP_MN_SET_POWER] = PciIdeSetPdoPowerState;
  199. PdoPowerDispatchTable[IRP_MN_QUERY_POWER] = PciIdeXQueryPowerState;
  200. //
  201. // FDO WMI Dispatch Table
  202. //
  203. for (i=0; i<NUM_WMI_MINOR_FUNCTION; i++) {
  204. FdoWmiDispatchTable[i] = PassDownToNextDriver;
  205. }
  206. //
  207. // PDO WMI Dispatch Table
  208. //
  209. for (i=0; i<NUM_WMI_MINOR_FUNCTION; i++) {
  210. PdoWmiDispatchTable[i] = NoSupportIrp;
  211. }
  212. //
  213. // Create device object name directory
  214. //
  215. IdeCreateIdeDirectory();
  216. return status;
  217. } // PciIdeXInitialize
  218. NTSTATUS
  219. PciIdeXAlwaysStatusSuccessIrp (
  220. IN PDEVICE_OBJECT DeviceObject,
  221. IN OUT PIRP Irp
  222. /*++
  223. Routine Description:
  224. Generic routine to STATUS_SUCCESS an irp
  225. Arguments:
  226. DeviceObject - Pointer to the device object for which this IRP applies.
  227. Irp - Pointer to the IRP.
  228. Return Value:
  229. NT status.
  230. --*/
  231. )
  232. {
  233. Irp->IoStatus.Status = STATUS_SUCCESS;
  234. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  235. return STATUS_SUCCESS;
  236. } // PciIdeXAlwaysStatusSuccessIrp
  237. NTSTATUS
  238. DispatchPower(
  239. IN PDEVICE_OBJECT DeviceObject,
  240. IN OUT PIRP Irp
  241. )
  242. {
  243. PIO_STACK_LOCATION thisIrpSp;
  244. NTSTATUS status;
  245. PDEVICE_EXTENSION_HEADER doExtension;
  246. //
  247. // Get a pointer to our stack location and take appropriate action based
  248. // on the minor function.
  249. //
  250. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  251. doExtension = (PDEVICE_EXTENSION_HEADER) DeviceObject->DeviceExtension;
  252. DebugPrint ((2,
  253. "PciIde: %s %d got %s\n",
  254. doExtension->AttacheeDeviceObject ? "FDO" : "PDO",
  255. doExtension->AttacheeDeviceObject ? 0 :
  256. ((PCHANPDO_EXTENSION) doExtension)->ChannelNumber,
  257. IdeDebugPowerIrpName[thisIrpSp->MinorFunction]));
  258. switch (thisIrpSp->MinorFunction) {
  259. case IRP_MN_WAIT_WAKE:
  260. DebugPrint ((2, "IRP_MN_WAIT_WAKE\n"));
  261. break;
  262. case IRP_MN_POWER_SEQUENCE:
  263. DebugPrint ((2, "IRP_MN_POWER_SEQUENCE\n"));
  264. break;
  265. case IRP_MN_SET_POWER:
  266. DebugPrint ((2, "IRP_MN_SET_POWER\n"));
  267. break;
  268. case IRP_MN_QUERY_POWER:
  269. DebugPrint ((2, "IRP_MN_QUERY_POWER\n"));
  270. break;
  271. default:
  272. DebugPrint ((2, "IRP_MN_0x%x\n", thisIrpSp->MinorFunction));
  273. break;
  274. }
  275. // Should always pass the irp down. It is taken care by the corresponding dispatch
  276. // funtion.
  277. //
  278. if (thisIrpSp->MinorFunction < NUM_POWER_MINOR_FUNCTION) {
  279. status = doExtension->PowerDispatchTable[thisIrpSp->MinorFunction] (DeviceObject, Irp);
  280. } else {
  281. DebugPrint ((1,
  282. "ATAPI: Power Dispatch Table too small\n"
  283. ));
  284. status = doExtension->DefaultDispatch (DeviceObject, Irp);
  285. }
  286. return status;
  287. } // DispatchPower
  288. NTSTATUS
  289. DispatchPnp(
  290. IN PDEVICE_OBJECT DeviceObject,
  291. IN OUT PIRP Irp
  292. )
  293. /*++
  294. Routine Description:
  295. This routine handles all IRP_MJ_PNP_POWER IRPs for this driver.
  296. Arguments:
  297. DeviceObject - Pointer to the device object for which this IRP applies.
  298. Irp - Pointer to the IRP_MJ_PNP_POWER IRP to dispatch.
  299. Return Value:
  300. NT status.
  301. --*/
  302. {
  303. PIO_STACK_LOCATION thisIrpSp;
  304. NTSTATUS status;
  305. PDEVICE_EXTENSION_HEADER doExtension;
  306. PAGED_CODE();
  307. //
  308. // Get a pointer to our stack location and take appropriate action based
  309. // on the minor function.
  310. //
  311. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  312. doExtension = (PDEVICE_EXTENSION_HEADER) DeviceObject->DeviceExtension;
  313. DebugPrint ((2,
  314. "PciIde: %s %d got %s\n",
  315. doExtension->AttacheeDeviceObject ? "FDO" : "PDO",
  316. doExtension->AttacheeDeviceObject ? 0 :
  317. ((PCHANPDO_EXTENSION) doExtension)->ChannelNumber,
  318. IdeDebugPnpIrpName[thisIrpSp->MinorFunction]));
  319. if (thisIrpSp->MinorFunction < NUM_PNP_MINOR_FUNCTION) {
  320. status = doExtension->PnPDispatchTable[thisIrpSp->MinorFunction] (DeviceObject, Irp);
  321. } else {
  322. if (thisIrpSp->MinorFunction != 0xff) {
  323. ASSERT (!"ATAPI: PnP Dispatch Table too small\n");
  324. }
  325. status = doExtension->DefaultDispatch (DeviceObject, Irp);
  326. }
  327. return status;
  328. } // DispatchPnp
  329. NTSTATUS
  330. DispatchWmi(
  331. IN PDEVICE_OBJECT DeviceObject,
  332. IN OUT PIRP Irp
  333. )
  334. /*++
  335. Routine Description:
  336. This routine handles all IRP_MJ_SYSTEM_CONTROL (WMI) IRPs for this driver.
  337. Arguments:
  338. DeviceObject - Pointer to the device object for which this IRP applies.
  339. Irp - Pointer to the IRP_MJ_PNP_POWER IRP to dispatch.
  340. Return Value:
  341. NT status.
  342. --*/
  343. {
  344. PIO_STACK_LOCATION thisIrpSp;
  345. NTSTATUS status;
  346. PDEVICE_EXTENSION_HEADER doExtension;
  347. PAGED_CODE();
  348. //
  349. // Get a pointer to our stack location and take appropriate action based
  350. // on the minor function.
  351. //
  352. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  353. doExtension = (PDEVICE_EXTENSION_HEADER) DeviceObject->DeviceExtension;
  354. DebugPrint ((2,
  355. "PciIde: %s %d got %s\n",
  356. doExtension->AttacheeDeviceObject ? "FDO" : "PDO",
  357. doExtension->AttacheeDeviceObject ? 0 :
  358. ((PCHANPDO_EXTENSION) doExtension)->ChannelNumber,
  359. IdeDebugWmiIrpName[thisIrpSp->MinorFunction]));
  360. if (thisIrpSp->MinorFunction < NUM_WMI_MINOR_FUNCTION) {
  361. status = doExtension->WmiDispatchTable[thisIrpSp->MinorFunction] (DeviceObject, Irp);
  362. } else {
  363. DebugPrint ((1,
  364. "ATAPI: WMI Dispatch Table too small\n"
  365. ));
  366. status = doExtension->DefaultDispatch (DeviceObject, Irp);
  367. }
  368. return status;
  369. } // DispatchWmi()
  370. NTSTATUS
  371. PassDownToNextDriver (
  372. IN PDEVICE_OBJECT DeviceObject,
  373. IN OUT PIRP Irp
  374. )
  375. {
  376. PDEVICE_EXTENSION_HEADER deviceExtensionHeader;
  377. NTSTATUS status;
  378. PIO_STACK_LOCATION thisIrpSp;
  379. PAGED_CODE();
  380. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  381. deviceExtensionHeader = (PDEVICE_EXTENSION_HEADER) DeviceObject->DeviceExtension;
  382. ASSERT (deviceExtensionHeader->AttacheeDeviceObject);
  383. if (thisIrpSp->MajorFunction == IRP_MJ_POWER) {
  384. //
  385. // call PoStartNextPowerIrp before completing a power irp
  386. //
  387. PoStartNextPowerIrp (Irp);
  388. IoSkipCurrentIrpStackLocation (Irp);
  389. status = PoCallDriver (deviceExtensionHeader->AttacheeDeviceObject, Irp);
  390. } else {
  391. //
  392. // Not a power irp
  393. //
  394. IoSkipCurrentIrpStackLocation (Irp);
  395. status = IoCallDriver (deviceExtensionHeader->AttacheeDeviceObject, Irp);
  396. }
  397. return status;
  398. } // PassDownToNextDriver
  399. NTSTATUS
  400. StatusSuccessAndPassDownToNextDriver (
  401. IN PDEVICE_OBJECT DeviceObject,
  402. IN OUT PIRP Irp
  403. )
  404. {
  405. PDEVICE_EXTENSION_HEADER deviceExtensionHeader;
  406. PAGED_CODE();
  407. IoSkipCurrentIrpStackLocation (Irp);
  408. deviceExtensionHeader = (PDEVICE_EXTENSION_HEADER) DeviceObject->DeviceExtension;
  409. Irp->IoStatus.Status = STATUS_SUCCESS;
  410. return IoCallDriver (deviceExtensionHeader->AttacheeDeviceObject, Irp);
  411. } // PassDownToNextDriver
  412. NTSTATUS
  413. NoSupportIrp (
  414. IN PDEVICE_OBJECT DeviceObject,
  415. IN OUT PIRP Irp
  416. )
  417. {
  418. PIO_STACK_LOCATION thisIrpSp;
  419. NTSTATUS status = Irp->IoStatus.Status;
  420. thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
  421. //
  422. // You should call PoStartNextPowerIrp before completing a power irp
  423. //
  424. if (thisIrpSp->MajorFunction == IRP_MJ_POWER) {
  425. PoStartNextPowerIrp (Irp);
  426. }
  427. DebugPrint ((
  428. 1,
  429. "IdePort: devobj 0x%x failing unsupported Irp (0x%x, 0x%x) with status = %x\n",
  430. DeviceObject,
  431. thisIrpSp->MajorFunction,
  432. thisIrpSp->MinorFunction,
  433. status
  434. ));
  435. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  436. return status;
  437. } // NoSupportIrp
  438. NTSTATUS
  439. PciIdeXGetBusData(
  440. IN PVOID DeviceExtension,
  441. IN PVOID Buffer,
  442. IN ULONG ConfigDataOffset,
  443. IN ULONG BufferLength
  444. )
  445. {
  446. PCTRLFDO_EXTENSION fdoExtension = ((PCTRLFDO_EXTENSION) DeviceExtension) - 1;
  447. return PciIdeBusData(
  448. fdoExtension,
  449. Buffer,
  450. ConfigDataOffset,
  451. BufferLength,
  452. TRUE
  453. );
  454. } // PciIdeXGetBusData
  455. NTSTATUS
  456. PciIdeXSetBusData(
  457. IN PVOID DeviceExtension,
  458. IN PVOID Buffer,
  459. IN PVOID DataMask,
  460. IN ULONG ConfigDataOffset,
  461. IN ULONG BufferLength
  462. )
  463. {
  464. PCTRLFDO_EXTENSION fdoExtension = ((PCTRLFDO_EXTENSION) DeviceExtension) - 1;
  465. NTSTATUS status;
  466. PUCHAR pciData;
  467. KIRQL currentIrql;
  468. pciData = ExAllocatePool (NonPagedPool, BufferLength);
  469. if (pciData == NULL) {
  470. return STATUS_INSUFFICIENT_RESOURCES;
  471. }
  472. KeAcquireSpinLock(
  473. &fdoExtension->PciConfigDataLock,
  474. &currentIrql);
  475. //
  476. // get the current values
  477. //
  478. status = PciIdeBusData(
  479. fdoExtension,
  480. pciData,
  481. ConfigDataOffset,
  482. BufferLength,
  483. TRUE
  484. );
  485. if (NT_SUCCESS(status)) {
  486. ULONG i;
  487. PUCHAR dataMask = (PUCHAR) DataMask;
  488. PUCHAR newData = (PUCHAR) Buffer;
  489. for (i=0; i<BufferLength; i++) {
  490. // optimize for ULONG
  491. //
  492. // update bits according to the mask
  493. //
  494. pciData[i] = (pciData[i] & ~dataMask[i]) | (dataMask[i] & newData[i]);
  495. }
  496. status = PciIdeBusData(
  497. fdoExtension,
  498. pciData,
  499. ConfigDataOffset,
  500. BufferLength,
  501. FALSE
  502. );
  503. }
  504. KeReleaseSpinLock(
  505. &fdoExtension->PciConfigDataLock,
  506. currentIrql);
  507. ExFreePool (pciData);
  508. return status;
  509. } // PciIdeXSetBusData
  510. NTSTATUS
  511. PciIdeBusData(
  512. IN PCTRLFDO_EXTENSION FdoExtension,
  513. IN OUT PVOID Buffer,
  514. IN ULONG ConfigDataOffset,
  515. IN ULONG BufferLength,
  516. IN BOOLEAN ReadConfigData
  517. )
  518. {
  519. ULONG byteTransferred;
  520. PGET_SET_DEVICE_DATA BusDataFunction;
  521. if (ReadConfigData) {
  522. BusDataFunction = FdoExtension->BusInterface.GetBusData;
  523. } else {
  524. BusDataFunction = FdoExtension->BusInterface.SetBusData;
  525. }
  526. // if (!BusDataFunction) {
  527. // DebugPrint((0, "PCIIDEX: ERROR: NULL BusDataFunction\n"));
  528. // return STATUS_UNSUCCESSFUL;
  529. //}
  530. byteTransferred = BusDataFunction (
  531. FdoExtension->BusInterface.Context,
  532. PCI_WHICHSPACE_CONFIG,
  533. Buffer,
  534. ConfigDataOffset,
  535. BufferLength
  536. );
  537. if (byteTransferred != BufferLength) {
  538. return STATUS_UNSUCCESSFUL;
  539. } else {
  540. return STATUS_SUCCESS;
  541. }
  542. } // PciIdeBusData
  543. NTSTATUS
  544. PciIdeBusDataCompletionRoutine(
  545. PDEVICE_OBJECT DeviceObject,
  546. PIRP Irp,
  547. PVOID Context
  548. )
  549. {
  550. PIO_STATUS_BLOCK ioStatus = (PIO_STATUS_BLOCK) Context;
  551. PKEVENT event;
  552. ioStatus->Status = Irp->IoStatus.Status;
  553. event = (PKEVENT) ioStatus->Information;
  554. KeSetEvent (event, 0, FALSE);
  555. IoFreeIrp (Irp);
  556. return STATUS_MORE_PROCESSING_REQUIRED;
  557. } // PciIdeBusDataCompletionRoutine
  558. NTSTATUS
  559. PciIdeInternalDeviceIoControl (
  560. IN PDEVICE_OBJECT DeviceObject,
  561. IN OUT PIRP Irp
  562. )
  563. {
  564. PDEVICE_EXTENSION_HEADER DoExtensionHeader;
  565. NTSTATUS status;
  566. PAGED_CODE();
  567. DoExtensionHeader = DeviceObject->DeviceExtension;
  568. if (DoExtensionHeader->AttacheeDeviceObject == NULL) {
  569. //
  570. // PDO
  571. //
  572. status = ChannelInternalDeviceIoControl (
  573. DeviceObject,
  574. Irp
  575. );
  576. } else {
  577. //
  578. // FDO
  579. //
  580. status = Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  581. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  582. }
  583. return status;
  584. } // PciIdeInternalDeviceIoControl
  585. NTSTATUS
  586. PciIdeXRegQueryRoutine (
  587. IN PWSTR ValueName,
  588. IN ULONG ValueType,
  589. IN PVOID ValueData,
  590. IN ULONG ValueLength,
  591. IN PVOID Context,
  592. IN PVOID EntryContext
  593. )
  594. {
  595. PVOID *parameterValue = EntryContext;
  596. PAGED_CODE();
  597. if (ValueType == REG_MULTI_SZ) {
  598. *parameterValue = ExAllocatePool(PagedPool, ValueLength);
  599. if (*parameterValue) {
  600. RtlMoveMemory(*parameterValue, ValueData, ValueLength);
  601. return STATUS_SUCCESS;
  602. }
  603. } else if (ValueType == REG_DWORD) {
  604. PULONG ulongValue;
  605. ulongValue = (PULONG) parameterValue;
  606. *ulongValue = *((PULONG) ValueData);
  607. return STATUS_SUCCESS;
  608. }
  609. return STATUS_UNSUCCESSFUL;
  610. }
  611. NTSTATUS
  612. PciIdeXGetDeviceParameterEx (
  613. IN PDEVICE_OBJECT DeviceObject,
  614. IN PWSTR ParameterName,
  615. IN OUT PVOID *ParameterValue
  616. )
  617. /*++
  618. Routine Description:
  619. retrieve a devnode registry parameter
  620. Arguments:
  621. FdoExtension - FDO Extension
  622. ParameterName - parameter name to look up
  623. ParameterValuse - default parameter value
  624. Return Value:
  625. NT Status
  626. --*/
  627. {
  628. NTSTATUS status;
  629. HANDLE deviceParameterHandle;
  630. RTL_QUERY_REGISTRY_TABLE queryTable[2];
  631. ULONG i;
  632. ULONG flag;
  633. PAGED_CODE();
  634. *ParameterValue = NULL;
  635. for (i=0; i<2; i++) {
  636. if (i == 0) {
  637. flag = PLUGPLAY_REGKEY_DRIVER | PLUGPLAY_REGKEY_CURRENT_HWPROFILE;
  638. } else {
  639. flag = PLUGPLAY_REGKEY_DRIVER;
  640. }
  641. //
  642. // open the given parameter
  643. //
  644. status = IoOpenDeviceRegistryKey(DeviceObject,
  645. flag,
  646. KEY_READ,
  647. &deviceParameterHandle);
  648. if(!NT_SUCCESS(status)) {
  649. continue;
  650. }
  651. RtlZeroMemory(queryTable, sizeof(queryTable));
  652. queryTable->QueryRoutine = PciIdeXRegQueryRoutine;
  653. queryTable->Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
  654. queryTable->Name = ParameterName;
  655. queryTable->EntryContext = ParameterValue;
  656. queryTable->DefaultType = REG_NONE;
  657. queryTable->DefaultData = NULL;
  658. queryTable->DefaultLength = 0;
  659. status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  660. (PWSTR) deviceParameterHandle,
  661. queryTable,
  662. NULL,
  663. NULL);
  664. if (!NT_SUCCESS(status)) {
  665. *ParameterValue = NULL;
  666. }
  667. //
  668. // close what we open
  669. //
  670. ZwClose(deviceParameterHandle);
  671. if (NT_SUCCESS(status)) {
  672. break;
  673. }
  674. }
  675. return status;
  676. } // PciIdeXGetDeviceParameter
  677. NTSTATUS
  678. PciIdeXGetDeviceParameter (
  679. IN PDEVICE_OBJECT DeviceObject,
  680. IN PWSTR ParameterName,
  681. IN OUT PULONG ParameterValue
  682. )
  683. /*++
  684. Routine Description:
  685. retrieve a devnode registry parameter
  686. Arguments:
  687. FdoExtension - FDO Extension
  688. ParameterName - parameter name to look up
  689. ParameterValuse - default parameter value
  690. Return Value:
  691. NT Status
  692. --*/
  693. {
  694. NTSTATUS status;
  695. HANDLE deviceParameterHandle;
  696. RTL_QUERY_REGISTRY_TABLE queryTable[2];
  697. ULONG defaultParameterValue;
  698. ULONG i;
  699. ULONG flag;
  700. PAGED_CODE();
  701. for (i=0; i<2; i++) {
  702. if (i == 0) {
  703. flag = PLUGPLAY_REGKEY_DRIVER | PLUGPLAY_REGKEY_CURRENT_HWPROFILE;
  704. } else {
  705. flag = PLUGPLAY_REGKEY_DRIVER;
  706. }
  707. //
  708. // open the given parameter
  709. //
  710. status = IoOpenDeviceRegistryKey(DeviceObject,
  711. flag,
  712. KEY_READ,
  713. &deviceParameterHandle);
  714. if(!NT_SUCCESS(status)) {
  715. continue;
  716. }
  717. RtlZeroMemory(queryTable, sizeof(queryTable));
  718. defaultParameterValue = *ParameterValue;
  719. queryTable->Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
  720. queryTable->Name = ParameterName;
  721. queryTable->EntryContext = ParameterValue;
  722. queryTable->DefaultType = REG_NONE;
  723. queryTable->DefaultData = NULL;
  724. queryTable->DefaultLength = 0;
  725. status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
  726. (PWSTR) deviceParameterHandle,
  727. queryTable,
  728. NULL,
  729. NULL);
  730. if (!NT_SUCCESS(status)) {
  731. *ParameterValue = defaultParameterValue;
  732. }
  733. //
  734. // close what we open
  735. //
  736. ZwClose(deviceParameterHandle);
  737. if (NT_SUCCESS(status)) {
  738. break;
  739. }
  740. }
  741. return status;
  742. } // PciIdeXGetDeviceParameter
  743. VOID
  744. PciIdeUnload(
  745. IN PDRIVER_OBJECT DriverObject
  746. )
  747. /*++
  748. Routine Description:
  749. get ready to be unloaded
  750. Arguments:
  751. DriverObject - the driver being unloaded
  752. Return Value:
  753. none
  754. --*/
  755. {
  756. PAGED_CODE();
  757. DebugPrint ((1, "PciIde: unloading...\n"));
  758. ASSERT (DriverObject->DeviceObject == NULL);
  759. return;
  760. } // PciIdeUnload
  761. NTSTATUS
  762. PciIdeXSyncSendIrp (
  763. IN PDEVICE_OBJECT TargetDeviceObject,
  764. IN PIO_STACK_LOCATION IrpSp,
  765. IN OUT OPTIONAL PIO_STATUS_BLOCK IoStatus
  766. )
  767. {
  768. PIO_STACK_LOCATION newIrpSp;
  769. PIRP newIrp;
  770. KEVENT event;
  771. NTSTATUS status;
  772. ASSERT (TargetDeviceObject);
  773. ASSERT (IrpSp);
  774. PAGED_CODE();
  775. //
  776. // Allocate an IRP for below
  777. //
  778. newIrp = IoAllocateIrp (TargetDeviceObject->StackSize, FALSE); // Get stack size from PDO
  779. if (newIrp == NULL) {
  780. DebugPrint ((0, "PciIdeXSyncSendIrp: Unable to get allocate an irp"));
  781. return STATUS_NO_MEMORY;
  782. }
  783. newIrpSp = IoGetNextIrpStackLocation(newIrp);
  784. RtlMoveMemory (newIrpSp, IrpSp, sizeof (*IrpSp));
  785. if (IoStatus) {
  786. newIrp->IoStatus.Status = IoStatus->Status;
  787. } else {
  788. newIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  789. }
  790. KeInitializeEvent(&event,
  791. NotificationEvent,
  792. FALSE);
  793. IoSetCompletionRoutine (
  794. newIrp,
  795. PciIdeXSyncSendIrpCompletionRoutine,
  796. &event,
  797. TRUE,
  798. TRUE,
  799. TRUE);
  800. status = IoCallDriver (TargetDeviceObject, newIrp);
  801. if (status == STATUS_PENDING) {
  802. status = KeWaitForSingleObject(&event,
  803. Executive,
  804. KernelMode,
  805. FALSE,
  806. NULL);
  807. }
  808. status = newIrp->IoStatus.Status;
  809. if (IoStatus) {
  810. *IoStatus = newIrp->IoStatus;
  811. }
  812. IoFreeIrp (newIrp);
  813. return status;
  814. } // PciIdeXSyncSendIrp
  815. NTSTATUS
  816. PciIdeXSyncSendIrpCompletionRoutine (
  817. IN PDEVICE_OBJECT DeviceObject,
  818. IN PIRP Irp,
  819. IN PVOID Context
  820. )
  821. {
  822. PKEVENT event = Context;
  823. KeSetEvent(
  824. event,
  825. EVENT_INCREMENT,
  826. FALSE
  827. );
  828. return STATUS_MORE_PROCESSING_REQUIRED;
  829. } // IdePortSyncSendIrpCompletionRoutine
  830. #if DBG
  831. NTSTATUS
  832. PciIdeXSaveDeviceParameter (
  833. IN PVOID DeviceExtension,
  834. IN PWSTR ParameterName,
  835. IN ULONG ParameterValue
  836. )
  837. /*++
  838. Routine Description:
  839. save a devnode registry parameter
  840. Arguments:
  841. FdoExtension - FDO Extension
  842. ParameterName - parameter name to save
  843. ParameterValuse - parameter value to save
  844. Return Value:
  845. NT Status
  846. --*/
  847. {
  848. NTSTATUS status;
  849. HANDLE deviceParameterHandle;
  850. PCTRLFDO_EXTENSION fdoExtension = ((PCTRLFDO_EXTENSION) DeviceExtension) - 1;
  851. PAGED_CODE();
  852. //
  853. // open the given parameter
  854. //
  855. status = IoOpenDeviceRegistryKey(fdoExtension->AttacheePdo,
  856. PLUGPLAY_REGKEY_DRIVER,
  857. KEY_WRITE,
  858. &deviceParameterHandle);
  859. if(!NT_SUCCESS(status)) {
  860. DebugPrint((1,
  861. "PciIdeXSaveDeviceParameter: IoOpenDeviceRegistryKey() returns 0x%x\n",
  862. status));
  863. return status;
  864. }
  865. //
  866. // write the parameter value
  867. //
  868. status = RtlWriteRegistryValue(
  869. RTL_REGISTRY_HANDLE,
  870. (PWSTR) deviceParameterHandle,
  871. ParameterName,
  872. REG_DWORD,
  873. &ParameterValue,
  874. sizeof (ParameterValue)
  875. );
  876. if(!NT_SUCCESS(status)) {
  877. DebugPrint((1,
  878. "PciIdeXSaveDeviceParameter: RtlWriteRegistryValue() returns 0x%x\n",
  879. status));
  880. }
  881. //
  882. // close what we open
  883. //
  884. ZwClose(deviceParameterHandle);
  885. return status;
  886. } // IdePortSaveDeviceParameter
  887. #endif // DBG