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.

455 lines
12 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. bulkusb.c
  5. Abstract:
  6. Bulk USB device driver for Intel 82930 USB test board
  7. Main module
  8. Author:
  9. Environment:
  10. kernel mode only
  11. Notes:
  12. Copyright (c) 2000 Microsoft Corporation.
  13. All Rights Reserved.
  14. --*/
  15. #include "bulkusb.h"
  16. #include "bulkpnp.h"
  17. #include "bulkpwr.h"
  18. #include "bulkdev.h"
  19. #include "bulkwmi.h"
  20. #include "bulkusr.h"
  21. #include "bulkrwr.h"
  22. //
  23. // Globals
  24. //
  25. GLOBALS Globals;
  26. ULONG DebugLevel = 1;
  27. NTSTATUS
  28. DriverEntry(
  29. IN PDRIVER_OBJECT DriverObject,
  30. IN PUNICODE_STRING UniRegistryPath
  31. );
  32. VOID
  33. BulkUsb_DriverUnload(
  34. IN PDRIVER_OBJECT DriverObject
  35. );
  36. NTSTATUS
  37. BulkUsb_AddDevice(
  38. IN PDRIVER_OBJECT DriverObject,
  39. IN PDEVICE_OBJECT PhysicalDeviceObject
  40. );
  41. #ifdef PAGE_CODE
  42. #ifdef ALLOC_PRAGMA
  43. #pragma alloc_text(INIT, DriverEntry)
  44. #pragma alloc_text(PAGE, BulkUsb_DriverUnload)
  45. #endif
  46. #endif
  47. NTSTATUS
  48. DriverEntry(
  49. IN PDRIVER_OBJECT DriverObject,
  50. IN PUNICODE_STRING UniRegistryPath
  51. )
  52. /*++
  53. Routine Description:
  54. Installable driver initialization entry point.
  55. This entry point is called directly by the I/O system.
  56. Arguments:
  57. DriverObject - pointer to driver object
  58. RegistryPath - pointer to a unicode string representing the path to driver
  59. specific key in the registry.
  60. Return Values:
  61. NT status value
  62. --*/
  63. {
  64. NTSTATUS ntStatus;
  65. PUNICODE_STRING registryPath;
  66. //
  67. // initialization of variables
  68. //
  69. registryPath = &Globals.BulkUsb_RegistryPath;
  70. //
  71. // Allocate pool to hold a null-terminated copy of the path.
  72. // Safe in paged pool since all registry routines execute at
  73. // PASSIVE_LEVEL.
  74. //
  75. registryPath->MaximumLength = UniRegistryPath->Length + sizeof(UNICODE_NULL);
  76. registryPath->Length = UniRegistryPath->Length;
  77. registryPath->Buffer = ExAllocatePool(PagedPool,
  78. registryPath->MaximumLength);
  79. if (!registryPath->Buffer) {
  80. BulkUsb_DbgPrint(1, ("Failed to allocate memory for registryPath\n"));
  81. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  82. goto DriverEntry_Exit;
  83. }
  84. RtlZeroMemory (registryPath->Buffer,
  85. registryPath->MaximumLength);
  86. RtlMoveMemory (registryPath->Buffer,
  87. UniRegistryPath->Buffer,
  88. UniRegistryPath->Length);
  89. ntStatus = STATUS_SUCCESS;
  90. //
  91. // Initialize the driver object with this driver's entry points.
  92. //
  93. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = BulkUsb_DispatchDevCtrl;
  94. DriverObject->MajorFunction[IRP_MJ_POWER] = BulkUsb_DispatchPower;
  95. DriverObject->MajorFunction[IRP_MJ_PNP] = BulkUsb_DispatchPnP;
  96. DriverObject->MajorFunction[IRP_MJ_CREATE] = BulkUsb_DispatchCreate;
  97. DriverObject->MajorFunction[IRP_MJ_CLOSE] = BulkUsb_DispatchClose;
  98. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = BulkUsb_DispatchClean;
  99. DriverObject->MajorFunction[IRP_MJ_READ] =
  100. DriverObject->MajorFunction[IRP_MJ_WRITE] = BulkUsb_DispatchReadWrite;
  101. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = BulkUsb_DispatchSysCtrl;
  102. DriverObject->DriverUnload = BulkUsb_DriverUnload;
  103. DriverObject->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE)
  104. BulkUsb_AddDevice;
  105. DriverEntry_Exit:
  106. return ntStatus;
  107. }
  108. VOID
  109. BulkUsb_DriverUnload(
  110. IN PDRIVER_OBJECT DriverObject
  111. )
  112. /*++
  113. Description:
  114. This function will free the memory allocations in DriverEntry.
  115. Arguments:
  116. DriverObject - pointer to driver object
  117. Return:
  118. None
  119. --*/
  120. {
  121. PUNICODE_STRING registryPath;
  122. BulkUsb_DbgPrint(3, ("BulkUsb_DriverUnload - begins\n"));
  123. registryPath = &Globals.BulkUsb_RegistryPath;
  124. if(registryPath->Buffer) {
  125. ExFreePool(registryPath->Buffer);
  126. registryPath->Buffer = NULL;
  127. }
  128. BulkUsb_DbgPrint(3, ("BulkUsb_DriverUnload - ends\n"));
  129. return;
  130. }
  131. NTSTATUS
  132. BulkUsb_AddDevice(
  133. IN PDRIVER_OBJECT DriverObject,
  134. IN PDEVICE_OBJECT PhysicalDeviceObject
  135. )
  136. /*++
  137. Description:
  138. Arguments:
  139. DriverObject - Store the pointer to the object representing us.
  140. PhysicalDeviceObject - Pointer to the device object created by the
  141. undelying bus driver.
  142. Return:
  143. STATUS_SUCCESS - if successful
  144. STATUS_UNSUCCESSFUL - otherwise
  145. --*/
  146. {
  147. NTSTATUS ntStatus;
  148. PDEVICE_OBJECT deviceObject;
  149. PDEVICE_EXTENSION deviceExtension;
  150. POWER_STATE state;
  151. KIRQL oldIrql;
  152. BulkUsb_DbgPrint(3, ("BulkUsb_AddDevice - begins\n"));
  153. deviceObject = NULL;
  154. ntStatus = IoCreateDevice(
  155. DriverObject, // our driver object
  156. sizeof(DEVICE_EXTENSION), // extension size for us
  157. NULL, // name for this device
  158. FILE_DEVICE_UNKNOWN,
  159. FILE_AUTOGENERATED_DEVICE_NAME, // device characteristics
  160. FALSE, // Not exclusive
  161. &deviceObject); // Our device object
  162. if(!NT_SUCCESS(ntStatus)) {
  163. //
  164. // returning failure here prevents the entire stack from functioning,
  165. // but most likely the rest of the stack will not be able to create
  166. // device objects either, so it is still OK.
  167. //
  168. BulkUsb_DbgPrint(1, ("Failed to create device object\n"));
  169. return ntStatus;
  170. }
  171. //
  172. // Initialize the device extension
  173. //
  174. deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
  175. deviceExtension->FunctionalDeviceObject = deviceObject;
  176. deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
  177. deviceObject->Flags |= DO_DIRECT_IO;
  178. //
  179. // initialize the device state lock and set the device state
  180. //
  181. KeInitializeSpinLock(&deviceExtension->DevStateLock);
  182. INITIALIZE_PNP_STATE(deviceExtension);
  183. //
  184. //initialize OpenHandleCount
  185. //
  186. deviceExtension->OpenHandleCount = 0;
  187. //
  188. // Initialize the selective suspend variables
  189. //
  190. KeInitializeSpinLock(&deviceExtension->IdleReqStateLock);
  191. deviceExtension->IdleReqPend = 0;
  192. deviceExtension->PendingIdleIrp = NULL;
  193. //
  194. // Hold requests until the device is started
  195. //
  196. deviceExtension->QueueState = HoldRequests;
  197. //
  198. // Initialize the queue and the queue spin lock
  199. //
  200. InitializeListHead(&deviceExtension->NewRequestsQueue);
  201. KeInitializeSpinLock(&deviceExtension->QueueLock);
  202. //
  203. // Initialize the remove event to not-signaled.
  204. //
  205. KeInitializeEvent(&deviceExtension->RemoveEvent,
  206. SynchronizationEvent,
  207. FALSE);
  208. //
  209. // Initialize the stop event to signaled.
  210. // This event is signaled when the OutstandingIO becomes 1
  211. //
  212. KeInitializeEvent(&deviceExtension->StopEvent,
  213. SynchronizationEvent,
  214. TRUE);
  215. //
  216. // OutstandingIo count biased to 1.
  217. // Transition to 0 during remove device means IO is finished.
  218. // Transition to 1 means the device can be stopped
  219. //
  220. deviceExtension->OutStandingIO = 1;
  221. KeInitializeSpinLock(&deviceExtension->IOCountLock);
  222. //
  223. // Delegating to WMILIB
  224. //
  225. ntStatus = BulkUsb_WmiRegistration(deviceExtension);
  226. if(!NT_SUCCESS(ntStatus)) {
  227. BulkUsb_DbgPrint(1, ("BulkUsb_WmiRegistration failed with %X\n", ntStatus));
  228. IoDeleteDevice(deviceObject);
  229. return ntStatus;
  230. }
  231. //
  232. // set the flags as underlying PDO
  233. //
  234. if(PhysicalDeviceObject->Flags & DO_POWER_PAGABLE) {
  235. deviceObject->Flags |= DO_POWER_PAGABLE;
  236. }
  237. //
  238. // Typically, the function driver for a device is its
  239. // power policy owner, although for some devices another
  240. // driver or system component may assume this role.
  241. // Set the initial power state of the device, if known, by calling
  242. // PoSetPowerState.
  243. //
  244. deviceExtension->DevPower = PowerDeviceD0;
  245. deviceExtension->SysPower = PowerSystemWorking;
  246. state.DeviceState = PowerDeviceD0;
  247. PoSetPowerState(deviceObject, DevicePowerState, state);
  248. //
  249. // attach our driver to device stack
  250. // The return value of IoAttachDeviceToDeviceStack is the top of the
  251. // attachment chain. This is where all the IRPs should be routed.
  252. //
  253. deviceExtension->TopOfStackDeviceObject =
  254. IoAttachDeviceToDeviceStack(deviceObject,
  255. PhysicalDeviceObject);
  256. if(NULL == deviceExtension->TopOfStackDeviceObject) {
  257. BulkUsb_WmiDeRegistration(deviceExtension);
  258. IoDeleteDevice(deviceObject);
  259. return STATUS_NO_SUCH_DEVICE;
  260. }
  261. //
  262. // Register device interfaces
  263. //
  264. ntStatus = IoRegisterDeviceInterface(deviceExtension->PhysicalDeviceObject,
  265. &GUID_CLASS_I82930_BULK,
  266. NULL,
  267. &deviceExtension->InterfaceName);
  268. if(!NT_SUCCESS(ntStatus)) {
  269. BulkUsb_WmiDeRegistration(deviceExtension);
  270. IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
  271. IoDeleteDevice(deviceObject);
  272. return ntStatus;
  273. }
  274. if(IoIsWdmVersionAvailable(1, 0x20)) {
  275. deviceExtension->WdmVersion = WinXpOrBetter;
  276. }
  277. else if(IoIsWdmVersionAvailable(1, 0x10)) {
  278. deviceExtension->WdmVersion = Win2kOrBetter;
  279. }
  280. else if(IoIsWdmVersionAvailable(1, 0x5)) {
  281. deviceExtension->WdmVersion = WinMeOrBetter;
  282. }
  283. else if(IoIsWdmVersionAvailable(1, 0x0)) {
  284. deviceExtension->WdmVersion = Win98OrBetter;
  285. }
  286. deviceExtension->SSRegistryEnable = 0;
  287. deviceExtension->SSEnable = 0;
  288. //
  289. // WinXP only
  290. // check the registry flag -
  291. // whether the device should selectively
  292. // suspend when idle
  293. //
  294. if(WinXpOrBetter == deviceExtension->WdmVersion) {
  295. BulkUsb_GetRegistryDword(BULKUSB_REGISTRY_PARAMETERS_PATH,
  296. L"BulkUsbEnable",
  297. &deviceExtension->SSRegistryEnable);
  298. if(deviceExtension->SSRegistryEnable) {
  299. //
  300. // initialize DPC
  301. //
  302. KeInitializeDpc(&deviceExtension->DeferredProcCall,
  303. DpcRoutine,
  304. deviceObject);
  305. //
  306. // initialize the timer.
  307. // the DPC and the timer in conjunction,
  308. // monitor the state of the device to
  309. // selectively suspend the device.
  310. //
  311. KeInitializeTimerEx(&deviceExtension->Timer,
  312. NotificationTimer);
  313. //
  314. // Initialize the NoDpcWorkItemPendingEvent to signaled state.
  315. // This event is cleared when a Dpc is fired and signaled
  316. // on completion of the work-item.
  317. //
  318. KeInitializeEvent(&deviceExtension->NoDpcWorkItemPendingEvent,
  319. NotificationEvent,
  320. TRUE);
  321. //
  322. // Initialize the NoIdleReqPendEvent to ensure that the idle request
  323. // is indeed complete before we unload the drivers.
  324. //
  325. KeInitializeEvent(&deviceExtension->NoIdleReqPendEvent,
  326. NotificationEvent,
  327. TRUE);
  328. }
  329. }
  330. //
  331. // Clear the DO_DEVICE_INITIALIZING flag.
  332. // Note: Do not clear this flag until the driver has set the
  333. // device power state and the power DO flags.
  334. //
  335. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  336. BulkUsb_DbgPrint(3, ("BulkUsb_AddDevice - ends\n"));
  337. return ntStatus;
  338. }