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.

1880 lines
61 KiB

  1. /*++
  2. Copyright (c) 1995,1996 Microsoft Corporation
  3. :ts=4
  4. Module Name:
  5. async.c
  6. Abstract:
  7. This module manages bulk, interrupt & control type
  8. transactions on the USB.
  9. Environment:
  10. kernel mode only
  11. Notes:
  12. Revision History:
  13. 11-01-95 : created
  14. --*/
  15. #include "wdm.h"
  16. #include "stdarg.h"
  17. #include "stdio.h"
  18. #include "usbdi.h"
  19. #include "hcdi.h"
  20. #include "uhcd.h"
  21. // handle control transfers with this code
  22. #define CONTROL 1
  23. #define CONTROL_TRANSFER(ep) ((ep)->Type == USB_ENDPOINT_TYPE_CONTROL)
  24. // true if we'll need more TDs than are available to setup this
  25. // request
  26. #define ASYNC_TRANSFER_OVERFLOW(needed, ep, xtra) (BOOLEAN)(needed > ep->TDCount - xtra)
  27. #define UHCD_RESET_TD_LIST(ep) \
  28. { \
  29. HW_DESCRIPTOR_PHYSICAL_ADDRESS td; \
  30. td = (ep)->TDList->TDs[0].PhysicalAddress; \
  31. SET_T_BIT(td); \
  32. (ep)->QueueHead->HW_VLink = td; \
  33. }
  34. USBD_STATUS
  35. UHCD_MapTDError(
  36. PDEVICE_EXTENSION DeviceExtension,
  37. ULONG Td_Status,
  38. ULONG ActualLength
  39. )
  40. /*++
  41. Routine Description:
  42. Maps Error from TD.
  43. 1. STALL+BABBLE indicates that the td buffer was too small to
  44. hold all the data ie buffer overrun.
  45. 2. STALL if onlt stall bit is set then we recieved a stall PID
  46. 3. CRC_TIMEOUT+STALL indicates the device is not responding
  47. 4. CRC_TIMEOUT with no data indicates no response
  48. 5. CRC_TIMEOUT with data indicates CRC error
  49. Arguments:
  50. Return Value:
  51. usb status will be returned if transfer is complete.
  52. --*/
  53. {
  54. USBD_STATUS status;
  55. // Translate the TD status field to a USBD error code
  56. if (Td_Status == 0x3f) {
  57. // all bits on means software error
  58. status = USBD_STATUS_NO_MEMORY;
  59. UHCD_KdBreak((2, "'no mem\n"));
  60. DeviceExtension->Stats.SWErrorCount++;
  61. goto UHCD_MapTDError_Done;
  62. }
  63. if (Td_Status & TD_STATUS_BABBLE) {
  64. UHCD_KdBreak((2, "'babble\n"));
  65. DeviceExtension->FrameBabbleRecoverTD->Active = 1;
  66. }
  67. if (Td_Status == (TD_STATUS_STALL | TD_STATUS_BABBLE)) {
  68. status = USBD_STATUS_BUFFER_OVERRUN;
  69. DeviceExtension->Stats.BufferOverrunErrorCount++;
  70. } else if (Td_Status == TD_STATUS_STALL) {
  71. // if only the the stall bit is set in the TD then
  72. // we have a stall pid
  73. UHCD_KdBreak((2, "'stall 1\n"));
  74. DeviceExtension->Stats.StallPidCount++;
  75. status = USBD_STATUS_STALL_PID;
  76. } else if (Td_Status == (TD_STATUS_CRC_TIMEOUT | TD_STATUS_STALL)) {
  77. // stall and timeout bit indicates device not responding
  78. UHCD_KdBreak((2, "'stall 2\n"));
  79. DeviceExtension->Stats.TimeoutErrorCount++;
  80. status = USBD_STATUS_DEV_NOT_RESPONDING;
  81. } else if (Td_Status == TD_STATUS_CRC_TIMEOUT &&
  82. ActualLength != 0) {
  83. status = USBD_STATUS_CRC;
  84. DeviceExtension->Stats.CrcErrorCount++;
  85. } else if (Td_Status == TD_STATUS_CRC_TIMEOUT &&
  86. ActualLength == 0) {
  87. status = USBD_STATUS_DEV_NOT_RESPONDING;
  88. DeviceExtension->Stats.TimeoutErrorCount++;
  89. } else if (Td_Status == TD_STATUS_FIFO) {
  90. status = USBD_STATUS_DATA_OVERRUN;
  91. DeviceExtension->Stats.DataOverrunErrorCount++;
  92. } else {
  93. status = USBD_STATUS_INTERNAL_HC_ERROR;
  94. DeviceExtension->Stats.InternalHcErrorCount++;
  95. }
  96. UHCD_MapTDError_Done:
  97. LOGENTRY(LOG_MISC, 'MAPe', Td_Status, status, 0);
  98. return status;
  99. }
  100. //
  101. // queue is busy if the T bit is not set in the HW link pointed to by the queue head
  102. //
  103. __inline VOID
  104. UHCD_InitializeAsyncTD(
  105. IN PUHCD_ENDPOINT Endpoint,
  106. IN PHW_TRANSFER_DESCRIPTOR TransferDescriptor
  107. )
  108. /*++
  109. Routine Description:
  110. Initialize a TD for transfer use, initializes all
  111. fields possibly changed by execution of the TD.
  112. Arguments:
  113. TransferDescriptor - TD to recycle
  114. Return Value:
  115. None.
  116. --*/
  117. {
  118. TransferDescriptor->PID = 0;
  119. TransferDescriptor->Isochronous = 0;
  120. TransferDescriptor->InterruptOnComplete = 0;
  121. TransferDescriptor->Active = 1;
  122. TransferDescriptor->ActualLength = 0;
  123. TransferDescriptor->StatusField = 0;
  124. // set based on field in endpoint
  125. TransferDescriptor->LowSpeedControl =
  126. (Endpoint->EndpointFlags & EPFLAG_LOWSPEED) ? 1 : 0;
  127. TransferDescriptor->ReservedMBZ = 0;
  128. // All bits on
  129. TransferDescriptor->ErrorCounter = 3;
  130. CLEAR_T_BIT(TransferDescriptor->HW_Link);
  131. }
  132. __inline
  133. BOOLEAN
  134. UHCD_QueueBusy(
  135. IN PDEVICE_OBJECT DeviceObject,
  136. IN PUHCD_ENDPOINT Endpoint,
  137. OUT PULONG QueueTD
  138. )
  139. /*++
  140. Routine Description:
  141. Determine if a particular queue head is 'busy' ie
  142. still processing TDs
  143. Arguments:
  144. Return Value:
  145. TRUE if busy, FALSE otherwise.
  146. --*/
  147. {
  148. BOOLEAN busy = FALSE;
  149. ULONG i, active;
  150. HW_DESCRIPTOR_PHYSICAL_ADDRESS currentLink, vLink;
  151. PDEVICE_EXTENSION deviceExtension;
  152. deviceExtension = DeviceObject->DeviceExtension;
  153. // slot = urbWork->Slot;
  154. // UHCD_ASSERT(Endpoint->TDList == Endpoint->SlotTDList[slot]);
  155. vLink = Endpoint->QueueHead->HW_VLink;
  156. LOGENTRY(LOG_MISC, 'QBSY', vLink, 0, 0);
  157. if (!(vLink & UHCD_CF_TERMINATE)) {
  158. // T-bit not set see if the current TD has errored out
  159. //
  160. // locate the TD that the queue head is currently
  161. // pointing to.
  162. //
  163. currentLink =
  164. vLink & UHCD_DESCRIPTOR_PTR_MASK;
  165. for (i=0; i<Endpoint->TDCount; i++) {
  166. active = Endpoint->TDList->TDs[i].Active;
  167. if (currentLink ==
  168. (Endpoint->TDList->TDs[i].PhysicalAddress &
  169. UHCD_DESCRIPTOR_PTR_MASK)) {
  170. break;
  171. }
  172. }
  173. LOGENTRY(LOG_MISC, 'Qlnk', Endpoint, currentLink, i);
  174. LOGENTRY(LOG_MISC, 'Qlk2', Endpoint->QueueHead->HW_VLink, 0, 0);
  175. UHCD_ASSERT(currentLink == (Endpoint->TDList->TDs[i].PhysicalAddress &
  176. UHCD_DESCRIPTOR_PTR_MASK));
  177. //
  178. // Check the queue head, if it is busy then no processing
  179. // will be performed at this time.
  180. //
  181. busy = TRUE;
  182. if (!active) {
  183. //
  184. // Queue head points to an inactive TD we need to check
  185. // for one of the follwing cases
  186. //
  187. // 1. Short packet detected on an IN with a B0 stepping
  188. // version of the host controller.
  189. //
  190. // 2. The TD completed with an error.
  191. //
  192. // 3. Queue header update problem.
  193. //
  194. LOGENTRY(LOG_MISC, 'Qsts', deviceExtension->SteppingVersion,
  195. UHCD_USB_TO_SYSTEM_BUFFER_LENGTH(Endpoint->TDList->TDs[i].ActualLength),
  196. &Endpoint->TDList->TDs[i]);
  197. // check error
  198. if ((Endpoint->TDList->TDs[i].StatusField != 0) ||
  199. // check short packet
  200. (UHCD_USB_TO_SYSTEM_BUFFER_LENGTH(Endpoint->TDList->TDs[i].ActualLength) <
  201. UHCD_USB_TO_SYSTEM_BUFFER_LENGTH(Endpoint->TDList->TDs[i].MaxLength)
  202. && Endpoint->TDList->TDs[i].PID == USB_IN_PID &&
  203. deviceExtension->SteppingVersion >= UHCD_B0_STEP)) {
  204. // (UHCD_USB_TO_SYSTEM_BUFFER_LENGTH(Endpoint->TDList->TDs[i].ActualLength) <
  205. // Endpoint->MaxPacketSize && Endpoint->TDList->TDs[i].PID == USB_IN_PID &&
  206. // deviceExtension->SteppingVersion >= UHCD_B0_STEP)) {
  207. UHCD_ASSERT((Endpoint->QueueHead->HW_VLink &
  208. UHCD_DESCRIPTOR_PTR_MASK) ==
  209. (Endpoint->TDList->TDs[i].PhysicalAddress &
  210. UHCD_DESCRIPTOR_PTR_MASK));
  211. #if DBG
  212. if (Endpoint->TDList->TDs[i].StatusField) {
  213. LOGENTRY(LOG_MISC, 'Qerr', 0,
  214. Endpoint->TDList->TDs[i].StatusField,
  215. &Endpoint->TDList->TDs[i]);
  216. // TEST_TRAP();
  217. } else {
  218. // TEST_TRAP();
  219. LOGENTRY(LOG_MISC, 'Qsh2', Endpoint->MaxPacketSize,
  220. UHCD_USB_TO_SYSTEM_BUFFER_LENGTH(Endpoint->TDList->TDs[i].ActualLength),
  221. &Endpoint->TDList->TDs[i]);
  222. }
  223. #endif
  224. //
  225. // queue head is stopped
  226. //
  227. busy = FALSE;
  228. } else {
  229. HW_DESCRIPTOR_PHYSICAL_ADDRESS linkNow;
  230. // the td we are point to is not active and
  231. // has no error status, now we check for
  232. // queue header update problem ie is the queue
  233. // stuck?
  234. //
  235. linkNow = Endpoint->QueueHead->HW_VLink;
  236. LOGENTRY(LOG_MISC, 'QHp?',
  237. vLink,
  238. linkNow,
  239. Endpoint->TDList->TDs[i].HW_Link);
  240. if (linkNow & UHCD_CF_TERMINATE) {
  241. // pointing at a descriptor with the T bit,
  242. // indicate the queue is not busy
  243. busy = FALSE;
  244. } else if ((linkNow & UHCD_DESCRIPTOR_PTR_MASK) ==
  245. (vLink & UHCD_DESCRIPTOR_PTR_MASK)) {
  246. // bump the current TD int the queue head to the next TD
  247. // manually
  248. LOGENTRY(LOG_MISC, 'QHp!',
  249. vLink,
  250. linkNow,
  251. Endpoint->TDList->TDs[i].HW_Link);
  252. UHCD_ASSERT((linkNow & UHCD_DESCRIPTOR_PTR_MASK)
  253. == (Endpoint->TDList->TDs[i].PhysicalAddress & UHCD_DESCRIPTOR_PTR_MASK));
  254. Endpoint->QueueHead->HW_VLink =
  255. Endpoint->TDList->TDs[i].HW_Link;
  256. }
  257. }
  258. }
  259. }
  260. if (QueueTD) {
  261. *QueueTD = i;
  262. }
  263. return busy;
  264. }
  265. __inline
  266. BOOLEAN
  267. UHCD_PrepareAsyncDataPacket(
  268. IN PDEVICE_OBJECT DeviceObject,
  269. IN PHW_TRANSFER_DESCRIPTOR TransferDescriptor,
  270. IN PUHCD_ENDPOINT Endpoint,
  271. IN PHCD_URB Urb,
  272. IN BOOLEAN TransferOverflow,
  273. IN BOOLEAN ZeroLengthTransfer,
  274. IN BOOLEAN InitializeTransfer
  275. )
  276. /*++
  277. Routine Description:
  278. Prepare a data packet for an async transfer.
  279. Arguments:
  280. TransferDescriptor -
  281. Endpoint - endpoint associated with this transfer.
  282. Urb - pointer to URB Request for this transfer.
  283. Status - pointer to USBD status, will be filled in if transfer
  284. is complete.
  285. TransferOverflow - boolean flag indicates that we needed more
  286. TDs than we have.
  287. Return Value:
  288. None.
  289. --*/
  290. {
  291. PHCD_EXTENSION urbWork = HCD_AREA(Urb).HcdExtension;
  292. BOOLEAN status = FALSE;
  293. BOOLEAN setToggle = TRUE;
  294. USHORT packetSize;
  295. PDEVICE_EXTENSION deviceExtension;
  296. deviceExtension = DeviceObject->DeviceExtension;
  297. //
  298. // tracks the nth packet in this transfer
  299. //
  300. if (InitializeTransfer &&
  301. // if this is init for multiple
  302. // slot endpoint then don't
  303. // mess with the data toggle
  304. // until the xfer is active
  305. Endpoint->MaxRequests > 1) {
  306. setToggle = FALSE;
  307. }
  308. urbWork->PacketsProcessed++;
  309. LOGENTRY(LOG_MISC, 'Pasy', urbWork->TransferOffset, urbWork, TransferDescriptor);
  310. #if DBG
  311. if (!ZeroLengthTransfer) {
  312. UHCD_ASSERT(urbWork->TransferOffset < Urb->HcdUrbCommonTransfer.TransferBufferLength);
  313. }
  314. #endif
  315. //
  316. // possibly re-using this TD
  317. //
  318. UHCD_InitializeAsyncTD(Endpoint, TransferDescriptor);
  319. if (setToggle) {
  320. urbWork->Flags |= UHCD_TOGGLE_READY;
  321. TransferDescriptor->RetryToggle = Endpoint->DataToggle;
  322. Endpoint->DataToggle ^=1;
  323. }
  324. #if DBG
  325. // Use this field to detect if we
  326. // process the same TD twice
  327. TransferDescriptor->Frame = 0;
  328. #endif
  329. TransferDescriptor->PID = DATA_DIRECTION_IN(Urb) ? USB_IN_PID : USB_OUT_PID;
  330. if (DATA_DIRECTION_IN(Urb)) {
  331. if (deviceExtension->SteppingVersion < UHCD_B0_STEP) {
  332. //
  333. // Direction is IN, we'll need an interrupt an T bit
  334. // set on every packet to check for short packet.
  335. //
  336. // The B0 step does not have this problem
  337. //
  338. TransferDescriptor->InterruptOnComplete = 1;
  339. SET_T_BIT(TransferDescriptor->HW_Link);
  340. } else {
  341. // TEST_TRAP();
  342. TransferDescriptor->ShortPacketDetect = 1;
  343. }
  344. }
  345. if (TransferOverflow) {
  346. //
  347. // if we need more descriptors than we
  348. // have then so we'll set an interrupt on a middle packet to
  349. // give us a chance to prepare more.
  350. //
  351. // lets try every 4th packet
  352. if (urbWork->PacketsProcessed % 4 == 0) {
  353. TransferDescriptor->InterruptOnComplete = 1;
  354. }
  355. }
  356. // get the part of the buffer this TD represents
  357. // The urbWork structure contains a list of logical addresses we got
  358. // from IoMapTransfer -- these are the valid physical addresses we will
  359. // give to the host controller.
  360. //
  361. // compute the packet size for this packet
  362. //
  363. if (urbWork->TransferOffset + Endpoint->MaxPacketSize
  364. <= Urb->HcdUrbCommonTransfer.TransferBufferLength) {
  365. packetSize = Endpoint->MaxPacketSize;
  366. } else {
  367. packetSize = (USHORT)(Urb->HcdUrbCommonTransfer.TransferBufferLength -
  368. urbWork->TransferOffset);
  369. }
  370. if (ZeroLengthTransfer) {
  371. TransferDescriptor->PacketBuffer =
  372. urbWork->LogicalAddressList[0].LogicalAddress;
  373. TransferDescriptor->MaxLength =
  374. UHCD_SYSTEM_TO_USB_BUFFER_LENGTH(packetSize);
  375. LOGENTRY(LOG_MISC, 'zpak', TransferDescriptor->PacketBuffer,
  376. packetSize, 0);
  377. status = TRUE;
  378. } else if (TransferDescriptor->PacketBuffer =
  379. UHCD_GetPacketBuffer(DeviceObject,
  380. Endpoint,
  381. Urb,
  382. urbWork,
  383. urbWork->TransferOffset,
  384. packetSize)) {
  385. urbWork->TransferOffset += packetSize;
  386. LOGENTRY(LOG_MISC, 'Pbuf', TransferDescriptor->PacketBuffer, packetSize, urbWork->TransferOffset);
  387. UHCD_ASSERT(urbWork->TransferOffset <= Urb->HcdUrbCommonTransfer.TransferBufferLength);
  388. TransferDescriptor->MaxLength =
  389. UHCD_SYSTEM_TO_USB_BUFFER_LENGTH(packetSize);
  390. status = TRUE;
  391. }
  392. LOG_TD('daTD', TransferDescriptor);
  393. UHCD_KdPrint((2, "'**TD for BULK/INT/CONTROL DATA packet\n"));
  394. UHCD_Debug_DumpTD(TransferDescriptor);
  395. return status;
  396. }
  397. USBD_STATUS
  398. UHCD_InitializeAsyncTransfer(
  399. IN PDEVICE_OBJECT DeviceObject,
  400. IN PUHCD_ENDPOINT Endpoint,
  401. IN PHCD_URB Urb
  402. )
  403. /*++
  404. Routine Description:
  405. This routine initializes the TDs needed by the hardware
  406. to process this request, called from Transfer_StartIo.
  407. The transfer list for this URB should be ready for
  408. processing before returning from this routine.
  409. Arguments:
  410. DeviceObject - pointer to a device object.
  411. Endpoint - Endpoint associated with this Urb.
  412. Urb - pointer to URB Request Packet for this transfer.
  413. Return Value:
  414. Usbd status code.
  415. --*/
  416. {
  417. PDEVICE_EXTENSION deviceExtension;
  418. SHORT i, xtra, slot;
  419. USBD_STATUS usbStatus = USBD_STATUS_SUCCESS;
  420. PUHCD_TD_LIST tDList;
  421. #if DBG
  422. SHORT count;
  423. #endif
  424. USHORT dataDescriptorsNeeded;
  425. PHCD_EXTENSION urbWork = HCD_AREA(Urb).HcdExtension;
  426. PHW_QUEUE_HEAD queueHead;
  427. UHCD_KdPrint((2, "'enter UHCD_InitializeAsyncTransfer\n"));
  428. ASSERT_ENDPOINT(Endpoint);
  429. UHCD_ASSERT(Endpoint == HCD_AREA(Urb).HcdEndpoint);
  430. //
  431. // if we have already been initialized or the queue
  432. // is in use then just exit.
  433. //
  434. queueHead = Endpoint->QueueHead;
  435. if ((urbWork->Flags & UHCD_TRANSFER_INITIALIZED ||
  436. queueHead->Flags) &&
  437. !(urbWork->Flags & UHCD_TRANSFER_DEFER)) {
  438. goto UHCD_InitializeAsyncTransfer_Done;
  439. }
  440. //
  441. // note that we have initialized
  442. //
  443. urbWork->Flags |= UHCD_TRANSFER_INITIALIZED;
  444. queueHead->Flags |= UHCD_QUEUE_IN_USE;
  445. LOGENTRY(LOG_MISC, 'Iasx', Endpoint, Urb, DeviceObject);
  446. #ifdef CONTROL
  447. if (CONTROL_TRANSFER(Endpoint)) {
  448. LOGENTRY(LOG_MISC, 'Ctrl', Endpoint, Urb, DeviceObject);
  449. // data toggle must be 0 for setup
  450. // BUGBUG reset data toggle in ENDPOINT
  451. Endpoint->DataToggle = 0;
  452. }
  453. #endif
  454. deviceExtension = DeviceObject->DeviceExtension;
  455. //
  456. // Set up the TDs we will need to do this transfer
  457. //
  458. // do some general init stuff first,
  459. // TDs form a circular list
  460. slot = urbWork->Slot;
  461. tDList = Endpoint->SlotTDList[slot];
  462. for (i=0; i < Endpoint->TDCount; i++) {
  463. tDList->TDs[i].Endpoint = Endpoint->EndpointAddress;
  464. tDList->TDs[i].Address = Endpoint->DeviceAddress;
  465. tDList->TDs[i].HW_Link =
  466. tDList->TDs[(i+1) % Endpoint->TDCount].PhysicalAddress;
  467. UHCD_InitializeAsyncTD(Endpoint, &tDList->TDs[i]);
  468. }
  469. // current descriptor is first packet
  470. Endpoint->CurrentTDIdx[slot] = 0;
  471. // No tail descriptor yet
  472. Endpoint->LastTDInTransferIdx[slot] = -1;
  473. // if we have data to send or receive break it up into TDs,
  474. // do this until we run out of TDs or we finish the buffer
  475. // first, calculate how many data descriptors we will need
  476. // based on the transfer buffer length
  477. dataDescriptorsNeeded = (USHORT) (Urb->HcdUrbCommonTransfer.TransferBufferLength /
  478. Endpoint->MaxPacketSize);
  479. if ((ULONG)(dataDescriptorsNeeded)*Endpoint->MaxPacketSize < Urb->HcdUrbCommonTransfer.TransferBufferLength) {
  480. dataDescriptorsNeeded++;
  481. }
  482. // Initialize some endpoint fields
  483. urbWork->TransferOffset = 0;
  484. urbWork->BytesTransferred = 0;
  485. urbWork->PacketsProcessed = 0;
  486. //points to first available TD
  487. Endpoint->LastTDPreparedIdx[slot] = 0;
  488. LOGENTRY(LOG_MISC, 'XfrB', Urb, dataDescriptorsNeeded, Urb->HcdUrbCommonTransfer.TransferBufferLength);
  489. #ifdef CONTROL
  490. if (CONTROL_TRANSFER(Endpoint)) {
  491. // note that we'll need two extra TDs (for setup and status).
  492. xtra = 2;
  493. // Build a setup packet if necessary.
  494. UHCD_ASSERT(Endpoint->MaxRequests == 1);
  495. UHCD_PrepareSetupPacket(&tDList->TDs[Endpoint->LastTDPreparedIdx[slot]],
  496. Endpoint,
  497. Urb);
  498. // point to next available TD
  499. Endpoint->LastTDPreparedIdx[slot]++;
  500. } else {
  501. #endif
  502. xtra = 0;
  503. #ifdef CONTROL
  504. }
  505. #endif
  506. LOGENTRY(LOG_MISC, 'LBuf', 0, 0, urbWork->LogicalAddressList[0].LogicalAddress);
  507. //
  508. // Begin preparing Data TDs, Endpoint->LastTDPreparedIdx points
  509. // to the first available TD. Loop until we use up all the available
  510. // TDs or we finish off the client buffer.
  511. //
  512. #if DBG
  513. count = 0;
  514. #endif
  515. // remember the data toggle when we set up
  516. urbWork->DataToggle = Endpoint->DataToggle;
  517. while (Endpoint->LastTDPreparedIdx[slot]<Endpoint->TDCount) {
  518. if (Urb->HcdUrbCommonTransfer.TransferBufferLength == 0 &&
  519. !CONTROL_TRANSFER(Endpoint)) {
  520. //
  521. // special case the zero transfer
  522. //
  523. TEST_TRAP();
  524. dataDescriptorsNeeded = 1;
  525. if (!UHCD_PrepareAsyncDataPacket(DeviceObject,
  526. &tDList->TDs[Endpoint->LastTDPreparedIdx[slot]],
  527. Endpoint,
  528. Urb,
  529. // no overflow
  530. FALSE,
  531. TRUE,
  532. // init
  533. TRUE)) {
  534. // an error occurred forming the packet
  535. // bail out now
  536. TEST_TRAP();
  537. usbStatus = USBD_STATUS_NO_MEMORY;
  538. goto UHCD_InitializeAsyncTransfer_Done;
  539. }
  540. Endpoint->LastTDPreparedIdx[slot]++;
  541. break;
  542. }
  543. if (urbWork->TransferOffset < Urb->HcdUrbCommonTransfer.TransferBufferLength ) {
  544. if (!UHCD_PrepareAsyncDataPacket(DeviceObject,
  545. &tDList->TDs[Endpoint->LastTDPreparedIdx[slot]],
  546. Endpoint,
  547. Urb,
  548. ASYNC_TRANSFER_OVERFLOW(dataDescriptorsNeeded, Endpoint, xtra),
  549. FALSE,
  550. // init
  551. TRUE)) {
  552. // an error occurred forming the packet
  553. // bail out now
  554. TEST_TRAP();
  555. usbStatus = USBD_STATUS_NO_MEMORY;
  556. goto UHCD_InitializeAsyncTransfer_Done;
  557. }
  558. Endpoint->LastTDPreparedIdx[slot]++;
  559. #if DBG
  560. count++;
  561. #endif
  562. } else {
  563. break;
  564. }
  565. }
  566. #if DBG
  567. LOGENTRY(LOG_MISC, 'dTDs', Endpoint, count, dataDescriptorsNeeded);
  568. #endif
  569. //
  570. // We have more data than descriptors, save some state information
  571. // so we can continue the process later.
  572. //
  573. if (ASYNC_TRANSFER_OVERFLOW(dataDescriptorsNeeded, Endpoint, xtra)) {
  574. // set the T-bit for the last TD we were able to set up
  575. // set the interrupt bit so we can prepare more TDs
  576. LOGENTRY(LOG_MISC, 'Ovrf', Endpoint, dataDescriptorsNeeded, xtra);
  577. // LastTDPreparedIdx points to the last TD in the set
  578. Endpoint->LastTDPreparedIdx[slot] = Endpoint->TDCount-1;
  579. Endpoint->TDList->TDs[Endpoint->LastTDPreparedIdx[slot]].InterruptOnComplete = 1;
  580. SET_T_BIT(tDList->TDs[Endpoint->LastTDPreparedIdx[slot]].HW_Link);
  581. } else {
  582. // All the data fit, mark the tail so we know
  583. // when we are done.
  584. #ifdef CONTROL
  585. if (CONTROL_TRANSFER(Endpoint)) {
  586. Endpoint->LastTDPreparedIdx[slot] =
  587. Endpoint->LastTDInTransferIdx[slot] = dataDescriptorsNeeded+1;
  588. UHCD_PrepareStatusPacket(&tDList->TDs[Endpoint->LastTDInTransferIdx[slot]],
  589. Endpoint,
  590. Urb);
  591. } else {
  592. #endif
  593. Endpoint->LastTDPreparedIdx[slot] =
  594. Endpoint->LastTDInTransferIdx[slot] = dataDescriptorsNeeded-1;
  595. #ifdef CONTROL
  596. }
  597. #endif
  598. //
  599. // Set the IOC bit for this and T bit for the last TD in the
  600. // transfer
  601. //
  602. UHCD_KdPrint((2, "'IOC bit set for TD %x\n",
  603. &tDList->TDs[Endpoint->LastTDInTransferIdx[slot]]));
  604. tDList->TDs[Endpoint->LastTDInTransferIdx[slot]].InterruptOnComplete = 1;
  605. SET_T_BIT(tDList->TDs[Endpoint->LastTDInTransferIdx[slot]].HW_Link);
  606. }
  607. //
  608. // at this point...
  609. // LastTDPreparedIdx points to the last TD we set up for this transfer
  610. // LastTDInTransferIdx points to the last TD in the set or -1 if the transfer
  611. // required more TDs than we had.
  612. // CurrentTDIdx points to the first active TD in the set
  613. //
  614. UHCD_InitializeAsyncTransfer_Done:
  615. UHCD_KdPrint((2, "'exit UHCD_InitializeAsyncTransfer\n"));
  616. return usbStatus;
  617. }
  618. USBD_STATUS
  619. UHCD_ProcessAsyncTransfer(
  620. IN PDEVICE_OBJECT DeviceObject,
  621. IN PUHCD_ENDPOINT Endpoint,
  622. IN PHCD_URB Urb,
  623. IN OUT PBOOLEAN Completed
  624. )
  625. /*++
  626. Routine Description:
  627. Checks to see if an async transfer is complete.
  628. Arguments:
  629. DeviceObject - pointer to a device object.
  630. Endpoint - endpoint to check for completed transfers.
  631. Urb - ptr to URB to process.
  632. Completed - TRUE if this transfer is complete, Status set to proper
  633. error code.
  634. Return Value:
  635. usb status will be returned if transfer is complete.
  636. --*/
  637. {
  638. BOOLEAN resumed = FALSE;
  639. LONG i, queueTD, slot;
  640. PHW_TRANSFER_DESCRIPTOR transferDescriptor;
  641. BOOLEAN prepareMoreTDs = FALSE;
  642. PHCD_EXTENSION urbWork = HCD_AREA(Urb).HcdExtension;
  643. USBD_STATUS usbStatus = Urb->HcdUrbCommonTransfer.Status;
  644. PHW_QUEUE_HEAD queueHead;
  645. PDEVICE_EXTENSION deviceExtension;
  646. STARTPROC("Pas+");
  647. // UHCD_KdPrint((2, "'enter UHCD_ProcessAsyncTransfer\n"));
  648. ASSERT_ENDPOINT(Endpoint);
  649. *Completed = FALSE;
  650. queueHead = Endpoint->QueueHead;
  651. slot = urbWork->Slot;
  652. // can only process one TD list at a time
  653. LOGENTRY(LOG_MISC, 'Pasx', Endpoint->LastPacketDataToggle, slot, Urb);
  654. LOGENTRY(LOG_MISC, 'Pas1', Endpoint->TDList, slot, Endpoint->SlotTDList[slot]);
  655. LOGENTRY(LOG_MISC, 'PaEO', Endpoint, Endpoint->EndpointFlags, queueHead);
  656. #if DBG
  657. switch(Endpoint->Type) {
  658. case USB_ENDPOINT_TYPE_CONTROL:
  659. LOGENTRY(LOG_MISC, 'Pctr', 0, 0, queueHead);
  660. break;
  661. case USB_ENDPOINT_TYPE_BULK:
  662. LOGENTRY(LOG_MISC, 'Pblk', 0, 0, queueHead);
  663. break;
  664. }
  665. #endif
  666. deviceExtension=DeviceObject->DeviceExtension;
  667. //
  668. // if we marked the transfer canceling the go ahead
  669. // and completed it now.
  670. //
  671. if (Urb->HcdUrbCommonTransfer.Status == UHCD_STATUS_PENDING_CANCELING) {
  672. // set the data toggle based on the last packet completed
  673. Endpoint->DataToggle =
  674. Endpoint->LastPacketDataToggle ^1;
  675. LOGENTRY(LOG_MISC, 'PxxC',
  676. Endpoint->LastPacketDataToggle, Endpoint->DataToggle, Urb);
  677. *Completed = TRUE;
  678. usbStatus = USBD_STATUS_CANCELED;
  679. goto UHCD_ProcessAsyncTransfer_done;
  680. }
  681. //
  682. // see if the endpoint has been aborted, if so stop this transfer and
  683. // wait unitl the next frame to complete it.
  684. //
  685. if ((Endpoint->EndpointFlags & EPFLAG_ABORT_ACTIVE_TRANSFERS) ||
  686. Urb->HcdUrbCommonTransfer.Status == UHCD_STATUS_PENDING_XXX) {
  687. LOGENTRY(LOG_MISC, 'Pxxx', 0, slot, Urb);
  688. UHCD_RESET_TD_LIST(Endpoint);
  689. UHCD_RequestInterrupt(DeviceObject, -2);
  690. Urb->HcdUrbCommonTransfer.Status =
  691. UHCD_STATUS_PENDING_CANCELING;
  692. usbStatus = Urb->HcdUrbCommonTransfer.Status;
  693. goto UHCD_ProcessAsyncTransfer_done;
  694. }
  695. //
  696. // if queue is busy or endpoint stalled then no processing will be performed
  697. // at this time
  698. //
  699. if (Endpoint->EndpointFlags & EPFLAG_HOST_HALTED) {
  700. goto UHCD_ProcessAsyncTransfer_done;
  701. }
  702. // process an active transfer, only one can be current
  703. UHCD_ASSERT(Endpoint->TDList == Endpoint->SlotTDList[slot]);
  704. if (UHCD_QueueBusy(DeviceObject, Endpoint, &queueTD)) {
  705. //#if 0
  706. LOGENTRY(LOG_MISC, 'PRqh', Endpoint, queueTD, 0);
  707. // **
  708. // Code to process a queue head that the hardware is
  709. // currently accessing.
  710. // **
  711. //
  712. // Queue head is busy but we can still process and
  713. // set up more TDs
  714. //
  715. // attempt some processing now...
  716. //
  717. // scan through the retired TDs between current TD and the TD
  718. // that the queue head is pointing at, we should only encounter
  719. // IN and OUT TDs that have completed successfully
  720. i = Endpoint->CurrentTDIdx[slot];
  721. // currently pointed to by the queue head
  722. while (i != queueTD) {
  723. LOGENTRY(LOG_MISC, 'QuTD', Endpoint->CurrentTDIdx[slot], i, queueTD);
  724. if (i == Endpoint->LastTDInTransferIdx[slot]) {
  725. // if this is the last TD let the
  726. // process routine handle it.
  727. break;
  728. }
  729. transferDescriptor = &Endpoint->TDList->TDs[i];
  730. UHCD_ASSERT(transferDescriptor->Active == 0);
  731. UHCD_ASSERT(transferDescriptor->StatusField == 0);
  732. if (transferDescriptor->PID == USB_IN_PID ||
  733. transferDescriptor->PID == USB_OUT_PID) {
  734. urbWork->BytesTransferred += UHCD_USB_TO_SYSTEM_BUFFER_LENGTH(transferDescriptor->ActualLength);
  735. LOGENTRY(LOG_MISC, 'reTD', transferDescriptor,
  736. transferDescriptor->Frame, Urb->HcdUrbCommonTransfer.TransferBufferLength);
  737. Endpoint->LastPacketDataToggle =
  738. (UCHAR)transferDescriptor->RetryToggle;
  739. UHCD_ASSERT(transferDescriptor->Frame == 0);
  740. #if DBG
  741. transferDescriptor->Frame = 1;
  742. #endif
  743. UHCD_ASSERT(urbWork->BytesTransferred <=
  744. Urb->HcdUrbCommonTransfer.TransferBufferLength);
  745. }
  746. i = NEXT_TD(i, Endpoint);
  747. }
  748. //Endpoint->CurrentTDIdx = queueTD;
  749. Endpoint->CurrentTDIdx[slot] = (SHORT)i;
  750. //#endif
  751. if (Endpoint->LastTDInTransferIdx[slot] == -1) {
  752. //
  753. // This was an OVERFLOW transfer
  754. // ie we didn't have enough TDs to satisfy the request.
  755. //
  756. usbStatus = UHCD_PrepareMoreAsyncTDs(DeviceObject,
  757. Endpoint,
  758. Urb,
  759. TRUE);
  760. if (USBD_ERROR(usbStatus)) {
  761. //
  762. // if we get an error preparing more TDs
  763. // then we'll need to abort the transfer
  764. //
  765. TEST_TRAP();
  766. UHCD_RESET_TD_LIST(Endpoint);
  767. UHCD_RequestInterrupt(DeviceObject, -2);
  768. Urb->HcdUrbCommonTransfer.Status =
  769. UHCD_STATUS_PENDING_CANCELING;
  770. }
  771. }
  772. goto UHCD_ProcessAsyncTransfer_done;
  773. }
  774. LOGENTRY(LOG_MISC, 'Pasx', Endpoint, Endpoint->CurrentTDIdx[slot], DeviceObject);
  775. //
  776. // If we get here the queue is not busy.
  777. //
  778. //
  779. // Scan our active TDs starting with 'CurrentTDIdx' stop as soon as we find
  780. // a TD that is still active or we find that the STATUS TD is complete
  781. //
  782. //
  783. // Start at the last TD that had not completed
  784. i = Endpoint->CurrentTDIdx[slot];
  785. for (;;) {
  786. //
  787. // This loop terminates on the following conditions:
  788. // 1. An active TD is encountered.
  789. // 2. The last TD in the transfer is processed.
  790. // 3. An non-zero status value is encountered on
  791. // a completed TD.
  792. // 4. The last TD that had been set up for the
  793. // transfer is complete.
  794. transferDescriptor = &Endpoint->TDList->TDs[i];
  795. LOGENTRY(LOG_MISC, 'ckTD', i, transferDescriptor,
  796. Endpoint->CurrentTDIdx[slot]);
  797. //
  798. // Did this TD complete?
  799. //
  800. UHCD_KdPrint((2, "'checking TD %x\n", transferDescriptor));
  801. if (transferDescriptor->Active == 0) {
  802. LOG_TD('acTD', (PULONG) transferDescriptor);
  803. UHCD_KdPrint((2, "'TD %x completed\n", transferDescriptor));
  804. UHCD_Debug_DumpTD(transferDescriptor);
  805. Endpoint->LastPacketDataToggle = (UCHAR)transferDescriptor->RetryToggle;
  806. LOGENTRY(LOG_MISC, 'LPdt', Endpoint,
  807. Endpoint->LastPacketDataToggle, 0);
  808. //
  809. // Yes, TD completed figure out what to do
  810. //
  811. if (transferDescriptor->StatusField != 0) {
  812. // we got an error, map the status code and retire
  813. // this transfer
  814. *Completed = TRUE;
  815. usbStatus = UHCD_MapTDError(deviceExtension, transferDescriptor->StatusField,
  816. UHCD_USB_TO_SYSTEM_BUFFER_LENGTH(transferDescriptor->ActualLength));
  817. // Point the queue head at the first TD with the T-Bit set.
  818. // NOTE: we won't get here if the TD is marked with status NAK
  819. // because the active bit is still set.
  820. UHCD_ASSERT_QSTOPPED(DeviceObject, Endpoint, NULL);
  821. UHCD_RESET_TD_LIST(Endpoint);
  822. LOGENTRY(LOG_MISC, 'Stal', Endpoint, transferDescriptor->StatusField, usbStatus);
  823. UHCD_KdBreak((2, "'Stall\n"));
  824. break;
  825. }
  826. //
  827. // No Error, update bytes transferred for this
  828. // packet if it was data.
  829. //
  830. if (transferDescriptor->PID == USB_IN_PID ||
  831. transferDescriptor->PID == USB_OUT_PID) {
  832. urbWork->BytesTransferred += UHCD_USB_TO_SYSTEM_BUFFER_LENGTH(transferDescriptor->ActualLength);
  833. UHCD_ASSERT(transferDescriptor->Frame == 0);
  834. #if DBG
  835. transferDescriptor->Frame = 1;
  836. #endif
  837. UHCD_ASSERT(urbWork->BytesTransferred <=
  838. Urb->HcdUrbCommonTransfer.TransferBufferLength);
  839. }
  840. //
  841. // Check to see if we are done with the transfer.
  842. //
  843. if (i == Endpoint->LastTDInTransferIdx[slot]) {
  844. //
  845. // This is the last TD in the transfer, complete now.
  846. //
  847. // point the queue head at the first TD with the T-Bit set
  848. UHCD_ASSERT_QSTOPPED(DeviceObject, Endpoint, NULL);
  849. UHCD_RESET_TD_LIST(Endpoint);
  850. *Completed = TRUE;
  851. usbStatus = USBD_STATUS_SUCCESS;
  852. break;
  853. }
  854. //
  855. // Short packets cause the transfer to complete.
  856. //
  857. if (transferDescriptor->ActualLength != transferDescriptor->MaxLength) {
  858. //
  859. // We have a short transfer.
  860. //
  861. LOGENTRY(LOG_MISC, 'Shrt',
  862. transferDescriptor,
  863. transferDescriptor->ActualLength,
  864. transferDescriptor->MaxLength);
  865. #ifdef CONTROL
  866. #if DBG
  867. //
  868. // test handling short transfer_ok with control transfer
  869. //
  870. if (CONTROL_TRANSFER(Endpoint) &&
  871. !(Urb->HcdUrbCommonTransfer.TransferFlags & USBD_SHORT_TRANSFER_OK)) {
  872. TEST_TRAP();
  873. }
  874. #endif //DBG
  875. if (CONTROL_TRANSFER(Endpoint) &&
  876. Urb->HcdUrbCommonTransfer.TransferFlags & USBD_SHORT_TRANSFER_OK) {
  877. //
  878. // If this is a control transfer then we need to advance
  879. // to the status phase
  880. //
  881. if (Endpoint->LastTDInTransferIdx[slot] == -1) {
  882. // status phase has not been set up yet
  883. // do it now
  884. Endpoint->LastTDInTransferIdx[slot] = (SHORT) NEXT_TD(i, Endpoint);
  885. UHCD_PrepareStatusPacket(&Endpoint->TDList->TDs[Endpoint->LastTDInTransferIdx[slot]],
  886. Endpoint,
  887. Urb);
  888. SET_T_BIT(Endpoint->TDList->TDs[Endpoint->LastTDInTransferIdx[slot]].HW_Link);
  889. }
  890. // make the status p hase the current TD
  891. i = Endpoint->CurrentTDIdx[slot] =
  892. Endpoint->LastTDInTransferIdx[slot];
  893. // just point the queue head at the status packet
  894. // and go!
  895. queueHead->HW_VLink =
  896. Endpoint->TDList->TDs[Endpoint->LastTDInTransferIdx[slot]].PhysicalAddress;
  897. LOGENTRY(LOG_MISC, 'ShSt',
  898. queueHead,
  899. &Endpoint->TDList->TDs[Endpoint->LastTDInTransferIdx[slot]],
  900. 0);
  901. // Go to the top of the loop in case it completed,
  902. // we'll still get the interrupt but we may be able
  903. // to finish the transfer sooner.
  904. // note that we resumed the queue head
  905. // so we don't resume it agian.
  906. resumed = TRUE;
  907. continue;
  908. } else {
  909. #endif
  910. //
  911. // Short packet and not a control transfer or control transfer
  912. // and short transfer is to be treated as an error, just complete
  913. // the transfer now.
  914. //
  915. UHCD_ASSERT_QSTOPPED(DeviceObject, Endpoint, NULL);
  916. UHCD_RESET_TD_LIST(Endpoint);
  917. // adjust data toggle
  918. Endpoint->DataToggle =
  919. (UCHAR)transferDescriptor->RetryToggle;
  920. Endpoint->DataToggle ^=1;
  921. *Completed = TRUE;
  922. //check the SHORT_TRANSFER_OK flag
  923. if (Urb->HcdUrbCommonTransfer.TransferFlags & USBD_SHORT_TRANSFER_OK) {
  924. usbStatus = USBD_STATUS_SUCCESS;
  925. } else {
  926. TEST_TRAP();
  927. usbStatus = USBD_STATUS_ERROR_SHORT_TRANSFER;
  928. }
  929. break;
  930. #ifdef CONTROL
  931. }
  932. #endif
  933. //
  934. // end of short packet detection.
  935. //
  936. }
  937. //
  938. // Done with the TD but not with the transfer, advance our
  939. // index to the current TD.
  940. //
  941. Endpoint->CurrentTDIdx[slot] = NEXT_TD(Endpoint->CurrentTDIdx[slot], Endpoint);
  942. //
  943. // see if we need to prepare more TDs
  944. //
  945. LOGENTRY(LOG_MISC, 'chkM', i, Endpoint->LastTDPreparedIdx[slot],
  946. Endpoint->LastTDInTransferIdx[slot]);
  947. if (i == Endpoint->LastTDPreparedIdx[slot] &&
  948. Endpoint->LastTDInTransferIdx[slot] == -1) {
  949. //
  950. // This was the last TD prepared for an OVERLOW transfer
  951. // ie we didn't have enough TDs to satifsy the request.
  952. //
  953. // This is when we prepare more TDs.
  954. //
  955. usbStatus = UHCD_PrepareMoreAsyncTDs(DeviceObject,
  956. Endpoint,
  957. Urb,
  958. FALSE);
  959. if (USBD_ERROR(usbStatus)) {
  960. // an error occurred preparing more TDs
  961. // terminate the transfer now
  962. TEST_TRAP();
  963. // assert that the T-BIT is still set in the QH.
  964. UHCD_ASSERT_QSTOPPED(DeviceObject, Endpoint, NULL);
  965. UHCD_RESET_TD_LIST(Endpoint);
  966. *Completed = TRUE;
  967. goto UHCD_ProcessAsyncTransfer_done;
  968. }
  969. }
  970. // end active == 0
  971. } else {
  972. //
  973. // This TD is still active, stop processing TDs now.
  974. //
  975. break;
  976. }
  977. //
  978. // advance to the next TD in the list
  979. //
  980. i = NEXT_TD(i, Endpoint);
  981. } // end for (;;)
  982. if (!*Completed && !resumed) {
  983. // NOTE that if the QH is busy we
  984. // should not get here
  985. // make sure the queue head is still stopped
  986. UHCD_ASSERT_QSTOPPED(DeviceObject, Endpoint, NULL);
  987. LOGENTRY(LOG_MISC, 'rsum', Endpoint, Endpoint->CurrentTDIdx[slot],
  988. &Endpoint->TDList->TDs[Endpoint->CurrentTDIdx[slot]]);
  989. //
  990. // We get here if the transfer has not completed yet but the
  991. // queue head is stopped, this is caused by one of the following
  992. // conditions:
  993. //
  994. // 1. The last TD that could be set up for a transfer completed
  995. // and we had to set up more.
  996. //
  997. // 2. An IN Transfer completed for BULK or INT and it was not a
  998. // short packet and it was not the last TD in the transfer and
  999. // short packet detection is not enabled on the HC.
  1000. //
  1001. // In any case we'll need to resume the Queue head, we point
  1002. // the queue head at the current TD and go.
  1003. queueHead->HW_VLink =
  1004. Endpoint->TDList->TDs[Endpoint->CurrentTDIdx[slot]].PhysicalAddress;
  1005. }
  1006. UHCD_ProcessAsyncTransfer_done:
  1007. if (*Completed) {
  1008. queueHead->Flags &= ~UHCD_QUEUE_IN_USE;
  1009. // note that we don't activate the next transfer if we
  1010. // are in an abort scenario
  1011. if (Endpoint->MaxRequests > 1) {
  1012. //
  1013. // transfer completed, so queue is no longer in use
  1014. // try to start the next transfer here.
  1015. //
  1016. UHCD_ASSERT_QSTOPPED(DeviceObject, Endpoint, NULL);
  1017. //
  1018. // BUGBUG if MaxRequets is > 2 then we'll need some kind of sequence
  1019. // number so we can start the transfers in the right order.
  1020. // Since we have only two now the one that we are not completing
  1021. // is the next one to start.
  1022. //
  1023. // get the next ready transfer based on seq number
  1024. for (i=0; i< Endpoint->MaxRequests; i++) {
  1025. PHCD_URB localUrb;
  1026. PHCD_EXTENSION localWork;
  1027. UCHAR nextXfer = Endpoint->CurrentXferId+1;
  1028. localUrb = Endpoint->ActiveTransfers[i];
  1029. if (localUrb) {
  1030. localWork = HCD_AREA(localUrb).HcdExtension;
  1031. LOGENTRY(LOG_MISC, 'Cnxt', Endpoint->CurrentXferId, nextXfer,
  1032. localWork->XferId);
  1033. if (nextXfer == localWork->XferId) {
  1034. // this is the next transfer
  1035. LOGENTRY(LOG_MISC, 'NXTx', localUrb, nextXfer, i);
  1036. break;
  1037. }
  1038. }
  1039. }
  1040. if (i == Endpoint->MaxRequests) {
  1041. // no xfers available
  1042. LOGENTRY(LOG_MISC, 'NoXF', 0, Endpoint->CurrentXferId, i);
  1043. } else {
  1044. PHCD_EXTENSION localWork;
  1045. PHCD_URB localUrb;
  1046. //
  1047. // This will start the next active transfer
  1048. // for the endpoint.
  1049. //
  1050. UHCD_ASSERT(Endpoint->ActiveTransfers[i]);
  1051. localUrb = Endpoint->ActiveTransfers[i];
  1052. localWork = HCD_AREA(localUrb).HcdExtension;
  1053. UHCD_ASSERT(i == localWork->Slot);
  1054. #if DBG
  1055. if (Urb->HcdUrbCommonTransfer.Status != UHCD_STATUS_PENDING_CANCELING) {
  1056. UHCD_ASSERT(localWork->Flags & UHCD_TRANSFER_DEFER);
  1057. }
  1058. #endif
  1059. // now we need to set up the queue head
  1060. // BUGBUG -- we currently don't handle look ahead
  1061. // ie if this transfer was already linked
  1062. //
  1063. // This is where we would check.
  1064. // before linking in this transfer we
  1065. // need to fixup the data toggle based
  1066. // on the current toggle for the ED
  1067. UHCD_FixupDataToggle(DeviceObject,
  1068. Endpoint,
  1069. localUrb);
  1070. //UHCD_ASSERT((Endpoint->CurrentXferId+(UCHAR)1) == localWork->XferId);
  1071. // update the endpoints TDList
  1072. // slot id corresponds to TD list
  1073. LOGENTRY(LOG_MISC, 'mkC2', Endpoint->CurrentXferId, localWork->Slot,
  1074. localWork->XferId);
  1075. Endpoint->TDList =
  1076. Endpoint->SlotTDList[i];
  1077. LOGENTRY(LOG_MISC, 'NXgo', Endpoint->TDList, localWork->Slot,
  1078. Endpoint->TDList->TDs[0].PhysicalAddress);
  1079. Endpoint->QueueHead->HW_VLink =
  1080. Endpoint->TDList->TDs[0].PhysicalAddress;
  1081. // this enables the xfer to be processed
  1082. localWork->Flags &= ~UHCD_TRANSFER_DEFER;
  1083. }
  1084. }
  1085. // NOT USED
  1086. #if 0
  1087. else {
  1088. //
  1089. // Low speed control endpoints share a single queue head.
  1090. //
  1091. // If the endpoint is lowspeed control then we need to start
  1092. // the next control transfer on this queue head.
  1093. //
  1094. // If another low speed control queue head is waiting we will
  1095. // pick it up when we process the rest of the endpoint list
  1096. // for this interrupt. If the next control queue head is before
  1097. // us in the endpoint list then we will ask for an interrupt next
  1098. // frame so that we can start it.
  1099. //
  1100. if (Endpoint->LowSpeed) {
  1101. TEST_TRAP();
  1102. UHCD_RequestInterrupt(DeviceObject, -2);
  1103. }
  1104. }
  1105. #endif
  1106. }
  1107. // UHCD_KdPrint((2, "'exit UHCD_ProcessAsyncTransfer %d status = %x\n', completed, *Status));
  1108. ENDPROC("Pas-");
  1109. return usbStatus;
  1110. }
  1111. USBD_STATUS
  1112. UHCD_PrepareMoreAsyncTDs(
  1113. IN PDEVICE_OBJECT DeviceObject,
  1114. IN PUHCD_ENDPOINT Endpoint,
  1115. IN PHCD_URB Urb,
  1116. IN BOOLEAN Busy
  1117. )
  1118. /*++
  1119. Routine Description:
  1120. Arguments:
  1121. DeviceObject - pointer to a device object.
  1122. Endpoint - endpoint to check for completed transfers.
  1123. Urb - ptr to URB to process.
  1124. Status - pointer to USBD status, will be filled in if transfer
  1125. is complete.
  1126. Busy - indicates the stae of the queue head
  1127. Return Value:
  1128. TRUE if this transfer is complete, Status set to proper
  1129. error code.
  1130. --*/
  1131. {
  1132. ULONG count = 0;
  1133. SHORT i, slot;
  1134. SHORT start, oldLastTDPreparedIdx;
  1135. PHCD_EXTENSION urbWork = HCD_AREA(Urb).HcdExtension;
  1136. USBD_STATUS usbStatus = USBD_STATUS_SUCCESS;
  1137. PDEVICE_EXTENSION deviceExtension;
  1138. STARTPROC("Mas+");
  1139. //
  1140. // One of two conditions get us in to this routine:
  1141. //
  1142. // 1. The queue is stopped, waiting for us to prepare
  1143. // more TDs for an overflow transfer: Busy = FALSE
  1144. // && CurrentTDIdx is pointing at the first TD after
  1145. // the last TD prepared.
  1146. //
  1147. // 2. The queue is not stopped but we may be able to set
  1148. // up some more TDs
  1149. //
  1150. // can only process one TD list at a time
  1151. slot = urbWork->Slot;
  1152. UHCD_ASSERT(Endpoint->TDList == Endpoint->SlotTDList[slot]);
  1153. UHCD_KdPrint((2, "'enter UHCD_PrepareMoreAsyncTDs\n"));
  1154. deviceExtension = DeviceObject->DeviceExtension;
  1155. //
  1156. // Pick up where we left off, keep building TDs until we
  1157. // use up the client buffer or run out of TDs.
  1158. //
  1159. //
  1160. // Start at the first TD available after the last one prepared.
  1161. //
  1162. oldLastTDPreparedIdx = Endpoint->LastTDPreparedIdx[slot];
  1163. i = NEXT_TD(Endpoint->LastTDPreparedIdx[slot], Endpoint);
  1164. // Remember where we started...
  1165. start = i;
  1166. LOGENTRY(LOG_MISC, 'pmTD', Endpoint->LastTDPreparedIdx[slot],
  1167. Endpoint->LastTDInTransferIdx[slot], Busy);
  1168. if (Busy) {
  1169. // We want to avoid doing this if the number of free TDs is not worth
  1170. // the effort -- otherwise we'll end up with the T-Bit and ioc bit set
  1171. // for every packet.
  1172. // --
  1173. // Do a quick scan of the TDs if we have at least 4 inactive then go
  1174. // ahead and try
  1175. SHORT j, x = 0;
  1176. for (j=0; j<Endpoint->TDCount; j++) {
  1177. if (!Endpoint->TDList->TDs[j].Active) {
  1178. x++;
  1179. }
  1180. }
  1181. //
  1182. // x = the most TDs we can set up
  1183. //
  1184. if (x <= 3) {
  1185. goto UHCD_PrepareMoreAsyncTDs_Done;
  1186. }
  1187. LOGENTRY(LOG_MISC, 'frTD', x, Endpoint->QueueHead->HW_VLink, 0);
  1188. }
  1189. #if DBG
  1190. else {
  1191. UHCD_ASSERT(i == Endpoint->CurrentTDIdx[slot]);
  1192. // if we are not Busy then we got here because the T-bit was set
  1193. // this means that currentTD should be the first new TD we set
  1194. // up, and all TDs for this transfer have been processed.
  1195. // assert that the T-bit is set on the queue head
  1196. }
  1197. #endif
  1198. do {
  1199. LOGENTRY(LOG_MISC, 'mrTD', i, Endpoint->CurrentTDIdx,
  1200. Endpoint->LastTDPreparedIdx[slot]);
  1201. //
  1202. // If the Busy flag is set then the currentTD has not been
  1203. // processed yet so we need to stop if we hit it.
  1204. //
  1205. if (Busy && i == Endpoint->CurrentTDIdx[slot]) {
  1206. break;
  1207. }
  1208. //
  1209. // we should never encounter an active TD
  1210. //
  1211. UHCD_ASSERT(Endpoint->TDList->TDs[i].Active == 0);
  1212. //
  1213. // See if we have consumed the client buffer, if so then we are
  1214. // done, mark this TD as the last one and stop preparing TDs.
  1215. //
  1216. if (urbWork->TransferOffset < Urb->HcdUrbCommonTransfer.TransferBufferLength ) {
  1217. UHCD_KdPrint((2, "'offset = %x\n", urbWork->TransferOffset));
  1218. if (UHCD_PrepareAsyncDataPacket(DeviceObject,
  1219. &Endpoint->TDList->TDs[i],
  1220. Endpoint,
  1221. Urb,
  1222. TRUE,
  1223. FALSE,
  1224. // not init
  1225. FALSE)) {
  1226. Endpoint->LastTDPreparedIdx[slot] = i;
  1227. count++;
  1228. } else {
  1229. //
  1230. // error occurred forming packet, this will
  1231. // complete the transfer.
  1232. //
  1233. TEST_TRAP();
  1234. usbStatus = USBD_STATUS_NO_MEMORY;
  1235. goto UHCD_PrepareMoreAsyncTDs_Done;
  1236. }
  1237. } else {
  1238. #ifdef CONTROL
  1239. //
  1240. // Done with client buffer, if this is a control
  1241. // transfer then we'll need to do the status packet
  1242. //
  1243. if (CONTROL_TRANSFER(Endpoint)) {
  1244. UHCD_PrepareStatusPacket(&Endpoint->TDList->TDs[i],
  1245. Endpoint,
  1246. Urb);
  1247. Endpoint->LastTDPreparedIdx[slot] = i;
  1248. count++;
  1249. }
  1250. #endif
  1251. //
  1252. // Last TD in the transfer is the last one we set up,
  1253. // the current TD should be set to the first one we set up.
  1254. //
  1255. Endpoint->LastTDInTransferIdx[slot] =
  1256. Endpoint->LastTDPreparedIdx[slot];
  1257. //
  1258. // Set the T-bit and the IOC bit for the last TD in the transfer
  1259. //
  1260. // NOTE: for non-B0 systems the IOC bit and T-bit will be set on every
  1261. // packet for IN transfers.
  1262. //
  1263. SET_T_BIT(Endpoint->TDList->TDs[Endpoint->LastTDInTransferIdx[slot]].HW_Link);
  1264. Endpoint->TDList->TDs[Endpoint->LastTDInTransferIdx[slot]].InterruptOnComplete = 1;
  1265. if (!Busy) {
  1266. // if the queue head was stopped resume at the first TD we
  1267. // set up.
  1268. Endpoint->CurrentTDIdx[slot] = start;
  1269. }
  1270. break;
  1271. #ifdef CONTROL
  1272. }
  1273. #endif
  1274. i = NEXT_TD(Endpoint->LastTDPreparedIdx[slot], Endpoint);
  1275. //
  1276. // stop when we get to the TD we started at or we hit
  1277. // the current TD.
  1278. //
  1279. // if we were called to set up TDs while the endpoint is still busy
  1280. // then it is possible we'll run in to the current TD.
  1281. //
  1282. } while (i != start && i != Endpoint->CurrentTDIdx[slot]);
  1283. //
  1284. // We may not have finished setting up all the TDs for the transfer,
  1285. // if this is the case we'll need to set the T-Bit and IOC bit on the
  1286. // last TD we were able to prepare.
  1287. //
  1288. if (count && Endpoint->LastTDInTransferIdx[slot] == -1) {
  1289. SET_T_BIT(Endpoint->TDList->TDs[Endpoint->LastTDPreparedIdx[slot]].HW_Link);
  1290. Endpoint->TDList->TDs[Endpoint->LastTDPreparedIdx[slot]].InterruptOnComplete = 1;
  1291. // check to see if we finished the client buffer
  1292. // ie client buffer finished with the last TD we prepared.
  1293. if (urbWork->TransferOffset == Urb->HcdUrbCommonTransfer.TransferBufferLength &&
  1294. !CONTROL_TRANSFER(Endpoint)) {
  1295. Endpoint->LastTDInTransferIdx[slot] = Endpoint->LastTDPreparedIdx[slot];
  1296. }
  1297. }
  1298. if (Busy && count) {
  1299. // attempt to clear the old T-bit from the lastTD prepared
  1300. // we may not get it in time but if we do we'll avoid stopping
  1301. // the queue.
  1302. if (deviceExtension->SteppingVersion >= UHCD_B0_STEP ||
  1303. DATA_DIRECTION_OUT(Urb)) {
  1304. CLEAR_T_BIT(Endpoint->TDList->TDs[oldLastTDPreparedIdx].HW_Link);
  1305. // hit this if we ever actually set up more TDs while the Queue head
  1306. // is busy
  1307. }
  1308. }
  1309. //
  1310. // NOTE:
  1311. // Caller is responsible for resuming the QH at currentTDIdx.
  1312. //
  1313. UHCD_PrepareMoreAsyncTDs_Done:
  1314. UHCD_KdPrint((2, "'exit UHCD_PrepareMoreAsyncTDs\n"));
  1315. ENDPROC("Mas-");
  1316. return usbStatus;
  1317. }
  1318. HW_DESCRIPTOR_PHYSICAL_ADDRESS
  1319. UHCD_GetPacketBuffer(
  1320. IN PDEVICE_OBJECT DeviceObject,
  1321. IN PUHCD_ENDPOINT Endpoint,
  1322. IN PHCD_URB Urb,
  1323. IN PHCD_EXTENSION UrbWork,
  1324. IN ULONG Offset,
  1325. IN ULONG PacketSize
  1326. )
  1327. /*++
  1328. Routine Description:
  1329. Compute the packet buffer physical address we will give to the
  1330. host controller based on the current offset in the transfer.
  1331. We also check if the packet crosses a page boundry if so this
  1332. routine returns an address of a region of memory used to
  1333. double-buffer the packet.
  1334. Arguments:
  1335. PacketSize - size of the packet we are dealing with
  1336. Offset - is the start position in the transfer for this
  1337. packet
  1338. Return Value:
  1339. Physical address of a packet buffer we can give to the UHC hardware.
  1340. If the packet requires double buffering and no memory is available
  1341. the 0 is returned for the hw_address.
  1342. --*/
  1343. {
  1344. ULONG i, start = 0, end = 0;
  1345. HW_DESCRIPTOR_PHYSICAL_ADDRESS hw_address = 0;
  1346. STARTPROC("Gpb+");
  1347. ASSERT_ENDPOINT(Endpoint);
  1348. //
  1349. // Offset is the start position in the transfer
  1350. // buffer of the packet we must prepare.
  1351. //
  1352. LOGENTRY(LOG_MISC, 'GPBx', UrbWork,
  1353. UrbWork->NumberOfLogicalAddresses,
  1354. 0);
  1355. for (i=0; i< UrbWork->NumberOfLogicalAddresses; i++) {
  1356. // first find the base logical address associated with
  1357. // this packet
  1358. LOGENTRY(LOG_MISC, 'GPBf', &UrbWork->LogicalAddressList[i],
  1359. Offset,
  1360. UrbWork->LogicalAddressList[i].Length);
  1361. start = end;
  1362. end += UrbWork->LogicalAddressList[i].Length;
  1363. if (Offset < end) {
  1364. //
  1365. // found the logical address range that this packet
  1366. // starts in.
  1367. //
  1368. LOGENTRY(LOG_MISC, 'GPBm', end, PacketSize, Offset);
  1369. if (Offset + PacketSize <= end) {
  1370. //
  1371. // if the whole packet fits within the
  1372. // region associated with this logical
  1373. // address then we are OK -- just return the
  1374. // physical address.
  1375. //
  1376. hw_address =
  1377. UrbWork->LogicalAddressList[i].LogicalAddress +
  1378. Offset - start;
  1379. UHCD_ASSERT(UrbWork->LogicalAddressList[i].PacketMemoryDescriptor == NULL);
  1380. } else {
  1381. //
  1382. // packet crosses page boundry, get one of our
  1383. // packet buffers
  1384. //
  1385. LOGENTRY(LOG_MISC, 'PAK!', 0, Offset, PacketSize);
  1386. UrbWork->LogicalAddressList[i].PacketMemoryDescriptor =
  1387. UHCD_AllocateCommonBuffer(DeviceObject,
  1388. Endpoint->MaxPacketSize);
  1389. if (UrbWork->LogicalAddressList[i].PacketMemoryDescriptor) {
  1390. // if this is an out then we need to copy the data in
  1391. // to the packet buffer
  1392. UrbWork->LogicalAddressList[i].PacketOffset = Offset;
  1393. if (DATA_DIRECTION_OUT(Urb)) {
  1394. //TEST_TRAP();
  1395. LOGENTRY(LOG_MISC, 'DBpk', UrbWork->LogicalAddressList[i].PacketMemoryDescriptor->VirtualAddress,
  1396. (PUCHAR)UrbWork->SystemAddressForMdl +
  1397. UrbWork->LogicalAddressList[i].PacketOffset,
  1398. PacketSize);
  1399. RtlCopyMemory(UrbWork->LogicalAddressList[i].PacketMemoryDescriptor->VirtualAddress,
  1400. (PUCHAR) UrbWork->SystemAddressForMdl +
  1401. UrbWork->LogicalAddressList[i].PacketOffset,
  1402. PacketSize);
  1403. }
  1404. hw_address =
  1405. UrbWork->LogicalAddressList[i].PacketMemoryDescriptor->LogicalAddress;
  1406. }
  1407. #if DBG
  1408. else {
  1409. // NOTE:
  1410. // failure here should cause the transfer to be completed with error,
  1411. // we will return 0 for the hw_address;
  1412. TEST_TRAP();
  1413. }
  1414. #endif //DBG
  1415. }
  1416. break;
  1417. }
  1418. }
  1419. UHCD_ASSERT(i < UrbWork->NumberOfLogicalAddresses);
  1420. LOGENTRY(LOG_MISC, 'GPB0', hw_address, 0, 0);
  1421. ENDPROC("Gpb-");
  1422. return hw_address;
  1423. }
  1424. VOID
  1425. UHCD_FixupDataToggle(
  1426. IN PDEVICE_OBJECT DeviceObject,
  1427. IN PUHCD_ENDPOINT Endpoint,
  1428. IN PHCD_URB Urb
  1429. )
  1430. /*++
  1431. Routine Description:
  1432. Given a TDList that is already set up, fxuo the data toggle
  1433. based of the current EP data toggle
  1434. Arguments:
  1435. DeviceObject - pointer to a device object.
  1436. Endpoint - Endpoint associated with this Urb.
  1437. Urb - pointer to URB Request Packet for this transfer.
  1438. Return Value:
  1439. Usbd status code.
  1440. --*/
  1441. {
  1442. // PDEVICE_EXTENSION deviceExtension;
  1443. SHORT i, slot, start;
  1444. PUHCD_TD_LIST tDList;
  1445. PHCD_EXTENSION urbWork = HCD_AREA(Urb).HcdExtension;
  1446. UHCD_KdPrint((2, "'enter UHCD_FixupDataToggle\n"));
  1447. ASSERT_ENDPOINT(Endpoint);
  1448. UHCD_ASSERT(Endpoint == HCD_AREA(Urb).HcdEndpoint);
  1449. UHCD_ASSERT(!(urbWork->Flags & UHCD_TOGGLE_READY));
  1450. // do some general init stuff first,
  1451. // TDs form a circular list
  1452. slot = urbWork->Slot;
  1453. tDList = Endpoint->SlotTDList[slot];
  1454. //UHCD_ASSERT(urbWork->Flags & UHCD_TRANSFER_DEFER);
  1455. UHCD_ASSERT(urbWork->Flags & UHCD_TRANSFER_INITIALIZED);
  1456. start = i = Endpoint->CurrentTDIdx[slot];
  1457. do {
  1458. tDList->TDs[i].RetryToggle = Endpoint->DataToggle;
  1459. Endpoint->DataToggle ^=1;
  1460. if (i == Endpoint->LastTDInTransferIdx[slot]) {
  1461. // if this is the last TD the we are done
  1462. break;
  1463. }
  1464. i = NEXT_TD(i, Endpoint);
  1465. } while (i != start);
  1466. urbWork->Flags |= UHCD_TOGGLE_READY;
  1467. }