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.

1411 lines
44 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. async.c
  5. Abstract:
  6. miniport transfer code for control, interrupt and bulk
  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 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 6-26-99 : created, jdunn
  17. --*/
  18. #include "common.h"
  19. //implements the following miniport functions:
  20. //non paged
  21. //OHCI_OpenControlEndpoint
  22. //OHCI_InterruptTransfer
  23. //OHCI_OpenControlEndpoint
  24. USB_MINIPORT_STATUS
  25. OHCI_ControlTransfer(
  26. PDEVICE_DATA DeviceData,
  27. PENDPOINT_DATA EndpointData,
  28. PTRANSFER_PARAMETERS TransferParameters,
  29. PTRANSFER_CONTEXT TransferContext,
  30. PTRANSFER_SG_LIST TransferSGList
  31. )
  32. {
  33. PHCD_TRANSFER_DESCRIPTOR lastTd, td;
  34. ULONG lengthMapped, dataTDCount = 0;
  35. ULONG toggleForDataPhase = HcTDToggle_Data1;
  36. // see if we can handle this transfer (put it on the HW)
  37. // if not return BUSY, port driver will retry later
  38. ASSERT_TRANSFER(DeviceData, TransferContext);
  39. // NOTE: we can gate the number of transfers
  40. // by a number of methods:
  41. // - fixed count
  42. // - available TDs
  43. // - registry key
  44. // bugbug fixed to one transfer at a time for now
  45. //if (EndpointData->PendingTransfers ==
  46. // EndpointData->MaxPendingTransfers) {
  47. // TEST_TRAP();
  48. // return USBMP_STATUS_BUSY;
  49. //}
  50. // Need one TD for every page of the data buffer, plus one for the SETUP
  51. // TD and one for the STATUS TD.
  52. //
  53. if (TransferSGList->SgCount + 2 >
  54. OHCI_FreeTds(DeviceData, EndpointData)) {
  55. // not enough TDs!
  56. return USBMP_STATUS_BUSY;
  57. }
  58. EndpointData->PendingTransfers++;
  59. // we have enough tds, program the transfer
  60. //
  61. // first prepare a TD for the setup packet
  62. //
  63. LOGENTRY(DeviceData, G, '_CTR', EndpointData, TransferParameters, 0);
  64. //
  65. // grab the dummy TD from the tail of the queue
  66. //
  67. lastTd = td = EndpointData->HcdTailP;
  68. OHCI_ASSERT(DeviceData, td->Flags & TD_FLAG_BUSY);
  69. INITIALIZE_TD_FOR_TRANSFER(td, TransferContext);
  70. // count setup TD
  71. TransferContext->PendingTds++;
  72. //
  73. // Move setup data into TD (8 chars long)
  74. //
  75. RtlCopyMemory(&td->HwTD.Packet[0],
  76. &TransferParameters->SetupPacket[0],
  77. 8);
  78. td->HwTD.CBP = (ULONG)(((PCHAR) & td->HwTD.Packet[0])
  79. - ((PCHAR) &td->HwTD)) + td->PhysicalAddress;
  80. td->HwTD.BE = td->HwTD.CBP + 7;
  81. td->HwTD.Control = 0;
  82. td->HwTD.Asy.Direction = HcTDDirection_Setup;
  83. td->HwTD.Asy.IntDelay = HcTDIntDelay_NoInterrupt;
  84. td->HwTD.Asy.Toggle = HcTDToggle_Data0;
  85. td->HwTD.Asy.ConditionCode = HcCC_NotAccessed;
  86. LOGENTRY(DeviceData,
  87. G, '_set',
  88. td,
  89. *((PLONG) &TransferParameters->SetupPacket[0]),
  90. *((PLONG) &TransferParameters->SetupPacket[4]));
  91. // allocate another TD
  92. lastTd = td;
  93. td = OHCI_ALLOC_TD(DeviceData, EndpointData);
  94. OHCI_ASSERT(DeviceData, td != USB_BAD_PTR);
  95. INITIALIZE_TD_FOR_TRANSFER(td, TransferContext);
  96. SET_NEXT_TD(lastTd, td);
  97. //
  98. // now setup the data phase
  99. //
  100. lengthMapped = 0;
  101. while (lengthMapped < TransferParameters->TransferBufferLength) {
  102. //
  103. // fields for data TD
  104. //
  105. dataTDCount++;
  106. // count this Data TD
  107. TransferContext->PendingTds++;
  108. if (IN_TRANSFER(TransferParameters)) {
  109. td->HwTD.Asy.Direction = HcTDDirection_In;
  110. } else {
  111. td->HwTD.Asy.Direction = HcTDDirection_Out;
  112. }
  113. td->HwTD.Asy.IntDelay = HcTDIntDelay_NoInterrupt;
  114. td->HwTD.Asy.Toggle = toggleForDataPhase;
  115. td->HwTD.Asy.ConditionCode = HcCC_NotAccessed;
  116. // after the first TD get the toggle from ED
  117. toggleForDataPhase = HcTDToggle_FromEd;
  118. LOGENTRY(DeviceData,
  119. G, '_dta', td, lengthMapped, TransferParameters->TransferBufferLength);
  120. lengthMapped =
  121. OHCI_MapAsyncTransferToTd(DeviceData,
  122. EndpointData->Parameters.MaxPacketSize,
  123. lengthMapped,
  124. TransferContext,
  125. td,
  126. TransferSGList);
  127. // allocate another TD
  128. lastTd = td;
  129. td = OHCI_ALLOC_TD(DeviceData, EndpointData);
  130. OHCI_ASSERT(DeviceData, td != USB_BAD_PTR);
  131. INITIALIZE_TD_FOR_TRANSFER(td, TransferContext);
  132. SET_NEXT_TD(lastTd, td);
  133. }
  134. //
  135. // set the shortxfer OK bit on the last TD only
  136. //
  137. if (SHORT_TRANSFER_OK(TransferParameters)) {
  138. lastTd->HwTD.Asy.ShortXferOk = 1;
  139. SET_FLAG(TransferContext->TcFlags, TC_FLAGS_SHORT_XFER_OK);
  140. }
  141. //
  142. // now do the status phase
  143. //
  144. LOGENTRY(DeviceData, G, '_sta', td, 0, dataTDCount);
  145. #if DBG
  146. if (dataTDCount > 1) {
  147. TEST_TRAP();
  148. }
  149. #endif
  150. // status direction is opposite data direction,
  151. // specify interrupt on completion
  152. td->HwTD.Control = 0;
  153. td->HwTD.Asy.IntDelay = HcTDIntDelay_0ms;
  154. td->HwTD.Asy.Toggle = HcTDToggle_Data1;
  155. td->HwTD.Asy.ConditionCode = HcCC_NotAccessed;
  156. td->HwTD.CBP = 0;
  157. td->HwTD.BE = 0;
  158. // status phase moves no data
  159. td->TransferCount = 0;
  160. SET_FLAG(td->Flags, TD_FLAG_CONTROL_STATUS);
  161. if (IN_TRANSFER(TransferParameters)) {
  162. td->HwTD.Asy.Direction = HcTDDirection_Out;
  163. } else {
  164. td->HwTD.Asy.Direction = HcTDDirection_In;
  165. td->HwTD.Asy.ShortXferOk = 1;
  166. }
  167. // count status TD
  168. TransferContext->StatusTd = td;
  169. TransferContext->PendingTds++;
  170. OHCI_ASSERT(DeviceData, TransferContext->PendingTds == dataTDCount+2);
  171. //
  172. // now put a new dummy TD on the tail of the EP queue
  173. //
  174. // allocate the new dummy tail
  175. lastTd = td;
  176. td = OHCI_ALLOC_TD(DeviceData, EndpointData);
  177. OHCI_ASSERT(DeviceData, td != USB_BAD_PTR);
  178. SET_NEXT_TD(lastTd, td);
  179. SET_NEXT_TD_NULL(td);
  180. //
  181. // Set new TailP in ED
  182. // note: This is the last TD in the list and the place holder.
  183. //
  184. EndpointData->HcdTailP =
  185. TransferContext->NextXferTd = td;
  186. // put the request on the hardware queue
  187. LOGENTRY(DeviceData, G,
  188. '_Tal', TransferContext->PendingTds,
  189. td->PhysicalAddress, EndpointData->HcdEd->HwED.HeadP);
  190. EndpointData->HcdEd->HwED.TailP = td->PhysicalAddress;
  191. // tell the hc we have control transfers available
  192. OHCI_EnableList(DeviceData, EndpointData);
  193. return USBMP_STATUS_SUCCESS;
  194. }
  195. USB_MINIPORT_STATUS
  196. OHCI_BulkOrInterruptTransfer(
  197. PDEVICE_DATA DeviceData,
  198. PENDPOINT_DATA EndpointData,
  199. PTRANSFER_PARAMETERS TransferParameters,
  200. PTRANSFER_CONTEXT TransferContext,
  201. PTRANSFER_SG_LIST TransferSGList
  202. )
  203. {
  204. PHCD_TRANSFER_DESCRIPTOR lastTd, td;
  205. ULONG lengthMapped;
  206. // see if we have enough free TDs to handle this transfer
  207. // if not return BUSY, port driver will retry later
  208. LOGENTRY(DeviceData, G, '_ITR', EndpointData, TransferParameters,
  209. TransferContext);
  210. ASSERT_TRANSFER(DeviceData, TransferContext);
  211. //if (EndpointData->PendingTransfers ==
  212. // EndpointData->MaxPendingTransfers) {
  213. // LOGENTRY(DeviceData, G, '_bsy', EndpointData, TransferContext,
  214. // TransferParameters);
  215. //
  216. // return USBMP_STATUS_BUSY;
  217. //}
  218. if (TransferSGList->SgCount >
  219. OHCI_FreeTds(DeviceData, EndpointData)) {
  220. // not enough TDs
  221. return USBMP_STATUS_BUSY;
  222. }
  223. EndpointData->PendingTransfers++;
  224. // we have enough tds, program the transfer
  225. LOGENTRY(DeviceData, G, '_nby', EndpointData, TransferParameters,
  226. EndpointData->HcdEd);
  227. //
  228. // grab the dummy TD from the tail of the queue
  229. //
  230. lastTd = td = EndpointData->HcdTailP;
  231. OHCI_ASSERT(DeviceData, td->Flags & TD_FLAG_BUSY);
  232. //
  233. // now setup the data TDs
  234. //
  235. // always build at least one data td
  236. lengthMapped = 0;
  237. do {
  238. INITIALIZE_TD_FOR_TRANSFER(td, TransferContext);
  239. //
  240. // fields for data TD
  241. //
  242. td->HwTD.Control = 0;
  243. td->HwTD.Asy.IntDelay = HcTDIntDelay_NoInterrupt;
  244. td->HwTD.Asy.Toggle = HcTDToggle_FromEd;
  245. td->HwTD.Asy.ConditionCode = HcCC_NotAccessed;
  246. if (IN_TRANSFER(TransferParameters)) {
  247. td->HwTD.Asy.Direction = HcTDDirection_In;
  248. } else {
  249. // short transfers are OK on out packets.
  250. // actually I'm not even sure what this does
  251. // for outbound requests
  252. td->HwTD.Asy.Direction = HcTDDirection_Out;
  253. td->HwTD.Asy.ShortXferOk = 1;
  254. }
  255. LOGENTRY(DeviceData,
  256. G, '_ita', td, lengthMapped, TransferParameters->TransferBufferLength);
  257. TransferContext->PendingTds++;
  258. if (TransferParameters->TransferBufferLength != 0) {
  259. lengthMapped =
  260. OHCI_MapAsyncTransferToTd(DeviceData,
  261. EndpointData->Parameters.MaxPacketSize,
  262. lengthMapped,
  263. TransferContext,
  264. td,
  265. TransferSGList);
  266. } else {
  267. OHCI_ASSERT(DeviceData, TransferSGList->SgCount == 0);
  268. td->HwTD.CBP = 0;
  269. td->HwTD.BE = 0;
  270. td->TransferCount = 0;
  271. }
  272. // allocate another TD
  273. lastTd = td;
  274. td = OHCI_ALLOC_TD(DeviceData, EndpointData);
  275. OHCI_ASSERT(DeviceData, td != USB_BAD_PTR);
  276. SET_NEXT_TD(lastTd, td);
  277. } while (lengthMapped < TransferParameters->TransferBufferLength);
  278. //
  279. // About ShortXferOk:
  280. //
  281. // This bit will trigger the controller to generate an error
  282. // and halt the ed if it is not set. The client may specify
  283. // behavior on short transfers (packets) in the transfersFlags
  284. // field of the URB.
  285. //
  286. // we must not set short transfer OK on split transfers since
  287. // the next transfer may not be a new transfer
  288. if (SHORT_TRANSFER_OK(TransferParameters) &&
  289. !TEST_FLAG(TransferParameters->MiniportFlags, MPTX_SPLIT_TRANSFER)) {
  290. // we can only set this bit in the last TD of the
  291. // transfer since that TD points to the next transfer.
  292. //
  293. // All other TDs must still generate an error and the
  294. // ed must be resumed by us.
  295. lastTd->HwTD.Asy.ShortXferOk = 1;
  296. SET_FLAG(TransferContext->TcFlags, TC_FLAGS_SHORT_XFER_OK);
  297. }
  298. lastTd->HwTD.Asy.IntDelay = HcTDIntDelay_0ms;
  299. //
  300. // now put a new dummy TD on the tail of the EP queue
  301. //
  302. SET_NEXT_TD(lastTd, td);
  303. SET_NEXT_TD_NULL(td);
  304. //
  305. // Set new TailP in ED
  306. // note: This is the last TD in the list and the place holder.
  307. //
  308. TransferContext->NextXferTd =
  309. EndpointData->HcdTailP = td;
  310. // put the request on the hardware queue
  311. LOGENTRY(DeviceData, G,
  312. '_Tal', TransferContext->PendingTds ,
  313. td->PhysicalAddress, EndpointData->HcdEd->HwED.HeadP);
  314. EndpointData->HcdEd->HwED.TailP = td->PhysicalAddress;
  315. LOGENTRY(DeviceData, G, '_ego', EndpointData->HcdHeadP,
  316. TransferContext->TcFlags, 0);
  317. // tell the hc we have bulk/interrupt transfers available
  318. OHCI_EnableList(DeviceData, EndpointData);
  319. return USBMP_STATUS_SUCCESS;
  320. }
  321. USB_MINIPORT_STATUS
  322. OHCI_OpenControlEndpoint(
  323. PDEVICE_DATA DeviceData,
  324. PENDPOINT_PARAMETERS EndpointParameters,
  325. PENDPOINT_DATA EndpointData
  326. )
  327. /*++
  328. Routine Description:
  329. Arguments:
  330. Return Value:
  331. --*/
  332. {
  333. PUCHAR buffer;
  334. HW_32BIT_PHYSICAL_ADDRESS phys, edPhys;
  335. PHCD_ENDPOINT_DESCRIPTOR ed;
  336. ULONG i, available, tdCount;
  337. LOGENTRY(DeviceData, G, '_opC', 0, 0, 0);
  338. buffer = EndpointParameters->CommonBufferVa;
  339. phys = EndpointParameters->CommonBufferPhys;
  340. available = EndpointParameters->CommonBufferBytes;
  341. #if DBG
  342. {
  343. ULONG offset;
  344. offset = BYTE_OFFSET(buffer);
  345. // OHCI requires 16 byte alignemnt
  346. OHCI_ASSERT(DeviceData, (offset % 16) == 0);
  347. }
  348. #endif
  349. // use control list
  350. EndpointData->StaticEd =
  351. &DeviceData->StaticEDList[ED_CONTROL];
  352. // make the Ed
  353. ed = (PHCD_ENDPOINT_DESCRIPTOR) buffer;
  354. edPhys = phys;
  355. phys += sizeof(HCD_ENDPOINT_DESCRIPTOR);
  356. buffer += sizeof(HCD_ENDPOINT_DESCRIPTOR);
  357. available -= sizeof(HCD_ENDPOINT_DESCRIPTOR);
  358. EndpointData->TdList = (PHCD_TD_LIST) buffer;
  359. tdCount = available/sizeof(HCD_TRANSFER_DESCRIPTOR);
  360. LOGENTRY(DeviceData, G, '_tdC', tdCount, TDS_PER_CONTROL_ENDPOINT, 0);
  361. OHCI_ASSERT(DeviceData, tdCount >= TDS_PER_CONTROL_ENDPOINT);
  362. EndpointData->TdCount = tdCount;
  363. for (i=0; i<tdCount; i++) {
  364. OHCI_InitializeTD(DeviceData,
  365. EndpointData,
  366. &EndpointData->TdList->Td[i],
  367. phys);
  368. phys += sizeof(HCD_TRANSFER_DESCRIPTOR);
  369. }
  370. EndpointData->HcdEd =
  371. OHCI_InitializeED(DeviceData,
  372. EndpointData,
  373. ed,
  374. &EndpointData->TdList->Td[0],
  375. edPhys);
  376. // control endpoints do not halt
  377. ed->EdFlags = EDFLAG_CONTROL | EDFLAG_NOHALT;
  378. OHCI_InsertEndpointInSchedule(DeviceData,
  379. EndpointData);
  380. return USBMP_STATUS_SUCCESS;
  381. }
  382. USB_MINIPORT_STATUS
  383. OHCI_OpenInterruptEndpoint(
  384. PDEVICE_DATA DeviceData,
  385. PENDPOINT_PARAMETERS EndpointParameters,
  386. PENDPOINT_DATA EndpointData
  387. )
  388. /*++
  389. Routine Description:
  390. Arguments:
  391. Return Value:
  392. --*/
  393. {
  394. PUCHAR buffer;
  395. HW_32BIT_PHYSICAL_ADDRESS phys, edPhys;
  396. PHCD_ENDPOINT_DESCRIPTOR ed;
  397. ULONG i, bytes, offset;
  398. // this is an index table that converts the
  399. // period to a list index
  400. UCHAR periodTable[8] = {
  401. ED_INTERRUPT_1ms, //period = 1ms
  402. ED_INTERRUPT_2ms, //period = 2ms
  403. ED_INTERRUPT_4ms, //period = 4ms
  404. ED_INTERRUPT_8ms, //period = 8ms
  405. ED_INTERRUPT_16ms,//period = 16ms
  406. ED_INTERRUPT_32ms,//period = 32ms
  407. ED_INTERRUPT_32ms,//period = 64ms
  408. ED_INTERRUPT_32ms //period = 128ms
  409. };
  410. // carve up our common buffer
  411. // TDS_PER_ENDPOINT TDs plus an ED
  412. LOGENTRY(DeviceData, G, '_opI', 0, 0, EndpointParameters->Period);
  413. // select the proper list
  414. // the period is a power of 2 ie
  415. // 32,16,8,4,2,1
  416. // we just need to find which bit is set
  417. GET_BIT_SET(EndpointParameters->Period, i);
  418. OHCI_ASSERT(DeviceData, i < 8);
  419. OHCI_ASSERT(DeviceData, EndpointParameters->Period < 64);
  420. buffer = EndpointParameters->CommonBufferVa;
  421. phys = EndpointParameters->CommonBufferPhys;
  422. bytes = EndpointParameters->CommonBufferBytes;
  423. offset = EndpointParameters->ScheduleOffset;
  424. EndpointData->StaticEd =
  425. &DeviceData->StaticEDList[periodTable[i]+offset];
  426. LOGENTRY(DeviceData, G, '_lst', i, periodTable[i], offset);
  427. // we found the correct base list
  428. EndpointData->StaticEd->AllocatedBandwidth +=
  429. EndpointParameters->Bandwidth;
  430. // make the Ed
  431. ed = (PHCD_ENDPOINT_DESCRIPTOR) buffer;
  432. edPhys = phys;
  433. phys += sizeof(HCD_ENDPOINT_DESCRIPTOR);
  434. buffer += sizeof(HCD_ENDPOINT_DESCRIPTOR);
  435. bytes -= sizeof(HCD_ENDPOINT_DESCRIPTOR);
  436. EndpointData->TdList = (PHCD_TD_LIST) buffer;
  437. EndpointData->TdCount = bytes/sizeof(HCD_TRANSFER_DESCRIPTOR);
  438. OHCI_ASSERT(DeviceData,
  439. EndpointData->TdCount >= TDS_PER_INTERRUPT_ENDPOINT);
  440. // Bugbug - use what we get
  441. for (i=0; i<EndpointData->TdCount; i++) {
  442. OHCI_InitializeTD(DeviceData,
  443. EndpointData,
  444. &EndpointData->TdList->Td[i],
  445. phys);
  446. phys += sizeof(HCD_TRANSFER_DESCRIPTOR);
  447. }
  448. EndpointData->HcdEd =
  449. OHCI_InitializeED(DeviceData,
  450. EndpointData,
  451. ed,
  452. &EndpointData->TdList->Td[0],
  453. edPhys);
  454. OHCI_InsertEndpointInSchedule(DeviceData,
  455. EndpointData);
  456. return USBMP_STATUS_SUCCESS;
  457. }
  458. USB_MINIPORT_STATUS
  459. OHCI_OpenBulkEndpoint(
  460. PDEVICE_DATA DeviceData,
  461. PENDPOINT_PARAMETERS EndpointParameters,
  462. PENDPOINT_DATA EndpointData
  463. )
  464. /*++
  465. Routine Description:
  466. Arguments:
  467. Return Value:
  468. --*/
  469. {
  470. PUCHAR buffer;
  471. HW_32BIT_PHYSICAL_ADDRESS phys, edPhys;
  472. PHCD_ENDPOINT_DESCRIPTOR ed;
  473. ULONG i, bytes;
  474. LOGENTRY(DeviceData, G, '_opB', 0, 0, 0);
  475. buffer = EndpointParameters->CommonBufferVa;
  476. phys = EndpointParameters->CommonBufferPhys;
  477. bytes = EndpointParameters->CommonBufferBytes;
  478. // use control list
  479. EndpointData->StaticEd =
  480. &DeviceData->StaticEDList[ED_BULK];
  481. // make the Ed
  482. ed = (PHCD_ENDPOINT_DESCRIPTOR) buffer;
  483. edPhys = phys;
  484. phys += sizeof(HCD_ENDPOINT_DESCRIPTOR);
  485. buffer += sizeof(HCD_ENDPOINT_DESCRIPTOR);
  486. bytes -= sizeof(HCD_ENDPOINT_DESCRIPTOR);
  487. EndpointData->TdList = (PHCD_TD_LIST) buffer;
  488. EndpointData->TdCount = bytes/sizeof(HCD_TRANSFER_DESCRIPTOR);
  489. OHCI_ASSERT(DeviceData,
  490. EndpointData->TdCount >= TDS_PER_BULK_ENDPOINT);
  491. // Bugbug - use what we get
  492. for (i=0; i<EndpointData->TdCount; i++) {
  493. OHCI_InitializeTD(DeviceData,
  494. EndpointData,
  495. &EndpointData->TdList->Td[i],
  496. phys);
  497. phys += sizeof(HCD_TRANSFER_DESCRIPTOR);
  498. }
  499. EndpointData->HcdEd =
  500. OHCI_InitializeED(DeviceData,
  501. EndpointData,
  502. ed,
  503. &EndpointData->TdList->Td[0],
  504. edPhys);
  505. OHCI_InsertEndpointInSchedule(DeviceData,
  506. EndpointData);
  507. return USBMP_STATUS_SUCCESS;
  508. }
  509. //
  510. // When the HEADP is set to a new value we risk loosing
  511. // the current data toggle stored there.
  512. // This macro resets headp and preserves the flags which
  513. // include the toggle.
  514. //
  515. #define RESET_HEADP(dd, ed, address) \
  516. {\
  517. ULONG headp;\
  518. headp = ((ed)->HwED.HeadP & HcEDHeadP_FLAGS) | (address);\
  519. LOGENTRY((dd), G, '_rhp', headp, (ed), 0); \
  520. (ed)->HwED.HeadP = headp; \
  521. }
  522. VOID
  523. OHCI_PollAsyncEndpoint(
  524. PDEVICE_DATA DeviceData,
  525. PENDPOINT_DATA EndpointData
  526. )
  527. /*++
  528. Routine Description:
  529. Called when the endpoint 'needs attention'
  530. The goal here is to determine which TDs, if any,
  531. have completed and complete ant associated transfers
  532. Arguments:
  533. Return Value:
  534. --*/
  535. {
  536. PHCD_TRANSFER_DESCRIPTOR td, currentTd;
  537. PHCD_ENDPOINT_DESCRIPTOR ed;
  538. ULONG i;
  539. PTRANSFER_CONTEXT transfer;
  540. BOOLEAN clearHalt = FALSE;
  541. HW_32BIT_PHYSICAL_ADDRESS headP;
  542. ed = EndpointData->HcdEd;
  543. LOGENTRY(DeviceData, G, '_pol', ed, EndpointData, 0);
  544. // note it is important the the compiler generate a
  545. // dword move when reading the queuehead HeadP register
  546. // since this location is also accessed by the host
  547. // hardware
  548. headP = ed->HwED.HeadP;
  549. // get the 'currentTD'
  550. currentTd = (PHCD_TRANSFER_DESCRIPTOR)
  551. USBPORT_PHYSICAL_TO_VIRTUAL(headP & ~HcEDHeadP_FLAGS,
  552. DeviceData,
  553. EndpointData);
  554. LOGENTRY(DeviceData, G, '_cTD', currentTd,
  555. headP & ~HcEDHeadP_FLAGS,
  556. TRANSFER_CONTEXT_PTR(currentTd->TransferContext));
  557. if (ed->HwED.HeadP & HcEDHeadP_HALT) {
  558. // ed is 'halted'
  559. LOGENTRY(DeviceData, G, '_hlt', ed, EndpointData->HcdHeadP, 0);
  560. clearHalt = (BOOLEAN) (ed->EdFlags & EDFLAG_NOHALT);
  561. // walk the swHeadP to the currentTD this (this will
  562. // be the first TD after the offending TD)
  563. td = EndpointData->HcdHeadP;
  564. while (td != currentTd) {
  565. transfer = TRANSFER_CONTEXT_PTR(td->TransferContext);
  566. ASSERT_TRANSFER(DeviceData, transfer);
  567. OHCI_ASSERT(DeviceData, !TEST_FLAG(td->Flags, TD_FLAG_DONE));
  568. LOGENTRY(DeviceData, G, '_wtd', td, transfer->TcFlags, transfer);
  569. if (td->HwTD.Asy.ConditionCode == HcCC_NoError) {
  570. // not the offending TD,
  571. // mark this TD done
  572. SET_FLAG(td->Flags, TD_FLAG_DONE);
  573. OHCI_ASSERT(DeviceData, td->DoneLink.Flink == NULL &&
  574. td->DoneLink.Blink == NULL);
  575. InsertTailList(&EndpointData->DoneTdList,
  576. &td->DoneLink);
  577. } else {
  578. // some kind of error
  579. if (td->HwTD.Asy.ConditionCode == HcCC_NotAccessed) {
  580. // if the 'current transfer' is DONE because
  581. // of a short packet then the remaining TDs
  582. // need to be flushed out.
  583. // current TD should be pointing at the next
  584. // TD to run (next transfer or status for control)
  585. SET_FLAG(td->Flags, TD_FLAG_DONE);
  586. SET_FLAG(td->Flags, TD_FLAG_SKIP);
  587. OHCI_ASSERT(DeviceData, td->DoneLink.Flink == NULL &&
  588. td->DoneLink.Blink == NULL);
  589. InsertTailList(&EndpointData->DoneTdList,
  590. &td->DoneLink);
  591. LOGENTRY(DeviceData, G, '_fld', td, 0, 0);
  592. } else if (td->HwTD.Asy.ConditionCode == HcCC_DataUnderrun &&
  593. TEST_FLAG(transfer->TcFlags, TC_FLAGS_SHORT_XFER_OK)) {
  594. // special case HcCC_DataUnderrun. this error
  595. // needs to be ignored if shortxferOK is set.
  596. // cases handled (HcCC_DataUnderrun):
  597. //
  598. // 1. control transfer and error before the status phase w/
  599. // short xfer OK
  600. // we need to advance to the status phase and ignore
  601. // error and resume ep
  602. //
  603. // 2. interrupt/bulk with short xfer OK, ignore the error
  604. // advance to the next transfer resume ep
  605. //
  606. LOGENTRY(DeviceData, G, '_sok', td, 0, 0);
  607. // reset the error on the offending Td
  608. td->HwTD.Asy.ConditionCode = HcCC_NoError;
  609. // resume the ep
  610. clearHalt = TRUE;
  611. // if this is a control transfer bump
  612. // HW headp to the status phase
  613. if (!TEST_FLAG(td->Flags, TD_FLAG_CONTROL_STATUS) &&
  614. transfer->StatusTd != NULL) {
  615. // control transfer data phase, bump
  616. // HW headp to the status phase
  617. TEST_TRAP();
  618. RESET_HEADP(DeviceData, ed, transfer->StatusTd->PhysicalAddress);
  619. currentTd = transfer->StatusTd;
  620. } else {
  621. // if the current transfer is a split we must flush
  622. // all other split elements as well.
  623. if (transfer->TransferParameters->MiniportFlags &
  624. MPTX_SPLIT_TRANSFER) {
  625. PTRANSFER_CONTEXT tmpTransfer;
  626. PHCD_TRANSFER_DESCRIPTOR tmpTd;
  627. ULONG seq;
  628. TEST_TRAP();
  629. seq = transfer->TransferParameters->SequenceNumber;
  630. tmpTd = transfer->NextXferTd;
  631. tmpTransfer =
  632. TRANSFER_CONTEXT_PTR(tmpTd->TransferContext);
  633. // find the first tranfer with a new sequence
  634. // number or the tail of the list
  635. while (tmpTransfer != FREE_TD_CONTEXT &&
  636. tmpTransfer->TransferParameters->SequenceNumber
  637. == seq) {
  638. // mark all TDs done for this transfer
  639. tmpTd = tmpTransfer->NextXferTd;
  640. tmpTransfer =
  641. TRANSFER_CONTEXT_PTR(tmpTd->TransferContext);
  642. }
  643. RESET_HEADP(DeviceData, ed, tmpTd->PhysicalAddress);
  644. currentTd = tmpTd;
  645. } else {
  646. // bump HW headp to the next transfer
  647. RESET_HEADP(DeviceData, ed, transfer->NextXferTd->PhysicalAddress);
  648. currentTd = transfer->NextXferTd;
  649. }
  650. }
  651. SET_FLAG(td->Flags, TD_FLAG_DONE);
  652. OHCI_ASSERT(DeviceData, td->DoneLink.Flink == NULL &&
  653. td->DoneLink.Blink == NULL);
  654. InsertTailList(&EndpointData->DoneTdList,
  655. &td->DoneLink);
  656. } else {
  657. // general error, mark the TD as completed
  658. // update Headp to point to the next transfer
  659. LOGENTRY(DeviceData, G, '_ger', td, 0, 0);
  660. SET_FLAG(td->Flags, TD_FLAG_DONE);
  661. OHCI_ASSERT(DeviceData, td->DoneLink.Flink == NULL &&
  662. td->DoneLink.Blink == NULL);
  663. InsertTailList(&EndpointData->DoneTdList,
  664. &td->DoneLink);
  665. RESET_HEADP(DeviceData, ed, transfer->NextXferTd->PhysicalAddress)
  666. currentTd = transfer->NextXferTd;
  667. }
  668. }
  669. // we walk the SW links
  670. td = TRANSFER_DESCRIPTOR_PTR(td->NextHcdTD);
  671. } /* while */
  672. } else {
  673. // ed is not 'halted'
  674. // First walk the swHeadP to the current TD (hw headp)
  675. // mark all TDs we find as completed
  676. //
  677. // NOTE: this step may be skipped if the
  678. // done queue is reliable
  679. td = EndpointData->HcdHeadP;
  680. LOGENTRY(DeviceData, G, '_nht', td, currentTd, 0);
  681. while (td != currentTd) {
  682. LOGENTRY(DeviceData, G, '_mDN', td, 0, 0);
  683. SET_FLAG(td->Flags, TD_FLAG_DONE);
  684. OHCI_ASSERT(DeviceData, td->DoneLink.Flink == NULL &&
  685. td->DoneLink.Blink == NULL);
  686. InsertTailList(&EndpointData->DoneTdList,
  687. &td->DoneLink);
  688. td = TRANSFER_DESCRIPTOR_PTR(td->NextHcdTD);
  689. }
  690. }
  691. // set the sw headp to the new current head
  692. EndpointData->HcdHeadP = currentTd;
  693. // now flush all completed TDs
  694. // do this in order of completion
  695. // now flush all completed TDs. Do it in order of completion.
  696. while (!IsListEmpty(&EndpointData->DoneTdList)) {
  697. PLIST_ENTRY listEntry;
  698. listEntry = RemoveHeadList(&EndpointData->DoneTdList);
  699. td = (PHCD_TRANSFER_DESCRIPTOR) CONTAINING_RECORD(
  700. listEntry,
  701. struct _HCD_TRANSFER_DESCRIPTOR,
  702. DoneLink);
  703. if ((td->Flags & (TD_FLAG_XFER | TD_FLAG_DONE)) ==
  704. (TD_FLAG_XFER | TD_FLAG_DONE)) {
  705. OHCI_ProcessDoneAsyncTd(DeviceData,
  706. td,
  707. TRUE);
  708. }
  709. }
  710. #if 0
  711. for (i=0; i<EndpointData->TdCount; i++) {
  712. td = &EndpointData->TdList->Td[i];
  713. if ((td->Flags & (TD_FLAG_XFER | TD_FLAG_DONE)) ==
  714. (TD_FLAG_XFER | TD_FLAG_DONE)) {
  715. OHCI_ProcessDoneAsyncTd(DeviceData,
  716. td,
  717. TRUE);
  718. }
  719. }
  720. #endif
  721. if (clearHalt) {
  722. // auto clear the halt condition and
  723. // resume processing on the endpoint
  724. LOGENTRY(DeviceData, G, '_cht', ed, 0, 0);
  725. ed->HwED.HeadP &= ~HcEDHeadP_HALT;
  726. }
  727. }
  728. VOID
  729. OHCI_ProcessDoneAsyncTd(
  730. PDEVICE_DATA DeviceData,
  731. PHCD_TRANSFER_DESCRIPTOR Td,
  732. BOOLEAN CompleteTransfer
  733. )
  734. /*++
  735. Routine Description:
  736. process a completed TD
  737. Parameters
  738. --*/
  739. {
  740. PTRANSFER_CONTEXT transferContext;
  741. PENDPOINT_DATA endpointData;
  742. USBD_STATUS usbdStatus;
  743. transferContext = TRANSFER_CONTEXT_PTR(Td->TransferContext);
  744. transferContext->PendingTds--;
  745. endpointData = transferContext->EndpointData;
  746. LOGENTRY(DeviceData, G, '_Dtd', transferContext,
  747. Td->HwTD.Asy.ConditionCode,
  748. Td);
  749. if (TEST_FLAG(Td->Flags, TD_FLAG_SKIP)) {
  750. OHCI_ASSERT(DeviceData, HcCC_NotAccessed == Td->HwTD.Asy.ConditionCode);
  751. // td was unused, part of short-transfer
  752. LOGENTRY(DeviceData, G, '_skT', Td, transferContext, 0);
  753. Td->HwTD.Asy.ConditionCode = HcCC_NoError;
  754. } else {
  755. if (Td->HwTD.CBP) {
  756. //
  757. // A value of 0 here indicates a zero length data packet
  758. // or that all bytes have been transfered.
  759. //
  760. // A non-zero value means we recieved a short packet and
  761. // therefore need to adjust the transferCount to reflect bytes
  762. // transferred
  763. //
  764. // The buffer is only spec'ed for length up to two 4K pages.
  765. // (BE is the physical address of the last byte in the
  766. // TD buffer. CBP is the current byte pointer)
  767. //
  768. // TransferCount is intailized to the number of bytes to transfer,
  769. // we need to subtract the difference between the end and
  770. // current ptr (ie end-current = bytes not transferred) and
  771. // update the TransferCount.
  772. // transfer count should never go negative
  773. // TransferCount will be zero on the status
  774. // phase of a control transfer so we skip
  775. // the calculation
  776. if (Td->TransferCount) {
  777. Td->TransferCount -=
  778. /* have we gone further than a page? */
  779. ((((Td->HwTD.BE ^ Td->HwTD.CBP) & ~OHCI_PAGE_SIZE_MASK)
  780. ? OHCI_PAGE_SIZE : 0) +
  781. /* minus the data buffer not used */
  782. ((Td->HwTD.BE & OHCI_PAGE_SIZE_MASK) -
  783. (Td->HwTD.CBP & OHCI_PAGE_SIZE_MASK)+1));
  784. }
  785. LOGENTRY(DeviceData, G, '_xfB', Td->HwTD.BE & OHCI_PAGE_SIZE_MASK,
  786. Td->HwTD.CBP & OHCI_PAGE_SIZE_MASK,
  787. Td->TransferCount);
  788. }
  789. if (HcTDDirection_Setup != Td->HwTD.Asy.Direction) {
  790. // data phase of a control transfer or a bulk/int
  791. // data transfer
  792. LOGENTRY(DeviceData, G, '_Idt', Td, transferContext, Td->TransferCount);
  793. transferContext->BytesTransferred += Td->TransferCount;
  794. }
  795. if (HcCC_NoError == Td->HwTD.Asy.ConditionCode) {
  796. LOGENTRY(DeviceData, G, '_tOK', Td->HwTD.CBP, 0, 0);
  797. } else {
  798. // map the error to code in USBDI.H
  799. transferContext->UsbdStatus =
  800. (Td->HwTD.Asy.ConditionCode | 0xC0000000);
  801. LOGENTRY(DeviceData, G, '_tER', transferContext->UsbdStatus, 0, 0);
  802. }
  803. }
  804. // mark the TD free
  805. OHCI_FREE_TD(DeviceData, endpointData, Td);
  806. if (transferContext->PendingTds == 0 && CompleteTransfer) {
  807. // all TDs for this transfer are done
  808. // clear the HAVE_TRANSFER flag to indicate
  809. // we can teake another
  810. endpointData->PendingTransfers--;
  811. LOGENTRY(DeviceData, G, '_cpt',
  812. transferContext->UsbdStatus,
  813. transferContext,
  814. transferContext->BytesTransferred);
  815. USBPORT_COMPLETE_TRANSFER(DeviceData,
  816. endpointData,
  817. transferContext->TransferParameters,
  818. transferContext->UsbdStatus,
  819. transferContext->BytesTransferred);
  820. }
  821. }
  822. // figure out which sgentry a particular offset in to
  823. // a client buffer falls
  824. #define GET_SG_INDEX(sg, i, offset)\
  825. do {\
  826. for((i)=0; (i) < (sg)->SgCount; (i)++) {\
  827. if ((offset) >= (sg)->SgEntry[(i)].StartOffset &&\
  828. (offset) < (sg)->SgEntry[(i)].StartOffset+\
  829. (sg)->SgEntry[(i)].Length) {\
  830. break;\
  831. }\
  832. }\
  833. } while (0)
  834. #define GET_SG_OFFSET(sg, i, offset, sgoffset)\
  835. (sgoffset) = (offset) - (sg)->SgEntry[(i)].StartOffset
  836. ULONG
  837. OHCI_MapAsyncTransferToTd(
  838. PDEVICE_DATA DeviceData,
  839. ULONG MaxPacketSize,
  840. ULONG LengthMapped,
  841. PTRANSFER_CONTEXT TransferContext,
  842. PHCD_TRANSFER_DESCRIPTOR Td,
  843. PTRANSFER_SG_LIST SgList
  844. )
  845. /*++
  846. Routine Description:
  847. Maps a data buffer to TDs according to OHCI rules
  848. An OHCI TD can cover up to 8k with a single page crossing.
  849. Each sg entry represents one 4k OHCI 'page'
  850. x = pagebreak
  851. c = current ptr
  852. b = buffer start
  853. e = buffer end
  854. {..sg[sgIdx]..}
  855. b...|---
  856. x--c----
  857. [ ]
  858. \
  859. sgOffset
  860. [ ]
  861. \
  862. LengthMapped
  863. case 1: (1 sg entry remains)
  864. (A)- transfer < 4k, no page breaks (if c=b sgOffset = 0)
  865. {.sg0...}
  866. | b---->e
  867. x-c------x
  868. [..TD.]
  869. (B)- last part of a transfer
  870. {..sgN..}
  871. b.....|.c---->e
  872. x--------x
  873. [..TD.]
  874. case 2: (2 sg entries remain)
  875. (A)- transfer < 8k, one page break (if c=b sgOffset = 0)
  876. {..sg0..}{..sg1..}
  877. | b----|----->e
  878. x---c----x--------x
  879. [.....TD....]
  880. (B)- last 8k of transfer
  881. {.sgN-1.}{..sgN..}
  882. b....|--------|---->e
  883. x-c------x--------x
  884. [.....TD.......]
  885. case 3: (3+ sg entries remain)
  886. (A)- transfer 8k, two page breaks (c=b)
  887. {..sg0..}{..sg1..}{..sg2..}
  888. b----|--------|--->e
  889. x---c----x--------x--------x
  890. [.....TD...<>]
  891. <>=<TD length must be multiple of MaxPacketSize>
  892. (B)- continuation of large tarnsfer
  893. {.sgN-2.}{.sgN-1.}{..sgN..}
  894. b..|--------------------->e
  895. x--c-----x--------x--------x
  896. [.....TD......]
  897. <TD length must be multiple of MaxPacketSize>
  898. Interesting DMA tests (USBTEST):
  899. length, offset - cases hit
  900. 4096 0 - 1a
  901. 4160 0 - 2a
  902. 4096 512 - 2a
  903. 8192 512 - 3a, 1b
  904. 8192 513 - 3a, 2b
  905. 12288 1 - 3a, 3b, 2b
  906. Arguments:
  907. Returns:
  908. LengthMapped
  909. --*/
  910. {
  911. HW_32BIT_PHYSICAL_ADDRESS logicalStart, logicalEnd;
  912. ULONG sgIdx, sgOffset;
  913. ULONG lengthThisTd;
  914. PTRANSFER_PARAMETERS transferParameters;
  915. // A TD can have up to one page crossing. This means we
  916. // can put two sg entries in to one TD, one for the first
  917. // physical page, and one for the second.
  918. // point to first entry
  919. LOGENTRY(DeviceData, G, '_Mpr', TransferContext,
  920. 0, LengthMapped);
  921. transferParameters = TransferContext->TransferParameters;
  922. OHCI_ASSERT(DeviceData, SgList->SgCount != 0);
  923. GET_SG_INDEX(SgList, sgIdx, LengthMapped);
  924. LOGENTRY(DeviceData, G, '_Mpp', SgList, 0, sgIdx);
  925. OHCI_ASSERT(DeviceData, sgIdx < SgList->SgCount);
  926. // check for one special case where the SG entries
  927. // all map to the same physical page
  928. if (TEST_FLAG(SgList->SgFlags, USBMP_SGFLAG_SINGLE_PHYSICAL_PAGE)) {
  929. // in this case we map each sg entry to a single TD
  930. LOGENTRY(DeviceData, G, '_cOD', SgList, 0, sgIdx);
  931. // TEST_TRAP();
  932. // adjust for the amount of buffer consumed by the
  933. // previous TD
  934. logicalStart =
  935. SgList->SgEntry[sgIdx].LogicalAddress.Hw32;
  936. lengthThisTd = SgList->SgEntry[sgIdx].Length;
  937. logicalEnd = SgList->SgEntry[sgIdx].LogicalAddress.Hw32;
  938. logicalEnd += lengthThisTd;
  939. OHCI_ASSERT(DeviceData, lengthThisTd <= OHCI_PAGE_SIZE)
  940. goto OHCI_MapAsyncTransferToTd_Done;
  941. }
  942. if ((SgList->SgCount-sgIdx) == 1) {
  943. // first case, 1 entries left
  944. // ie <4k, we can fit this in
  945. // a single TD.
  946. #if DBG
  947. if (sgIdx == 0) {
  948. // case 1A
  949. // USBT dma test length 4096, offset 0
  950. // will hit this case
  951. // TEST_TRAP();
  952. LOGENTRY(DeviceData, G, '_c1a', SgList, 0, sgIdx);
  953. } else {
  954. // case 1B
  955. // USBT dma test length 8192 offset 512
  956. // will hit this case
  957. LOGENTRY(DeviceData, G, '_c1b', SgList, 0, sgIdx);
  958. }
  959. #endif
  960. lengthThisTd =
  961. transferParameters->TransferBufferLength - LengthMapped;
  962. // compute offset into this TD
  963. GET_SG_OFFSET(SgList, sgIdx, LengthMapped, sgOffset);
  964. LOGENTRY(DeviceData, G, '_sgO', sgOffset, sgIdx, LengthMapped);
  965. // adjust for the amount of buffer consumed by the
  966. // previous TD
  967. logicalStart =
  968. SgList->SgEntry[sgIdx].LogicalAddress.Hw32 + sgOffset;
  969. lengthThisTd -= sgOffset;
  970. logicalEnd = SgList->SgEntry[sgIdx].LogicalAddress.Hw32;
  971. logicalEnd += lengthThisTd;
  972. LOGENTRY(DeviceData, G, '_sg1', logicalStart, 0, logicalEnd);
  973. } else if ((SgList->SgCount - sgIdx) == 2) {
  974. // second case, 2 entries left
  975. // ie <8k we can also fit this in
  976. // a single TD.
  977. #if DBG
  978. if (sgIdx == 0) {
  979. // case 2A
  980. // USBT dma test length 4160 offset 0
  981. // will hit this case
  982. LOGENTRY(DeviceData, G, '_c2a', SgList, 0, sgIdx);
  983. } else {
  984. // case 2B
  985. // USBT dma test length 8192 offset 513
  986. // will hit this case
  987. LOGENTRY(DeviceData, G, '_c2b', SgList, 0, sgIdx);
  988. //TEST_TRAP();
  989. // bugbug run with DMA test
  990. }
  991. #endif
  992. lengthThisTd =
  993. transferParameters->TransferBufferLength - LengthMapped;
  994. // compute offset into first TD
  995. GET_SG_OFFSET(SgList, sgIdx, LengthMapped, sgOffset);
  996. LOGENTRY(DeviceData, G, '_sgO', sgOffset, sgIdx, LengthMapped);
  997. #if DBG
  998. if (sgIdx == 0) {
  999. OHCI_ASSERT(DeviceData, sgOffset == 0);
  1000. }
  1001. #endif
  1002. // adjust pointers for amount consumed by previous TD
  1003. logicalStart = SgList->SgEntry[sgIdx].LogicalAddress.Hw32 +
  1004. sgOffset;
  1005. logicalEnd = SgList->SgEntry[sgIdx+1].LogicalAddress.Hw32;
  1006. logicalEnd += SgList->SgEntry[sgIdx+1].Length;
  1007. LOGENTRY(DeviceData, G, '_sg2', logicalStart,
  1008. lengthThisTd, logicalEnd);
  1009. } else {
  1010. // third case, more than 2 sg entries.
  1011. //
  1012. ULONG adjust, packetCount;
  1013. #if DBG
  1014. if (sgIdx == 0) {
  1015. // case 3A
  1016. // USBT dma test length 8192 offset 512
  1017. // will hit this case
  1018. LOGENTRY(DeviceData, G, '_c3a', SgList, 0, sgIdx);
  1019. } else {
  1020. // case 3B
  1021. // USBT dma test length 12288 offset 1
  1022. // will hit this case
  1023. LOGENTRY(DeviceData, G, '_c3b', SgList, 0, sgIdx);
  1024. }
  1025. #endif
  1026. // sg offset is the offset in to the current TD to start
  1027. // using
  1028. // ie it is the number of bytes already consumed by the
  1029. // previous td
  1030. GET_SG_OFFSET(SgList, sgIdx, LengthMapped, sgOffset);
  1031. LOGENTRY(DeviceData, G, '_sgO', sgOffset, sgIdx, LengthMapped);
  1032. #if DBG
  1033. if (sgIdx == 0) {
  1034. OHCI_ASSERT(DeviceData, sgOffset == 0);
  1035. }
  1036. #endif
  1037. //
  1038. // consume the next two sg entrys
  1039. //
  1040. logicalStart = SgList->SgEntry[sgIdx].LogicalAddress.Hw32+
  1041. sgOffset;
  1042. logicalEnd = SgList->SgEntry[sgIdx+1].LogicalAddress.Hw32+
  1043. SgList->SgEntry[sgIdx+1].Length;
  1044. lengthThisTd = SgList->SgEntry[sgIdx].Length +
  1045. SgList->SgEntry[sgIdx+1].Length -
  1046. sgOffset;
  1047. // round TD length down to the highest multiple
  1048. // of max_packet size
  1049. packetCount = lengthThisTd/MaxPacketSize;
  1050. LOGENTRY(DeviceData, G, '_sg3', logicalStart, packetCount, logicalEnd);
  1051. adjust = lengthThisTd - packetCount*MaxPacketSize;
  1052. lengthThisTd = packetCount*MaxPacketSize;
  1053. if (adjust) {
  1054. OHCI_ASSERT(DeviceData, adjust > (logicalEnd & 0x00000FFF));
  1055. logicalEnd-=adjust;
  1056. LOGENTRY(DeviceData, G, '_adj', adjust, lengthThisTd, logicalEnd);
  1057. }
  1058. OHCI_ASSERT(DeviceData, lengthThisTd != 0);
  1059. OHCI_ASSERT(DeviceData, lengthThisTd >= SgList->SgEntry[sgIdx].Length);
  1060. }
  1061. OHCI_MapAsyncTransferToTd_Done:
  1062. Td->HwTD.CBP = logicalStart;
  1063. Td->HwTD.BE = logicalEnd-1;
  1064. LengthMapped += lengthThisTd;
  1065. Td->TransferCount = lengthThisTd;
  1066. LOGENTRY(DeviceData, G, '_Mp1', LengthMapped, lengthThisTd, Td);
  1067. return LengthMapped;
  1068. }