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.

373 lines
9.6 KiB

  1. /*
  2. *************************************************************************
  3. * File: PNP.C
  4. *
  5. * Module: HID1394.SYS
  6. * HID (Human Input Device) minidriver for IEEE 1394 devices.
  7. *
  8. * Copyright (c) 1998 Microsoft Corporation
  9. *
  10. *
  11. * Author: ervinp
  12. *
  13. *************************************************************************
  14. */
  15. #include <wdm.h>
  16. #include <hidport.h>
  17. #include <1394.h>
  18. #include "hid1394.h"
  19. #include "debug.h"
  20. #ifdef ALLOC_PRAGMA
  21. #pragma alloc_text(PAGE, HIDT_PnP)
  22. #pragma alloc_text(PAGE, HIDT_StartDevice)
  23. #pragma alloc_text(PAGE, HIDT_StopDevice)
  24. #pragma alloc_text(PAGE, HIDT_RemoveDevice)
  25. #pragma alloc_text(PAGE, HIDT_AbortPendingRequests)
  26. #endif
  27. /*
  28. ************************************************************
  29. * HIDT_PnP
  30. ************************************************************
  31. *
  32. * Process PnP IRPs sent to this device.
  33. *
  34. */
  35. NTSTATUS HIDT_PnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  36. {
  37. NTSTATUS ntStatus = STATUS_SUCCESS;
  38. PIO_STACK_LOCATION irpSp;
  39. PDEVICE_EXTENSION DeviceExtension;
  40. PAGED_CODE();
  41. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
  42. irpSp = IoGetCurrentIrpStackLocation (Irp);
  43. switch(irpSp->MinorFunction){
  44. case IRP_MN_START_DEVICE:
  45. ntStatus = HIDT_StartDevice(DeviceObject);
  46. break;
  47. case IRP_MN_STOP_DEVICE:
  48. ntStatus = HIDT_StopDevice(DeviceObject);
  49. break;
  50. case IRP_MN_REMOVE_DEVICE:
  51. ntStatus = HIDT_RemoveDevice(DeviceObject);
  52. break;
  53. }
  54. if (NT_SUCCESS(ntStatus)){
  55. /*
  56. * Our processing has succeeded.
  57. * So pass this IRP down to the next driver.
  58. */
  59. IoCopyCurrentIrpStackLocationToNext(Irp);
  60. IoSetCompletionRoutine(Irp,
  61. HIDT_PnpCompletion,
  62. DeviceExtension, // context
  63. TRUE,
  64. TRUE,
  65. TRUE );
  66. ntStatus = IoCallDriver(GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);
  67. }
  68. else {
  69. ASSERT(NT_SUCCESS(ntStatus));
  70. Irp->IoStatus.Status = ntStatus;
  71. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  72. }
  73. return ntStatus;
  74. }
  75. /*
  76. ************************************************************
  77. * HIDT_Power
  78. ************************************************************
  79. *
  80. * Process Power IRPs sent to this device.
  81. *
  82. */
  83. NTSTATUS HIDT_Power(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  84. {
  85. NTSTATUS status;
  86. IoCopyCurrentIrpStackLocationToNext(Irp);
  87. status = PoCallDriver(GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);
  88. return status;
  89. }
  90. /*
  91. ************************************************************
  92. * HIDT_StartDevice
  93. ************************************************************
  94. *
  95. *
  96. */
  97. NTSTATUS HIDT_StartDevice(IN PDEVICE_OBJECT DeviceObject)
  98. {
  99. PDEVICE_EXTENSION DeviceExtension;
  100. PAGED_CODE();
  101. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
  102. DeviceExtension->DeviceState = DEVICE_STATE_STARTING;
  103. DeviceExtension->NumPendingRequests = 0;
  104. KeInitializeEvent( &DeviceExtension->AllRequestsCompleteEvent,
  105. NotificationEvent,
  106. FALSE);
  107. return STATUS_SUCCESS;
  108. }
  109. /*
  110. ************************************************************
  111. * HIDT_InitDevice
  112. ************************************************************
  113. *
  114. * Get the device information and attempt to initialize a configuration
  115. * for a device. If we cannot identify this as a valid HID device or
  116. * configure the device, our start device function is failed.
  117. *
  118. * Note: This function is called from the PnP completion routine,
  119. * so it cannot be pageable.
  120. */
  121. NTSTATUS HIDT_InitDevice(IN PDEVICE_OBJECT DeviceObject)
  122. {
  123. NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
  124. // BUGBUG FINISH
  125. return ntStatus;
  126. }
  127. /*
  128. ************************************************************
  129. * HIDT_StopDevice
  130. ************************************************************
  131. *
  132. *
  133. */
  134. NTSTATUS HIDT_StopDevice(IN PDEVICE_OBJECT DeviceObject)
  135. {
  136. ULONG Size;
  137. NTSTATUS ntStatus = STATUS_SUCCESS;
  138. PDEVICE_EXTENSION DeviceExtension;
  139. PAGED_CODE();
  140. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
  141. DeviceExtension->DeviceState = DEVICE_STATE_STOPPING;
  142. /*
  143. * Abort all pending IO on the device.
  144. * We do an extra decrement here, which causes the
  145. * NumPendingRequests to eventually go to -1, which causes
  146. * AllRequestsCompleteEvent to get set.
  147. * NumPendingRequests will get reset to 0 when we re-start.
  148. */
  149. HIDT_AbortPendingRequests(DeviceObject);
  150. HIDT_DecrementPendingRequestCount(DeviceExtension);
  151. KeWaitForSingleObject( &DeviceExtension->AllRequestsCompleteEvent,
  152. Executive,
  153. KernelMode,
  154. FALSE,
  155. NULL );
  156. // BUGBUG FINISH - select NULL configuration
  157. if (!NT_SUCCESS(ntStatus)){
  158. /*
  159. * We will not pass this IRP down,
  160. * so our completion routine will not set the device's
  161. * state to DEVICE_STATE_STOPPED; so set it here.
  162. */
  163. ASSERT(NT_SUCCESS(ntStatus));
  164. DeviceExtension->DeviceState = DEVICE_STATE_STOPPED;
  165. }
  166. return ntStatus;
  167. }
  168. /*
  169. ************************************************************
  170. * HIDT_AbortPendingRequests
  171. ************************************************************
  172. *
  173. *
  174. */
  175. NTSTATUS HIDT_AbortPendingRequests(IN PDEVICE_OBJECT DeviceObject)
  176. {
  177. NTSTATUS status = STATUS_UNSUCCESSFUL;
  178. PAGED_CODE();
  179. // BUGBUG FINISH
  180. ASSERT(NT_SUCCESS(status));
  181. return status;
  182. }
  183. /*
  184. ************************************************************
  185. * HIDT_PnpCompletion
  186. ************************************************************
  187. *
  188. */
  189. NTSTATUS HIDT_PnpCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
  190. {
  191. PDEVICE_EXTENSION DeviceExtension;
  192. PIO_STACK_LOCATION irpSp;
  193. NTSTATUS status;
  194. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
  195. irpSp = IoGetCurrentIrpStackLocation (Irp);
  196. status = Irp->IoStatus.Status;
  197. switch(irpSp->MinorFunction){
  198. case IRP_MN_START_DEVICE:
  199. if (NT_SUCCESS(status)) {
  200. DeviceExtension->DeviceState = DEVICE_STATE_RUNNING;
  201. status = HIDT_InitDevice(DeviceObject);
  202. if (!NT_SUCCESS(status)) {
  203. DBGWARN(("HIDT_InitDevice failed; failing IRP_MN_START_DEVICE."));
  204. DeviceExtension->DeviceState = DEVICE_STATE_START_FAILED;
  205. Irp->IoStatus.Status = status;
  206. }
  207. }
  208. else {
  209. ASSERT(NT_SUCCESS(status));
  210. DeviceExtension->DeviceState = DEVICE_STATE_START_FAILED;
  211. }
  212. break;
  213. case IRP_MN_STOP_DEVICE:
  214. DeviceExtension->DeviceState = DEVICE_STATE_STOPPED;
  215. /*
  216. * Release resources
  217. */
  218. // BUGBUG FINISH
  219. break;
  220. case IRP_MN_QUERY_CAPABILITIES:
  221. /*
  222. * The lower driver set the capabilities flags for this device.
  223. * Since all 1394 devices are hot-unpluggable,
  224. * add the SurpriseRemovalOK bit.
  225. */
  226. if (NT_SUCCESS(status)){
  227. irpSp->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
  228. }
  229. break;
  230. }
  231. /*
  232. * If the lower driver returned PENDING, mark our stack location as
  233. * pending also. This prevents the IRP's thread from being freed if
  234. * the client's call returns pending.
  235. */
  236. if (Irp->PendingReturned){
  237. IoMarkIrpPending(Irp);
  238. }
  239. return status;
  240. }
  241. /*
  242. ************************************************************
  243. * HIDT_RemoveDevice
  244. ************************************************************
  245. *
  246. *
  247. */
  248. NTSTATUS HIDT_RemoveDevice(IN PDEVICE_OBJECT DeviceObject)
  249. {
  250. NTSTATUS ntStatus = STATUS_SUCCESS;
  251. PDEVICE_EXTENSION DeviceExtension;
  252. ULONG oldDeviceState;
  253. PAGED_CODE();
  254. //
  255. // Get a pointer to the device extension
  256. //
  257. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
  258. //
  259. // Set device state, this prevents new IOs from starting
  260. //
  261. oldDeviceState = DeviceExtension->DeviceState;
  262. DeviceExtension->DeviceState = DEVICE_STATE_REMOVING;
  263. //
  264. // Cancel any outstanding IRPs if the device was running
  265. //
  266. if (oldDeviceState == DEVICE_STATE_RUNNING){
  267. ntStatus = HIDT_AbortPendingRequests( DeviceObject );
  268. /*
  269. * Note: RemoveDevice does an extra decrement, so we complete
  270. * the REMOVE IRP on the transition to -1, whether this
  271. * happens in RemoveDevice itself or subsequently while
  272. * RemoveDevice is waiting for this event to fire.
  273. */
  274. HIDT_DecrementPendingRequestCount(DeviceExtension);
  275. KeWaitForSingleObject( &DeviceExtension->AllRequestsCompleteEvent,
  276. Executive,
  277. KernelMode,
  278. FALSE,
  279. NULL );
  280. }
  281. else if (oldDeviceState == DEVICE_STATE_STOPPING){
  282. ASSERT(!(PVOID)"PnP IRPs are not synchronized! -- got REMOVE_DEVICE before STOP_DEVICE completed!");
  283. }
  284. else {
  285. ASSERT(DeviceExtension->NumPendingRequests == -1);
  286. }
  287. //
  288. // Release any resources
  289. //
  290. // BUGBUG FINISH
  291. ntStatus = STATUS_SUCCESS;
  292. return ntStatus;
  293. }