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.

2371 lines
77 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. async.c
  5. Abstract:
  6. This module manages interrupts from the HCD
  7. and contains all Defered Procedure Calls.
  8. Environment:
  9. kernel mode only
  10. Notes:
  11. Revision History:
  12. 1996-03-14: created kenray
  13. --*/
  14. #include "openhci.h"
  15. VOID OpenHCI_CancelTDsForED(PHCD_ENDPOINT_DESCRIPTOR ED);
  16. VOID OpenHCI_CompleteUsbdTransferRequest(PHCD_URB, USBD_STATUS, NTSTATUS,
  17. BOOLEAN);
  18. VOID OpenHCI_ProcessDoneQueue(PHCD_DEVICE_DATA, ULONG);
  19. BOOLEAN OpenHCI_ProcessDoneAsyncTD(PHCD_DEVICE_DATA,
  20. PHCD_TRANSFER_DESCRIPTOR,
  21. PHCD_ENDPOINT,
  22. PHC_TRANSFER_DESCRIPTOR,
  23. NTSTATUS *,
  24. USBD_STATUS *,
  25. PHCD_URB,
  26. BOOLEAN);
  27. BOOLEAN OpenHCI_ProcessDoneIsoTD(PHCD_DEVICE_DATA,
  28. PHCD_TRANSFER_DESCRIPTOR,
  29. PHCD_ENDPOINT,
  30. PHC_TRANSFER_DESCRIPTOR,
  31. NTSTATUS *,
  32. USBD_STATUS *,
  33. PHCD_URB,
  34. BOOLEAN);
  35. BOOLEAN
  36. OpenHCI_InterruptService(
  37. IN PKINTERRUPT Interrupt,
  38. IN VOID *ServiceContext
  39. )
  40. /*++
  41. Routine Description:
  42. Process all interrupts potentially from the USB.
  43. Stop the Host Controller from signalling interrupt
  44. and receive all time critical information.
  45. Currently the master interrupt is disabled (HC will not signal)
  46. until the DPC is completed.
  47. Arguments:
  48. Ye old standard interrutp arguments.
  49. We hope that the service context is really a Device Object.
  50. Return Value:
  51. Bool : (Is the interrupt is for us?)
  52. --*/
  53. {
  54. ULONG ContextInfo, Temp, Frame;
  55. PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT) ServiceContext;
  56. PHCD_DEVICE_DATA DeviceData;
  57. PHC_OPERATIONAL_REGISTER HC;
  58. DeviceData = (PHCD_DEVICE_DATA) DeviceObject->DeviceExtension;
  59. HC = DeviceData->HC;
  60. if (DeviceData->CurrentDevicePowerState != PowerDeviceD0) {
  61. // we cannot be generating interrupts unless we are
  62. // in D0
  63. #ifdef WIN98
  64. {
  65. ULONG status;
  66. Temp = READ_REGISTER_ULONG (&HC->HcInterruptEnable);
  67. status = (READ_REGISTER_ULONG(&HC->HcInterruptStatus) & Temp);
  68. if (DeviceData->CurrentDevicePowerState == PowerDeviceD2 &&
  69. status & HcInt_ResumeDetected) {
  70. goto OHCI_ACK_RESUME;
  71. }
  72. }
  73. #endif
  74. return FALSE;
  75. }
  76. #ifdef WIN98
  77. OHCI_ACK_RESUME:
  78. #endif
  79. Temp = READ_REGISTER_ULONG (&HC->HcInterruptEnable);
  80. ContextInfo = (READ_REGISTER_ULONG (&HC->HcInterruptStatus) & Temp);
  81. if (0 == ContextInfo) {
  82. return FALSE; /* Not our interrupt */
  83. }
  84. if (0xFFFFFFFF == ContextInfo) {
  85. return FALSE; /* Our device is not there! */
  86. }
  87. if (! (Temp & HcInt_MasterInterruptEnable)) {
  88. return FALSE;
  89. }
  90. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_ISR_NOISE,
  91. ("'take interrupt status: 0x%x\n", ContextInfo));
  92. // any interrupt resets the idle counter
  93. DeviceData->IdleTime = 0;
  94. #if 0
  95. if (DeviceData->HcFlags & HC_FLAG_USE_HYDRA_HACK) {
  96. //hydra requires us to acknowlege the writeback done queue interrupt
  97. //here
  98. if (ContextInfo & HcInt_WritebackDoneHead) {
  99. if (ContextInfo & HcInt_StartOfFrame) {
  100. //TEST_TRAP();
  101. // don't ack the done queue int
  102. ContextInfo &= ~HcInt_WritebackDoneHead;
  103. OHCI_ASSERT(DeviceData->LastHccaDoneHead == 0);
  104. DeviceData->LastHccaDoneHead = DeviceData->HCCA->HccaDoneHead;
  105. OHCI_ASSERT(DeviceData->LastHccaDoneHead != 0);
  106. DeviceData->HCCA->HccaDoneHead = 0;
  107. WRITE_REGISTER_ULONG(&HC->HcInterruptStatus,
  108. HcInt_WritebackDoneHead); /* ack inq */
  109. // enable SOF interrupt
  110. WRITE_REGISTER_ULONG(&HC->HcInterruptEnable,
  111. HcInt_StartOfFrame);
  112. } else {
  113. //TEST_TRAP();
  114. // enable SOF interrupt
  115. WRITE_REGISTER_ULONG(&HC->HcInterruptEnable,
  116. HcInt_StartOfFrame);
  117. // don't ack the done queue int
  118. ContextInfo &= ~HcInt_WritebackDoneHead;
  119. }
  120. }
  121. }
  122. #endif
  123. if (DeviceData->HcFlags & HC_FLAG_IDLE) {
  124. OpenHCI_KdPrint((1, "'interrupt while controller is idle %x\n", ContextInfo));
  125. #if DBG
  126. // should only see the rh status change
  127. if ((ContextInfo & ~(HcInt_RootHubStatusChange | HcInt_ResumeDetected))
  128. #if FAKEPORTCHANGE
  129. && !DeviceData->FakePortChange
  130. #endif
  131. )
  132. {
  133. TEST_TRAP();
  134. }
  135. #endif
  136. }
  137. /* Our interrupt, prevent HC from doing it to us again til we're finished */
  138. WRITE_REGISTER_ULONG(&HC->HcInterruptDisable, HcInt_MasterInterruptEnable);
  139. DeviceData->CurrentHcControl.ul |= DeviceData->ListEnablesAtNextSOF.ul;
  140. DeviceData->ListEnablesAtNextSOF.ul = 0;
  141. WRITE_REGISTER_ULONG(&HC->HcControl.ul, DeviceData->CurrentHcControl.ul);
  142. #if 0
  143. if (HC->HcControlHeadED) {
  144. WRITE_REGISTER_ULONG(&HC->HcCommandStatus.ul, HcCmd_ControlListFilled);
  145. }
  146. if (HC->HcBulkHeadED) {
  147. WRITE_REGISTER_ULONG(&HC->HcCommandStatus.ul, HcCmd_BulkListFilled);
  148. }
  149. #endif
  150. // Note: The NEC controller is broken, writing a zero to the
  151. // CommandStatus register for HcCmd_ControlListFilled or
  152. // HcCmd_BulkListFilled will disable the list (in violation
  153. // of the OHCI spec)
  154. {
  155. ULONG listFilled = 0;
  156. Temp = READ_REGISTER_ULONG (&HC->HcControlHeadED);
  157. if (Temp) {
  158. listFilled |= HcCmd_ControlListFilled;
  159. }
  160. Temp = READ_REGISTER_ULONG (&HC->HcBulkHeadED);
  161. if (Temp) {
  162. listFilled |= HcCmd_BulkListFilled;
  163. }
  164. //LOGENTRY(G, 'ENAL', listFilled, 0, 0);
  165. WRITE_REGISTER_ULONG(&HC->HcCommandStatus.ul, listFilled);
  166. }
  167. Frame = Get32BitFrameNumber(DeviceData);
  168. if (ContextInfo & (HcInt_SchedulingOverrun
  169. | HcInt_WritebackDoneHead
  170. | HcInt_StartOfFrame
  171. | HcInt_FrameNumberOverflow))
  172. ContextInfo |= HcInt_MasterInterruptEnable; /* flag for EOF irq's */
  173. // Today we ack but otherwise ignore a SchedulingOverrun interrupt.
  174. // In the future we may want to do something as suggested in section
  175. // 5.2.10.1 of the OpenHCI specification.
  176. //
  177. if (ContextInfo & HcInt_SchedulingOverrun)
  178. {
  179. WRITE_REGISTER_ULONG(&HC->HcInterruptStatus,
  180. HcInt_SchedulingOverrun); /* ack int */
  181. ContextInfo &= ~HcInt_SchedulingOverrun;
  182. }
  183. /* Check for Frame Number Overflow The following insures that the 32 bit
  184. * frame never runs backward. */
  185. if (ContextInfo & HcInt_FrameNumberOverflow) {
  186. DeviceData->FrameHighPart
  187. += 0x10000 - (0x8000 & (DeviceData->HCCA->HccaFrameNumber
  188. ^ DeviceData->FrameHighPart));
  189. WRITE_REGISTER_ULONG(&HC->HcInterruptStatus,
  190. HcInt_FrameNumberOverflow);
  191. ContextInfo &= ~HcInt_FrameNumberOverflow;
  192. #if DBG
  193. Temp = Get32BitFrameNumber(DeviceData);
  194. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_ISR_NOISE,
  195. ("'Frame number advance: 0x%x\n", Temp));
  196. #endif
  197. }
  198. /* Construct a DPC with all the goodies and schedule it. */
  199. DeviceData->IsrDpc_Context.Frame = Frame;
  200. DeviceData->IsrDpc_Context.ContextInfo = ContextInfo;
  201. KeInsertQueueDpc(&DeviceData->IsrDPC, NULL, (PVOID) DeviceData);
  202. return TRUE;
  203. }
  204. VOID
  205. OpenHCI_IsrDPC(
  206. PKDPC Dpc,
  207. PVOID DeviceObjectPtr,
  208. PVOID LaGarbage,
  209. PVOID DeviceDataPtr
  210. )
  211. /*++
  212. Routine Description:
  213. Arguments:
  214. Return Value:
  215. --*/
  216. {
  217. KIRQL oldIrql;
  218. PHC_OPERATIONAL_REGISTER HC;
  219. PHCD_ENDPOINT_DESCRIPTOR ed;
  220. PHCD_ENDPOINT endpoint;
  221. ULONG frame, ContextInfo, DoneQueue;
  222. PHCD_DEVICE_DATA deviceData = DeviceDataPtr;
  223. ULONG HcDoneHead;
  224. frame = deviceData->IsrDpc_Context.Frame;
  225. ContextInfo = deviceData->IsrDpc_Context.ContextInfo;
  226. HC = deviceData->HC;
  227. KeAcquireSpinLockAtDpcLevel(&deviceData->HcFlagSpin);
  228. #if DBG
  229. OHCI_ASSERT((deviceData->HcFlags & HC_FLAG_IN_DPC) == 0);
  230. deviceData->HcFlags |= HC_FLAG_IN_DPC;
  231. #endif
  232. if (deviceData->HcFlags & HC_FLAG_IDLE) {
  233. OpenHCI_KdPrint((1, "'controller going off idle\n"));
  234. LOGENTRY(G, 'OFFi', deviceData, 0, 0);
  235. // not idle anymore
  236. deviceData->HcFlags &= ~HC_FLAG_IDLE;
  237. if (!KeSynchronizeExecution(deviceData->InterruptObject,
  238. OpenHCI_StartController,
  239. deviceData)) {
  240. TRAP(); //something has gone terribly wrong
  241. }
  242. }
  243. KeReleaseSpinLockFromDpcLevel(&deviceData->HcFlagSpin);
  244. OpenHCI_KdPrintDD(deviceData, OHCI_DBG_ISR_TRACE,
  245. ("'OpenHCI_IsrDpc, DD 0x%x, ContextInfo: 0x%x \n",
  246. deviceData, ContextInfo));
  247. if (ContextInfo & HcInt_UnrecoverableError) {
  248. /*
  249. * Here the controller is hung!
  250. */
  251. OpenHCI_KdPrint((0, "'Controller: Unrecoverable error!\n"));
  252. LOGENTRY(G, 'HC!!', deviceData, HC, ContextInfo);
  253. #if DBG
  254. KeAcquireSpinLockAtDpcLevel(&deviceData->HcFlagSpin);
  255. deviceData->HcFlags &= ~HC_FLAG_IN_DPC;
  256. KeReleaseSpinLockFromDpcLevel(&deviceData->HcFlagSpin);
  257. #endif
  258. // If we're not checking for a hung HC in OpenHCI_DeadmanDPC()
  259. // go ahead and reset the host controller now.
  260. //
  261. if ( !(deviceData->HcFlags & HC_FLAG_HUNG_CHECK_ENABLE) )
  262. {
  263. OpenHCI_ResurrectHC(deviceData);
  264. }
  265. return;
  266. }
  267. #if DBG
  268. if (ContextInfo & HcInt_ResumeDetected) {
  269. /* Resume has been requested by a device on the USB. HCD must wait
  270. * 20ms then put controller in the UsbOperational state. */
  271. // LARGE_INTEGER time;
  272. // time.QuadPart = 20 * 10000 * -1;
  273. /* Time is in units of 100-nanoseconds. Neg vals are relative time. */
  274. // KeSetTimer(&deviceData->ResumeTimer, time, &deviceData->ResumeDPC);
  275. // Note: Nothing to do here accept possibly complete the waitwake irp
  276. // the root hub will handle resume signalling on the appropriate port
  277. LOGENTRY(G, 'reHC', deviceData, 0, ContextInfo);
  278. #ifdef MAX_DEBUG
  279. TEST_TRAP();
  280. #endif
  281. }
  282. #endif
  283. /*
  284. * Process the Done Queue
  285. */
  286. //
  287. // If the HC froze, first process any TDs that completed during the
  288. // last frame in which the TD froze.
  289. //
  290. HcDoneHead = InterlockedExchange(&deviceData->FrozenHcDoneHead, 0);
  291. if (HcDoneHead)
  292. {
  293. OpenHCI_ProcessDoneQueue(deviceData, HcDoneHead);
  294. }
  295. #if 0
  296. if (ContextInfo & HcInt_WritebackDoneHead &&
  297. !(deviceData->HcFlags & HC_FLAG_USE_HYDRA_HACK)) {
  298. // should not get here is hydra fix is enabled
  299. OHCI_ASSERT(!(deviceData->HcFlags & HC_FLAG_USE_HYDRA_HACK));
  300. #else
  301. if (ContextInfo & HcInt_WritebackDoneHead) {
  302. #endif
  303. DoneQueue = deviceData->HCCA->HccaDoneHead;
  304. LOGENTRY(G, 'donQ', deviceData, DoneQueue, ContextInfo);
  305. if (DoneQueue == 0)
  306. {
  307. //
  308. // We got an HcInt_WritebackDoneHead but the HCCA->HccaDoneHead
  309. // was zero. Apparently the HC failed to properly update the
  310. // HCCA->HccaDoneHead. Try to recover the lost done head.
  311. //
  312. DoneQueue = FindLostDoneHead(deviceData);
  313. LOGENTRY(G, 'Lost', deviceData, DoneQueue, ContextInfo);
  314. OHCI_ASSERT(DoneQueue != 0);
  315. }
  316. deviceData->HCCA->HccaDoneHead = 0;
  317. LOGENTRY(G, 'dnQZ', deviceData, DoneQueue, ContextInfo);
  318. OpenHCI_KdPrintDD(deviceData,
  319. OHCI_DBG_ISR_TRACE, ("'Checking WritebackDoneHead\n"));
  320. if (DoneQueue) {
  321. OpenHCI_ProcessDoneQueue(deviceData, (DoneQueue & 0xFFFFfffe));
  322. //
  323. // Note: No interrupts can come in while processing the done queue.
  324. //
  325. }
  326. }
  327. #if 0
  328. if (deviceData->LastHccaDoneHead) {
  329. // should only get here if hydra fix is enabled
  330. // TEST_TRAP();
  331. OHCI_ASSERT(deviceData->HcFlags & HC_FLAG_USE_HYDRA_HACK);
  332. DoneQueue = deviceData->LastHccaDoneHead;
  333. deviceData->LastHccaDoneHead = 0;
  334. LOGENTRY(G, 'dnQ2', deviceData, DoneQueue, ContextInfo);
  335. OpenHCI_ProcessDoneQueue(deviceData, (DoneQueue & 0xFFFFfffe));
  336. }
  337. #endif
  338. /*
  339. * Process Root Hub changes
  340. */
  341. if (ContextInfo & HcInt_RootHubStatusChange
  342. #if FAKEPORTCHANGE
  343. || deviceData->FakePortChange
  344. #endif
  345. ) {
  346. OpenHCI_KdPrintDD(deviceData, OHCI_DBG_ISR_TRACE,
  347. ("' ROOT HUB STATUS CHANGE ! \n"));
  348. /*
  349. * EmulateRootHubInterruptXfer will complete a
  350. * HCD_TRANSFER_DESCRIPTOR which we then pass to ProcessDoneQueue to
  351. * emulate an HC completion.
  352. */
  353. LOGENTRY(G, 'RHxf', deviceData, 0, ContextInfo);
  354. if (deviceData->RootHubInterrupt) {
  355. EmulateRootHubInterruptXfer(deviceData, HC);
  356. } else {
  357. // no root hub data, root hub is closed
  358. // disable the interrupt and ack the change
  359. WRITE_REGISTER_ULONG(&HC->HcInterruptDisable,
  360. HcInt_RootHubStatusChange);
  361. WRITE_REGISTER_ULONG(&HC->HcInterruptStatus,
  362. HcInt_RootHubStatusChange);
  363. }
  364. /*
  365. * clear the RootHubStatusChange bit in context info
  366. * we have already cleared the status and/or disabled
  367. * the interrupt if necessary.
  368. */
  369. ContextInfo &= ~HcInt_RootHubStatusChange;
  370. }
  371. if (ContextInfo & HcInt_OwnershipChange) {
  372. OpenHCI_KdPrintDD(deviceData, OHCI_DBG_ISR_INFO,
  373. ("'OpenHCI_IsrDpc: Ownership CHANGE!\n"));
  374. LOGENTRY(G, 'OWnr', deviceData, 0, ContextInfo);
  375. /* Only SMM drivers need implement this. */
  376. TEST_TRAP(); // No code path for this.
  377. }
  378. /*
  379. * interrupt for SOF
  380. */
  381. if (ContextInfo & HcInt_StartOfFrame) {
  382. //LOGENTRY(G, 'SOFi', deviceData, 0, ContextInfo);
  383. /*
  384. * we asked for an interrupt on the next SOF,
  385. * now that we've gotten one we can disable again
  386. */
  387. #if 0
  388. if (!(deviceData->HcFlags & HC_FLAG_USE_HYDRA_HACK))
  389. #endif
  390. {
  391. ContextInfo &= ~HcInt_StartOfFrame;
  392. WRITE_REGISTER_ULONG(&HC->HcInterruptDisable, HcInt_StartOfFrame);
  393. }
  394. }
  395. /*
  396. * We've complete the actual service of the HC interrupts, now we must
  397. * deal with the effects.
  398. */
  399. /*
  400. * Look for things on the PausedEDRestart list.
  401. *
  402. * Any ED that is on the pusedRestart list will be removed, its TDs
  403. * canceled and then restarted.
  404. *
  405. */
  406. frame = Get32BitFrameNumber(deviceData);
  407. KeAcquireSpinLock(&deviceData->PausedSpin, &oldIrql);
  408. while (!IsListEmpty(&deviceData->PausedEDRestart))
  409. {
  410. OpenHCI_KdPrintDD(deviceData,
  411. OHCI_DBG_ISR_TRACE, ("'Checking paused restart list\n"));
  412. ed = CONTAINING_RECORD(deviceData->PausedEDRestart.Flink,
  413. HCD_ENDPOINT_DESCRIPTOR,
  414. PausedLink);
  415. endpoint = ed->Endpoint;
  416. ASSERT_ENDPOINT(endpoint);
  417. LOGENTRY(G, 'pasR', deviceData, endpoint, ed);
  418. if ((LONG) ed->ReclamationFrame - (LONG) frame > 0) {
  419. /*
  420. * Now is the wrong time to remove this entry. but most likely
  421. * the very next frame will be so we will ask for an interrupt
  422. * at next SOF
  423. */
  424. ContextInfo |= HcInt_StartOfFrame;
  425. break;
  426. }
  427. /*
  428. * remove the ed from the paused list and reset
  429. * the state.
  430. */
  431. RemoveEntryList(&ed->PausedLink);
  432. if ((ed->HcED.HeadP & HcEDHeadP_HALT) || ed->HcED.sKip) {
  433. KeReleaseSpinLock(&deviceData->PausedSpin, oldIrql);
  434. } else {
  435. // HC has not paused the ep yet, put it back on the list
  436. TEST_TRAP();
  437. InsertTailList(&deviceData->PausedEDRestart, &ed->PausedLink);
  438. continue;
  439. }
  440. /*
  441. * cancel the current transfers queued to this ed
  442. */
  443. OpenHCI_CancelTDsForED(ed);
  444. KeAcquireSpinLock(&deviceData->PausedSpin, &oldIrql);
  445. }
  446. KeReleaseSpinLock(&deviceData->PausedSpin, oldIrql);
  447. /*
  448. * This code processed our reclimation lists ie EDs that
  449. * we need to free
  450. */
  451. if (ContextInfo & HcInt_MasterInterruptEnable) {
  452. // Do we have an "end of Frame" type interrupt? //
  453. ULONG newControlED = 0;
  454. ULONG newBulkED = 0;
  455. ULONG currentControlED
  456. = READ_REGISTER_ULONG(&HC->HcControlCurrentED);
  457. ULONG currentBulkED
  458. = READ_REGISTER_ULONG(&HC->HcBulkCurrentED);
  459. KeSynch_HcControl context;
  460. //
  461. // If of course either the control or bulk list is not stalled, then
  462. // the current ED pointer will continue to advance. Here we are
  463. // making the ASSUMPTION that the only way an ED from either of these
  464. // two lists made it onto the ReclamationList was by stalling their
  465. // respective Control or Bulk list. In that case the Current ED
  466. // pointer will remain quite happily the same number until the
  467. // control or bulk list is restarted.
  468. //
  469. /* Look for things on the StalledEDReclamation list */
  470. KeAcquireSpinLock(&deviceData->ReclamationSpin, &oldIrql);
  471. while (!IsListEmpty(&deviceData->StalledEDReclamation)) {
  472. OpenHCI_KdPrintDD(deviceData, OHCI_DBG_ISR_TRACE,
  473. ("'Checking Stalled Reclamation list\n"));
  474. ed = CONTAINING_RECORD(deviceData->StalledEDReclamation.Flink,
  475. HCD_ENDPOINT_DESCRIPTOR,
  476. Link);
  477. LOGENTRY(G, 'REcs', deviceData, ed, 0);
  478. ASSERT(NULL == ed->Endpoint);
  479. /*
  480. * The only way that this ED could have gotten itself on the
  481. * reclamation list was for it to have been placed there by a
  482. * RemoveEDForEndpoint call. This would have severed the
  483. * Endpoint.
  484. */
  485. RemoveEntryList(&ed->Link);
  486. KeReleaseSpinLock(&deviceData->ReclamationSpin, oldIrql);
  487. if (ed->PhysicalAddress == currentControlED) {
  488. newControlED = currentControlED = ed->HcED.NextED;
  489. } else if (ed->PhysicalAddress == currentBulkED) {
  490. newBulkED = currentBulkED = ed->HcED.NextED;
  491. }
  492. OpenHCI_Free_HcdED(deviceData, ed);
  493. // Need to enable SOF interrupts to generate an interrupt
  494. // so that HcControl is updated with ListEnablesAtNextSOF
  495. // to turn BLE and CLE back on after the next SOF.
  496. //
  497. ContextInfo |= HcInt_StartOfFrame;
  498. KeAcquireSpinLock(&deviceData->ReclamationSpin, &oldIrql);
  499. }
  500. KeReleaseSpinLock(&deviceData->ReclamationSpin, oldIrql);
  501. if (newControlED) {
  502. LOGENTRY(G, 'nQ1S', deviceData, newControlED, newBulkED);
  503. WRITE_REGISTER_ULONG(&HC->HcControlCurrentED, newControlED);
  504. }
  505. if (newBulkED) {
  506. LOGENTRY(G, 'nQ2S', deviceData, newControlED, newBulkED);
  507. WRITE_REGISTER_ULONG(&HC->HcBulkCurrentED, newBulkED);
  508. }
  509. /* Restart both queues. */
  510. context.DeviceData = DeviceDataPtr;
  511. context.NewHcControl.ul = HcCtrl_ControlListEnable
  512. | HcCtrl_BulkListEnable;
  513. KeSynchronizeExecution(deviceData->InterruptObject,
  514. OpenHCI_ListEnablesAtNextSOF,
  515. &context);
  516. }
  517. frame = Get32BitFrameNumber(deviceData);
  518. /* Look for things on the runningReclamationList */
  519. KeAcquireSpinLock(&deviceData->ReclamationSpin, &oldIrql);
  520. while (!IsListEmpty(&deviceData->RunningEDReclamation)) {
  521. PHCD_ENDPOINT_DESCRIPTOR ed;
  522. OpenHCI_KdPrintDD(deviceData, OHCI_DBG_ISR_TRACE,
  523. ("'Checking running reclamation list\n"));
  524. ed = CONTAINING_RECORD(deviceData->RunningEDReclamation.Flink,
  525. HCD_ENDPOINT_DESCRIPTOR,
  526. Link);
  527. if ((LONG) ed->ReclamationFrame - (LONG) frame > 0) {
  528. ContextInfo |= HcInt_StartOfFrame;
  529. /*
  530. * We need to remove this ED from the list, but now is not the
  531. * appropriate time. Most likely, however, the very next Frame
  532. * will be the correct time, so reenable the start of frame
  533. * interrupt.
  534. */
  535. break;
  536. }
  537. LOGENTRY(G, 'REcr', deviceData, ed, 0);
  538. ASSERT(NULL == ed->Endpoint);
  539. /* The only way that this bad boy could have gotten itself on the
  540. * reclamation list was for it to have been placed there by a
  541. * RemoveEDForEndpoint call. THis would have severed the Endpoint. */
  542. RemoveEntryList(&ed->Link);
  543. KeReleaseSpinLock(&deviceData->ReclamationSpin, oldIrql);
  544. OpenHCI_Free_HcdED(deviceData, ed);
  545. KeAcquireSpinLock(&deviceData->ReclamationSpin, &oldIrql);
  546. }
  547. KeReleaseSpinLock(&deviceData->ReclamationSpin, oldIrql);
  548. // Loop thru the list of active endpoints and see if we have a deferred
  549. // work to do.
  550. KeAcquireSpinLock(&deviceData->HcDmaSpin, &oldIrql);
  551. // attempt to lock out access to ep worker
  552. deviceData->HcDma++;
  553. //LOGENTRY(G, 'pEPl', 0, 0, deviceData->HcDma);
  554. if (deviceData->HcDma) {
  555. // EP worker is busy, bail
  556. deviceData->HcDma--;
  557. KeReleaseSpinLock(&deviceData->HcDmaSpin, oldIrql);
  558. goto Openhci_ISRDPC_Done;
  559. }
  560. if (IsListEmpty(&deviceData->ActiveEndpointList)) {
  561. // queue is empty, bail
  562. //LOGENTRY(G, 'EPmt', 0, 0, deviceData->HcDma);
  563. deviceData->HcDma--;
  564. KeReleaseSpinLock(&deviceData->HcDmaSpin, oldIrql);
  565. goto Openhci_ISRDPC_Done;
  566. }
  567. // at this point we have exclusive access to ep worker
  568. do {
  569. PHCD_ENDPOINT endpoint;
  570. PLIST_ENTRY entry;
  571. LOGENTRY(G, 'epLS', &deviceData->ActiveEndpointList, 0, 0);
  572. entry = RemoveHeadList(&deviceData->ActiveEndpointList);
  573. // use DMA spin to serialize access to the list
  574. endpoint = CONTAINING_RECORD(entry,
  575. HCD_ENDPOINT,
  576. EndpointListEntry);
  577. LOGENTRY(G, 'gtEP', endpoint, 0, 0);
  578. CLR_EPFLAG(endpoint, EP_IN_ACTIVE_LIST);
  579. KeReleaseSpinLock(&deviceData->HcDmaSpin, oldIrql);
  580. OpenHCI_EndpointWorker(endpoint);
  581. KeAcquireSpinLock(&deviceData->HcDmaSpin, &oldIrql);
  582. } while (!IsListEmpty(&deviceData->ActiveEndpointList));
  583. LOGENTRY(G, 'pEPd', 0, 0, 0);
  584. // release ep worker
  585. deviceData->HcDma--;
  586. KeReleaseSpinLock(&deviceData->HcDmaSpin, oldIrql);
  587. Openhci_ISRDPC_Done:
  588. OpenHCI_KdPrintDD(deviceData,
  589. OHCI_DBG_ISR_TRACE, ("'Exit Isr DPC routine\n"));
  590. #if DBG
  591. //
  592. // As soon as interrupts are reenabled, the interrupt service routine
  593. // may execute and queue another call to the DPC. This routine must
  594. // be prepared to be reentered as soon as interrupts are reenabled.
  595. // So this routine should not do anything that cannot handle being
  596. // reentered after interrupts are reenabled.
  597. //
  598. KeAcquireSpinLockAtDpcLevel(&deviceData->HcFlagSpin);
  599. deviceData->HcFlags &= ~HC_FLAG_IN_DPC;
  600. KeReleaseSpinLockFromDpcLevel(&deviceData->HcFlagSpin);
  601. #endif
  602. // Acknowledge the interrupts we handled and reenable interrupts.
  603. //
  604. ContextInfo |= HcInt_MasterInterruptEnable;
  605. WRITE_REGISTER_ULONG(&HC->HcInterruptStatus, ContextInfo);
  606. WRITE_REGISTER_ULONG(&HC->HcInterruptEnable, ContextInfo);
  607. }
  608. VOID
  609. OpenHCI_Free_HcdED(
  610. PHCD_DEVICE_DATA DeviceData,
  611. PHCD_ENDPOINT_DESCRIPTOR Ed
  612. )
  613. /*
  614. * Place the corresponding ED back onto the Free Descriptors list.
  615. * Presumably the only reason the ED got here was because it was
  616. * FIRST sent to RemoveEDForEndpoint which freed all of the
  617. * outstanding TD's, INCLUDING the stub TD.
  618. *
  619. * This of course means that the pointers to TD's are invalid.
  620. * SECOND the ED was placed on the reclamation list and the
  621. * DPCforIRQ moved it here.
  622. * This function is only called in the DPC for Irq. If another
  623. * function wishes to free an endpoint it must call RemoveEDForEndpoint,
  624. * which will add the ED to the reclamation list to be freed on the
  625. * next Start O Frame.
  626. */
  627. {
  628. OHCI_ASSERT(Ed);
  629. OHCI_ASSERT(NULL == Ed->Endpoint);
  630. OHCI_ASSERT((Ed->HcED.HeadP & ~0X0F) == Ed->HcED.TailP);
  631. LOGENTRY(G, 'frED', DeviceData, Ed, 0);
  632. OHCI_ASSERT((Ed->PhysicalAddress & (PAGE_SIZE-1)) ==
  633. ((ULONG_PTR)Ed & (PAGE_SIZE-1)));
  634. OHCI_ASSERT(Ed->Flags == (TD_FLAG_INUSE | TD_FLAG_IS_ED));
  635. Ed->Flags = 0;
  636. ExInterlockedPushEntryList(&DeviceData->FreeDescriptorList,
  637. (PSINGLE_LIST_ENTRY) Ed,
  638. &DeviceData->DescriptorsSpin);
  639. }
  640. VOID
  641. OpenHCI_CancelTDsForED(
  642. PHCD_ENDPOINT_DESCRIPTOR Ed
  643. )
  644. /*++
  645. Routine Description:
  646. Given an ED search through the list of TDs and weed out those with
  647. problems.
  648. It is ASSUMED that if the ED got to this list that either
  649. it has been paused (the sKip bit is set & a new SOF has occured)
  650. or it has been halted by the HC.
  651. It is possible that at the time of cancel of TD's for this endpoint
  652. that some of the canceled TDs had already made it to the done queue.
  653. We catch that by setting the TD Status field to .
  654. That way, when we are processing the DoneQueue, we can skip over those
  655. TDs.
  656. Note: This routine was originally called ProcessPausedED.
  657. Aguments:
  658. ED - the ED that is inspected.
  659. --*/
  660. {
  661. PHCD_ENDPOINT endpoint;
  662. PHCD_DEVICE_DATA DeviceData;
  663. PHC_OPERATIONAL_REGISTER HC;
  664. PHCD_URB urb;
  665. PHCD_TRANSFER_DESCRIPTOR td;
  666. PHCD_TRANSFER_DESCRIPTOR last = NULL;
  667. PHCD_TRANSFER_DESCRIPTOR *previous;
  668. BOOLEAN B4Head = TRUE;
  669. ULONG physicalHeadP;
  670. KIRQL oldIrql;
  671. LIST_ENTRY CancelList;
  672. PIRP AbortIrp;
  673. endpoint = Ed->Endpoint;
  674. ASSERT_ENDPOINT(endpoint);
  675. OHCI_ASSERT(NULL != endpoint);
  676. OHCI_ASSERT((Ed->HcED.HeadP & HcEDHeadP_HALT) || Ed->HcED.sKip);
  677. OHCI_ASSERT(Ed->PauseFlag == HCD_ED_PAUSE_NEEDED);
  678. if (endpoint->TrueTail) {
  679. LOGENTRY(G, 'cTTl', endpoint->TrueTail,
  680. endpoint->HcdTailP, endpoint);
  681. // Bump the software tail pointer to the true tail for this transfer
  682. //
  683. endpoint->HcdTailP = endpoint->TrueTail;
  684. endpoint->TrueTail = NULL;
  685. // Bump the hardware tail pointer to the true tail for this transfer
  686. //
  687. endpoint->HcdED->HcED.TailP = endpoint->HcdTailP->PhysicalAddress;
  688. }
  689. //
  690. // The endpoint has been stopped, we need to walk thru
  691. // the list of HW TDs and remove any that are associated
  692. // canceled transfers.
  693. //
  694. DeviceData = endpoint->DeviceData;
  695. HC = DeviceData->HC;
  696. InitializeListHead(&CancelList);
  697. KeAcquireSpinLock(&DeviceData->PausedSpin, &oldIrql);
  698. CancelTDsOneMoreTime:
  699. Ed->PauseFlag = HCD_ED_PAUSE_PROCESSING;
  700. KeReleaseSpinLock(&DeviceData->PausedSpin, oldIrql);
  701. // lock down the endpoint
  702. OpenHCI_LockAndCheckEndpoint(endpoint,
  703. NULL,
  704. NULL,
  705. &oldIrql);
  706. LOGENTRY(G, 'xxED', DeviceData, endpoint, Ed);
  707. td = endpoint->HcdHeadP;
  708. previous = &endpoint->HcdHeadP;
  709. LOGENTRY(G, 'xED1', DeviceData, td, previous);
  710. /* aka the location where the previous TD holds the current TD. */
  711. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_TRACE,
  712. ("'Calling Cancel TD's For ED %x %x hd = %x\n",
  713. endpoint->HcdHeadP,
  714. endpoint->HcdTailP,
  715. &endpoint->HcdHeadP));
  716. physicalHeadP = (Ed->HcED.HeadP & ~HcEDHeadP_FLAGS);
  717. while (td != endpoint->HcdTailP) {
  718. LOGENTRY(G, 'xEDy', td->PhysicalAddress, td, physicalHeadP);
  719. if (physicalHeadP == td->PhysicalAddress) {
  720. // aka is The first TD on the Enpoint list of TD's is the
  721. // same as the first HC_TD on the Host Controller list
  722. // of HC_TD's?
  723. // The HC could have processed some TD's that we have yet to
  724. // process.
  725. //
  726. B4Head = FALSE;
  727. }
  728. //
  729. // get the urb associated with this TD
  730. //
  731. urb = td->UsbdRequest;
  732. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_NOISE,
  733. ("'Endpoint:%x ED:%x TD:%x trans:%x stat:%x abort:%x\n",
  734. endpoint, Ed, td,
  735. &urb->HcdUrbCommonTransfer,
  736. urb->UrbHeader.Status,
  737. endpoint->EpFlags));
  738. LOGENTRY(G, 'xREQ', DeviceData, urb, td);
  739. //
  740. // either this is a specific request to cancel or
  741. // we are aborting all transfers for the ED
  742. //
  743. if ((USBD_STATUS_CANCELING == urb->UrbHeader.Status) ||
  744. endpoint->EpFlags & EP_ABORT) {
  745. PHC_TRANSFER_DESCRIPTOR hcTD;
  746. struct _URB_HCD_COMMON_TRANSFER *transfer;
  747. OpenHCI_KdPrintDD(DeviceData,
  748. OHCI_DBG_TD_NOISE, ("'Killing TD\n"));
  749. LOGENTRY(G, 'xxTD', DeviceData, urb, td);
  750. OHCI_ASSERT(!td->Canceled);
  751. RemoveEntryList(&td->RequestList);
  752. td->Canceled = TRUE;
  753. td->Endpoint = NULL;
  754. transfer = &urb->HcdUrbCommonTransfer;
  755. hcTD = &td->HcTD;
  756. // Only update transfer count if transfer count is non-zero
  757. //
  758. if (td->TransferCount)
  759. {
  760. td->TransferCount -=
  761. /* have we gone further than a page? */
  762. ((((hcTD->BE ^ hcTD->CBP) & ~OHCI_PAGE_SIZE_MASK)
  763. ? OHCI_PAGE_SIZE : 0) +
  764. /* minus the data buffer not used */
  765. ((hcTD->BE & OHCI_PAGE_SIZE_MASK) -
  766. (hcTD->CBP & OHCI_PAGE_SIZE_MASK)+1));
  767. LOGENTRY(G, 'xfB2', hcTD->BE & OHCI_PAGE_SIZE_MASK,
  768. hcTD->CBP & OHCI_PAGE_SIZE_MASK,
  769. td->TransferCount);
  770. transfer->TransferBufferLength += td->TransferCount;
  771. }
  772. if (IsListEmpty(&urb->HcdUrbCommonTransfer.hca.HcdListEntry2))
  773. {
  774. // AKA all of the TD's for this URB have been delt with.
  775. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_TRACE,
  776. ("'Return canceled off hardware\n"));
  777. LOGENTRY(G, 'CANu', DeviceData, urb, td);
  778. // Put it on the cancel list
  779. //
  780. if (!urb->HcdUrbCommonTransfer.hca.HcdListEntry.Flink)
  781. {
  782. LOGENTRY(G, 'canA', DeviceData, urb, td);
  783. InsertTailList(&CancelList,
  784. &urb->HcdUrbCommonTransfer.hca.HcdListEntry);
  785. }
  786. }
  787. *previous = td->NextHcdTD;
  788. // link around the TD
  789. if (NULL == last) {
  790. //
  791. // For bulk and interrupt endpoints, TDs are queued with a
  792. // dataToggle == 00b. After the first data packet is
  793. // successfully transferred, the MSb of dataToggle is set to
  794. // indicate that the LSb indicates the next toggle value.
  795. // The toggleCarry of the ED is only updated with the dataToggle
  796. // of the TD when the TD makes it to the doneQueue. Manually
  797. // update the ED with the toggle of the last TD that transferred
  798. // data when a transfer is cancelled.
  799. //
  800. if (td->HcTD.Toggle == 3) {
  801. Ed->HcED.HeadP = (td->HcTD.NextTD & ~HcEDHeadP_FLAGS) |
  802. HcEDHeadP_CARRY;
  803. } else if (td->HcTD.Toggle == 2) {
  804. Ed->HcED.HeadP = (td->HcTD.NextTD & ~HcEDHeadP_FLAGS);
  805. } else {
  806. Ed->HcED.HeadP = ((td->HcTD.NextTD & ~HcEDHeadP_FLAGS) |
  807. (Ed->HcED.HeadP & HcEDHeadP_CARRY));
  808. }
  809. LOGENTRY(G, 'BMPh', DeviceData, td->HcTD.Toggle, 0);
  810. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_NOISE,
  811. ("'cancelTDsForED bumping HeadP\n"));
  812. } else {
  813. last->HcTD.NextTD = td->HcTD.NextTD;
  814. LOGENTRY(G, 'BMPn', DeviceData, 0, 0);
  815. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_NOISE,
  816. ("'cancelTDsForED not bumping HeadP\n"));
  817. }
  818. //
  819. // If the TD is not yet on the Done queue,
  820. // aka the HC has yet to see it, then Free it now.
  821. // Otherwise flag it so that the Process Done Queue
  822. // routine can free it later
  823. //
  824. if (!B4Head) {
  825. OpenHCI_Free_HcdTD(DeviceData, td);
  826. }
  827. } else {
  828. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_NOISE,
  829. ("'TD Spared, next = %x\n", &td->NextHcdTD));
  830. LOGENTRY(G, 'skTD', DeviceData, td, 0);
  831. previous = &td->NextHcdTD;
  832. if (!B4Head) {
  833. last = td;
  834. }
  835. }
  836. td = *previous;
  837. }
  838. LOGENTRY(G, 'uTal', DeviceData, Ed->HcED.TailP,
  839. endpoint->HcdTailP->PhysicalAddress);
  840. Ed->HcED.TailP = endpoint->HcdTailP->PhysicalAddress;
  841. OpenHCI_UnlockEndpoint(endpoint,
  842. oldIrql);
  843. // Now complete all of the transfers which we put it on the cancel list.
  844. //
  845. while (!IsListEmpty(&CancelList))
  846. {
  847. PLIST_ENTRY entry;
  848. entry = RemoveHeadList(&CancelList);
  849. urb = CONTAINING_RECORD(entry,
  850. HCD_URB,
  851. HcdUrbCommonTransfer.hca.HcdListEntry);
  852. LOGENTRY(G, 'CANq', DeviceData, urb, 0);
  853. //
  854. // We may be canceling a request that is still in the
  855. // cancelable state (if we got here because the abortAll
  856. // flag was set) in that case we take the cancel spinlock
  857. // and set the cancel routine
  858. //
  859. IoAcquireCancelSpinLock(&oldIrql);
  860. IoSetCancelRoutine(urb->HcdUrbCommonTransfer.hca.HcdIrp, NULL);
  861. IoReleaseCancelSpinLock(oldIrql);
  862. OpenHCI_CompleteUsbdTransferRequest(urb,
  863. USBD_STATUS_CANCELED,
  864. STATUS_CANCELLED,
  865. TRUE);
  866. }
  867. //
  868. // If we completed any requests above, it might have triggered the
  869. // cancelling of additional requests on the same endpoint. Process
  870. // cancelling the TDs for this ED one more time, if necessary.
  871. //
  872. KeAcquireSpinLock(&DeviceData->PausedSpin, &oldIrql);
  873. if (Ed->PauseFlag == HCD_ED_PAUSE_NEEDED)
  874. {
  875. goto CancelTDsOneMoreTime;
  876. }
  877. else
  878. {
  879. Ed->PauseFlag = HCD_ED_PAUSE_NOT_PAUSED;
  880. if (endpoint->EpFlags & EP_FREE)
  881. {
  882. KeReleaseSpinLock(&DeviceData->PausedSpin, oldIrql);
  883. RemoveEDForEndpoint(endpoint);
  884. }
  885. else
  886. {
  887. /*
  888. * restart the ED
  889. */
  890. Ed->HcED.HeadP = (endpoint->HcdHeadP->PhysicalAddress
  891. | (Ed->HcED.HeadP & HcEDHeadP_CARRY))
  892. & ~HcEDHeadP_HALT;
  893. Ed->HcED.sKip = FALSE;
  894. //
  895. // tell the HC we have something on the ED lists
  896. //
  897. ENABLE_LIST(HC, endpoint)
  898. KeReleaseSpinLock(&DeviceData->PausedSpin, oldIrql);
  899. }
  900. }
  901. // Complete the abort irp now if we have one
  902. //
  903. KeAcquireSpinLock(&DeviceData->PausedSpin, &oldIrql);
  904. AbortIrp = endpoint->AbortIrp;
  905. endpoint->AbortIrp = NULL;
  906. CLR_EPFLAG(endpoint, EP_ABORT);
  907. KeReleaseSpinLock(&DeviceData->PausedSpin, oldIrql);
  908. if (AbortIrp != NULL)
  909. {
  910. LOGENTRY(G, 'cABR', 0, endpoint, AbortIrp);
  911. OpenHCI_CompleteIrp(DeviceData->DeviceObject, AbortIrp, STATUS_SUCCESS);
  912. }
  913. LOGENTRY(G, 'xED>', DeviceData, endpoint, 0);
  914. }
  915. VOID
  916. OpenHCI_CompleteUsbdTransferRequest(
  917. PHCD_URB Urb,
  918. USBD_STATUS UsbdStatus,
  919. NTSTATUS Completion,
  920. BOOLEAN RequestWasOnHardware
  921. )
  922. /*++
  923. Routine Description:
  924. This urb in the posible linked list of urbs has finished.
  925. First return its resources back to the system.
  926. Then (if it is the last of the urbs in the list) inform
  927. the original caller by completing the IRP.
  928. Arguments:
  929. The request that will be completed.
  930. The completion code for the IRP.
  931. --*/
  932. {
  933. struct _URB_HCD_COMMON_TRANSFER *transfer =
  934. &Urb->HcdUrbCommonTransfer;
  935. PMDL mdl = transfer->TransferBufferMDL;
  936. PHCD_ENDPOINT endpoint = transfer->hca.HcdEndpoint;
  937. PHCD_DEVICE_DATA DeviceData = endpoint->DeviceData;
  938. LONG epStatus;
  939. ASSERT_ENDPOINT(endpoint);
  940. LOGENTRY(G, 'cmpt', DeviceData, endpoint, Urb);
  941. // The transfer only has map registers allocated if it made it through
  942. // IoAllocateAdapterChannel() to OpenHCI_QueueGeneralRequest(), in which
  943. // case the status should no longer be HCD_PENDING_STATUS_QUEUED.
  944. // Don't call IoFlushAdapterBuffers() and IoFreeMapRegisters() if the
  945. // request has not made it through IoAllocateAdapterChannel() yet.
  946. //
  947. if (NULL != mdl &&
  948. transfer->Status != HCD_PENDING_STATUS_QUEUED)
  949. {
  950. ULONG NumberMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES
  951. (MmGetMdlVirtualAddress(mdl),
  952. MmGetMdlByteCount(mdl));
  953. LOGENTRY(G, 'flsh', DeviceData, mdl, NumberMapRegisters);
  954. IoFlushAdapterBuffers(
  955. DeviceData->AdapterObject, // BusMaster card
  956. transfer->TransferBufferMDL,
  957. transfer->hca.HcdExtension, // The MapRegisterBase
  958. (char *) MmGetMdlVirtualAddress(transfer->TransferBufferMDL),
  959. transfer->TransferBufferLength,
  960. (BOOLEAN) !
  961. (transfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN));
  962. LOGENTRY(G, 'frmp', DeviceData, mdl, NumberMapRegisters);
  963. IoFreeMapRegisters(DeviceData->AdapterObject,
  964. transfer->hca.HcdExtension, //MmGetMdlVirtualAddress(mdl),
  965. NumberMapRegisters);
  966. } else {
  967. LOGENTRY(G, 'frmZ', DeviceData, transfer->Status, 0);
  968. // IoFreeMapRegisters(DeviceData->AdapterObject,
  969. // NULL,/* VirtualAddress */
  970. // 0); /* Number of map registers */
  971. }
  972. if (RequestWasOnHardware) {
  973. epStatus = InterlockedDecrement(&endpoint->EndpointStatus);
  974. LOGENTRY(G, 'dcS1', 0, endpoint, epStatus );
  975. #if DBG
  976. if (endpoint->MaxRequest == 1) {
  977. // in limit xfer mode we should always be 0 here.
  978. OHCI_ASSERT(epStatus == 0);
  979. }
  980. #endif
  981. } else {
  982. epStatus = endpoint->EndpointStatus;
  983. LOGENTRY(G, 'epS1', 0, endpoint, epStatus );
  984. }
  985. OHCI_ASSERT(epStatus >= 0);
  986. LOGENTRY(G, 'epck', DeviceData, endpoint->MaxRequest, epStatus);
  987. if (endpoint->MaxRequest > epStatus) {
  988. /*
  989. * If there is space in the hardware TD queue (There is always room
  990. * for two entries) then pop whatever is on the top of the software
  991. * queue and place it and the hardware queue as a TD: aka start it.
  992. *
  993. * EndpointStatus is now zero based, not -1 based so the rest of the
  994. * comment below is not quite correct...
  995. *
  996. * Why not (InterlockedDecrement < 1) as the test you might ask... If
  997. * there is only one transfer turned into TD's, then EndpointStatus
  998. * is 0, and the decrement makes it -1. In this case we know we do
  999. * not need to call EndpointWorker. There is nothing on the software
  1000. * queue. If there were, than when it was actually added to the
  1001. * queue, it would have noticed that there was room to convert it
  1002. * into actual TD's (making EndpointStatus = 1).
  1003. */
  1004. OpenHCI_ProcessEndpoint(DeviceData, endpoint);
  1005. }
  1006. //
  1007. // update the status
  1008. //
  1009. ASSERT(transfer->Status == HCD_PENDING_STATUS_SUBMITTED ||
  1010. transfer->Status == HCD_PENDING_STATUS_QUEUED ||
  1011. transfer->Status == USBD_STATUS_CANCELING);
  1012. LOGENTRY(G, 'cmST', DeviceData, transfer, UsbdStatus);
  1013. transfer->Status = UsbdStatus;
  1014. ASSERT(transfer->UrbLink == NULL);
  1015. transfer->Status = UsbdStatus;
  1016. OpenHCI_CompleteIrp(endpoint->DeviceData->DeviceObject,
  1017. transfer->hca.HcdIrp,
  1018. Completion);
  1019. }
  1020. VOID
  1021. OpenHCI_CancelTransfer(
  1022. PDEVICE_OBJECT UsbDeviceObject,
  1023. PIRP Irp
  1024. )
  1025. /*++
  1026. Routine Description:
  1027. Remove from the software and hardware queues any and all URB's and TD's
  1028. associated with this Irp. Mark as cancelling each URB from this Irp,
  1029. they may be linked, and then put the endpoint into a paused state. The
  1030. function, Cancel TDs for ED will then remove all TD associated with a
  1031. cancelling URB.
  1032. STATUS_PENDING_QUEUED means we put it in the endpoint QUEUE
  1033. STATUS_PENDING_SUBMITTED means we programmed it to the hardware
  1034. Arguments:
  1035. Device: The device Object for which the Irp was destined.
  1036. Irp: The doomed IRP.
  1037. --*/
  1038. {
  1039. PHCD_DEVICE_DATA DeviceData;
  1040. PHCD_ENDPOINT endpoint;
  1041. KIRQL oldIrql;
  1042. struct _URB_HCD_COMMON_TRANSFER *transfer;
  1043. PDEVICE_OBJECT deviceObject;
  1044. PUSBD_EXTENSION de;
  1045. BOOLEAN wasOnHardware = FALSE;
  1046. BOOLEAN wasQueued = TRUE;
  1047. //
  1048. // first we need our extension
  1049. //
  1050. de = UsbDeviceObject->DeviceExtension;
  1051. if (de->TrueDeviceExtension == de) {
  1052. deviceObject = UsbDeviceObject;
  1053. } else {
  1054. de = de->TrueDeviceExtension;
  1055. deviceObject = de->HcdDeviceObject;
  1056. }
  1057. DeviceData = (PHCD_DEVICE_DATA) deviceObject->DeviceExtension;
  1058. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_CANCEL_TRACE,
  1059. ("'Cancel Transfer irp = %x\n", Irp));
  1060. ASSERT(TRUE == Irp->Cancel);
  1061. transfer = &((PHCD_URB) URB_FROM_IRP(Irp))->HcdUrbCommonTransfer;
  1062. endpoint = transfer->hca.HcdEndpoint;
  1063. ASSERT_ENDPOINT(endpoint);
  1064. LOGENTRY(G, 'CANx', DeviceData, Irp, endpoint);
  1065. IoSetCancelRoutine(Irp, NULL);
  1066. // lock down the endpoint
  1067. OpenHCI_LockAndCheckEndpoint(endpoint,
  1068. NULL,
  1069. NULL,
  1070. &oldIrql);
  1071. //
  1072. // now find all transfers linked to this irp and
  1073. // cancel them, 'transfer' points to the first one.
  1074. //
  1075. while (transfer) {
  1076. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_CANCEL_INFO,
  1077. ("'Canceling URB trans 0x%x End 0x%x \n",
  1078. transfer, endpoint));
  1079. LOGENTRY(G, 'CAur', Irp, transfer, endpoint);
  1080. ASSERT((URB_FUNCTION_CONTROL_TRANSFER == transfer->Function) ||
  1081. (URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER == transfer->Function) ||
  1082. (URB_FUNCTION_ISOCH_TRANSFER == transfer->Function));
  1083. // Here we are assuming that all URBs on a single IRP have are
  1084. // desten for the same endpoint.
  1085. ASSERT(transfer->hca.HcdEndpoint == endpoint);
  1086. //
  1087. // cancel this transfer
  1088. //
  1089. if (transfer->Status == HCD_PENDING_STATUS_QUEUED) {
  1090. //
  1091. // See if the request is still queued and we need to remove it
  1092. //
  1093. if (transfer->hca.HcdListEntry.Flink != NULL)
  1094. {
  1095. // pull it off our queue
  1096. //
  1097. LOGENTRY(G, 'caQR', Irp, transfer, endpoint);
  1098. OHCI_ASSERT(transfer->hca.HcdListEntry.Blink != NULL);
  1099. RemoveEntryList(&transfer->hca.HcdListEntry);
  1100. transfer->hca.HcdListEntry.Flink = NULL;
  1101. transfer->hca.HcdListEntry.Blink = NULL;
  1102. }
  1103. else
  1104. {
  1105. // The request no longer appears to be queued on the
  1106. // endpoint.
  1107. //
  1108. LOGENTRY(G, 'caNR', Irp, transfer, endpoint);
  1109. wasQueued = FALSE;
  1110. }
  1111. } else if (transfer->Status == HCD_PENDING_STATUS_SUBMITTED) {
  1112. //
  1113. // this transfer urb is on the hardware
  1114. //
  1115. LOGENTRY(G, 'caPR', Irp, transfer, endpoint);
  1116. transfer->Status = USBD_STATUS_CANCELING;
  1117. // put it on the cancel list before we release with
  1118. // the endpoint, onec we release the endpoint
  1119. // CaneclTDsforED can pick it up and cancel it
  1120. wasOnHardware = TRUE;
  1121. OHCI_ASSERT(transfer->hca.HcdListEntry.Flink == NULL);
  1122. LOGENTRY(G, 'cXAQ', Irp, transfer, transfer->Status);
  1123. // CancelTDsFor ED will put this on the cancel list
  1124. // when the TDS have been removed from the EP
  1125. //InsertTailList(&endpoint->CancelList,
  1126. // &transfer->hca.HcdListEntry);
  1127. }
  1128. if (transfer->UrbLink) {
  1129. transfer = &transfer->UrbLink->HcdUrbCommonTransfer;
  1130. } else {
  1131. transfer = NULL;
  1132. }
  1133. }
  1134. OpenHCI_UnlockEndpoint(endpoint,
  1135. oldIrql);
  1136. //
  1137. // the transfer is now removed from the endpoint
  1138. // it is safe to let things run now
  1139. LOGENTRY(G, 'Rcsp', DeviceData, Irp, Irp->CancelIrql);
  1140. IoReleaseCancelSpinLock(Irp->CancelIrql);
  1141. // now complete the transfers that were queued
  1142. if (wasOnHardware) {
  1143. // note that if the transfer was on the hardware it may be complet
  1144. // by now so we cannot touch it
  1145. LOGENTRY(G, 'WAhw', endpoint, 0, 0);
  1146. // this will cause cancelTDs for ED to pick it up and
  1147. // cancel it
  1148. OpenHCI_PauseED(endpoint);
  1149. } else if (wasQueued) {
  1150. transfer = &((PHCD_URB) URB_FROM_IRP(Irp))->HcdUrbCommonTransfer;
  1151. while (transfer) {
  1152. LOGENTRY(G, 'caDN', Irp, transfer, transfer->Status);
  1153. if (transfer->Status == HCD_PENDING_STATUS_QUEUED) {
  1154. struct _URB_HCD_COMMON_TRANSFER *nextTransfer;
  1155. LOGENTRY(G, 'caQD', Irp, transfer, transfer->Status);
  1156. // check the link before we complete
  1157. if (transfer->UrbLink) {
  1158. nextTransfer = &transfer->UrbLink->HcdUrbCommonTransfer;
  1159. } else {
  1160. nextTransfer = NULL;
  1161. }
  1162. OpenHCI_CompleteUsbdTransferRequest((PHCD_URB) transfer,
  1163. USBD_STATUS_CANCELED,
  1164. STATUS_CANCELLED,
  1165. FALSE);
  1166. transfer = nextTransfer;
  1167. } else if (transfer->Status == USBD_STATUS_CANCELING) {
  1168. //
  1169. // at least one of the urbs for this Irp is on the hardware
  1170. // so we'll need to stop the ed and remove the TDs.
  1171. //
  1172. TRAP();
  1173. // sould not get here
  1174. } else {
  1175. // the transfer completed while we were canecling
  1176. //
  1177. // we need to complete it here
  1178. //
  1179. struct _URB_HCD_COMMON_TRANSFER *nextTransfer;
  1180. LOGENTRY(G, 'CALc', 0, transfer, transfer->Status);
  1181. // check the link before we complete
  1182. if (transfer->UrbLink) {
  1183. nextTransfer = &transfer->UrbLink->HcdUrbCommonTransfer;
  1184. } else {
  1185. nextTransfer = NULL;
  1186. }
  1187. OpenHCI_CompleteUsbdTransferRequest((PHCD_URB) transfer,
  1188. USBD_STATUS_CANCELED,
  1189. STATUS_CANCELLED,
  1190. FALSE);
  1191. transfer = nextTransfer;
  1192. }
  1193. }
  1194. }
  1195. OpenHCI_KdPrintDD(DeviceData,
  1196. OHCI_DBG_CANCEL_TRACE, ("'Exit Cancel Trans\n"));
  1197. }
  1198. VOID
  1199. OpenHCI_ProcessDoneTD(
  1200. PHCD_DEVICE_DATA DeviceData,
  1201. PHCD_TRANSFER_DESCRIPTOR Td,
  1202. BOOLEAN FreeTD
  1203. )
  1204. /*++
  1205. Routine Description:
  1206. Parameters
  1207. --*/
  1208. {
  1209. PHCD_URB urb;
  1210. struct _URB_HCD_COMMON_TRANSFER *transfer;
  1211. PHCD_ENDPOINT endpoint;
  1212. PHC_TRANSFER_DESCRIPTOR hcTD;
  1213. PHC_ENDPOINT_DESCRIPTOR hcED;
  1214. USBD_STATUS usbdStatus;
  1215. BOOLEAN complete = FALSE;
  1216. NTSTATUS status = STATUS_SUCCESS;
  1217. PHCD_ENDPOINT_DESCRIPTOR ed;
  1218. KIRQL oldIrql;
  1219. hcTD = &Td->HcTD;
  1220. LOGENTRY(G, 'TDdn', DeviceData, Td, 0);
  1221. if (Td->Canceled) {
  1222. // td has been marked canceled -- this means it was
  1223. // already processed by cancel, all we need to do is
  1224. // free it.
  1225. // (See the CancelTDsForED routine)
  1226. LOGENTRY(G, 'frCA', DeviceData, Td, 0);
  1227. if (FreeTD) {
  1228. OpenHCI_Free_HcdTD(DeviceData, Td);
  1229. }
  1230. return;
  1231. }
  1232. OHCI_ASSERT(Td->UsbdRequest != MAGIC_SIG);
  1233. urb = Td->UsbdRequest;
  1234. endpoint = Td->Endpoint;
  1235. transfer = &urb->HcdUrbCommonTransfer;
  1236. LOGENTRY(G, 'TDde', endpoint, urb, transfer);
  1237. ASSERT_ENDPOINT(endpoint);
  1238. OHCI_ASSERT(urb);
  1239. OHCI_ASSERT(transfer);
  1240. OHCI_ASSERT(TD_NOREQUEST_SIG != urb);
  1241. // process the completed TD
  1242. ed = endpoint->HcdED;
  1243. hcED = &ed->HcED;
  1244. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_NOISE,
  1245. ("'Endpoint: %x ED: %x\n", endpoint, ed));
  1246. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_TRACE,
  1247. ("'TD Done, code: %x, Directn: %x, addr: %d, end#: %d\n",
  1248. hcTD->ConditionCode, hcTD->Direction,
  1249. hcED->FunctionAddress, hcED->EndpointNumber));
  1250. if (endpoint->Type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
  1251. complete =
  1252. OpenHCI_ProcessDoneIsoTD(DeviceData,
  1253. Td,
  1254. endpoint,
  1255. hcTD,
  1256. &status,
  1257. &usbdStatus,
  1258. urb,
  1259. FreeTD);
  1260. } else {
  1261. complete =
  1262. OpenHCI_ProcessDoneAsyncTD(DeviceData,
  1263. Td,
  1264. endpoint,
  1265. hcTD,
  1266. &status,
  1267. &usbdStatus,
  1268. urb,
  1269. FreeTD);
  1270. }
  1271. if (complete) {
  1272. //
  1273. // urb associated with this TD is complete
  1274. //
  1275. IoAcquireCancelSpinLock(&oldIrql);
  1276. //
  1277. // now that we have cleared the cancel routine
  1278. // it is safe to modify the status field of
  1279. // the urb.
  1280. //
  1281. IoSetCancelRoutine(transfer->hca.HcdIrp, NULL);
  1282. IoReleaseCancelSpinLock(oldIrql);
  1283. // now comlete the urb
  1284. LOGENTRY(G, 'urbC', urb, status, usbdStatus);
  1285. OpenHCI_CompleteUsbdTransferRequest(urb,
  1286. usbdStatus,
  1287. status,
  1288. TRUE);
  1289. }
  1290. }
  1291. VOID
  1292. OpenHCI_ProcessDoneQueue(
  1293. PHCD_DEVICE_DATA DeviceData,
  1294. ULONG physHcTD
  1295. )
  1296. /*++
  1297. Routine Description:
  1298. Periodically the HC places the list of TD's that is has completed
  1299. on to the DoneList.
  1300. This routine, called by Dpc for ISR, walks that list, which must
  1301. be reversed, and finishes any processing.
  1302. There are packets that completed normally, Ins and outs.
  1303. There are also canceled TDs,
  1304. Parameters
  1305. physHcTD - Hcca Done Head pointer (logical address)
  1306. --*/
  1307. {
  1308. PHCD_TRANSFER_DESCRIPTOR td, tdList = NULL;
  1309. PHC_OPERATIONAL_REGISTER HC;
  1310. KIRQL oldIrql;
  1311. #if DBG
  1312. //PCHAR Buffer;
  1313. #endif
  1314. BOOLEAN complete = FALSE;
  1315. NTSTATUS status = STATUS_SUCCESS;
  1316. OpenHCI_KdPrintDD(DeviceData,
  1317. OHCI_DBG_TD_TRACE, ("'Phys TD:%x\n", physHcTD));
  1318. if (0 == physHcTD) {
  1319. //
  1320. // nothing to do
  1321. //
  1322. LOGENTRY(G, 'idle', DeviceData, 0, 0);
  1323. return;
  1324. }
  1325. //
  1326. // OK we have some TDs on the list,
  1327. // process them
  1328. HC = DeviceData->HC;
  1329. KeAcquireSpinLock(&DeviceData->PageListSpin, &oldIrql);
  1330. do {
  1331. td = OpenHCI_LogDesc_to_PhyDesc(DeviceData, physHcTD);
  1332. LOGENTRY(G, 'dnTD', DeviceData, td, physHcTD);
  1333. OHCI_ASSERT(td);
  1334. //
  1335. // If TD comes back from LogDesc to PhyDesc as zero then
  1336. // this was not a HcTD corresponding to a know HcdTD.
  1337. // The controller has given us a bogus hardware address for HcTD.
  1338. //
  1339. if (td == NULL)
  1340. {
  1341. // Something is not quite right, hope we haven't lost some TDs.
  1342. //
  1343. break;
  1344. }
  1345. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_NOISE,
  1346. ("'---Virt TD %x from done list: %x\n",
  1347. td, physHcTD));
  1348. physHcTD = td->HcTD.NextTD;
  1349. //
  1350. // Since the HC places TD's into the done list
  1351. // in the reverse order in which they were processed,
  1352. // we nee to reverse this list.
  1353. //
  1354. // We do this by bastadizing the NextTD which used
  1355. // to hold logical addresses.
  1356. // This ASSUMES that a ULONG is the same size as a pointer.
  1357. //
  1358. LOGENTRY(G, 'dnT1', td, td->SortNext, (ULONG_PTR) tdList);
  1359. LOGENTRY(G, 'dnTn', td, physHcTD, 0);
  1360. td->SortNext = (ULONG_PTR) tdList;
  1361. tdList = td;
  1362. } while (physHcTD);
  1363. KeReleaseSpinLock(&DeviceData->PageListSpin, oldIrql);
  1364. //
  1365. // tdList is now a linked list of completed TDs in the
  1366. // order of completion, walk the list processing each one
  1367. while (NULL != tdList) {
  1368. td = tdList;
  1369. /* bastardizing */
  1370. tdList = (PHCD_TRANSFER_DESCRIPTOR) td->SortNext;
  1371. OpenHCI_ProcessDoneTD(DeviceData, td, TRUE);
  1372. } /* while tdList */
  1373. }
  1374. BOOLEAN
  1375. OpenHCI_ProcessDoneAsyncTD(
  1376. PHCD_DEVICE_DATA DeviceData,
  1377. PHCD_TRANSFER_DESCRIPTOR Td,
  1378. PHCD_ENDPOINT Endpoint,
  1379. PHC_TRANSFER_DESCRIPTOR HcTD,
  1380. NTSTATUS *NtStatus,
  1381. USBD_STATUS *UsbdStatus,
  1382. PHCD_URB Urb,
  1383. BOOLEAN FreeTD
  1384. )
  1385. /*++
  1386. Routine Description:
  1387. Parameters
  1388. --*/
  1389. {
  1390. BOOLEAN control;
  1391. struct _URB_HCD_COMMON_TRANSFER *transfer;
  1392. BOOLEAN complete = FALSE;
  1393. PHCD_ENDPOINT_DESCRIPTOR ed;
  1394. PHCD_TRANSFER_DESCRIPTOR tn, nextTd;
  1395. PLIST_ENTRY entry;
  1396. PHC_OPERATIONAL_REGISTER HC;
  1397. transfer = &Urb->HcdUrbCommonTransfer;
  1398. ed = Endpoint->HcdED;
  1399. HC = DeviceData->HC;
  1400. control = Endpoint->Type == USB_ENDPOINT_TYPE_CONTROL;
  1401. OHCI_ASSERT(USB_ENDPOINT_TYPE_ISOCHRONOUS != Endpoint->Type);
  1402. if (HcTD->CBP) {
  1403. //
  1404. // A value of 0 here indicates a zero length data packet
  1405. // or that all bytes have been transfered.
  1406. //
  1407. // The buffer is only spec'ed for length up to two 4K pages.
  1408. // (BE is the physical address of the last byte in the
  1409. // TD buffer. CBP is the current byte pointer)
  1410. //
  1411. // TransferCount is intailized to the number of bytes to transfer,
  1412. // we need to subtract the difference between the end and
  1413. // current ptr (ie end-current = bytes not transferred) and
  1414. // update the TransferCount.
  1415. // transfer count should never go negative
  1416. // TransferCount will be zero on the status
  1417. // phase of a control transfer so we skip
  1418. // the calculation
  1419. if (Td->TransferCount) {
  1420. Td->TransferCount -=
  1421. /* have we gone further than a page? */
  1422. ((((HcTD->BE ^ HcTD->CBP) & ~OHCI_PAGE_SIZE_MASK)
  1423. ? OHCI_PAGE_SIZE : 0) +
  1424. /* minus the data buffer not used */
  1425. ((HcTD->BE & OHCI_PAGE_SIZE_MASK) -
  1426. (HcTD->CBP & OHCI_PAGE_SIZE_MASK)+1));
  1427. }
  1428. LOGENTRY(G, 'xfrB', HcTD->BE & OHCI_PAGE_SIZE_MASK,
  1429. HcTD->CBP & OHCI_PAGE_SIZE_MASK,
  1430. Td->TransferCount);
  1431. }
  1432. if (!control ||
  1433. HcTDDirection_Setup != HcTD->Direction) {
  1434. // data phase of a control transfer or a bulk/int
  1435. // data transfer
  1436. LOGENTRY(G, 'BIdt', Td, transfer, Td->TransferCount);
  1437. if (transfer->TransferBufferMDL) {
  1438. transfer->TransferBufferLength += Td->TransferCount;
  1439. #if DBG
  1440. if (0 == Td->TransferCount) {
  1441. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_ERROR,
  1442. ("'TD no data %x %x\n", Td->HcTD.CBP, Td->HcTD.BE));
  1443. }
  1444. #endif
  1445. //
  1446. // ASSERT (TD->TransferCount);
  1447. // TransferCount could be zero but only if the TD returned in
  1448. // error.
  1449. //
  1450. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_NOISE,
  1451. ("'Data Transferred 0x%x bytes \n", Td->TransferCount));
  1452. LOGENTRY(G, 'xfrT', DeviceData, Td->TransferCount, 0);
  1453. #if 0
  1454. {
  1455. PUCHAR buffer =
  1456. MmGetSystemAddressForMdl(transfer->TransferBufferMDL);
  1457. //
  1458. // Print out contents of buffer received.
  1459. //
  1460. if ((trans->TransferFlags & USBD_TRANSFER_DIRECTION_IN) &&
  1461. (USB_ENDPOINT_TYPE_CONTROL == Endpoint->Type)) {
  1462. ULONG j;
  1463. OpenHCI_KdPrintDD(DeviceData,
  1464. OHCI_DBG_TD_NOISE, ("'Buffer: "));
  1465. for (j = 0;
  1466. (j < trans->TransferBufferLength) && (j < 16);
  1467. j++) {
  1468. if (DeviceData->DebugLevel & OHCI_DBG_TD_NOISE) {
  1469. DbgPrint("'%02.2x ", ((unsigned int) *(Buffer + j)));
  1470. }
  1471. }
  1472. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_NOISE, ("'\n"));
  1473. }
  1474. }
  1475. #endif
  1476. } /* trans->TransferBufferMDL */
  1477. }
  1478. // If EP_ONE_TD is set for the endpoint then the buffer Rounding
  1479. // bit will be set for every TD, regardless of whether or not the
  1480. // USBD_SHORT_TRANSFER_OK is set. If the buffer Rounding bit is
  1481. // set then the condition code will be NoError even if there is
  1482. // a short transfer. If there is a short transfer, CBP will be
  1483. // non-zero. If a short transfer occurs when EP_ONE_TD is set
  1484. // and there isn't any other error, pretend there was a DataUnderrun
  1485. // error so the TD error handling code will remove all of the
  1486. // remaining TDs for the transfer. If USBD_SHORT_TRANSFER_OK is set,
  1487. // the TD error handling code will then pretend the pretend
  1488. // DataUnderrun error didn't occur.
  1489. //
  1490. if ((Endpoint->EpFlags & EP_ONE_TD) &&
  1491. (HcCC_NoError == HcTD->ConditionCode) &&
  1492. (HcTD->CBP != 0))
  1493. {
  1494. LOGENTRY(G, 'Shrt', HcTD->Control, Td->HcTD.CBP, Td->HcTD.BE);
  1495. ed->HcED.HeadP |= HcEDHeadP_HALT;
  1496. HcTD->ConditionCode = HcCC_DataUnderrun;
  1497. }
  1498. //
  1499. // check for errors
  1500. //
  1501. if (HcCC_NoError == HcTD->ConditionCode) {
  1502. //
  1503. // TD completed without error, remove it from
  1504. // the USBD_REQUEST list, if USBD_REQUEST list
  1505. // is now empty, then complete.
  1506. //
  1507. Endpoint->HcdHeadP = Td->NextHcdTD;
  1508. // Remove the TD from the HCD list of TDs
  1509. //
  1510. // Note: Currently we only have one irq DPC routine running
  1511. // at a time. This means that the CancelTDsForED and
  1512. // ProcessDoneQ cannot run concurrently. For this reason,
  1513. // we do not need to worry with moving the Endpoint's head
  1514. // pointer to TD's.
  1515. //
  1516. // If these routines could run concurrently then DoneQ
  1517. // could test for canceled. The Cancle routine could then
  1518. // notice that a TD was in the DoneQ and mark it for cancel
  1519. // then a canceled TD would be here. The RemoveListEntry
  1520. // call would fail as would the CompleteUsbdRequest.
  1521. //
  1522. //
  1523. // Note also that because the linked list of SoftwareTD's
  1524. // is only a singly linked list (Endpoint->HcdHeadP = TD->Next)
  1525. // We cannot receive TDs out of order.
  1526. //
  1527. RemoveEntryList(&Td->RequestList);
  1528. if (IsListEmpty(&transfer->hca.HcdListEntry2)) {
  1529. //
  1530. // no more TD's for this URB.
  1531. //
  1532. complete = TRUE;
  1533. *UsbdStatus = USBD_STATUS_SUCCESS;
  1534. *NtStatus = STATUS_SUCCESS;
  1535. LOGENTRY(G, 'xfrC', DeviceData, transfer, 0);
  1536. if (Endpoint->TrueTail) {
  1537. // this transfer complete, set true tail ptr to
  1538. // NULL (trueTail is only used when we limit the
  1539. // endpoint to one active TD)
  1540. OHCI_ASSERT(Endpoint->TrueTail == Endpoint->HcdHeadP);
  1541. Endpoint->TrueTail = NULL;
  1542. }
  1543. if (FreeTD) {
  1544. OpenHCI_Free_HcdTD(DeviceData, Td);
  1545. }
  1546. } else {
  1547. LOGENTRY(G, 'xfrP', DeviceData, transfer, Endpoint->TrueTail);
  1548. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_TRACE,
  1549. ("'No Complete IRP more TD pending\n"));
  1550. // see if we need to update the tail ptr
  1551. if (Endpoint->TrueTail) {
  1552. nextTd = Td->NextHcdTD;
  1553. //HcED headp should be pointing to this TD
  1554. OHCI_ASSERT((ed->HcED.HeadP & ~HcEDHeadP_FLAGS) == nextTd->PhysicalAddress);
  1555. LOGENTRY(G, 'upTL', Endpoint->TrueTail, Endpoint, nextTd);
  1556. // The nextTD should not be the same as the TrueTail TD.
  1557. // If it was, then that should mean that there are no TDs
  1558. // left for this URB and the IsListEmpty() above should
  1559. // have been true and we should not be in this else clause.
  1560. //
  1561. OHCI_ASSERT(nextTd != Endpoint->TrueTail);
  1562. // We have already asserted that the HeadP is the same
  1563. // as nextTD at this point. Bump nextTD to the next one
  1564. // for the new TailP.
  1565. //
  1566. nextTd = nextTd->NextHcdTD;
  1567. LOGENTRY(G, 'upT2', Endpoint->TrueTail, Endpoint, nextTd);
  1568. Endpoint->HcdTailP = nextTd;
  1569. ed->HcED.TailP = nextTd->PhysicalAddress;
  1570. ENABLE_LIST(HC, Endpoint)
  1571. }
  1572. if (FreeTD) {
  1573. OpenHCI_Free_HcdTD(DeviceData, Td);
  1574. }
  1575. }
  1576. } else {
  1577. /*
  1578. * TD completed with an error, remove it and
  1579. * the TDs for the same request, set appropriate
  1580. * status in USBD_REQUEST and then complete it.
  1581. *
  1582. * TWO SPECIAL CASES:
  1583. * (1)
  1584. * DataUnderrun for Bulk or Interrupt and
  1585. * ShortXferOK. do not report error to USBD
  1586. * and restart the endpoint.
  1587. * (2)
  1588. * DataUnderrun on Control and ShortXferOK.
  1589. * The final status TD for the Request should
  1590. * not be canceled, the Request should not be
  1591. * completed, and the endpoint should be
  1592. * restarted.
  1593. *
  1594. * NOTE:
  1595. * In all error cases the endpoint
  1596. * has been halted by controller.
  1597. */
  1598. LOGENTRY(G, 'tERR', DeviceData, Td, Td->HcTD.ConditionCode);
  1599. // The ED better be Halted because we're going to mess with
  1600. // the ED HeadP and TailP pointers
  1601. //
  1602. ASSERT(ed->HcED.HeadP & HcEDHeadP_HALT);
  1603. if (Endpoint->TrueTail) {
  1604. LOGENTRY(G, 'eTTl', Endpoint->TrueTail,
  1605. Endpoint->HcdTailP, Endpoint);
  1606. // Bump the software tail pointer to the true tail for this transfer
  1607. //
  1608. Endpoint->HcdTailP = Endpoint->TrueTail;
  1609. Endpoint->TrueTail = NULL;
  1610. // Bump the hardware tail pointer to the true tail for this transfer
  1611. //
  1612. Endpoint->HcdED->HcED.TailP = Endpoint->HcdTailP->PhysicalAddress;
  1613. }
  1614. for (tn = Endpoint->HcdHeadP;
  1615. tn != Endpoint->HcdTailP;
  1616. tn = tn->NextHcdTD) {
  1617. LOGENTRY(G, 'bump', DeviceData, Td, tn);
  1618. //
  1619. // We want to flush out to the end of this current URB
  1620. // request since there could still be TD's linked together
  1621. // for the the current URB.
  1622. // Move tn until it points to the first TD that we
  1623. // wish to leave ``on the hardware''.
  1624. //
  1625. if ((Urb != tn->UsbdRequest) || /* another request */
  1626. ((HcCC_DataUnderrun == Td->HcTD.ConditionCode)
  1627. && (USBD_SHORT_TRANSFER_OK & transfer->TransferFlags)
  1628. && (Td->HcTD.Direction != tn->HcTD.Direction))) {
  1629. // ^^^^ Here we have the status TD for a Short
  1630. // control
  1631. // Transfer. We still need run this last TD.
  1632. LOGENTRY(G, 'stpB', DeviceData, Td, Td->HcTD.ConditionCode);
  1633. break;
  1634. }
  1635. }
  1636. // Bump the software head pointer over all TD's until tn
  1637. //
  1638. Endpoint->HcdHeadP = tn;
  1639. // Bump the hardware head pointer over all TD's until tn, preserving
  1640. // the current ED Halted and toggle Carry bits.
  1641. //
  1642. ed->HcED.HeadP = tn->PhysicalAddress
  1643. | (ed->HcED.HeadP & HcEDHeadP_FLAGS);
  1644. // all TDs unlinked, now we just need to free them
  1645. while (!IsListEmpty(&transfer->hca.HcdListEntry2)) {
  1646. entry = RemoveHeadList(&transfer->hca.HcdListEntry2);
  1647. tn = CONTAINING_RECORD(entry,
  1648. HCD_TRANSFER_DESCRIPTOR,
  1649. RequestList);
  1650. if ((tn != Td) &&
  1651. (tn != Endpoint->HcdHeadP) &&
  1652. FreeTD) {
  1653. OpenHCI_Free_HcdTD(DeviceData, tn);
  1654. }
  1655. }
  1656. // if we are still pointing to the current Urb
  1657. // then this is a status phase for a short
  1658. // control transfer (ShortTransferOK).
  1659. if (Endpoint->HcdHeadP->UsbdRequest == Urb) {
  1660. TEST_TRAP();
  1661. // We should use the status of this last TD (the status td)
  1662. // to return in the URB, so place this TD back onto the list
  1663. // for this endpoint and allow things to run normally.
  1664. LOGENTRY(G, 'putB', DeviceData, Td, transfer);
  1665. InsertTailList(&transfer->hca.HcdListEntry2,
  1666. &Endpoint->HcdHeadP->RequestList);
  1667. } else {
  1668. //
  1669. // This transfer is done
  1670. //
  1671. // NOTE: we do not modify the status in the urb yet because
  1672. // the cancel routine looks at this value to determine
  1673. // what action to take.
  1674. //
  1675. if (HcCC_DataUnderrun == Td->HcTD.ConditionCode) {
  1676. //
  1677. // Behave the same way here as UHCD does. If the
  1678. // SHORT_TRANSFER_OK flag is set, ignore the DataUnderrun
  1679. // error and return USBD_STATUS_SUCCESS, else return
  1680. // USBD_STATUS_ERROR_SHORT_TRANSFER. In either case
  1681. // the endpoint is not left in the Halted state.
  1682. //
  1683. if (USBD_SHORT_TRANSFER_OK & transfer->TransferFlags) {
  1684. LOGENTRY(G, 'shOK', DeviceData, Td, transfer);
  1685. *UsbdStatus = USBD_STATUS_SUCCESS;
  1686. } else {
  1687. LOGENTRY(G, 'shNO', DeviceData, Td, transfer);
  1688. *UsbdStatus = USBD_STATUS_ERROR_SHORT_TRANSFER;
  1689. }
  1690. // Clear the Halted bit in the ED
  1691. //
  1692. ed->HcED.HeadP &= ~HcEDHeadP_HALT;
  1693. // Tell the HC we have something on the ED lists
  1694. //
  1695. ENABLE_LIST(HC, Endpoint);
  1696. } else {
  1697. *UsbdStatus = (Td->HcTD.ConditionCode | 0xC0000000);
  1698. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_ERROR,
  1699. ("'Done queue: TD error: 0x%x CBP: 0x%x BE: 0x%x\n",
  1700. HcTD->ConditionCode,
  1701. HcTD->CBP,
  1702. HcTD->BE));
  1703. //#if DBG
  1704. // if (5 != Td->HcTD.ConditionCode) {
  1705. // TRAP(); // Code trap requested by WDM lab
  1706. // }
  1707. //#endif
  1708. }
  1709. if (FreeTD) {
  1710. OpenHCI_Free_HcdTD(DeviceData, Td);
  1711. }
  1712. complete = TRUE;
  1713. *NtStatus = STATUS_SUCCESS;
  1714. }
  1715. if ((USB_ENDPOINT_TYPE_CONTROL == Endpoint->Type) &&
  1716. (ed->HcED.HeadP & HcEDHeadP_HALT)) {
  1717. //
  1718. // For Control Endpoints, we always clear the
  1719. // halt condition automatically.
  1720. //
  1721. LOGENTRY(G, 'clrH', DeviceData, Td, transfer);
  1722. ed->HcED.HeadP &= ~HcEDHeadP_HALT;
  1723. ENABLE_LIST(HC, Endpoint);
  1724. }
  1725. } // error
  1726. return complete;
  1727. }
  1728. USBD_STATUS
  1729. OpenHCI_ProcessHWPacket(
  1730. struct _URB_ISOCH_TRANSFER *Iso,
  1731. PHCD_TRANSFER_DESCRIPTOR Td,
  1732. ULONG Idx,
  1733. ULONG LastFrame
  1734. )
  1735. {
  1736. struct _USBD_ISO_PACKET_DESCRIPTOR *pkt;
  1737. PHC_OFFSET_PSW psw;
  1738. USBD_STATUS err;
  1739. ULONG length;
  1740. pkt = &(Iso->IsoPacket[Idx + Td->BaseIsocURBOffset]);
  1741. psw = &(Td->HcTD.Packet[Idx]);
  1742. //
  1743. // always return whatever size we got
  1744. // unless the error was Not_accessed
  1745. //
  1746. if (Iso->TransferFlags & USBD_TRANSFER_DIRECTION_IN) {
  1747. length = (psw->PSW & HcPSW_RETURN_SIZE);
  1748. } else {
  1749. // compute the length requested
  1750. length = Iso->IsoPacket[Idx + Td->BaseIsocURBOffset].Length;
  1751. }
  1752. err = (psw->PSW & HcPSW_CONDITION_CODE_MASK)
  1753. >> HcPSW_CONDITION_CODE_SHIFT;
  1754. LOGENTRY(G, 'PKTs',
  1755. err,
  1756. (psw->PSW & HcPSW_CONDITION_CODE_MASK)
  1757. >> HcPSW_CONDITION_CODE_SHIFT,
  1758. length);
  1759. switch(err) {
  1760. case HcCC_DataUnderrun :
  1761. // not a full packet,
  1762. // data underrun is OK, we don't fail the
  1763. // urb but we do return the status for the
  1764. // packet.
  1765. //
  1766. pkt->Status = err;
  1767. err = USBD_STATUS_SUCCESS;
  1768. LOGENTRY(G, 'ISOu', err, Idx, 0);
  1769. break;
  1770. case HcCC_NotAccessed:
  1771. length = 0;
  1772. break;
  1773. }
  1774. if (err) {
  1775. //
  1776. // we have a legitamate error
  1777. //
  1778. err |= 0xC0000000;
  1779. pkt->Status = err;
  1780. LOGENTRY(G, 'ISO!', err, Idx, 0);
  1781. }
  1782. // set return length
  1783. if (Iso->TransferFlags & USBD_TRANSFER_DIRECTION_IN) {
  1784. // return the length for in transfers
  1785. pkt->Length = length;
  1786. }
  1787. // update length with whatever we got
  1788. Iso->TransferBufferLength +=
  1789. length;
  1790. LOGENTRY(G, 'isoL', length, Iso->TransferBufferLength, 0);
  1791. if (err == USBD_STATUS_SUCCESS) {
  1792. pkt->Status = USBD_STATUS_SUCCESS;
  1793. } else {
  1794. Iso->ErrorCount++;
  1795. }
  1796. return err;
  1797. }
  1798. BOOLEAN
  1799. OpenHCI_ProcessDoneIsoTD(
  1800. PHCD_DEVICE_DATA DeviceData,
  1801. PHCD_TRANSFER_DESCRIPTOR Td,
  1802. PHCD_ENDPOINT Endpoint,
  1803. PHC_TRANSFER_DESCRIPTOR HcTD,
  1804. NTSTATUS *NtStatus,
  1805. USBD_STATUS *UsbdStatus,
  1806. PHCD_URB Urb,
  1807. BOOLEAN FreeTD
  1808. )
  1809. /*++
  1810. Routine Description:
  1811. Parameters
  1812. --*/
  1813. {
  1814. struct _URB_HCD_COMMON_TRANSFER *transfer;
  1815. struct _URB_ISOCH_TRANSFER *iso;
  1816. BOOLEAN complete = FALSE;
  1817. PHCD_ENDPOINT_DESCRIPTOR ed;
  1818. BOOLEAN gotError = FALSE;
  1819. ULONG frames, j, lengthCurrent;
  1820. USBD_STATUS status;
  1821. iso = (PVOID) transfer = (PVOID) &Urb->HcdUrbCommonTransfer;
  1822. ed = Endpoint->HcdED;
  1823. OHCI_ASSERT(USB_ENDPOINT_TYPE_ISOCHRONOUS == Endpoint->Type);
  1824. // Frames is one less than the number of PSW's
  1825. // in this TD.
  1826. frames = (Td->HcTD.Control & HcTDControl_FRAME_COUNT_MASK)
  1827. >> HcTDControl_FRAME_COUNT_SHIFT;
  1828. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_NOISE,
  1829. ("'--------Done q: ISO pkt!\n"));
  1830. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_NOISE,
  1831. ("' Starting Frame: %x Frame Cnt: %x Cur Frame: %x\n",
  1832. Td->HcTD.StartingFrame,
  1833. Td->HcTD.FrameCount + 1,
  1834. Get32BitFrameNumber(DeviceData)));
  1835. LOGENTRY(M, 'IsoD', Td, transfer, 0);
  1836. *NtStatus = STATUS_SUCCESS;
  1837. *UsbdStatus = USBD_STATUS_SUCCESS;
  1838. // Remove the TD from the HCD list of TDs
  1839. Endpoint->HcdHeadP = Td->NextHcdTD;
  1840. // walk through the TD and update the packet entries
  1841. // in the urb
  1842. OHCI_ASSERT(frames <= 7);
  1843. for (j = 0; j < frames+1; j++) {
  1844. status = OpenHCI_ProcessHWPacket(iso, Td, j, frames);
  1845. if (USBD_ERROR(status)) {
  1846. gotError = TRUE;
  1847. }
  1848. }
  1849. if (gotError) {
  1850. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_ERROR,
  1851. ("'Done queue: ISOC TD error: 0x%x CBP: 0x%x BE: 0x%x\n",
  1852. HcTD->ConditionCode,
  1853. HcTD->CBP,
  1854. HcTD->BE));
  1855. LOGENTRY(M, 'IsoE', Td->HcTD.ConditionCode,
  1856. Td->HcTD.CBP,
  1857. Td->HcTD.BE);
  1858. // TEST_TRAP();
  1859. //
  1860. // For Isoc and Control Endpoints, we always clear the halt
  1861. // condition automatically.
  1862. //
  1863. if (ed->HcED.HeadP & HcEDHeadP_HALT) {
  1864. ed->HcED.HeadP &= ~HcEDHeadP_HALT;
  1865. }
  1866. }
  1867. //
  1868. // the TD is done
  1869. //
  1870. //
  1871. // flush buffers or this TD, we flush up to the offset+length
  1872. // of the last packet in this TD
  1873. //
  1874. lengthCurrent = iso->IsoPacket[frames + Td->BaseIsocURBOffset].Offset +
  1875. iso->IsoPacket[frames + Td->BaseIsocURBOffset].Length;
  1876. OHCI_ASSERT(transfer->TransferBufferMDL);
  1877. RemoveEntryList(&Td->RequestList);
  1878. if (FreeTD) {
  1879. OpenHCI_Free_HcdTD(DeviceData, Td);
  1880. }
  1881. LOGENTRY(M, 'Iso>', lengthCurrent,
  1882. transfer,
  1883. &transfer->hca.HcdListEntry2);
  1884. if (IsListEmpty(&transfer->hca.HcdListEntry2)) {
  1885. // AKA no more TD's for this URB.
  1886. if (iso->ErrorCount == iso->NumberOfPackets) {
  1887. // all errors set error code for urb
  1888. *UsbdStatus = USBD_STATUS_ISOCH_REQUEST_FAILED;
  1889. }
  1890. LOGENTRY(M, 'IsoC', *UsbdStatus,
  1891. transfer->TransferBufferLength,
  1892. iso->ErrorCount);
  1893. //
  1894. // zero out the length field for OUT transfers
  1895. //
  1896. if (USBD_TRANSFER_DIRECTION(iso->TransferFlags) ==
  1897. USBD_TRANSFER_DIRECTION_OUT) {
  1898. for (j=0; j< iso->NumberOfPackets; j++) {
  1899. iso->IsoPacket[j].Length = 0;
  1900. }
  1901. }
  1902. *NtStatus = STATUS_SUCCESS;
  1903. complete = TRUE;
  1904. }
  1905. return complete;
  1906. }