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.

449 lines
12 KiB

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