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.

482 lines
16 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation All Rights Reserved
  3. Module Name:
  4. lower.c
  5. Abstract:
  6. This module contains the lower filter specific IRP handlers.
  7. The functions in this module all have the same prototypes and so
  8. are documented here:
  9. NTSTATUS
  10. HpsXxxLower(
  11. IN PIRP Irp,
  12. IN PHPS_DEVICE_EXTENSION Extension,
  13. IN PIO_STACK_LOCATION IrpStack
  14. )
  15. Arguments:
  16. Irp - a pointer to the IRP currently being handled
  17. Extension - a pointer to the device extension of this device. In
  18. some functions this is of type PHPS_COMMON_EXTENSION if this
  19. reduced extension is all that is required.
  20. IrpStack - the current IRP stack location
  21. Return Value:
  22. an NT status code
  23. Environment:
  24. Kernel Mode
  25. Revision History:
  26. Davis Walker (dwalker) Oct 1 2000
  27. --*/
  28. #include "hpsp.h"
  29. NTSTATUS
  30. HpsStartLower(
  31. IN PIRP Irp,
  32. IN PHPS_DEVICE_EXTENSION Extension,
  33. IN PIO_STACK_LOCATION IrpStack
  34. )
  35. {
  36. NTSTATUS status;
  37. status = HpsDeferProcessing((PHPS_COMMON_EXTENSION)Extension,
  38. Irp
  39. );
  40. if (!NT_SUCCESS(status)) {
  41. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  42. }
  43. status = IoSetDeviceInterfaceState(Extension->SymbolicName,
  44. TRUE // enable
  45. );
  46. Irp->IoStatus.Status = status;
  47. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  48. return status;
  49. }
  50. NTSTATUS
  51. HpsRemoveLower(
  52. IN PIRP Irp,
  53. IN PHPS_DEVICE_EXTENSION Extension,
  54. IN PIO_STACK_LOCATION IrpStack
  55. )
  56. {
  57. ULONG i;
  58. IoSetDeviceInterfaceState(Extension->SymbolicName,
  59. FALSE
  60. );
  61. IoWMIRegistrationControl(Extension->Self,
  62. WMIREG_ACTION_DEREGISTER
  63. );
  64. if (Extension->SoftDevices) {
  65. for (i=0; i<Extension->HwInitData.NumSlots;i++) {
  66. if (Extension->SoftDevices[i]) {
  67. ExFreePool(Extension->SoftDevices[i]);
  68. }
  69. }
  70. ExFreePool(Extension->SoftDevices);
  71. }
  72. if (Extension->SymbolicName) {
  73. ExFreePool(Extension->SymbolicName);
  74. }
  75. if (Extension->WmiEventContext) {
  76. ExFreePool(Extension->WmiEventContext);
  77. }
  78. return HpsRemoveCommon(Irp,
  79. (PHPS_COMMON_EXTENSION)Extension,
  80. IrpStack
  81. );
  82. }
  83. NTSTATUS
  84. HpsStopLower(
  85. IN PIRP Irp,
  86. IN PHPS_DEVICE_EXTENSION Extension,
  87. IN PIO_STACK_LOCATION IrpStack
  88. )
  89. {
  90. IoSetDeviceInterfaceState(Extension->SymbolicName,
  91. FALSE
  92. );
  93. return HpsPassIrp(Irp,
  94. (PHPS_COMMON_EXTENSION)Extension,
  95. IrpStack
  96. );
  97. }
  98. NTSTATUS
  99. HpsQueryInterfaceLower(
  100. IN PIRP Irp,
  101. IN PHPS_DEVICE_EXTENSION Extension,
  102. IN PIO_STACK_LOCATION IrpStack
  103. )
  104. {
  105. NTSTATUS status = STATUS_NOT_SUPPORTED;
  106. PHPS_REGISTER_INTERRUPT_INTERFACE interruptInterface;
  107. PHPS_MEMORY_INTERFACE memInterface;
  108. PHPS_PING_INTERFACE pingInterface;
  109. if (HPS_EQUAL_GUID(IrpStack->Parameters.QueryInterface.InterfaceType,
  110. &GUID_BUS_INTERFACE_STANDARD
  111. )) {
  112. if (Extension->UseConfig) {
  113. //
  114. // Someone is requesting a bus interface standard. We need to capture
  115. // this request and fill it in with our own.
  116. //
  117. DbgPrintEx(DPFLTR_HPS_ID,
  118. DPFLTR_INFO_LEVEL,
  119. "HPS-IRP QueryInterface for Bus Interface\n"
  120. );
  121. if (IrpStack->Parameters.QueryInterface.Size <
  122. sizeof(BUS_INTERFACE_STANDARD)) {
  123. status = STATUS_NOT_SUPPORTED;
  124. } else {
  125. //
  126. // This is a query for access to config space, which we need to trap
  127. // after PCI has filled it in.
  128. //
  129. status = HpsDeferProcessing((PHPS_COMMON_EXTENSION)Extension,
  130. Irp
  131. );
  132. if (NT_SUCCESS(status)) {
  133. // PDO filled in the interface, so we can trap and modify it.
  134. status = HpsTrapBusInterface(Extension,
  135. IrpStack
  136. );
  137. //
  138. // the status of the trap operation is the status of the IRP.
  139. // complete the IRP with whatever status that happens to be.
  140. //
  141. Irp->IoStatus.Status = status;
  142. }
  143. //
  144. // Complete the deferred IRP
  145. //
  146. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  147. return status;
  148. }
  149. }
  150. } else if (HPS_EQUAL_GUID(IrpStack->Parameters.QueryInterface.InterfaceType,
  151. &GUID_HPS_MEMORY_INTERFACE
  152. )) {
  153. if (IrpStack->Parameters.QueryInterface.Size <
  154. sizeof(HPS_MEMORY_INTERFACE)) {
  155. status = STATUS_NOT_SUPPORTED;
  156. } else {
  157. memInterface = (PHPS_MEMORY_INTERFACE)
  158. IrpStack->Parameters.QueryInterface.Interface;
  159. memInterface->Context = Extension;
  160. memInterface->InterfaceReference = HpsMemoryInterfaceReference;
  161. memInterface->InterfaceDereference = HpsMemoryInterfaceDereference;
  162. memInterface->ReadRegister = HpsReadRegister;
  163. memInterface->WriteRegister = HpsWriteRegister;
  164. memInterface->InterfaceReference(memInterface->Context);
  165. status = STATUS_SUCCESS;
  166. }
  167. } else if (HPS_EQUAL_GUID(IrpStack->Parameters.QueryInterface.InterfaceType,
  168. &GUID_HPS_PING_INTERFACE
  169. )) {
  170. DbgPrintEx(DPFLTR_HPS_ID,
  171. DPFLTR_INFO_LEVEL,
  172. "HPS-IRP QueryInterface for Ping Interface\n"
  173. );
  174. if (IrpStack->Parameters.QueryInterface.Size <
  175. sizeof(HPS_PING_INTERFACE)) {
  176. status = STATUS_NOT_SUPPORTED;
  177. } else {
  178. //
  179. // The upper filter is querying to see if there is another
  180. // instance of the driver below it. Inform it that there is.
  181. //
  182. pingInterface = (PHPS_PING_INTERFACE)
  183. IrpStack->Parameters.QueryInterface.Interface;
  184. if (pingInterface->SenderDevice != Extension->Self) {
  185. pingInterface->Context = Extension->Self;
  186. pingInterface->InterfaceReference = HpsGenericInterfaceReference;
  187. pingInterface->InterfaceDereference = HpsGenericInterfaceDereference;
  188. }
  189. pingInterface->InterfaceReference(pingInterface->Context);
  190. status = STATUS_SUCCESS;
  191. }
  192. } else if (HPS_EQUAL_GUID(IrpStack->Parameters.QueryInterface.InterfaceType,
  193. &GUID_REGISTER_INTERRUPT_INTERFACE
  194. )) {
  195. DbgPrintEx(DPFLTR_HPS_ID,
  196. DPFLTR_INFO_LEVEL,
  197. "HPS-IRP QueryInterface for Interrupt Interface\n"
  198. );
  199. if (IrpStack->Parameters.QueryInterface.Size <
  200. sizeof(HPS_REGISTER_INTERRUPT_INTERFACE)) {
  201. status = STATUS_NOT_SUPPORTED;
  202. } else {
  203. //
  204. // The hotplug driver is querying for an interface that allows it
  205. // to register a fake interrupt. Provide the interface.
  206. //
  207. interruptInterface = (PHPS_REGISTER_INTERRUPT_INTERFACE)
  208. IrpStack->Parameters.QueryInterface.Interface;
  209. interruptInterface->InterfaceReference = HpsGenericInterfaceReference;
  210. interruptInterface->InterfaceDereference = HpsGenericInterfaceDereference;
  211. interruptInterface->ConnectISR = HpsConnectInterrupt;
  212. interruptInterface->DisconnectISR = HpsDisconnectInterrupt;
  213. interruptInterface->SyncExecutionRoutine = HpsSynchronizeExecution;
  214. interruptInterface->Context = Extension;
  215. status = STATUS_SUCCESS;
  216. }
  217. }
  218. if (NT_SUCCESS(status)) {
  219. Irp->IoStatus.Status = status;
  220. }
  221. IoSkipCurrentIrpStackLocation(Irp);
  222. return IoCallDriver(Extension->LowerDO,
  223. Irp
  224. );
  225. }
  226. NTSTATUS
  227. HpsWriteConfigLower(
  228. IN PIRP Irp,
  229. IN PHPS_DEVICE_EXTENSION Extension,
  230. IN PIO_STACK_LOCATION IrpStack
  231. )
  232. {
  233. if (Extension->UseConfig) {
  234. DbgPrintEx(DPFLTR_HPS_ID,
  235. DPFLTR_INFO_LEVEL,
  236. "HPS-IRP Write Config at offset %d for length %d\n",
  237. IrpStack->Parameters.ReadWriteConfig.Offset,
  238. IrpStack->Parameters.ReadWriteConfig.Length
  239. );
  240. if (IS_SUBSET(IrpStack->Parameters.ReadWriteConfig.Offset,
  241. IrpStack->Parameters.ReadWriteConfig.Length,
  242. Extension->ConfigOffset,
  243. sizeof(SHPC_CONFIG_SPACE)
  244. )) {
  245. //
  246. // Handle the IRP internally. The request lines up with the config space
  247. // offset of the SHPC capability.
  248. //
  249. HpsWriteConfig (Extension,
  250. IrpStack->Parameters.ReadWriteConfig.Buffer,
  251. IrpStack->Parameters.ReadWriteConfig.Offset,
  252. IrpStack->Parameters.ReadWriteConfig.Length
  253. );
  254. //
  255. // Since the write may have altered the register set, we have to recopy the
  256. // result into the buffer before passing the IRP to Soft PCI
  257. //
  258. RtlCopyMemory(IrpStack->Parameters.ReadWriteConfig.Buffer,
  259. (PUCHAR)&Extension->ConfigSpace + IrpStack->Parameters.ReadWriteConfig.Offset,
  260. IrpStack->Parameters.ReadWriteConfig.Length
  261. );
  262. }
  263. }
  264. //
  265. // We've handled the IRP internally, but we want to keep SoftPCI in the loop,
  266. // so pass it down.
  267. //
  268. IoSkipCurrentIrpStackLocation(Irp);
  269. return IoCallDriver (Extension->LowerDO,
  270. Irp
  271. );
  272. }
  273. NTSTATUS
  274. HpsDeviceControlLower(
  275. PIRP Irp,
  276. PHPS_DEVICE_EXTENSION Extension,
  277. PIO_STACK_LOCATION IrpStack
  278. )
  279. {
  280. NTSTATUS status;
  281. PHPTEST_WRITE_CONFIG writeDescriptor;
  282. PHPTEST_BRIDGE_INFO bridgeInfo;
  283. switch (IrpStack->Parameters.DeviceIoControl.IoControlCode) {
  284. case IOCTL_HPS_READ_REGISTERS:
  285. //
  286. // Usermode wants a copy of the register set. This is a test
  287. // IOCTL
  288. //
  289. DbgPrintEx(DPFLTR_HPS_ID,
  290. DPFLTR_INFO_LEVEL,
  291. "HPS-Device Control IOCTL_HPS_READ_REGISTERS\n"
  292. );
  293. if (!Irp->AssociatedIrp.SystemBuffer ||
  294. (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
  295. sizeof(SHPC_WORKING_REGISTERS))) {
  296. //
  297. // We didn't get the buffer we expected. Fail.
  298. //
  299. return STATUS_INVALID_PARAMETER;
  300. }
  301. RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
  302. &Extension->RegisterSet,
  303. sizeof(SHPC_WORKING_REGISTERS)
  304. );
  305. Irp->IoStatus.Information = sizeof(SHPC_WORKING_REGISTERS);
  306. status = STATUS_SUCCESS;
  307. break;
  308. case IOCTL_HPS_READ_CAPABILITY:
  309. //
  310. // Usermode wants a copy of the SHPC capability structure. This
  311. // is a test IOCTL
  312. //
  313. DbgPrintEx(DPFLTR_HPS_ID,
  314. DPFLTR_INFO_LEVEL,
  315. "HPS-Device Control IOCTL_HPS_READ_CAPABILITY\n"
  316. );
  317. if (!Irp->AssociatedIrp.SystemBuffer ||
  318. (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
  319. sizeof(SHPC_CONFIG_SPACE))) {
  320. //
  321. // We didn't get the buffer we expected. Fail.
  322. //
  323. return STATUS_INVALID_PARAMETER;
  324. }
  325. HpsHandleDirectReadConfig(Extension,
  326. PCI_WHICHSPACE_CONFIG,
  327. Irp->AssociatedIrp.SystemBuffer,
  328. Extension->ConfigOffset,
  329. sizeof(SHPC_CONFIG_SPACE)
  330. );
  331. Irp->IoStatus.Information = sizeof(SHPC_CONFIG_SPACE);
  332. status = STATUS_SUCCESS;
  333. break;
  334. case IOCTL_HPS_WRITE_CAPABILITY:
  335. //
  336. // Usermode is overwriting the SHPC capability structure. This
  337. // is a test IOCTL.
  338. //
  339. DbgPrintEx(DPFLTR_HPS_ID,
  340. DPFLTR_INFO_LEVEL,
  341. "HPS-Device Control IOCTL_HPS_WRITE_CAPABILITY\n"
  342. );
  343. if (!Irp->AssociatedIrp.SystemBuffer ||
  344. (IrpStack->Parameters.DeviceIoControl.InputBufferLength <
  345. sizeof(HPTEST_WRITE_CONFIG))) {
  346. //
  347. // We didn't get the buffer we expected. Fail.
  348. //
  349. return STATUS_INVALID_PARAMETER;
  350. }
  351. writeDescriptor = (PHPTEST_WRITE_CONFIG)Irp->AssociatedIrp.SystemBuffer;
  352. HpsHandleDirectWriteConfig(Extension,
  353. PCI_WHICHSPACE_CONFIG,
  354. (PUCHAR)&writeDescriptor->Buffer + writeDescriptor->Offset,
  355. Extension->ConfigOffset+writeDescriptor->Offset,
  356. writeDescriptor->Length
  357. );
  358. status = STATUS_SUCCESS;
  359. break;
  360. case IOCTL_HPS_BRIDGE_INFO:
  361. //
  362. // Usermode is requesting the bus/dev/func for this device for
  363. // identification purposes. This is a test IOCTL.
  364. //
  365. DbgPrintEx(DPFLTR_HPS_ID,
  366. DPFLTR_INFO_LEVEL,
  367. "HPS-Device Control IOCTL_HPS_BRIDGE_INFO\n"
  368. );
  369. if (!Irp->AssociatedIrp.SystemBuffer ||
  370. (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
  371. sizeof(HPTEST_BRIDGE_INFO))) {
  372. //
  373. // We didn't get the buffer we expected. Fail.
  374. //
  375. return STATUS_INVALID_PARAMETER;
  376. }
  377. bridgeInfo = (PHPTEST_BRIDGE_INFO)Irp->AssociatedIrp.SystemBuffer;
  378. HpsGetBridgeInfo(Extension,
  379. bridgeInfo
  380. );
  381. Irp->IoStatus.Information = sizeof(HPTEST_BRIDGE_INFO);
  382. status = STATUS_SUCCESS;
  383. break;
  384. default:
  385. status = STATUS_NOT_SUPPORTED;
  386. }
  387. return status;
  388. }