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.

963 lines
23 KiB

  1. /*++
  2. Copyright (c) 1995,1996 Microsoft Corporation
  3. :ts=4
  4. Module Name:
  5. hub.c
  6. Abstract:
  7. The UHC driver for USB, this module contains the root hub
  8. interface code.
  9. Environment:
  10. kernel mode only
  11. Notes:
  12. Revision History:
  13. 2-08-96 : created
  14. --*/
  15. #include "wdm.h"
  16. #include "stdarg.h"
  17. #include "stdio.h"
  18. #include "usbdi.h"
  19. #include "hcdi.h"
  20. #include "uhcd.h"
  21. typedef struct _ROOT_HUB_TIMER {
  22. KTIMER Timer;
  23. KDPC Dpc;
  24. PDEVICE_OBJECT DeviceObject;
  25. PROOTHUB_TIMER_ROUTINE TimerRoutine;
  26. PVOID Context;
  27. } ROOT_HUB_TIMER, *PROOT_HUB_TIMER;
  28. NTSTATUS
  29. UHCD_RootHub_OpenEndpoint(
  30. IN PDEVICE_OBJECT DeviceObject,
  31. IN PIRP Irp,
  32. IN PHCD_URB Urb
  33. )
  34. /*++
  35. Routine Description:
  36. This function is called at Dispatch level
  37. to process commands bound for the root hub.
  38. Arguments:
  39. DeviceObject - pointer to a device object
  40. Irp - pointer to an I/O Request Packet
  41. Urb - urb for this request
  42. Return Value:
  43. NT status code.
  44. --*/
  45. {
  46. NTSTATUS ntStatus = STATUS_SUCCESS;
  47. PDEVICE_EXTENSION deviceExtension;
  48. PUHCD_ENDPOINT endpoint;
  49. PUSB_ENDPOINT_DESCRIPTOR endpointDescriptor;
  50. UHCD_KdPrint((2, "'enter UHCD_RootHub_OpenEndpoint\n"));
  51. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  52. LOGENTRY(LOG_MISC, 'rhOE', deviceExtension, 0, 0);
  53. endpoint = (PUHCD_ENDPOINT) GETHEAP(NonPagedPool,
  54. sizeof(UHCD_ENDPOINT));
  55. if (endpoint) {
  56. //
  57. // initialize endpoint structures, state variables.
  58. //
  59. // start endpoint initialization
  60. RtlZeroMemory(endpoint, sizeof(*endpoint));
  61. endpoint->Sig = SIG_EP;
  62. SET_EPFLAG(endpoint, EPFLAG_ROOT_HUB);
  63. endpointDescriptor = Urb->HcdUrbOpenEndpoint.EndpointDescriptor;
  64. endpoint->MaxRequests = MAX_REQUESTS(endpointDescriptor,
  65. endpoint->EndpointFlags);
  66. ntStatus = UHCD_FinishInitializeEndpoint(DeviceObject,
  67. endpoint,
  68. endpointDescriptor,
  69. Urb);
  70. if (NT_SUCCESS(ntStatus)) {
  71. Urb->HcdUrbOpenEndpoint.HcdEndpoint = endpoint;
  72. URB_HEADER(Urb).Status = USBD_STATUS_SUCCESS;
  73. //
  74. // if this is the interrupt endpoint start a timer Dpc to be called
  75. // based on the endpoint polling interval.
  76. //
  77. if (endpoint->Type == USB_ENDPOINT_TYPE_INTERRUPT) {
  78. LARGE_INTEGER dueTime;
  79. LONG period;
  80. endpoint->Interval = endpointDescriptor->bInterval;
  81. UHCD_ASSERT(endpoint->Interval != 0);
  82. deviceExtension->RootHubInterruptEndpoint = endpoint;
  83. KeInitializeTimer(&deviceExtension->RootHubPollTimer);
  84. KeInitializeDpc(&deviceExtension->RootHubPollDpc,
  85. UHCD_RootHubPollDpc,
  86. DeviceObject);
  87. deviceExtension->RootHubPollTimerInitialized = TRUE;
  88. dueTime.QuadPart = -10000 * endpoint->Interval;
  89. period = 100; //every 100 ms
  90. UHCD_KdPrint((2, "'UHCD Poll Interval = (0x%x) %x %x\n",
  91. endpoint->Interval, dueTime.LowPart, dueTime.HighPart));
  92. KeSetTimerEx(&deviceExtension->RootHubPollTimer,
  93. dueTime,
  94. period,
  95. &deviceExtension->RootHubPollDpc);
  96. }
  97. } else {
  98. RETHEAP(endpoint);
  99. }
  100. }
  101. UHCD_CompleteIrp(DeviceObject, Irp, ntStatus, 0, NULL);
  102. UHCD_KdPrint((2, "'exit UHCD_RootHub_OpenEndpoint (%x)\n", ntStatus));
  103. return ntStatus;
  104. }
  105. NTSTATUS
  106. UHCD_RootHub_CloseEndpoint(
  107. IN PDEVICE_OBJECT DeviceObject,
  108. IN PIRP Irp,
  109. IN PHCD_URB Urb
  110. )
  111. /*++
  112. Routine Description:
  113. This function is called at Dispatch level
  114. to process commands bound for the root hub.
  115. Arguments:
  116. DeviceObject - pointer to a device object
  117. Irp - pointer to an I/O Request Packet
  118. Urb - urb for this request
  119. Return Value:
  120. NT status code.
  121. --*/
  122. {
  123. NTSTATUS ntStatus = STATUS_SUCCESS;
  124. PDEVICE_EXTENSION deviceExtension;
  125. PUHCD_ENDPOINT endpoint;
  126. UHCD_KdPrint((2, "'enter UHCD_RootHub_CloseEndpoint\n"));
  127. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  128. endpoint = Urb->HcdUrbCloseEndpoint.HcdEndpoint;
  129. ASSERT_ENDPOINT(endpoint);
  130. if (endpoint->ActiveTransfers[0]) {
  131. URB_HEADER(Urb).Status = USBD_STATUS_ERROR_BUSY;
  132. } else {
  133. if (endpoint == deviceExtension->RootHubInterruptEndpoint) {
  134. // closing the interrupt endpoint,
  135. // this means the root hub is stopped
  136. deviceExtension->RootHubDeviceAddress = USB_DEFAULT_DEVICE_ADDRESS;
  137. // if the timer fires before we cancel it then this
  138. // will stop the polling process
  139. deviceExtension->RootHubInterruptEndpoint = NULL;
  140. // if this is the interrupt endpoint kill the timer here
  141. KeCancelTimer(&deviceExtension->RootHubPollTimer);
  142. }
  143. RETHEAP(endpoint);
  144. URB_HEADER(Urb).Status = USBD_STATUS_SUCCESS;
  145. }
  146. UHCD_CompleteIrp(DeviceObject, Irp, ntStatus, 0, NULL);
  147. UHCD_KdPrint((2, "'exit UHCD_RootHub_CloseEndpoint (%x)\n", ntStatus));
  148. return ntStatus;
  149. }
  150. NTSTATUS
  151. UHCD_RootHub_ControlTransfer(
  152. IN PDEVICE_OBJECT DeviceObject,
  153. IN PIRP Irp,
  154. IN PHCD_URB Urb
  155. )
  156. /*++
  157. Routine Description:
  158. This function is called at Dispatch level
  159. to process commands bound for the root hub.
  160. Arguments:
  161. DeviceObject - pointer to a device object
  162. Irp - pointer to an I/O Request Packet
  163. Urb - urb for this request
  164. Return Value:
  165. NT status code.
  166. --*/
  167. {
  168. NTSTATUS ntStatus = STATUS_SUCCESS;
  169. PDEVICE_EXTENSION deviceExtension;
  170. PUHCD_ENDPOINT endpoint;
  171. RHSTATUS rootHubReturnCode;
  172. KIRQL irql;
  173. PVOID mappedSystemVa;
  174. UHCD_KdPrint((2, "'enter UHCD_RootHub_ControlTransfer\n"));
  175. INCREMENT_PENDING_URB_COUNT(Irp);
  176. IoAcquireCancelSpinLock(&irql);
  177. if (Irp->Cancel) {
  178. TEST_TRAP();
  179. //BUGBUG Irp was canceled
  180. IoReleaseCancelSpinLock(irql);
  181. UHCD_CompleteIrp(DeviceObject, Irp, STATUS_CANCELLED, 0, Urb);
  182. goto UHCD_RootHub_ControlTransfer_Done;
  183. } else {
  184. IoSetCancelRoutine(Irp, NULL);
  185. IoReleaseCancelSpinLock(irql);
  186. }
  187. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  188. endpoint = HCD_AREA(Urb).HcdEndpoint;
  189. ASSERT_ENDPOINT(endpoint);
  190. // NOTE:
  191. // should not get control transfers for anything but
  192. // the default pipe
  193. //
  194. UHCD_ASSERT(endpoint->EndpointAddress == 0);
  195. //BUGBUG no support for linked URBs yet
  196. UHCD_ASSERT(Urb->HcdUrbCommonTransfer.UrbLink == NULL);
  197. if (endpoint->EndpointAddress != 0) {
  198. URB_HEADER(Urb).Status = USBD_STATUS_INVALID_PARAMETER;
  199. } else {
  200. //
  201. // convert transfer buffer from MDL
  202. //
  203. mappedSystemVa =
  204. Urb->HcdUrbCommonTransfer.TransferBufferLength ?
  205. Urb->HcdUrbCommonTransfer.TransferBufferMDL->MappedSystemVa :
  206. NULL;
  207. //UHCD_KdPrint((2, "' Mapped systemVa = 0x%x \n", mappedSystemVa));
  208. rootHubReturnCode =
  209. RootHub_Endpoint0(deviceExtension->RootHub,
  210. (PRH_SETUP)Urb->HcdUrbCommonTransfer.Extension.u.SetupPacket,
  211. (PUCHAR) &deviceExtension->RootHubDeviceAddress,
  212. mappedSystemVa,
  213. &Urb->HcdUrbCommonTransfer.TransferBufferLength);
  214. switch (rootHubReturnCode) {
  215. case RH_SUCCESS:
  216. URB_HEADER(Urb).Status = USBD_STATUS_SUCCESS;
  217. #if DBG
  218. // restore the original transfer buffer address
  219. Urb->HcdUrbCommonTransfer.TransferBuffer =
  220. mappedSystemVa;
  221. #endif
  222. break;
  223. case RH_NAK:
  224. case RH_STALL:
  225. // return stall error and set the endpoint state to
  226. // stalled on the host side
  227. if (endpoint->EndpointFlags & EPFLAG_NO_HALT) {
  228. URB_HEADER(Urb).Status =
  229. USBD_STATUS(USBD_STATUS_STALL_PID)
  230. | USBD_STATUS_ERROR;
  231. } else {
  232. SET_EPFLAG(endpoint, EPFLAG_HOST_HALTED);
  233. URB_HEADER(Urb).Status = USBD_STATUS_STALL_PID;
  234. }
  235. //
  236. // if we get here it is probably a bug in the root hub
  237. // code or the hub driver.
  238. //
  239. UHCD_KdTrap(("Root hub stalled request\n"));
  240. }
  241. }
  242. UHCD_CompleteIrp(DeviceObject, Irp, ntStatus, 0, Urb);
  243. UHCD_RootHub_ControlTransfer_Done:
  244. UHCD_KdPrint((2, "'exit UHCD_RootHub_ControlTransfer (%x)\n", ntStatus));
  245. return ntStatus;
  246. }
  247. NTSTATUS
  248. UHCD_RootHub_InterruptTransfer(
  249. IN PDEVICE_OBJECT DeviceObject,
  250. IN PIRP Irp,
  251. IN PHCD_URB Urb
  252. )
  253. /*++
  254. Routine Description:
  255. This function is called at Dispatch level
  256. to process commands bound for the root hub.
  257. Arguments:
  258. DeviceObject - pointer to a device object
  259. Irp - pointer to an I/O Request Packet
  260. Urb - urb for this request
  261. Return Value:
  262. NT status code.
  263. --*/
  264. {
  265. NTSTATUS ntStatus = STATUS_SUCCESS;
  266. PDEVICE_EXTENSION deviceExtension;
  267. PUHCD_ENDPOINT endpoint;
  268. KIRQL irql;
  269. PHCD_EXTENSION urbWork;
  270. UHCD_KdPrint((2, "'enter UHCD_RootHub_InterruptTransfer\n"));
  271. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  272. INCREMENT_PENDING_URB_COUNT(Irp);
  273. endpoint = HCD_AREA(Urb).HcdEndpoint;
  274. ASSERT_ENDPOINT(endpoint);
  275. ASSERT(HCD_AREA(Urb).HcdExtension != NULL);
  276. urbWork = HCD_AREA(Urb).HcdExtension;
  277. // set interrupt transfer to active.
  278. urbWork->Flags |= UHCD_TRANSFER_ACTIVE;
  279. //
  280. // BUGBUG
  281. // we only allow one transfer outstanding
  282. // at a time here.
  283. //
  284. if (endpoint->ActiveTransfers[0] != NULL) {
  285. TEST_TRAP();
  286. URB_HEADER(Urb).Status = USBD_STATUS_REQUEST_FAILED;
  287. UHCD_CompleteIrp(DeviceObject, Irp, ntStatus, 0, Urb);
  288. } else if (Urb->HcdUrbCommonTransfer.UrbLink != NULL) {
  289. TEST_TRAP();
  290. URB_HEADER(Urb).Status = USBD_STATUS_INVALID_PARAMETER;
  291. UHCD_CompleteIrp(DeviceObject, Irp, ntStatus, 0, Urb);
  292. } else {
  293. endpoint->ActiveTransfers[0] = Urb;
  294. URB_HEADER(Urb).Status = UHCD_STATUS_PENDING_CURRENT;
  295. //
  296. // set up a cancel routine
  297. //
  298. IoAcquireCancelSpinLock(&irql);
  299. if (Irp->Cancel) {
  300. TEST_TRAP();
  301. //BUGBUG Irp was canceled
  302. IoReleaseCancelSpinLock(irql);
  303. // call cancel routine
  304. UHCD_RootHub_InterruptTransferCancel(DeviceObject, Irp);
  305. goto UHCD_RootHub_InterruptTransfer_Done;
  306. } else {
  307. IoSetCancelRoutine(Irp, UHCD_RootHub_InterruptTransferCancel);
  308. IoReleaseCancelSpinLock(irql);
  309. }
  310. ntStatus = STATUS_PENDING;
  311. UHCD_KdPrint((2, "'Pending transfer for root hub\n"));
  312. Irp->IoStatus.Status = ntStatus;
  313. Irp->IoStatus.Information = 0;
  314. IoMarkIrpPending(Irp);
  315. }
  316. UHCD_RootHub_InterruptTransfer_Done:
  317. UHCD_KdPrint((2, "'exit UHCD_RootHub_InterruptTransfer (%x)\n", ntStatus));
  318. return ntStatus;
  319. }
  320. VOID
  321. UHCD_RootHubPoll(
  322. IN PDEVICE_OBJECT DeviceObject,
  323. IN PUHCD_ENDPOINT Endpoint
  324. )
  325. /*++
  326. Routine Description:
  327. This function is called at DPC level from the ISR DPC routine
  328. to process transfers queued to for the root hub.
  329. Arguments:
  330. DeviceObject - pointer to a device object
  331. Return Value:
  332. NT status code.
  333. --*/
  334. {
  335. PHCD_URB urb;
  336. PDEVICE_EXTENSION deviceExtension;
  337. PIRP irp;
  338. RHSTATUS rootHubReturnCode;
  339. BOOLEAN completeIt = TRUE;
  340. KIRQL irql;
  341. PVOID mappedSystemVa;
  342. NTSTATUS status = STATUS_SUCCESS;
  343. //UHCD_KdPrint((2, "'enter UHCD_RootHub_Poll\n"));
  344. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  345. //
  346. // See if we need to poll an endpoint for the
  347. // root hub.
  348. //
  349. // if the current PM state is not 'ON' we will not poll the endpoint
  350. // it means the HC has not fully resumed yet.
  351. //
  352. if (Endpoint &&
  353. deviceExtension->CurrentDevicePowerState == PowerDeviceD0) {
  354. // Yes, poll
  355. ASSERT_ENDPOINT(Endpoint);
  356. urb = Endpoint->ActiveTransfers[0];
  357. // see if we have an abort request
  358. if ((Endpoint->EndpointFlags & EPFLAG_ABORT_PENDING_TRANSFERS) && urb) {
  359. CLR_EPFLAG(Endpoint, EPFLAG_ABORT_PENDING_TRANSFERS);
  360. urb->HcdUrbCommonTransfer.Status =
  361. USBD_STATUS_CANCELED;
  362. completeIt = TRUE;
  363. // BUGBUG do we need the error bit set here?
  364. } else if (urb) {
  365. //
  366. // convert transfer buffer from MDL
  367. //
  368. if (urb->HcdUrbCommonTransfer.TransferBufferLength != 0) {
  369. urb->HcdUrbCommonTransfer.TransferBufferMDL->MdlFlags
  370. |= MDL_MAPPING_CAN_FAIL;
  371. mappedSystemVa =
  372. MmGetSystemAddressForMdl(urb->HcdUrbCommonTransfer
  373. .TransferBufferMDL);
  374. urb->HcdUrbCommonTransfer.TransferBufferMDL->MdlFlags
  375. &= ~MDL_MAPPING_CAN_FAIL;
  376. if (mappedSystemVa == NULL) {
  377. rootHubReturnCode = RH_STALL;
  378. status = STATUS_INSUFFICIENT_RESOURCES;
  379. goto UHCD_RootHubPollError;
  380. }
  381. } else{
  382. mappedSystemVa = NULL;
  383. }
  384. //UHCD_KdPrint((2, "' Mapped systemVa = 0x%x \n", mappedSystemVa));
  385. rootHubReturnCode =
  386. RootHub_Endpoint1(deviceExtension->RootHub, mappedSystemVa,
  387. &urb->HcdUrbCommonTransfer
  388. .TransferBufferLength);
  389. //
  390. // set urb error code if necessary
  391. //
  392. switch (rootHubReturnCode) {
  393. case RH_SUCCESS:
  394. urb->HcdUrbCommonTransfer.Status = USBD_STATUS_SUCCESS;
  395. #if DBG
  396. // restore the original transfer buffer address
  397. urb->HcdUrbCommonTransfer.TransferBuffer =
  398. mappedSystemVa;
  399. #endif
  400. break;
  401. case RH_STALL:
  402. if (Endpoint->EndpointFlags & EPFLAG_NO_HALT) {
  403. // if we dont halt clear th ehalt bit on
  404. // the error code
  405. URB_HEADER(urb).Status =
  406. USBD_STATUS(USBD_STATUS_STALL_PID) | USBD_STATUS_ERROR;
  407. } else {
  408. SET_EPFLAG(Endpoint, EPFLAG_HOST_HALTED);
  409. URB_HEADER(urb).Status = USBD_STATUS_STALL_PID;
  410. }
  411. //
  412. // if we get here it is probably a bug in the root hub code
  413. //
  414. UHCD_KdTrap(("root hub stalled request\n"));
  415. break;
  416. case RH_NAK:
  417. // NAK, don't complete request
  418. completeIt = FALSE;
  419. break;
  420. default:
  421. UHCD_KdTrap(("bogus return code from RootHub_Endpoint1\n"));
  422. }
  423. } else {
  424. // no transfer, same as NAK
  425. completeIt = FALSE;
  426. }
  427. UHCD_RootHubPollError:;
  428. if (completeIt) {
  429. UHCD_ASSERT(urb != NULL);
  430. //
  431. // Remove the Irp from the cancelable state
  432. // before passing it to the Root Hub Code.
  433. //
  434. irp = HCD_AREA(urb).HcdIrp;
  435. IoAcquireCancelSpinLock(&irql);
  436. if (irp->Cancel) {
  437. TEST_TRAP();
  438. //BUGBUG Irp was canceled
  439. IoReleaseCancelSpinLock(irql);
  440. UHCD_RootHub_InterruptTransferCancel(DeviceObject, irp);
  441. } else {
  442. IoSetCancelRoutine(irp, NULL);
  443. IoReleaseCancelSpinLock(irql);
  444. //
  445. // have data or error, complete the irp
  446. //
  447. // BUGBUG we are not supporting queued
  448. // transfers for the hub driver.
  449. Endpoint->ActiveTransfers[0] = NULL;
  450. UHCD_ASSERT(irp != NULL);
  451. UHCD_CompleteIrp(DeviceObject,
  452. irp,
  453. status,
  454. 0,
  455. urb);
  456. }
  457. }
  458. }
  459. //UHCD_KdPrint((2, "'exit UHCD_RootHub_Poll\n"));
  460. return;
  461. }
  462. //
  463. // Root Hub Services
  464. //
  465. // These services are provided to the root
  466. // hub code by UHCD.
  467. //
  468. USHORT
  469. UHCD_RootHub_ReadPort(
  470. IN PROOTHUB_PORT HubPort
  471. )
  472. /*++
  473. Routine Description:
  474. Arguments:
  475. Return Value:
  476. returns the value of the requested hub
  477. register for a given controller identified
  478. by HcdPtr.
  479. --*/
  480. {
  481. PDEVICE_EXTENSION deviceExtension;
  482. USHORT dataVal;
  483. deviceExtension = HubPort->DeviceObject->DeviceExtension;
  484. dataVal = READ_PORT_USHORT(
  485. (PUSHORT) (deviceExtension->DeviceRegisters[0] +
  486. HubPort->Address));
  487. // UHCD_KdPrint((2, "'RooHub -- read port %x\n", dataVal));
  488. return dataVal;
  489. }
  490. //BUGBUG need a return code here
  491. VOID
  492. UHCD_RootHub_Timer(
  493. IN PVOID HcdPtr,
  494. IN LONG WaitTime,
  495. IN PROOTHUB_TIMER_ROUTINE RootHubTimerRoutine,
  496. IN PVOID TimerContext
  497. )
  498. /*++
  499. Routine Description:
  500. This Routine can only be called at passive level,
  501. it iniializes a timer object and starts the timer
  502. for the root hub code.
  503. Arguments:
  504. HcdPtr - pointer passed to the root hub code during
  505. initialization.
  506. WaitTime - time to wait before signaling (in ms)
  507. RootHubTimerRoutine - root hub function to call
  508. when timer expires.
  509. TimerContext - context pointer passed to RootHubTimerRoutine
  510. when timer expires.
  511. Return Value:
  512. None
  513. --*/
  514. {
  515. PDEVICE_OBJECT deviceObject = HcdPtr;
  516. PDEVICE_EXTENSION deviceExtension;
  517. LARGE_INTEGER dueTime;
  518. PROOT_HUB_TIMER rootHubTimer;
  519. ULONG timerIncerent;
  520. deviceExtension = deviceObject->DeviceExtension;
  521. rootHubTimer = GETHEAP(NonPagedPool, sizeof(ROOT_HUB_TIMER));
  522. // compute timeout value (convert millisec to nanosec)
  523. UHCD_ASSERT(WaitTime == 10); // BUGBUG root hub should always use 10ms
  524. timerIncerent = KeQueryTimeIncrement() - 1;
  525. dueTime.HighPart = -1;
  526. // round up to the next highest timer increment
  527. dueTime.LowPart = -1 * (10000 * WaitTime + timerIncerent);
  528. if (rootHubTimer) {
  529. UHCD_KdPrint((2, "'roothub timer set %d (%x %x)\n", WaitTime,
  530. dueTime.LowPart, dueTime.HighPart));
  531. rootHubTimer->DeviceObject = deviceObject;
  532. rootHubTimer->TimerRoutine = RootHubTimerRoutine;
  533. rootHubTimer->Context = TimerContext;
  534. deviceExtension->RootHubTimersActive++;
  535. //BUGBUG Timer DPCs not working with NTKERN
  536. //#ifdef NTKERN
  537. //#pragma message ("warning: using workaround for bugs in ntkern")
  538. // (VOID) KeDelayExecutionThread(KernelMode,
  539. // FALSE,
  540. // &dueTime);
  541. // UHCD_RootHubTimerDpc(&rootHubTimer->Dpc,
  542. // rootHubTimer,
  543. // NULL,
  544. // NULL);
  545. //#else
  546. KeInitializeTimer(&rootHubTimer->Timer);
  547. KeInitializeDpc(&rootHubTimer->Dpc,
  548. UHCD_RootHubTimerDpc,
  549. rootHubTimer);
  550. KeSetTimer(&rootHubTimer->Timer,
  551. dueTime,
  552. &rootHubTimer->Dpc);
  553. //#endif
  554. }
  555. }
  556. VOID
  557. UHCD_RootHubTimerDpc(
  558. IN PKDPC Dpc,
  559. IN PVOID DeferredContext,
  560. IN PVOID SystemArgument1,
  561. IN PVOID SystemArgument2
  562. )
  563. /*++
  564. Routine Description:
  565. This routine runs at DISPATCH_LEVEL IRQL.
  566. Arguments:
  567. Dpc - Pointer to the DPC object.
  568. DeferredContext - supplies the RootHubTimer.
  569. SystemArgument1 - not used.
  570. SystemArgument2 - not used.
  571. Return Value:
  572. None.
  573. --*/
  574. {
  575. PROOT_HUB_TIMER rootHubTimer = DeferredContext;
  576. PDEVICE_EXTENSION deviceExtension;
  577. UHCD_KdPrint((2, "'enter roothub timer Dpc\n"));
  578. deviceExtension = rootHubTimer->DeviceObject->DeviceExtension;
  579. //
  580. // call the root hub code callback
  581. //
  582. rootHubTimer->TimerRoutine(rootHubTimer->Context);
  583. UHCD_ASSERT(deviceExtension->RootHubTimersActive != 0);
  584. deviceExtension->RootHubTimersActive--;
  585. RETHEAP(rootHubTimer);
  586. }
  587. VOID
  588. UHCD_RootHub_WritePort(
  589. IN PROOTHUB_PORT HubPort,
  590. IN USHORT DataVal
  591. )
  592. /*++
  593. Routine Description:
  594. This routine is called by the root hub code to perform
  595. writes to a specific HC register.
  596. Arguments:
  597. Return Value:
  598. None.
  599. --*/
  600. {
  601. PDEVICE_EXTENSION deviceExtension;
  602. deviceExtension = HubPort->DeviceObject->DeviceExtension;
  603. //
  604. // mask off bits 13:15 (see UHCI design guide)
  605. //
  606. DataVal &= 0x1fff;
  607. // UHCD_KdPrint((2, "'RooHub -- write port %x\n", DataVal));
  608. WRITE_PORT_USHORT(
  609. (PUSHORT) (deviceExtension->DeviceRegisters[0] +
  610. HubPort->Address), DataVal);
  611. }
  612. VOID
  613. UHCD_RootHub_InterruptTransferCancel(
  614. IN PDEVICE_OBJECT DeviceObject,
  615. IN PIRP Irp
  616. )
  617. /*++
  618. Routine Description:
  619. This function is called to cancel at interrupt
  620. transfer request pending in the root hub code .
  621. Arguments:
  622. DeviceObject - pointer to a device object
  623. Irp - pointer to an I/O Request Packet
  624. Return Value:
  625. NT status code.
  626. --*/
  627. {
  628. PHCD_URB urb;
  629. PUHCD_ENDPOINT endpoint;
  630. UHCD_KdPrint((2, "'enter UHCD_RootHub_InterruptTransferCancel\n"));
  631. IoReleaseCancelSpinLock(Irp->CancelIrql);
  632. urb = (PHCD_URB) URB_FROM_IRP(Irp);
  633. // BUGBUG we are not supporting queued
  634. // transfers for the hub driver.
  635. endpoint = HCD_AREA(urb).HcdEndpoint;
  636. ASSERT_ENDPOINT(endpoint);
  637. endpoint->ActiveTransfers[0] = NULL;
  638. UHCD_CompleteIrp(DeviceObject,
  639. Irp,
  640. STATUS_CANCELLED,
  641. 0,
  642. urb);
  643. UHCD_KdPrint((2, "'exit UHCD_RootHub_InterruptTransferCancel\n"));
  644. }
  645. VOID
  646. UHCD_RootHubPollDpc(
  647. IN PKDPC Dpc,
  648. IN PVOID DeferredContext,
  649. IN PVOID SystemArgument1,
  650. IN PVOID SystemArgument2
  651. )
  652. /*++
  653. Routine Description:
  654. This routine runs at DISPATCH_LEVEL IRQL.
  655. Arguments:
  656. Dpc - Pointer to the DPC object.
  657. DeferredContext - supplies the device object.
  658. SystemArgument1 - not used.
  659. SystemArgument2 - not used.
  660. Return Value:
  661. None.
  662. --*/
  663. {
  664. PDEVICE_OBJECT deviceObject = DeferredContext;
  665. PUHCD_ENDPOINT endpoint;
  666. PDEVICE_EXTENSION deviceExtension;
  667. deviceExtension = deviceObject->DeviceExtension;
  668. endpoint = deviceExtension->RootHubInterruptEndpoint;
  669. // LOGENTRY(LOG_MISC, 'rhpX', deviceExtension, 0, 0);
  670. if (deviceExtension->InterruptObject) {
  671. UHCD_IsrDpc(
  672. NULL,
  673. DeferredContext,
  674. NULL,
  675. NULL);
  676. }
  677. UHCD_CheckIdle(deviceObject);
  678. if (endpoint == NULL ||
  679. (deviceExtension->HcFlags & HCFLAG_HCD_STOPPED)) {
  680. // root hub has been closed, no more polling
  681. // please.
  682. LOGENTRY(LOG_MISC, 'rhpS', deviceExtension, 0,
  683. deviceExtension->HcFlags);
  684. return;
  685. }
  686. ASSERT_ENDPOINT(endpoint);
  687. UHCD_RootHubPoll(deviceObject, endpoint);
  688. }