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.

758 lines
19 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. service.c
  5. Abstract:
  6. DLL Services provided by usbport.sys
  7. This module conatins the load and initialization code
  8. used by the port driver to link up with the miniport.
  9. Environment:
  10. kernel mode only
  11. Notes:
  12. Revision History:
  13. 6-20-99 : created
  14. --*/
  15. #define USBPORT
  16. #include "common.h"
  17. extern USBPORT_SPIN_LOCK USBPORT_GlobalsSpinLock;
  18. extern LIST_ENTRY USBPORT_USB2fdoList;
  19. extern LIST_ENTRY USBPORT_USB1fdoList;
  20. #ifdef ALLOC_PRAGMA
  21. //#pragma alloc_text(PAGE, USBD_InternalGetInterfaceLength)
  22. #endif
  23. NTSTATUS
  24. DllUnload(
  25. VOID
  26. )
  27. {
  28. extern BOOLEAN USBPORT_GlobalInitialized;
  29. USBPORT_KdPrint((1, "'unloading USBPORT\n"));
  30. // this will cause us to re-init even if our
  31. // image is not unloaded or the data segment
  32. // is not re-initialized (this happens on win9x)
  33. if (USBPORT_GlobalInitialized && USBPORT_DummyUsbdExtension) {
  34. FREE_POOL(NULL, USBPORT_DummyUsbdExtension);
  35. }
  36. USBPORT_GlobalInitialized = FALSE;
  37. USBPORT_DummyUsbdExtension = NULL;
  38. return STATUS_SUCCESS;
  39. }
  40. ULONG
  41. USBPORT_GetHciMn(
  42. )
  43. {
  44. return USB_HCI_MN;
  45. }
  46. PDEVICE_OBJECT
  47. USBPORT_FindUSB2Controller(
  48. PDEVICE_OBJECT CcFdoDeviceObject
  49. )
  50. /*++
  51. Routine Description:
  52. Given a companion controller find the FDO for the parent
  53. Arguments:
  54. Return Value:
  55. --*/
  56. {
  57. PDEVICE_OBJECT deviceObject = NULL;
  58. PDEVICE_EXTENSION devExt;
  59. KIRQL irql;
  60. PLIST_ENTRY listEntry;
  61. PDEVICE_EXTENSION ccExt;
  62. GET_DEVICE_EXT(ccExt, CcFdoDeviceObject);
  63. ASSERT_FDOEXT(ccExt);
  64. KeAcquireSpinLock(&USBPORT_GlobalsSpinLock.sl, &irql);
  65. GET_HEAD_LIST(USBPORT_USB2fdoList, listEntry);
  66. while (listEntry &&
  67. listEntry != &USBPORT_USB2fdoList) {
  68. devExt = (PDEVICE_EXTENSION) CONTAINING_RECORD(
  69. listEntry,
  70. struct _DEVICE_EXTENSION,
  71. Fdo.ControllerLink);
  72. // find the USB 2 controller assocaited with this CC
  73. if (devExt->Fdo.BusNumber == ccExt->Fdo.BusNumber &&
  74. devExt->Fdo.BusDevice == ccExt->Fdo.BusDevice) {
  75. deviceObject = devExt->HcFdoDeviceObject;
  76. break;
  77. }
  78. listEntry = devExt->Fdo.ControllerLink.Flink;
  79. }
  80. KeReleaseSpinLock(&USBPORT_GlobalsSpinLock.sl, irql);
  81. return deviceObject;
  82. }
  83. BOOLEAN
  84. USBPORT_IsCCForFdo(
  85. PDEVICE_OBJECT Usb2FdoDeviceObject,
  86. PDEVICE_EXTENSION CcExt
  87. )
  88. /*++
  89. --*/
  90. {
  91. PDEVICE_EXTENSION usb2Ext;
  92. GET_DEVICE_EXT(usb2Ext, Usb2FdoDeviceObject);
  93. ASSERT_FDOEXT(usb2Ext);
  94. ASSERT_FDOEXT(CcExt);
  95. if (usb2Ext->Fdo.BusNumber == CcExt->Fdo.BusNumber &&
  96. usb2Ext->Fdo.BusDevice == CcExt->Fdo.BusDevice) {
  97. return TRUE;
  98. }
  99. return FALSE;
  100. }
  101. PDEVICE_RELATIONS
  102. USBPORT_FindCompanionControllers(
  103. PDEVICE_OBJECT Usb2FdoDeviceObject,
  104. BOOLEAN ReferenceObjects,
  105. BOOLEAN ReturnFdo
  106. )
  107. /*++
  108. Routine Description:
  109. Given a companion controller find the FDO for the parent
  110. Arguments:
  111. Return Value:
  112. --*/
  113. {
  114. PDEVICE_OBJECT deviceObject = NULL;
  115. PDEVICE_EXTENSION devExt;
  116. PLIST_ENTRY listEntry;
  117. KIRQL irql;
  118. PDEVICE_RELATIONS deviceRelations = NULL;
  119. ULONG count = 0;
  120. KeAcquireSpinLock(&USBPORT_GlobalsSpinLock.sl, &irql);
  121. GET_HEAD_LIST(USBPORT_USB1fdoList, listEntry);
  122. while (listEntry &&
  123. listEntry != &USBPORT_USB1fdoList) {
  124. devExt = (PDEVICE_EXTENSION) CONTAINING_RECORD(
  125. listEntry,
  126. struct _DEVICE_EXTENSION,
  127. Fdo.ControllerLink);
  128. if (TEST_FDO_FLAG(devExt, USBPORT_FDOFLAG_IS_CC) &&
  129. USBPORT_IsCCForFdo(Usb2FdoDeviceObject, devExt)) {
  130. count++;
  131. }
  132. listEntry = devExt->Fdo.ControllerLink.Flink;
  133. } /* while */
  134. LOGENTRY(NULL, Usb2FdoDeviceObject, LOG_MISC, 'fccR', count, 0,
  135. Usb2FdoDeviceObject);
  136. if (count) {
  137. ALLOC_POOL_OSOWNED(deviceRelations,
  138. NonPagedPool,
  139. sizeof(*deviceRelations)*count);
  140. }
  141. if (deviceRelations != NULL) {
  142. deviceRelations->Count = count;
  143. count = 0;
  144. GET_HEAD_LIST(USBPORT_USB1fdoList, listEntry);
  145. while (listEntry &&
  146. listEntry != &USBPORT_USB1fdoList) {
  147. devExt = (PDEVICE_EXTENSION) CONTAINING_RECORD(
  148. listEntry,
  149. struct _DEVICE_EXTENSION,
  150. Fdo.ControllerLink);
  151. if (TEST_FDO_FLAG(devExt, USBPORT_FDOFLAG_IS_CC) &&
  152. USBPORT_IsCCForFdo(Usb2FdoDeviceObject, devExt)) {
  153. USBPORT_ASSERT(count < deviceRelations->Count);
  154. deviceRelations->Objects[count] = devExt->Fdo.PhysicalDeviceObject;
  155. if (ReferenceObjects) {
  156. ObReferenceObject(deviceRelations->Objects[count]);
  157. }
  158. if (ReturnFdo) {
  159. deviceRelations->Objects[count] =
  160. devExt->HcFdoDeviceObject;
  161. }
  162. USBPORT_KdPrint((1, "'Found CC %x\n", deviceRelations->Objects[count]));
  163. count++;
  164. }
  165. listEntry = devExt->Fdo.ControllerLink.Flink;
  166. } /* while */
  167. }
  168. KeReleaseSpinLock(&USBPORT_GlobalsSpinLock.sl, irql);
  169. return deviceRelations;
  170. }
  171. VOID
  172. USBPORT_RegisterUSB2fdo(
  173. PDEVICE_OBJECT FdoDeviceObject
  174. )
  175. /*++
  176. Routine Description:
  177. tracks an instance of a USB 2 device
  178. Arguments:
  179. Return Value:
  180. --*/
  181. {
  182. PDEVICE_EXTENSION devExt;
  183. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  184. ASSERT_FDOEXT(devExt);
  185. SET_FDO_FLAG(devExt, USBPORT_FDOFLAG_FDO_REGISTERED);
  186. ExInterlockedInsertTailList(&USBPORT_USB2fdoList,
  187. &devExt->Fdo.ControllerLink,
  188. &USBPORT_GlobalsSpinLock.sl);
  189. }
  190. VOID
  191. USBPORT_RegisterUSB1fdo(
  192. PDEVICE_OBJECT FdoDeviceObject
  193. )
  194. /*++
  195. Routine Description:
  196. tracks an instance of a USB 2 device
  197. Arguments:
  198. Return Value:
  199. --*/
  200. {
  201. PDEVICE_EXTENSION devExt;
  202. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  203. ASSERT_FDOEXT(devExt);
  204. SET_FDO_FLAG(devExt, USBPORT_FDOFLAG_FDO_REGISTERED);
  205. ExInterlockedInsertTailList(&USBPORT_USB1fdoList,
  206. &devExt->Fdo.ControllerLink,
  207. &USBPORT_GlobalsSpinLock.sl);
  208. }
  209. VOID
  210. USBPORT_DeregisterUSB2fdo(
  211. PDEVICE_OBJECT FdoDeviceObject
  212. )
  213. /*++
  214. Routine Description:
  215. tracks an instance of a USB 2 device
  216. Arguments:
  217. Return Value:
  218. --*/
  219. {
  220. PDEVICE_EXTENSION devExt;
  221. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  222. ASSERT_FDOEXT(devExt);
  223. USBPORT_ASSERT(devExt->Fdo.ControllerLink.Flink != NULL);
  224. USBPORT_ASSERT(devExt->Fdo.ControllerLink.Blink != NULL);
  225. USBPORT_InterlockedRemoveEntryList(&devExt->Fdo.ControllerLink,
  226. &USBPORT_GlobalsSpinLock.sl);
  227. CLEAR_FDO_FLAG(devExt, USBPORT_FDOFLAG_FDO_REGISTERED);
  228. devExt->Fdo.ControllerLink.Blink = NULL;
  229. devExt->Fdo.ControllerLink.Flink = NULL;
  230. }
  231. VOID
  232. USBPORT_DeregisterUSB1fdo(
  233. PDEVICE_OBJECT FdoDeviceObject
  234. )
  235. /*++
  236. Routine Description:
  237. tracks an instance of a USB 2 device
  238. Arguments:
  239. Return Value:
  240. --*/
  241. {
  242. PDEVICE_EXTENSION devExt;
  243. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  244. ASSERT_FDOEXT(devExt);
  245. USBPORT_ASSERT(devExt->Fdo.ControllerLink.Flink != NULL);
  246. USBPORT_ASSERT(devExt->Fdo.ControllerLink.Blink != NULL);
  247. USBPORT_InterlockedRemoveEntryList(&devExt->Fdo.ControllerLink,
  248. &USBPORT_GlobalsSpinLock.sl);
  249. CLEAR_FDO_FLAG(devExt, USBPORT_FDOFLAG_FDO_REGISTERED);
  250. devExt->Fdo.ControllerLink.Blink = NULL;
  251. devExt->Fdo.ControllerLink.Flink = NULL;
  252. }
  253. NTSTATUS
  254. USBPORT_RegisterUSBPortDriver(
  255. PDRIVER_OBJECT DriverObject,
  256. ULONG MiniportHciVersion,
  257. PUSBPORT_REGISTRATION_PACKET RegistrationPacket
  258. )
  259. /*++
  260. Routine Description:
  261. Called from DriverEntry by miniport.
  262. The opposite of this function is the DriverObject->Unload
  263. routine which we hook.
  264. Arguments:
  265. Return Value:
  266. --*/
  267. {
  268. PUSBPORT_MINIPORT_DRIVER miniportDriver;
  269. extern LIST_ENTRY USBPORT_MiniportDriverList;
  270. extern USBPORT_SPIN_LOCK USBPORT_GlobalsSpinLock;
  271. extern BOOLEAN USBPORT_GlobalInitialized;
  272. NTSTATUS ntStatus;
  273. extern ULONG USB2LIB_HcContextSize;
  274. extern ULONG USB2LIB_EndpointContextSize;
  275. extern ULONG USB2LIB_TtContextSize;
  276. ULONG regPacketLength = 0;
  277. // get global registry parameters, check on every
  278. // miniport load
  279. GET_GLOBAL_DEBUG_PARAMETERS();
  280. USBPORT_KdPrint((1, "'USBPORT Universal Serial Bus Host Controller Port Driver.\n"));
  281. USBPORT_KdPrint((1, "'Using USBDI version %x\n", USBDI_VERSION));
  282. USBPORT_KdPrint((2, "'Registration Packet %x\n", RegistrationPacket));
  283. DEBUG_BREAK();
  284. if (USBPORT_GlobalInitialized == FALSE) {
  285. // do some first time loaded stuff
  286. USBPORT_GlobalInitialized = TRUE;
  287. InitializeListHead(&USBPORT_MiniportDriverList);
  288. InitializeListHead(&USBPORT_USB2fdoList);
  289. InitializeListHead(&USBPORT_USB1fdoList);
  290. KeInitializeSpinLock(&USBPORT_GlobalsSpinLock.sl);
  291. ALLOC_POOL_Z(USBPORT_DummyUsbdExtension,
  292. NonPagedPool,
  293. USBPORT_DUMMY_USBD_EXT_SIZE);
  294. if (USBPORT_DummyUsbdExtension == NULL) {
  295. return STATUS_INSUFFICIENT_RESOURCES;
  296. }
  297. USB2LIB_InitializeLib(
  298. &USB2LIB_HcContextSize,
  299. &USB2LIB_EndpointContextSize,
  300. &USB2LIB_TtContextSize,
  301. USB2LIB_DbgPrint,
  302. USB2LIB_DbgBreak);
  303. }
  304. // non paged because we will call the function pointers
  305. // thru this structure
  306. ALLOC_POOL_Z(miniportDriver,
  307. NonPagedPool,
  308. sizeof(*miniportDriver));
  309. if (miniportDriver == NULL) {
  310. return STATUS_INSUFFICIENT_RESOURCES;
  311. }
  312. USBPORT_KdPrint((1, "'miniport driver: %x\n", miniportDriver));
  313. miniportDriver->DriverObject = DriverObject;
  314. //
  315. // Create dispatch points for appropriate irps
  316. //
  317. DriverObject->MajorFunction[IRP_MJ_CREATE]=
  318. DriverObject->MajorFunction[IRP_MJ_CLOSE] =
  319. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
  320. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] =
  321. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
  322. DriverObject->MajorFunction[IRP_MJ_PNP] =
  323. DriverObject->MajorFunction[IRP_MJ_POWER] = USBPORT_Dispatch;
  324. DriverObject->DriverExtension->AddDevice = USBPORT_PnPAddDevice;
  325. miniportDriver->MiniportUnload = DriverObject->DriverUnload;
  326. DriverObject->DriverUnload = USBPORT_Unload;
  327. // set up the registration packet and return our function pointers
  328. // miniport.
  329. // bump this for pre-release versions of the stack to prevent
  330. // compatibilty problms with pre-release miniports
  331. #define USBHDCDI_MIN_REV_SUPPORTED 100
  332. // remeber the registered version
  333. miniportDriver->HciVersion = MiniportHciVersion;
  334. if (MiniportHciVersion < USBHDCDI_MIN_REV_SUPPORTED) {
  335. return STATUS_UNSUCCESSFUL;
  336. }
  337. // do our version (1) stuff
  338. if (MiniportHciVersion >= 100) {
  339. // validate the registrtion packet
  340. // if (RegistrationPacket->
  341. // USBPORT_KdPrint((0, "'Miniport Registrtaion Packet is invalid!\n"));
  342. // DEBUG_BREAK();
  343. // ntStatus = STATUS_UNSUCCESSFUL;
  344. // goto USBPORT_RegisterUSBPortDriver_Done;
  345. // }
  346. // do our version (1) stuff
  347. RegistrationPacket->USBPORTSVC_DbgPrint =
  348. USBPORTSVC_DbgPrint;
  349. RegistrationPacket->USBPORTSVC_TestDebugBreak =
  350. USBPORTSVC_TestDebugBreak;
  351. RegistrationPacket->USBPORTSVC_AssertFailure =
  352. USBPORTSVC_AssertFailure;
  353. RegistrationPacket->USBPORTSVC_GetMiniportRegistryKeyValue =
  354. USBPORTSVC_GetMiniportRegistryKeyValue;
  355. RegistrationPacket->USBPORTSVC_InvalidateRootHub =
  356. USBPORTSVC_InvalidateRootHub;
  357. RegistrationPacket->USBPORTSVC_InvalidateEndpoint =
  358. USBPORTSVC_InvalidateEndpoint;
  359. RegistrationPacket->USBPORTSVC_CompleteTransfer =
  360. USBPORTSVC_CompleteTransfer;
  361. RegistrationPacket->USBPORTSVC_CompleteIsoTransfer =
  362. USBPORTSVC_CompleteIsoTransfer;
  363. RegistrationPacket->USBPORTSVC_LogEntry =
  364. USBPORTSVC_LogEntry;
  365. RegistrationPacket->USBPORTSVC_MapHwPhysicalToVirtual =
  366. USBPORTSVC_MapHwPhysicalToVirtual;
  367. RegistrationPacket->USBPORTSVC_RequestAsyncCallback =
  368. USBPORTSVC_RequestAsyncCallback;
  369. RegistrationPacket->USBPORTSVC_ReadWriteConfigSpace =
  370. USBPORTSVC_ReadWriteConfigSpace;
  371. RegistrationPacket->USBPORTSVC_Wait =
  372. USBPORTSVC_Wait;
  373. RegistrationPacket->USBPORTSVC_InvalidateController =
  374. USBPORTSVC_InvalidateController;
  375. RegistrationPacket->USBPORTSVC_BugCheck =
  376. USBPORTSVC_BugCheck;
  377. RegistrationPacket->USBPORTSVC_NotifyDoubleBuffer =
  378. USBPORTSVC_NotifyDoubleBuffer;
  379. regPacketLength = sizeof(USBPORT_REGISTRATION_PACKET_V1);
  380. USBPORT_KdPrint((1, "'Miniport Version 1 support\n"));
  381. }
  382. // do our version (2) stuff, this is a superset of version 1
  383. if (MiniportHciVersion >= 200) {
  384. USBPORT_KdPrint((1, "'Miniport Version 2 support\n"));
  385. regPacketLength = sizeof(USBPORT_REGISTRATION_PACKET);
  386. }
  387. // save a copy of the packet
  388. RtlCopyMemory(&miniportDriver->RegistrationPacket,
  389. RegistrationPacket,
  390. regPacketLength);
  391. // put this driver on our list
  392. ExInterlockedInsertTailList(&USBPORT_MiniportDriverList,
  393. &miniportDriver->ListEntry,
  394. &USBPORT_GlobalsSpinLock.sl);
  395. ntStatus = STATUS_SUCCESS;
  396. TEST_PATH(ntStatus, FAILED_REGISTERUSBPORT);
  397. USBPORT_RegisterUSBPortDriver_Done:
  398. return ntStatus;
  399. }
  400. /*
  401. Misc Miniport callable services
  402. */
  403. #if 0
  404. BOOLEAN
  405. USBPORTSVC_SyncWait(
  406. PDEVICE_DATA DeviceData,
  407. xxx WaitCompletePollFunction,
  408. ULONG MaxMillisecondsToWait
  409. )
  410. /*++
  411. Routine Description:
  412. Service exported to miniports to wait on the HW
  413. Arguments:
  414. Return Value:
  415. Returns true if the time expired before the WaitCompletePoll
  416. function returns true
  417. --*/
  418. {
  419. PDEVICE_EXTENSION devExt;
  420. PDEVICE_OBJECT fdoDeviceObject;
  421. LARGE_INTEGER finishTime, currentTime;
  422. DEVEXT_FROM_DEVDATA(devExt, DeviceData);
  423. ASSERT_FDOEXT(devExt);
  424. fdoDeviceObject = devExt->HcFdoDeviceObject;
  425. LOGENTRY(NULL, fdoDeviceObject, LOG_MISC, 'synW', 0, 0, 0);
  426. KeQuerySystemTime(&finishTime);
  427. // convert millisecs to nanosecs (10 ^-3 -> 10^-9)
  428. nonosecs.QuadPart = MaxMillisecondsToWait * 1000000
  429. // figure when we quit
  430. finishTime.QuadPart += nonosecs.QuadPart
  431. while (!MP_WaitPollFunction(xxx)) {
  432. KeQuerySystemTime(&currentTime);
  433. if (currentTime.QuadPart >= finishTime.QuadPart) {
  434. LOGENTRY(NULL, fdoDeviceObject, LOG_MISC, 'syTO', 0, 0, 0);
  435. return TRUE;
  436. }
  437. }
  438. return FALSE;
  439. }
  440. #endif
  441. typedef struct _USBPORT_ASYNC_TIMER {
  442. ULONG Sig;
  443. PDEVICE_OBJECT FdoDeviceObject;
  444. KTIMER Timer;
  445. KDPC Dpc;
  446. PMINIPORT_CALLBACK MpCallbackFunction;
  447. UCHAR MiniportContext[0];
  448. } USBPORT_ASYNC_TIMER, *PUSBPORT_ASYNC_TIMER;
  449. VOID
  450. USBPORT_AsyncTimerDpc(
  451. PKDPC Dpc,
  452. PVOID DeferredContext,
  453. PVOID SystemArgument1,
  454. PVOID SystemArgument2
  455. )
  456. /*++
  457. Routine Description:
  458. This routine runs at DISPATCH_LEVEL IRQL.
  459. Arguments:
  460. Dpc - Pointer to the DPC object.
  461. DeferredContext - supplies FdoDeviceObject.
  462. SystemArgument1 - not used.
  463. SystemArgument2 - not used.
  464. Return Value:
  465. None.
  466. --*/
  467. {
  468. PDEVICE_OBJECT fdoDeviceObject;
  469. KIRQL irql;
  470. PUSBPORT_ASYNC_TIMER asyncTimer = DeferredContext;
  471. PDEVICE_EXTENSION devExt;
  472. fdoDeviceObject = asyncTimer->FdoDeviceObject;
  473. GET_DEVICE_EXT(devExt, fdoDeviceObject);
  474. ASSERT_FDOEXT(devExt);
  475. LOGENTRY(NULL, fdoDeviceObject, LOG_RH, 'ayTM', fdoDeviceObject, asyncTimer, 0);
  476. // call the miniport
  477. asyncTimer->Sig = SIG_MP_TIMR;
  478. asyncTimer->MpCallbackFunction(devExt->Fdo.MiniportDeviceData,
  479. &asyncTimer->MiniportContext[0]);
  480. DECREMENT_PENDING_REQUEST_COUNT(fdoDeviceObject, NULL);
  481. FREE_POOL(fdoDeviceObject, asyncTimer);
  482. }
  483. VOID
  484. USBPORTSVC_RequestAsyncCallback(
  485. PDEVICE_DATA DeviceData,
  486. ULONG MilliSeconds,
  487. PVOID Context,
  488. ULONG ContextLength,
  489. PMINIPORT_CALLBACK CallbackFunction
  490. )
  491. /*++
  492. Routine Description:
  493. Service exported to miniports to wait on the HW
  494. and to time asynchronous events
  495. Arguments:
  496. Return Value:
  497. None.
  498. --*/
  499. {
  500. PDEVICE_EXTENSION devExt;
  501. PDEVICE_OBJECT fdoDeviceObject;
  502. LONG dueTime;
  503. ULONG timerIncerent;
  504. PUSBPORT_ASYNC_TIMER asyncTimer;
  505. SIZE_T siz;
  506. DEVEXT_FROM_DEVDATA(devExt, DeviceData);
  507. ASSERT_FDOEXT(devExt);
  508. fdoDeviceObject = devExt->HcFdoDeviceObject;
  509. // allocate a timer
  510. siz = sizeof(USBPORT_ASYNC_TIMER) + ContextLength;
  511. ALLOC_POOL_Z(asyncTimer, NonPagedPool, siz);
  512. LOGENTRY(NULL, fdoDeviceObject, LOG_RH, 'asyT', 0, siz, asyncTimer);
  513. // if this fails the miniport will be waiting a very long
  514. // time.
  515. if (asyncTimer != NULL) {
  516. if (ContextLength) {
  517. RtlCopyMemory(&asyncTimer->MiniportContext[0],
  518. Context,
  519. ContextLength);
  520. }
  521. asyncTimer->MpCallbackFunction = CallbackFunction;
  522. asyncTimer->FdoDeviceObject = fdoDeviceObject;
  523. KeInitializeTimer(&asyncTimer->Timer);
  524. KeInitializeDpc(&asyncTimer->Dpc,
  525. USBPORT_AsyncTimerDpc,
  526. asyncTimer);
  527. timerIncerent = KeQueryTimeIncrement() - 1;
  528. dueTime =
  529. -1 * (timerIncerent + MILLISECONDS_TO_100_NS_UNITS(MilliSeconds));
  530. KeSetTimer(&asyncTimer->Timer,
  531. RtlConvertLongToLargeInteger(dueTime),
  532. &asyncTimer->Dpc);
  533. INCREMENT_PENDING_REQUEST_COUNT(fdoDeviceObject, NULL);
  534. }
  535. }