Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1365 lines
43 KiB

  1. /*++
  2. Copyright (c) 1999, 2000 Microsoft Corporation
  3. Module Name:
  4. async.c
  5. Abstract:
  6. miniport transfer code for control, bulk and interrupt
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13. PURPOSE.
  14. Copyright (c) 1999, 2000 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 7-20-00 : created, jsenior
  17. --*/
  18. #include "pch.h"
  19. //implements the following miniport functions:
  20. // non paged
  21. //UhciInsertQh
  22. //UhciUnlinkQh
  23. //UhciMapAsyncTransferToTds
  24. //UhciQueueTransfer
  25. //UhciControlTransfer
  26. //UhciBulkOrInterruptTransfer
  27. //UhciSetAsyncEndpointState
  28. //UhciProcessDoneAsyncTd
  29. //UhciPollAsyncEndpoint
  30. //UhciAbortAsyncTransfer
  31. VOID
  32. UhciFixDataToggle(
  33. PDEVICE_DATA DeviceData,
  34. PENDPOINT_DATA EndpointData,
  35. PHCD_TRANSFER_DESCRIPTOR Td,
  36. ULONG Toggle
  37. )
  38. {
  39. LOGENTRY(DeviceData, G, '_Fdt', EndpointData, Toggle, 0);
  40. //
  41. // Loop through all the remaining TDs for this
  42. // endpoint and fix the data toggle.
  43. //
  44. while (Td) {
  45. Td->HwTD.Token.DataToggle = Toggle;
  46. Toggle = !Toggle;
  47. Td = Td->NextTd;
  48. }
  49. EndpointData->Toggle = Toggle;
  50. }
  51. VOID
  52. UhciInsertQh(
  53. IN PDEVICE_DATA DeviceData,
  54. IN PHCD_QUEUEHEAD_DESCRIPTOR FirstQh,
  55. IN PHCD_QUEUEHEAD_DESCRIPTOR LinkQh
  56. )
  57. /*++
  58. Routine Description:
  59. Insert an aync queue head into the HW list.
  60. Arguments:
  61. --*/
  62. {
  63. PHCD_QUEUEHEAD_DESCRIPTOR nextQh;
  64. QH_LINK_POINTER newLink;
  65. LOGENTRY(DeviceData, G, '_Ain', 0, FirstQh, LinkQh);
  66. UHCI_ASSERT(DeviceData, !TEST_FLAG(LinkQh->QhFlags, UHCI_QH_FLAG_IN_SCHEDULE));
  67. // ASYNC QUEUE looks like this:
  68. //
  69. //
  70. // |- we insert here
  71. //|static QH|<->|xfer QH|<->|xfer QH|<->
  72. // | |
  73. // ---------------<->--------------
  74. // link new qh to the current 'head' ie
  75. // first transfer QH
  76. nextQh = FirstQh->NextQh;
  77. LinkQh->HwQH.HLink = FirstQh->HwQH.HLink;
  78. LinkQh->NextQh = nextQh;
  79. LinkQh->PrevQh = FirstQh;
  80. if (nextQh) {
  81. nextQh->PrevQh = LinkQh;
  82. } else {
  83. // This is the last queuehead. I.e. a bulk queuehead.
  84. UHCI_ASSERT(DeviceData,
  85. (LinkQh->HwQH.HLink.HwAddress & ~HW_LINK_FLAGS_MASK) ==
  86. DeviceData->BulkQueueHead->PhysicalAddress);
  87. DeviceData->LastBulkQueueHead = LinkQh;
  88. }
  89. // put the new qh at the head of the queue
  90. newLink.HwAddress = LinkQh->PhysicalAddress;
  91. newLink.QHTDSelect = 1;
  92. UHCI_ASSERT(DeviceData, !newLink.Terminate);
  93. UHCI_ASSERT(DeviceData, !newLink.Reserved);
  94. FirstQh->HwQH.HLink = newLink;
  95. FirstQh->NextQh = LinkQh;
  96. SET_FLAG(LinkQh->QhFlags, UHCI_QH_FLAG_IN_SCHEDULE);
  97. }
  98. VOID
  99. UhciUnlinkQh(
  100. IN PDEVICE_DATA DeviceData,
  101. IN PHCD_QUEUEHEAD_DESCRIPTOR Qh
  102. )
  103. /*++
  104. Routine Description:
  105. Remove an async queue head from the HW list.
  106. Arguments:
  107. --*/
  108. {
  109. PHCD_QUEUEHEAD_DESCRIPTOR nextQh, prevQh;
  110. UHCI_ASSERT(DeviceData,
  111. TEST_FLAG(Qh->QhFlags, UHCI_QH_FLAG_IN_SCHEDULE) ||
  112. ((Qh->PrevQh == Qh) && (Qh->NextQh == Qh)));
  113. nextQh = Qh->NextQh;
  114. prevQh = Qh->PrevQh;
  115. // ASYNC QUEUE looks like this:
  116. //
  117. //|static QH|->|xfer QH|->|xfer QH|->
  118. // | |
  119. // -------------<----------------
  120. //
  121. // Check if this was the last bulk transfer. If so,
  122. // turn off the bulk bandwidth reclamation.
  123. //
  124. if (DeviceData->LastBulkQueueHead == Qh) {
  125. DeviceData->LastBulkQueueHead = prevQh;
  126. }
  127. // unlink
  128. LOGENTRY(DeviceData, G, '_Ulk', Qh, prevQh, nextQh);
  129. prevQh->HwQH.HLink = Qh->HwQH.HLink;
  130. prevQh->NextQh = nextQh;
  131. if (nextQh) {
  132. nextQh->PrevQh = prevQh;
  133. }
  134. // Protect ourselves from calling this function twice.
  135. Qh->NextQh = Qh->PrevQh = Qh;
  136. //
  137. // If this was a bulk QH, check if bulk bandwidth reclamation
  138. // is turned on. If so and there's nothing queued, then turn
  139. // it off. This is for the case where a device has become
  140. // unresponsive and the transfer is about to be aborted.
  141. //
  142. if (Qh->EndpointData->Parameters.TransferType == Bulk &&
  143. !DeviceData->LastBulkQueueHead->HwQH.HLink.Terminate) {
  144. PHCD_QUEUEHEAD_DESCRIPTOR qh;
  145. BOOLEAN activeBulkTDs = FALSE;
  146. //
  147. // This loop skips the td that has been inserted for
  148. // the PIIX4 problem, since it starts with the qh
  149. // the bulk queuehead is pointing at.
  150. // If the bulk queuehead is not pointing at anything,
  151. // then we're fine too, since it will have been
  152. // turned off already.
  153. //
  154. for (qh = DeviceData->BulkQueueHead->NextQh;
  155. qh;
  156. qh = qh->NextQh) {
  157. if (!qh->HwQH.VLink.Terminate) {
  158. activeBulkTDs = TRUE;
  159. break;
  160. }
  161. }
  162. // qh is pointing at either the first queuehead
  163. // with transfers pending or the bulk queuehead.
  164. if (!activeBulkTDs) {
  165. UHCI_ASSERT(DeviceData, !qh)
  166. DeviceData->LastBulkQueueHead->HwQH.HLink.Terminate = 1;
  167. }
  168. }
  169. CLEAR_FLAG(Qh->QhFlags, UHCI_QH_FLAG_IN_SCHEDULE);
  170. }
  171. VOID
  172. UhciQueueTransfer(
  173. IN PDEVICE_DATA DeviceData,
  174. IN PENDPOINT_DATA EndpointData,
  175. IN PHCD_TRANSFER_DESCRIPTOR FirstTd,
  176. IN PHCD_TRANSFER_DESCRIPTOR LastTd
  177. )
  178. /*++
  179. Routine Description:
  180. Links a bunch of TDs into a queuehead.
  181. Arguments:
  182. --*/
  183. {
  184. UHCI_ASSERT(DeviceData, FirstTd->PhysicalAddress & ~HW_LINK_FLAGS_MASK);
  185. UHCI_ASSERT(DeviceData, !(FirstTd->PhysicalAddress & HW_LINK_FLAGS_MASK));
  186. if (EndpointData->HeadTd) {
  187. PHCD_QUEUEHEAD_DESCRIPTOR qh;
  188. HW_32BIT_PHYSICAL_ADDRESS curTdPhys;
  189. // There's other transfer(s) queued. Add this one behind them.
  190. UHCI_ASSERT(DeviceData, EndpointData->TailTd);
  191. EndpointData->TailTd->NextTd = FirstTd;
  192. EndpointData->TailTd->HwTD.LinkPointer.HwAddress =
  193. FirstTd->PhysicalAddress;
  194. // Get the qh and current td
  195. qh = EndpointData->QueueHead;
  196. curTdPhys = qh->HwQH.VLink.HwAddress & ~HW_LINK_FLAGS_MASK;
  197. // If there is nothing on this queuehead, then we may have been
  198. // unsuccessful in queueing the transfer. Checking the active
  199. // bit on the td will tell us for sure.
  200. LOGENTRY(DeviceData, G, '_tqa', FirstTd, curTdPhys,
  201. FirstTd->HwTD.Control.Active);
  202. LOGENTRY(DeviceData, G, '_ttd', EndpointData->TailTd,
  203. EndpointData->TailTd->PhysicalAddress,
  204. EndpointData->TailTd->HwTD.Control.Active);
  205. if (FirstTd->HwTD.Control.Active) {
  206. if ((curTdPhys == EndpointData->TailTd->PhysicalAddress &&
  207. !EndpointData->TailTd->HwTD.Control.Active)) {
  208. TD_LINK_POINTER newLink;
  209. // Since the prior transfer had already completed when
  210. // we tried to queue the transfer, we need to add this td
  211. // directly into the hardware queuehead.
  212. // Note that the HC could be in the middle of updating the
  213. // queuehead's link pointer. That's what the second part of
  214. // the if statement above is for.
  215. // DO NOT call LOGENTRY until we set the queuehead!
  216. // This would cause a delay that might be bad.
  217. newLink.HwAddress = FirstTd->PhysicalAddress;
  218. newLink.Terminate = 0;
  219. newLink.QHTDSelect = 0;
  220. qh->HwQH.VLink = newLink;
  221. LOGENTRY(DeviceData, G, '_nlk', FirstTd, EndpointData,
  222. EndpointData->HeadTd);
  223. }
  224. }
  225. } else {
  226. // There's no other transfers queued currently.
  227. SET_QH_TD(DeviceData, EndpointData, FirstTd);
  228. }
  229. if (EndpointData->Parameters.TransferType == Bulk) {
  230. // Turn bulk bandwidth reclamation back on.
  231. DeviceData->LastBulkQueueHead->HwQH.HLink.Terminate = 0;
  232. }
  233. EndpointData->TailTd = LastTd;
  234. }
  235. ULONG
  236. UhciMapAsyncTransferToTds(
  237. PDEVICE_DATA DeviceData,
  238. PENDPOINT_DATA EndpointData,
  239. PTRANSFER_CONTEXT TransferContext,
  240. PHCD_TRANSFER_DESCRIPTOR *FirstDataTd,
  241. PHCD_TRANSFER_DESCRIPTOR *LastDataTd,
  242. PTRANSFER_SG_LIST SgList
  243. )
  244. /*++
  245. Routine Description:
  246. Maps an asynchronous transfer into the TDs
  247. required to complete the transfer, including
  248. any double buffering necessary for page boundaries.
  249. Arguments:
  250. Return Value:
  251. --*/
  252. {
  253. // indices and offsets
  254. ULONG sgIdx, sgOffset, i;
  255. // lengths
  256. ULONG lengthThisTd, bytesRemaining, mappedNextSg, lengthMapped = 0;
  257. USHORT maxPacketSize = EndpointData->Parameters.MaxPacketSize;
  258. // structure pointers
  259. PTRANSFER_PARAMETERS tp = TransferContext->TransferParameters;
  260. PASYNC_TRANSFER_BUFFER buffer = NULL;
  261. PHCD_TRANSFER_DESCRIPTOR lastTd = NULL, td;
  262. HW_32BIT_PHYSICAL_ADDRESS address;
  263. UCHAR pid;
  264. ULONG toggle;
  265. BOOLEAN pageCrossing = FALSE;
  266. BOOLEAN ZeroLengthTransfer = (SgList->SgCount == 0 &&
  267. EndpointData->Parameters.TransferType != Control);
  268. if (EndpointData->Parameters.TransferType == Control) {
  269. // Control pipes are bi-directional. Get the direction from the
  270. // transfer parameters.
  271. if (TEST_FLAG(tp->TransferFlags, USBD_TRANSFER_DIRECTION_IN)) {
  272. pid = InPID;
  273. } else {
  274. pid = OutPID;
  275. }
  276. // THe setup packet is Toggle 0.
  277. toggle = DataToggle1;
  278. } else {
  279. // All other pipes are uni-directional. Determine
  280. // the direction from the endpoint address.
  281. pid = GetPID(EndpointData->Parameters.EndpointAddress);
  282. // We have to continue the toggle pattern for bulk and interrupt.
  283. toggle = EndpointData->Toggle;
  284. }
  285. // lastTd points to the last data TD or the setup
  286. // if there was no data.
  287. for (i = 0; i<SgList->SgCount || ZeroLengthTransfer; i++) {
  288. LOGENTRY(DeviceData, G, '_sgc', SgList->SgCount, i, 0);
  289. address = SgList->SgEntry[i].LogicalAddress.Hw32;
  290. UHCI_ASSERT(DeviceData, address || ZeroLengthTransfer);
  291. bytesRemaining = SgList->SgEntry[i].Length;
  292. UHCI_ASSERT(DeviceData, bytesRemaining || ZeroLengthTransfer);
  293. LOGENTRY(DeviceData, G, '_sgX', SgList->SgEntry[i].Length, i,
  294. SgList->SgEntry[i].LogicalAddress.Hw32);
  295. if (pageCrossing) {
  296. // We have a page crossing here, so this one is double-buffered.
  297. address += mappedNextSg;
  298. bytesRemaining -= mappedNextSg;
  299. }
  300. mappedNextSg = 0;
  301. pageCrossing = FALSE;
  302. while (bytesRemaining || ZeroLengthTransfer) {
  303. ZeroLengthTransfer = FALSE;
  304. LOGENTRY(DeviceData, G, '_sg1', bytesRemaining, 0, 0);
  305. if (bytesRemaining < maxPacketSize) {
  306. if (i+1 < SgList->SgCount) {
  307. // We have to double buffer this TD since it crosses a page
  308. // boundary. We will always cross a page boundary now.
  309. LOGENTRY(DeviceData, G, '_sg2', bytesRemaining, 0, 0);
  310. pageCrossing = TRUE;
  311. if (SgList->SgEntry[i+1].Length + bytesRemaining >= maxPacketSize) {
  312. mappedNextSg = maxPacketSize - bytesRemaining;
  313. lengthThisTd = maxPacketSize;
  314. } else {
  315. lengthThisTd = SgList->SgEntry[i+1].Length + bytesRemaining;
  316. mappedNextSg = SgList->SgEntry[i+1].Length;
  317. }
  318. buffer = (PASYNC_TRANSFER_BUFFER)
  319. UHCI_ALLOC_DB(DeviceData, EndpointData, FALSE);
  320. UHCI_ASSERT(DeviceData, buffer);
  321. UHCI_ASSERT(DeviceData, buffer->Sig == SIG_HCD_ADB);
  322. UHCI_ASSERT(DeviceData, buffer->PhysicalAddress);
  323. buffer->SystemAddress = SgList->MdlSystemAddress + lengthMapped;
  324. UhciKdPrint((DeviceData, 2, "'Double buffer %x address %x offset %x\n", buffer, buffer->SystemAddress, lengthMapped));
  325. buffer->Size = lengthThisTd;
  326. UHCI_ASSERT(DeviceData, lengthThisTd <= MAX_ASYNC_PACKET_SIZE);
  327. if (OutPID == pid) {
  328. RtlCopyMemory(&buffer->Buffer[0],
  329. buffer->SystemAddress,
  330. lengthThisTd);
  331. }
  332. // Change the address for the TD
  333. address = buffer->PhysicalAddress;
  334. bytesRemaining = 0;
  335. } else {
  336. // Last TD
  337. LOGENTRY(DeviceData, G, '_sg3', bytesRemaining, 0, 0);
  338. lengthThisTd = bytesRemaining;
  339. bytesRemaining = 0;
  340. }
  341. } else {
  342. // Normal, non-buffered case.
  343. LOGENTRY(DeviceData, G, '_sg4', bytesRemaining, 0, 0);
  344. lengthThisTd = maxPacketSize;
  345. bytesRemaining -= lengthThisTd;
  346. UHCI_ASSERT(DeviceData, lengthThisTd <= SgList->SgEntry[i].Length);
  347. }
  348. TransferContext->PendingTds++;
  349. //
  350. // Allocate and initialize an async TD
  351. //
  352. td = UHCI_ALLOC_TD(DeviceData, EndpointData);
  353. INITIALIZE_TD_FOR_TRANSFER(td, TransferContext);
  354. td->HwTD.Token.Pid = pid;
  355. td->HwTD.Token.MaximumLength = MAXIMUM_LENGTH(lengthThisTd);
  356. td->HwTD.Token.DataToggle = toggle;
  357. td->HwTD.Control.ShortPacketDetect = 1;
  358. td->HwTD.Control.ActualLength = MAXIMUM_LENGTH(0);
  359. td->HwTD.Buffer = address;
  360. if (pageCrossing) {
  361. SET_FLAG(td->Flags, TD_FLAG_DOUBLE_BUFFERED);
  362. td->DoubleBuffer = (PTRANSFER_BUFFER) buffer;
  363. }
  364. address += lengthThisTd;
  365. lengthMapped += lengthThisTd;
  366. if (lastTd) {
  367. SET_NEXT_TD(lastTd, td);
  368. } else {
  369. *FirstDataTd = td;
  370. }
  371. lastTd = td;
  372. toggle = !toggle;
  373. } // while
  374. }
  375. *LastDataTd = lastTd;
  376. EndpointData->Toggle = toggle;
  377. UHCI_ASSERT(DeviceData, TransferContext->TransferParameters->TransferBufferLength == lengthMapped);
  378. return lengthMapped;
  379. }
  380. USB_MINIPORT_STATUS
  381. UhciControlTransfer(
  382. IN PDEVICE_DATA DeviceData,
  383. IN PENDPOINT_DATA EndpointData,
  384. IN PTRANSFER_PARAMETERS TransferParameters,
  385. IN PTRANSFER_CONTEXT TransferContext,
  386. IN PTRANSFER_SG_LIST TransferSGList
  387. )
  388. /*++
  389. Routine Description:
  390. Initialize a control transfer
  391. Arguments:
  392. --*/
  393. {
  394. PHCD_TRANSFER_DESCRIPTOR lastDataTd, firstDataTd, setupTd, statusTd;
  395. PASYNC_TRANSFER_BUFFER setupPacket;
  396. ULONG lengthMapped, dataTDCount = 0;
  397. // we have enough tds, program the transfer
  398. UhciKdPrint((DeviceData, 2, "'Control transfer on EP %x\n", EndpointData));
  399. LOGENTRY(DeviceData, G, '_CTR', EndpointData, TransferParameters, TransferContext);
  400. // bugbug should check here in advance to see if there enough
  401. // TDs if so proceed otherwise return status_busy.
  402. if (EndpointData->PendingTransfers > 1) {
  403. DecPendingTransfers(DeviceData, EndpointData);
  404. return USBMP_STATUS_BUSY;
  405. }
  406. // First prepare a TD for the setup packet. Grab the dummy TD from
  407. // the tail of the queue.
  408. TransferContext->PendingTds++;
  409. setupTd = UHCI_ALLOC_TD(DeviceData, EndpointData);
  410. INITIALIZE_TD_FOR_TRANSFER(setupTd, TransferContext);
  411. // Move setup data into TD (8 chars long).
  412. // We use a double buffer for this.
  413. setupTd->DoubleBuffer = UHCI_ALLOC_DB(DeviceData, EndpointData, FALSE);
  414. setupPacket = (PASYNC_TRANSFER_BUFFER) setupTd->DoubleBuffer;
  415. RtlCopyMemory(&setupPacket->Buffer[0],
  416. &TransferParameters->SetupPacket[0],
  417. 8);
  418. setupTd->HwTD.Buffer = setupPacket->PhysicalAddress;
  419. SET_FLAG(setupTd->Flags, TD_FLAG_DOUBLE_BUFFERED);
  420. setupTd->HwTD.Token.MaximumLength = MAXIMUM_LENGTH(8);
  421. setupTd->HwTD.Token.Pid = SetupPID;
  422. // setup stage is always toggle 0
  423. setupTd->HwTD.Token.DataToggle = DataToggle0;
  424. LOGENTRY(DeviceData,
  425. G, '_set',
  426. setupTd,
  427. *((PLONG) &TransferParameters->SetupPacket[0]),
  428. *((PLONG) &TransferParameters->SetupPacket[4]));
  429. // allocate the status phase TD now so we can
  430. // point the data TDs to it
  431. TransferContext->PendingTds++;
  432. statusTd = UHCI_ALLOC_TD(DeviceData, EndpointData);
  433. INITIALIZE_TD_FOR_TRANSFER(statusTd, TransferContext);
  434. // now setup the data phase
  435. lastDataTd = firstDataTd = NULL;
  436. lengthMapped =
  437. UhciMapAsyncTransferToTds(DeviceData,
  438. EndpointData,
  439. TransferContext,
  440. &firstDataTd,
  441. &lastDataTd,
  442. TransferSGList);
  443. if (firstDataTd && firstDataTd) {
  444. // Join the setup to the front and the status to the end.
  445. SET_NEXT_TD(setupTd, firstDataTd);
  446. SET_NEXT_TD(lastDataTd, statusTd);
  447. } else {
  448. // Join the setup to the status. No data stage.
  449. SET_NEXT_TD(setupTd, statusTd);
  450. }
  451. // now do the status phase
  452. // no bufferQueueHead
  453. statusTd->HwTD.Buffer = 0;
  454. statusTd->HwTD.Token.MaximumLength = MAXIMUM_LENGTH(0);
  455. // status stage is always toggle 1
  456. statusTd->HwTD.Token.DataToggle = DataToggle1;
  457. statusTd->HwTD.Control.InterruptOnComplete = 1;
  458. SET_FLAG(statusTd->Flags, TD_FLAG_STATUS_TD);
  459. // status phase is opposite data dirrection
  460. if (TEST_FLAG(TransferParameters->TransferFlags, USBD_TRANSFER_DIRECTION_IN)) {
  461. statusTd->HwTD.Token.Pid = OutPID;
  462. } else {
  463. statusTd->HwTD.Token.Pid = InPID;
  464. }
  465. SET_NEXT_TD_NULL(statusTd);
  466. // put the request on the hardware queue
  467. LOGENTRY(DeviceData, G,
  468. '_Tal', TransferContext->PendingTds, setupTd->PhysicalAddress, setupTd);
  469. // Attach the setup TD to the queuehead
  470. UhciQueueTransfer(DeviceData, EndpointData, setupTd, statusTd);
  471. return USBMP_STATUS_SUCCESS;
  472. }
  473. USB_MINIPORT_STATUS
  474. UhciBulkOrInterruptTransfer(
  475. IN PDEVICE_DATA DeviceData,
  476. IN PENDPOINT_DATA EndpointData,
  477. IN PTRANSFER_PARAMETERS TransferParameters,
  478. IN PTRANSFER_CONTEXT TransferContext,
  479. IN PTRANSFER_SG_LIST TransferSGList
  480. )
  481. /*++
  482. Routine Description:
  483. Initialize interrupt or bulk Transfer
  484. Arguments:
  485. --*/
  486. {
  487. PHCD_TRANSFER_DESCRIPTOR firstTd, lastTd;
  488. ULONG lengthMapped;
  489. ULONG maxPacketSize = EndpointData->Parameters.MaxPacketSize;
  490. ULONG i, numTds;
  491. UhciKdPrint((DeviceData, 2, "'BIT transfer on EP %x\n", EndpointData));
  492. UhciKdPrint((DeviceData, 2, "'BIT transfer length %d\n",
  493. TransferParameters->TransferBufferLength));
  494. LOGENTRY(DeviceData, G, '_BIT', EndpointData, TransferParameters, TransferContext);
  495. // Do we have enough free resources?
  496. for (i = 0, lengthMapped = 0; i < TransferSGList->SgCount; i++) {
  497. lengthMapped += TransferSGList->SgEntry[i].Length;
  498. }
  499. numTds = lengthMapped == 0 ? 1 :
  500. (lengthMapped + maxPacketSize - 1) / maxPacketSize;
  501. if (EndpointData->TdCount - EndpointData->TdsUsed < numTds) {
  502. // Not enough TDs to do this transfer yet.
  503. // Tell the port driver to wait.
  504. UhciKdPrint((DeviceData, 2, "'BIT must wait on EP %x. Not enough tds.\n", EndpointData));
  505. return USBMP_STATUS_BUSY;
  506. }
  507. if (TransferSGList->SgCount > 1 &&
  508. TransferSGList->SgEntry[0].Length % maxPacketSize != 0) {
  509. // We'll need DBs. Do we have enough?
  510. if (EndpointData->DbCount - EndpointData->DbsUsed <
  511. (lengthMapped + PAGE_SIZE - 1)/PAGE_SIZE) {
  512. // Not enough DBs to do this transfer yet.
  513. // Tell the port driver to wait.
  514. UhciKdPrint((DeviceData, 2, "'BIT must wait on EP %x. Not enough dbs.\n", EndpointData));
  515. return USBMP_STATUS_BUSY;
  516. }
  517. }
  518. // we have enough tds, program the transfer
  519. // now setup the data phase
  520. lastTd = firstTd = NULL;
  521. lengthMapped =
  522. UhciMapAsyncTransferToTds(DeviceData,
  523. EndpointData,
  524. TransferContext,
  525. &firstTd,
  526. &lastTd,
  527. TransferSGList);
  528. UHCI_ASSERT(DeviceData, lastTd && firstTd);
  529. lastTd->HwTD.Control.InterruptOnComplete = 1;
  530. SET_NEXT_TD_NULL(lastTd);
  531. // put the request on the hardware queue
  532. LOGENTRY(DeviceData, G,
  533. '_Tal', TransferContext->PendingTds, firstTd->PhysicalAddress, firstTd);
  534. // Attach the first TD to the queuehead
  535. UhciQueueTransfer(DeviceData, EndpointData, firstTd, lastTd);
  536. return USBMP_STATUS_SUCCESS;
  537. }
  538. VOID
  539. UhciSetAsyncEndpointState(
  540. IN PDEVICE_DATA DeviceData,
  541. IN PENDPOINT_DATA EndpointData,
  542. IN MP_ENDPOINT_STATE State
  543. )
  544. /*++
  545. Routine Description:
  546. Arguments:
  547. Return Value:
  548. --*/
  549. {
  550. PHCD_QUEUEHEAD_DESCRIPTOR qh;
  551. ENDPOINT_TRANSFER_TYPE epType;
  552. ULONG interruptQHIndex;
  553. LOGENTRY(DeviceData, G, '_Sas', EndpointData, State, 0);
  554. qh = EndpointData->QueueHead;
  555. epType = EndpointData->Parameters.TransferType;
  556. switch(State) {
  557. case ENDPOINT_ACTIVE:
  558. switch (epType) {
  559. case Interrupt:
  560. // put queue head in the schedule
  561. interruptQHIndex = EndpointData->Parameters.ScheduleOffset +
  562. QH_INTERRUPT_INDEX(EndpointData->Parameters.Period);
  563. UhciInsertQh(DeviceData,
  564. DeviceData->InterruptQueueHeads[interruptQHIndex],
  565. qh);
  566. break;
  567. case Control:
  568. // put queue head in the schedule
  569. UhciInsertQh(DeviceData, DeviceData->ControlQueueHead, qh);
  570. break;
  571. case Bulk:
  572. // put queue head in the schedule
  573. UhciInsertQh(DeviceData, DeviceData->BulkQueueHead, qh);
  574. break;
  575. default:
  576. TEST_TRAP()
  577. break;
  578. }
  579. break;
  580. case ENDPOINT_PAUSE:
  581. // remove queue head from the schedule
  582. switch (epType) {
  583. case Interrupt:
  584. case Bulk:
  585. case Control:
  586. //
  587. // Just flip the active bits at this point.
  588. //
  589. UhciUnlinkQh(DeviceData, qh);
  590. break;
  591. default:
  592. TEST_TRAP()
  593. break;
  594. }
  595. break;
  596. case ENDPOINT_REMOVE:
  597. qh->QhFlags |= UHCI_QH_FLAG_QH_REMOVED;
  598. switch (epType) {
  599. case Interrupt:
  600. case Bulk:
  601. case Control:
  602. // remove from the schedule and
  603. // free bandwidth
  604. // free the bw
  605. // EndpointData->StaticEd->AllocatedBandwidth -=
  606. // EndpointData->Parameters.Bandwidth;
  607. UhciUnlinkQh(DeviceData, qh);
  608. break;
  609. default:
  610. TEST_TRAP();
  611. break;
  612. }
  613. break;
  614. default:
  615. TEST_TRAP();
  616. }
  617. }
  618. VOID
  619. UhciProcessDoneAsyncTd(
  620. PDEVICE_DATA DeviceData,
  621. PHCD_TRANSFER_DESCRIPTOR Td
  622. )
  623. /*++
  624. Routine Description:
  625. process a completed TD
  626. Parameters
  627. --*/
  628. {
  629. PTRANSFER_CONTEXT transferContext;
  630. PENDPOINT_DATA endpointData;
  631. PTRANSFER_PARAMETERS tp;
  632. USBD_STATUS usbdStatus = USBD_STATUS_SUCCESS;
  633. ULONG byteCount;
  634. transferContext = Td->TransferContext;
  635. ASSERT_TRANSFER(DeviceData, transferContext);
  636. tp = transferContext->TransferParameters;
  637. transferContext->PendingTds--;
  638. endpointData = transferContext->EndpointData;
  639. if (TEST_FLAG(Td->Flags, TD_FLAG_SKIP)) {
  640. LOGENTRY(DeviceData, G, '_Ktd', transferContext,
  641. 0,
  642. Td);
  643. goto free_it;
  644. }
  645. if (TEST_FLAG(endpointData->Flags, UHCI_EDFLAG_HALTED)) {
  646. // completion status for this TD?
  647. // since the endpoint halts on error and short packet,
  648. // the error bits should have been written back to the TD
  649. // we use these bits to dermine the error
  650. usbdStatus = UhciGetErrorFromTD(DeviceData,
  651. Td);
  652. }
  653. LOGENTRY(DeviceData, G, '_Dtd', transferContext,
  654. usbdStatus,
  655. Td);
  656. // Only count the bytes transferred if we were successful (as per uhcd).
  657. byteCount = (usbdStatus == USBD_STATUS_SUCCESS) ? ACTUAL_LENGTH(Td->HwTD.Control.ActualLength) : 0;
  658. LOGENTRY(DeviceData, G, '_tln', byteCount, 0, 0);
  659. if (Td->HwTD.Token.Pid != SetupPID) {
  660. // data or status phase of a control transfer or a bulk/int
  661. // data transfer
  662. LOGENTRY(DeviceData, G, '_Idt', Td, transferContext, byteCount);
  663. transferContext->BytesTransferred += byteCount;
  664. }
  665. // For double buffered transfers, we now have to copy back
  666. // if this was an IN transfer.
  667. //
  668. if (Td->HwTD.Token.Pid == InPID &&
  669. TEST_FLAG(Td->Flags, TD_FLAG_DOUBLE_BUFFERED)) {
  670. PASYNC_TRANSFER_BUFFER buffer = &Td->DoubleBuffer->Async;
  671. UHCI_ASSERT(DeviceData, TEST_FLAG(buffer->Flags, DB_FLAG_BUSY));
  672. UhciKdPrint((DeviceData, 2, "'Copy back %x address %x\n", buffer, buffer->SystemAddress));
  673. RtlCopyMemory(buffer->SystemAddress,
  674. buffer->Buffer,
  675. buffer->Size);
  676. // tell usbport we double buffered so it can
  677. // triple buffer if necessary
  678. USBPORT_NOTIFY_DOUBLEBUFFER(DeviceData,
  679. tp,
  680. buffer->SystemAddress,
  681. buffer->Size);
  682. }
  683. // note that we only set transferContext->UsbdStatus
  684. // if we find a TD with an error this will cause us to
  685. // record the last TD with an error as the error for
  686. // the transfer.
  687. if (USBD_STATUS_SUCCESS != usbdStatus) {
  688. UhciKdPrint((DeviceData, 2, "'Error, usbdstatus %x", usbdStatus));
  689. // map the error to code in USBDI.H
  690. transferContext->UsbdStatus = usbdStatus;
  691. LOGENTRY(DeviceData, G, '_tER', transferContext->UsbdStatus, 0, 0);
  692. }
  693. free_it:
  694. // mark the TD free
  695. UHCI_FREE_TD(DeviceData, endpointData, Td);
  696. if (transferContext->PendingTds == 0) {
  697. // all TDs for this transfer are done
  698. // clear the HAVE_TRANSFER flag to indicate
  699. // we can take another
  700. DecPendingTransfers(DeviceData, endpointData);
  701. LOGENTRY(DeviceData, G, '_Cat',
  702. transferContext->UsbdStatus,
  703. transferContext,
  704. transferContext->BytesTransferred);
  705. UhciKdPrint((DeviceData, 2, "'Complete transfer w/ usbdstatus %x\n", transferContext->UsbdStatus));
  706. USBPORT_COMPLETE_TRANSFER(DeviceData,
  707. endpointData,
  708. tp,
  709. transferContext->UsbdStatus,
  710. transferContext->BytesTransferred);
  711. }
  712. }
  713. VOID
  714. UhciPollAsyncEndpoint(
  715. IN PDEVICE_DATA DeviceData,
  716. IN PENDPOINT_DATA EndpointData
  717. )
  718. /*++
  719. Routine Description:
  720. Called when the endpoint 'needs attention'
  721. The goal here is to determine which TDs, if any,
  722. have completed and complete any associated transfers.
  723. Arguments:
  724. Return Value:
  725. --*/
  726. {
  727. PHCD_TRANSFER_DESCRIPTOR td, currentTd;
  728. PHCD_QUEUEHEAD_DESCRIPTOR qh;
  729. HW_QUEUE_ELEMENT_TD overlay;
  730. HW_32BIT_PHYSICAL_ADDRESS curTdPhys, tmpPhys;
  731. ULONG i, j;
  732. PTRANSFER_CONTEXT transferContext, tmp;
  733. PTRANSFER_PARAMETERS tp;
  734. ULONG halted, active;
  735. BOOLEAN processed;
  736. if (TEST_FLAG(EndpointData->Flags, UHCI_EDFLAG_HALTED)) {
  737. // Endpoint is halted. Don't do anything.
  738. return;
  739. }
  740. // get the queue head and current td
  741. qh = EndpointData->QueueHead;
  742. curTdPhys = qh->HwQH.VLink.HwAddress;
  743. curTdPhys &= ~HW_LINK_FLAGS_MASK;
  744. // now convert the physical 'current' to a virtual address
  745. currentTd = curTdPhys ? (PHCD_TRANSFER_DESCRIPTOR)
  746. USBPORT_PHYSICAL_TO_VIRTUAL(curTdPhys,
  747. DeviceData,
  748. EndpointData) :
  749. (PHCD_TRANSFER_DESCRIPTOR) NULL;
  750. LOGENTRY(DeviceData, G, '_ctd', curTdPhys, currentTd, EndpointData);
  751. // walk the TD list up to the current TD and complete
  752. // all those TDs
  753. for (td = EndpointData->HeadTd; td != currentTd && td; td = td->NextTd) {
  754. SET_FLAG(td->Flags, TD_FLAG_DONE);
  755. InsertTailList(&EndpointData->DoneTdList,
  756. &td->DoneLink);
  757. // Is the queuehead pointing to nothing, but there are still
  758. // tds available to be queued?
  759. if (td->NextTd &&
  760. td->NextTd->HwTD.Control.Active) {
  761. if (!curTdPhys) {
  762. TD_LINK_POINTER newLink;
  763. // A transfer didn't make it onto the hardware because
  764. // the queuehead's td field wasn't set properly
  765. // in UhciQueueTransfer.
  766. // PERF NOTE: Because we're not making sure that the
  767. // transfer gets queued immediately, the transfer could
  768. // be delayed in making it onto the hardware. Better
  769. // late than never, though...
  770. EndpointData->HeadTd = currentTd = td->NextTd;
  771. LOGENTRY(DeviceData, G, '_Dly', currentTd, curTdPhys, qh);
  772. goto UhciPollAsyncEndpointSetNext;
  773. } else if (curTdPhys != td->NextTd->PhysicalAddress) {
  774. LOGENTRY(DeviceData, G, '_QEr', curTdPhys, td->NextTd->PhysicalAddress, td->NextTd);
  775. UHCI_ASSERT (DeviceData, FALSE);
  776. }
  777. }
  778. }
  779. EndpointData->HeadTd = currentTd;
  780. if (currentTd) {
  781. LOGENTRY(DeviceData, G, '_cTD', currentTd,
  782. curTdPhys,
  783. currentTd->TransferContext);
  784. // If active, get out of here.
  785. if (currentTd->HwTD.Control.Active) {
  786. ;// fall thru to completing whatever's completed;
  787. } else if ((currentTd->HwTD.Token.Pid == InPID) &&
  788. (currentTd->HwTD.Control.Stalled == 1) &&
  789. (currentTd->HwTD.Control.BabbleDetected == 0) &&
  790. (currentTd->HwTD.Control.NAKReceived == 0) &&
  791. (currentTd->HwTD.Control.TimeoutCRC == 1) &&
  792. (currentTd->HwTD.Control.BitstuffError == 0) &&
  793. !TEST_FLAG(currentTd->Flags, TD_FLAG_TIMEOUT_ERROR)) {
  794. // If this is the first time that the device or hc has been
  795. // unresponsive, cut it a break and try the transfer again.
  796. // Note that we don't check currentTd->HwTD.Control.DataBufferError
  797. // since a value of:
  798. // 1 means host controller did not respond to IN data sent by device
  799. // 0 means device did not NAK IN request.
  800. SET_FLAG(currentTd->Flags, TD_FLAG_TIMEOUT_ERROR);
  801. currentTd->HwTD.Control.ErrorCount = 3;
  802. currentTd->HwTD.Control.Stalled = 0;
  803. currentTd->HwTD.Control.TimeoutCRC = 0;
  804. currentTd->HwTD.Control.Active = 1;
  805. } else if (currentTd->HwTD.Control.Stalled ||
  806. currentTd->HwTD.Control.DataBufferError ||
  807. currentTd->HwTD.Control.BabbleDetected ||
  808. currentTd->HwTD.Control.TimeoutCRC ||
  809. currentTd->HwTD.Control.BitstuffError) {
  810. SET_FLAG(EndpointData->Flags, UHCI_EDFLAG_HALTED);
  811. //
  812. // Error. We need to flush.
  813. //
  814. // Flush all completed tds
  815. //
  816. // Complete transfer with error.
  817. // if the endpoint is halted we need to complete
  818. // the 'current' tarnsfer with an error walk all
  819. // the tds for the current transfer and mark
  820. // any that are not done as 'skipped'.
  821. UhciKdPrint((DeviceData, 2, "'Error on EP %x\n", EndpointData));
  822. LOGENTRY(DeviceData, G, '_erT', qh, currentTd, currentTd->HwTD.Control.ul);
  823. transferContext = currentTd->TransferContext;
  824. tp = transferContext->TransferParameters;
  825. SET_FLAG(currentTd->Flags, TD_FLAG_DONE);
  826. InsertTailList(&EndpointData->DoneTdList,
  827. &currentTd->DoneLink);
  828. // Skip all the remaining TDs in this transfer
  829. UHCI_ASSERT(DeviceData, td->TransferContext == transferContext);
  830. for (td;
  831. td &&
  832. td->TransferContext->TransferParameters->SequenceNumber == tp->SequenceNumber;
  833. td = td->NextTd) {
  834. if (!TEST_FLAG(td->Flags, TD_FLAG_DONE)) {
  835. LOGENTRY(DeviceData, G, '_skT', qh, 0, td);
  836. SET_FLAG(td->Flags, (TD_FLAG_DONE | TD_FLAG_SKIP));
  837. InsertTailList(&EndpointData->DoneTdList,
  838. &td->DoneLink);
  839. }
  840. }
  841. if (EndpointData->Parameters.TransferType != Control) {
  842. // Loop through all the remaining TDs for this
  843. // endpoint and fix the data toggle.
  844. UhciFixDataToggle(
  845. DeviceData,
  846. EndpointData,
  847. td,
  848. currentTd->HwTD.Token.DataToggle);
  849. }
  850. SET_QH_TD(DeviceData, EndpointData, td);
  851. } else if (ACTUAL_LENGTH(currentTd->HwTD.Control.ActualLength) <
  852. ACTUAL_LENGTH(currentTd->HwTD.Token.MaximumLength)) {
  853. //
  854. // Short packet. We need to flush.
  855. //
  856. // Flush all completed tds
  857. //
  858. // we need to walk all the tds for the current
  859. // transfer and mark any that are not done as
  860. // 'skipped'. EXCEPT if the last TD is a status
  861. // phase of a control transfer, in which case
  862. // we have to queue that one up.
  863. //
  864. tp = currentTd->TransferContext->TransferParameters;
  865. UhciKdPrint((DeviceData, 2, "'Short packet on EP %x\n", EndpointData));
  866. LOGENTRY(DeviceData, G, '_shP', qh, currentTd, currentTd->HwTD.Control.ul);
  867. SET_FLAG(currentTd->Flags, TD_FLAG_DONE);
  868. InsertTailList(&EndpointData->DoneTdList,
  869. &currentTd->DoneLink);
  870. // Skip all the remaining TDs in this transfer up to the status phase
  871. // If control transfer, queue up the status phase,
  872. // else go to the next transfer (if there is one).
  873. for (td;
  874. td &&
  875. td->TransferContext->TransferParameters->SequenceNumber == tp->SequenceNumber;
  876. td = td->NextTd) {
  877. if (TEST_FLAG(td->Flags, TD_FLAG_STATUS_TD) &&
  878. TEST_FLAG(tp->TransferFlags, USBD_SHORT_TRANSFER_OK)) {
  879. // Queue up the status phase of the control transfer.
  880. UHCI_ASSERT(DeviceData, EndpointData->Parameters.TransferType == Control);
  881. break;
  882. }
  883. if (!TEST_FLAG(td->Flags, TD_FLAG_DONE)) {
  884. LOGENTRY(DeviceData, G, '_skT', qh, 0, td);
  885. SET_FLAG(td->Flags, (TD_FLAG_DONE | TD_FLAG_SKIP));
  886. InsertTailList(&EndpointData->DoneTdList,
  887. &td->DoneLink);
  888. }
  889. }
  890. if (EndpointData->Parameters.TransferType != Control &&
  891. currentTd->NextTd) {
  892. // Loop through all the remaining TDs for this
  893. // endpoint and fix the data toggle.
  894. UhciFixDataToggle(
  895. DeviceData,
  896. EndpointData,
  897. td,
  898. currentTd->NextTd->HwTD.Token.DataToggle);
  899. }
  900. if (!TEST_FLAG(tp->TransferFlags, USBD_SHORT_TRANSFER_OK)) {
  901. SET_FLAG(EndpointData->Flags, UHCI_EDFLAG_HALTED);
  902. }
  903. // Next transfer or status phase of a control transfer.
  904. SET_QH_TD(DeviceData, EndpointData, td);
  905. } else {
  906. // Current td is not active.
  907. // If we're still pointing to the same td at this point in time,
  908. // then we're stuck and I have to manually advance the queuehead
  909. // to the next td.
  910. LOGENTRY(DeviceData, G, '_nuT', qh, currentTd, td);
  911. if (curTdPhys == (qh->HwQH.VLink.HwAddress & ~HW_LINK_FLAGS_MASK)) {
  912. // HW error. Td pointer for QH is not advancing.
  913. // Manually advance things.
  914. SET_FLAG(currentTd->Flags, TD_FLAG_DONE);
  915. InsertTailList(&EndpointData->DoneTdList,
  916. &currentTd->DoneLink);
  917. EndpointData->HeadTd = currentTd->NextTd;
  918. qh->HwQH.VLink.HwAddress = currentTd->HwTD.LinkPointer.HwAddress;
  919. LOGENTRY(DeviceData, G, '_nu+', qh, currentTd, td);
  920. }
  921. }
  922. } else {
  923. // All transfers completed normally
  924. UhciPollAsyncEndpointSetNext:
  925. // Flush all completed tds
  926. // Complete transfer
  927. // set the sw headp to the new current head
  928. // Next transfer or status phase of a control transfer.
  929. SET_QH_TD(DeviceData, EndpointData, currentTd);
  930. }
  931. // now flush all completed TDs. Do it in order of completion.
  932. while (!IsListEmpty(&EndpointData->DoneTdList)) {
  933. PLIST_ENTRY listEntry;
  934. listEntry = RemoveHeadList(&EndpointData->DoneTdList);
  935. td = (PHCD_TRANSFER_DESCRIPTOR) CONTAINING_RECORD(
  936. listEntry,
  937. struct _HCD_TRANSFER_DESCRIPTOR,
  938. DoneLink);
  939. if ((td->Flags & (TD_FLAG_XFER | TD_FLAG_DONE)) ==
  940. (TD_FLAG_XFER | TD_FLAG_DONE)) {
  941. UhciProcessDoneAsyncTd(DeviceData, td);
  942. }
  943. }
  944. #if 0
  945. // now flush all completed TDs. Do it in order of allocation.
  946. for (i = (EndpointData->TdsUsed <= (EndpointData->TdLastAllocced+1)) ?
  947. (EndpointData->TdLastAllocced + 1) - EndpointData->TdsUsed :
  948. (EndpointData->TdLastAllocced + EndpointData->TdCount + 1) - EndpointData->TdsUsed, j=0;
  949. j < EndpointData->TdCount;
  950. j++, i = (i+1 < EndpointData->TdCount) ? i+1 : 0) {
  951. td = &EndpointData->TdList->Td[i];
  952. if ((td->Flags & (TD_FLAG_XFER | TD_FLAG_DONE)) ==
  953. (TD_FLAG_XFER | TD_FLAG_DONE)) {
  954. UhciProcessDoneAsyncTd(DeviceData, td);
  955. }
  956. }
  957. #endif
  958. // certain types of endpoints do not halt eg control
  959. // we resume these endpoints here
  960. if (TEST_FLAG(EndpointData->Flags, UHCI_EDFLAG_NOHALT) &&
  961. TEST_FLAG(EndpointData->Flags, UHCI_EDFLAG_HALTED)) {
  962. LOGENTRY(DeviceData, G, '_clH', qh, 0, 0);
  963. UhciSetEndpointStatus(
  964. DeviceData,
  965. EndpointData,
  966. ENDPOINT_STATUS_RUN);
  967. }
  968. }
  969. VOID
  970. UhciAbortAsyncTransfer(
  971. IN PDEVICE_DATA DeviceData,
  972. IN PENDPOINT_DATA EndpointData,
  973. IN PTRANSFER_CONTEXT TransferContext,
  974. OUT PULONG BytesTransferred
  975. )
  976. /*++
  977. Routine Description:
  978. Aborts the specified transfer by freeing all the TDs
  979. associated with said transfer. The queuehead for this
  980. transfer will have already been removed from the
  981. hardware queue when a SetEndpointState (paused) was
  982. sent by the port driver.
  983. Note that if another transfer is queued on the same
  984. endpoint, we need to fix up the list structure. We
  985. will also fix up any toggle issues on bulk endpoints.
  986. Arguments:
  987. Return Value:
  988. --*/
  989. {
  990. PHCD_TRANSFER_DESCRIPTOR td;
  991. PHCD_QUEUEHEAD_DESCRIPTOR qh;
  992. PHCD_TRANSFER_DESCRIPTOR joinTd = NULL;
  993. BOOLEAN updateHead = FALSE;
  994. ULONG toggle;
  995. ULONG i;
  996. UhciKdPrint((DeviceData, 2, "'Abort async transfer on EP %x\n", EndpointData));
  997. qh = EndpointData->QueueHead;
  998. // The endpoint should not be in the schedule
  999. LOGENTRY(DeviceData, G, '_Aat', qh, TransferContext, 0);
  1000. UHCI_ASSERT(DeviceData, !TEST_FLAG(qh->QhFlags, UHCI_QH_FLAG_IN_SCHEDULE));
  1001. // our mission now is to remove all TDs associated with
  1002. // this transfer
  1003. // get the last known head, we update the head when we process
  1004. // (AKA poll) the endpoint.
  1005. UHCI_ASSERT(DeviceData, EndpointData->HeadTd);
  1006. // Find the first TD in the transfer to abort
  1007. for (td = EndpointData->HeadTd; td; td = td->NextTd) {
  1008. if (td->TransferContext == TransferContext) {
  1009. break;
  1010. }
  1011. joinTd = td;
  1012. }
  1013. UHCI_ASSERT(DeviceData, td);
  1014. // Gonna have to fix up the toggle for bulk.
  1015. toggle = td->HwTD.Token.DataToggle;
  1016. // Was it the first transfer for this endpoint?
  1017. if (td == EndpointData->HeadTd) {
  1018. // This was the first queued transfer. Need to update the head.
  1019. updateHead = TRUE;
  1020. }
  1021. UHCI_ASSERT(DeviceData, td->TransferContext == TransferContext);
  1022. //
  1023. // Loop through all the TDs for this transfer and free
  1024. // them.
  1025. //
  1026. while (td) {
  1027. if (td->TransferContext == TransferContext) {
  1028. LOGENTRY(DeviceData, G, '_abT', qh, 0, td);
  1029. // if the TD completed we need to track the data
  1030. if (td->HwTD.Control.Active == 0) {
  1031. TEST_TRAP();
  1032. UhciProcessDoneAsyncTd(DeviceData, td);
  1033. } else {
  1034. UHCI_FREE_TD(DeviceData, EndpointData, td);
  1035. }
  1036. } else {
  1037. // We're past the transfer to abort.
  1038. break;
  1039. }
  1040. td = td->NextTd;
  1041. }
  1042. UhciFixDataToggle(DeviceData, EndpointData, td, toggle);
  1043. if (updateHead) {
  1044. // The transfer we removed was the first one.
  1045. SET_QH_TD(DeviceData, EndpointData, td);
  1046. } else {
  1047. // The transfer we removed was not the first one.
  1048. UHCI_ASSERT(DeviceData, joinTd);
  1049. if (td) {
  1050. // This was a middle transfer.
  1051. SET_NEXT_TD(joinTd, td);
  1052. } else {
  1053. // The transfer we removed was the last one.
  1054. EndpointData->TailTd = joinTd;
  1055. SET_NEXT_TD_NULL(joinTd);
  1056. }
  1057. }
  1058. *BytesTransferred = TransferContext->BytesTransferred;
  1059. }