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.

2076 lines
57 KiB

  1. /*++
  2. Copyright (c) 1999, 2000 Microsoft Corporation
  3. Module Name:
  4. iso.c
  5. Abstract:
  6. miniport transfer code for interrupt endpoints
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13. PURPOSE.
  14. Copyright (c) 1999, 2000 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 1-1-01 : created, jdunn
  17. --*/
  18. #include "common.h"
  19. /*
  20. We build a table of 32 TDs for iso endpoints and insert them in the
  21. schedule, these TDs are static -- we only change the buffer pointers.
  22. The TD 'table' represents a 32ms snapshot of time.
  23. We end up with each iso endpoint siTD list as a column in the table
  24. frame dummyQH iso1 iso2 iso3 staticQH
  25. 1 | | | |---> (periodic lists)
  26. 2 | | | |
  27. 3 | | | |
  28. 4 | | | |
  29. ... | | | |
  30. | | | |
  31. 1024 | | | |
  32. */
  33. #define ISO_SCHEDULE_SIZE 32
  34. #define ISO_SCHEDULE_MASK 0x1f
  35. #define HIGHSPEED(ed) ((ed)->Parameters.DeviceSpeed == HighSpeed ? TRUE : FALSE)
  36. VOID
  37. EHCI_RebalanceIsoEndpoint(
  38. PDEVICE_DATA DeviceData,
  39. PENDPOINT_PARAMETERS EndpointParameters,
  40. PENDPOINT_DATA EndpointData
  41. )
  42. /*++
  43. Routine Description:
  44. compute how much common buffer we will need
  45. for this endpoint
  46. Arguments:
  47. Return Value:
  48. --*/
  49. {
  50. PHCD_SI_TRANSFER_DESCRIPTOR siTd;
  51. ULONG i, f;
  52. ULONG currentFrame;
  53. currentFrame = EHCI_Get32BitFrameNumber(DeviceData);
  54. // should only have to deal with s-mask and c-mask changes
  55. EHCI_ASSERT(DeviceData, !HIGHSPEED(EndpointData));
  56. //NOTE: irql should be raised for us
  57. // update internal copy of parameters
  58. EndpointData->Parameters = *EndpointParameters;
  59. f = currentFrame & ISO_SCHEDULE_MASK;
  60. for (i=0; i<EndpointData->TdCount; i++) {
  61. siTd = &EndpointData->SiTdList->Td[f];
  62. siTd->HwTD.Control.cMask =
  63. EndpointParameters->SplitCompletionMask;
  64. siTd->HwTD.Control.sMask =
  65. EndpointParameters->InterruptScheduleMask;
  66. f++;
  67. f &= ISO_SCHEDULE_MASK;
  68. }
  69. }
  70. VOID
  71. EHCI_InitializeSiTD(
  72. PDEVICE_DATA DeviceData,
  73. PENDPOINT_DATA EndpointData,
  74. PENDPOINT_PARAMETERS EndpointParameters,
  75. PHCD_SI_TRANSFER_DESCRIPTOR SiTd,
  76. PHCD_SI_TRANSFER_DESCRIPTOR PrevSiTd,
  77. HW_32BIT_PHYSICAL_ADDRESS PhysicalAddress
  78. )
  79. /*++
  80. Routine Description:
  81. Initailze a static SiTD for an endpoint
  82. Arguments:
  83. Return Value:
  84. none
  85. --*/
  86. {
  87. SiTd->Sig = SIG_HCD_SITD;
  88. SiTd->PhysicalAddress = PhysicalAddress;
  89. ISO_PACKET_PTR(SiTd->Packet) = NULL;
  90. SiTd->HwTD.Caps.ul = 0;
  91. SiTd->HwTD.Caps.DeviceAddress =
  92. EndpointParameters->DeviceAddress;
  93. SiTd->HwTD.Caps.EndpointNumber =
  94. EndpointParameters->EndpointAddress;
  95. SiTd->HwTD.Caps.HubAddress =
  96. EndpointParameters->TtDeviceAddress;
  97. SiTd->HwTD.Caps.PortNumber =
  98. EndpointParameters->TtPortNumber;
  99. // 1 = IN 0 = OUT
  100. SiTd->HwTD.Caps.Direction =
  101. (EndpointParameters->TransferDirection == In) ? 1 : 0;
  102. SiTd->HwTD.Control.ul = 0;
  103. SiTd->HwTD.Control.cMask =
  104. EndpointParameters->SplitCompletionMask;
  105. SiTd->HwTD.Control.sMask =
  106. EndpointParameters->InterruptScheduleMask;
  107. SiTd->HwTD.BackPointer.HwAddress =
  108. PrevSiTd->PhysicalAddress;
  109. SiTd->HwTD.State.ul = 0;
  110. }
  111. VOID
  112. EHCI_InsertIsoTdsInSchedule(
  113. PDEVICE_DATA DeviceData,
  114. PENDPOINT_DATA EndpointData,
  115. PENDPOINT_DATA PrevEndpointData,
  116. PENDPOINT_DATA NextEndpointData
  117. )
  118. /*++
  119. Routine Description:
  120. Insert an aync endpoint (queue head)
  121. into the HW list
  122. schedule should look like:
  123. DUMMYQH->ISOQH-ISOQH->INTQH
  124. Arguments:
  125. --*/
  126. {
  127. //PHW_32BIT_PHYSICAL_ADDRESS frameBase;
  128. ULONG i;
  129. LOGENTRY(DeviceData, G, '_iAD', PrevEndpointData,
  130. NextEndpointData, EndpointData);
  131. //frameBase = DeviceData->FrameListBaseAddress;
  132. for (i=0; i<USBEHCI_MAX_FRAME; i++) {
  133. PHCD_SI_TRANSFER_DESCRIPTOR siTd, nextSiTd;
  134. PHCD_QUEUEHEAD_DESCRIPTOR qh;
  135. PHCD_QUEUEHEAD_DESCRIPTOR dQh;
  136. ULONG phys;
  137. siTd = &EndpointData->SiTdList->Td[i&0x1f];
  138. // fixup next link
  139. if (NextEndpointData == NULL &&
  140. PrevEndpointData == NULL) {
  141. // list empty add to head
  142. if (i == 0) {
  143. EHCI_ASSERT(DeviceData, DeviceData->IsoEndpointListHead == NULL);
  144. DeviceData->IsoEndpointListHead = EndpointData;
  145. EndpointData->PrevEndpoint = NULL;
  146. EndpointData->NextEndpoint = NULL;
  147. }
  148. // list empty add to head
  149. // no iso endpoints, link to the interrupt
  150. // queue heads via the dummy qh
  151. //
  152. // point at the static perodic queue head pointed to
  153. // by the appropriate dummy
  154. // DUMMY->INTQH
  155. // to
  156. // ISOTD->INTQH
  157. dQh = EHCI_GetDummyQueueHeadForFrame(DeviceData, i);
  158. siTd->HwTD.NextLink.HwAddress = dQh->HwQH.HLink.HwAddress;
  159. HW_PTR(siTd->NextLink) = HW_PTR(dQh->NextLink);
  160. phys = siTd->PhysicalAddress;
  161. SET_SITD(phys);
  162. //
  163. // appropriate dummy should point to these TDs
  164. // DUMMY->INTQH, ISOTD->INTQH
  165. // to
  166. // DUMMY->ISOTD->INTQH
  167. dQh = EHCI_GetDummyQueueHeadForFrame(DeviceData, i);
  168. dQh->HwQH.HLink.HwAddress = phys;
  169. HW_PTR(dQh->NextLink) = (PUCHAR) siTd;
  170. } else {
  171. if (NextEndpointData == NULL) {
  172. // tail of list, list not empty
  173. // add to tail
  174. if (i == 0) {
  175. EHCI_ASSERT(DeviceData, PrevEndpointData != NULL);
  176. EHCI_ASSERT(DeviceData, DeviceData->IsoEndpointListHead != NULL);
  177. PrevEndpointData->NextEndpoint = EndpointData;
  178. EndpointData->PrevEndpoint = PrevEndpointData;
  179. EndpointData->NextEndpoint = NULL;
  180. }
  181. LOGENTRY(DeviceData, G, '_iTL', PrevEndpointData,
  182. NextEndpointData, EndpointData);
  183. // tail of list, link to qh
  184. // ISOTD->INTQH
  185. // to
  186. // ISOTD->newISOTD->INTQH
  187. //
  188. if (HIGHSPEED(PrevEndpointData)) {
  189. PHCD_HSISO_TRANSFER_DESCRIPTOR previTd;
  190. PUCHAR next;
  191. previTd = &PrevEndpointData->HsIsoTdList->Td[i];
  192. ASSERT_ITD(DeviceData, previTd);
  193. siTd = &EndpointData->SiTdList->Td[i&0x1f];
  194. ASSERT_SITD(DeviceData, siTd);
  195. // fixup current next ptr
  196. phys = previTd->HwTD.NextLink.HwAddress;
  197. next = HW_PTR(previTd->NextLink);
  198. siTd->HwTD.NextLink.HwAddress = phys;
  199. HW_PTR(siTd->NextLink) = next;
  200. // fixup prev next ptr
  201. HW_PTR(previTd->NextLink) = (PUCHAR) siTd;
  202. phys = siTd->PhysicalAddress;
  203. SET_SITD(phys);
  204. previTd->HwTD.NextLink.HwAddress = phys;
  205. } else {
  206. PHCD_SI_TRANSFER_DESCRIPTOR prevSiTd;
  207. PUCHAR next;
  208. prevSiTd = &PrevEndpointData->SiTdList->Td[i&0x1f];
  209. ASSERT_SITD(DeviceData, prevSiTd);
  210. siTd = &EndpointData->SiTdList->Td[i&0x1f];
  211. ASSERT_SITD(DeviceData, siTd);
  212. if (i<32) {
  213. //newISOTD->INTQH
  214. phys = prevSiTd->HwTD.NextLink.HwAddress;
  215. next = HW_PTR(prevSiTd->NextLink);
  216. siTd->HwTD.NextLink.HwAddress = phys;
  217. HW_PTR(siTd->NextLink) = next;
  218. LOGENTRY(DeviceData, G, '_in1', phys, next, siTd);
  219. //ISOTD->newISOTD
  220. phys = siTd->PhysicalAddress;
  221. SET_SITD(phys);
  222. next = (PUCHAR) siTd;
  223. prevSiTd->HwTD.NextLink.HwAddress = phys;
  224. HW_PTR(prevSiTd->NextLink) = next;
  225. LOGENTRY(DeviceData, G, '_in2', phys, next, siTd);
  226. }
  227. }
  228. // add to tail
  229. } else {
  230. // list not empty, not tail
  231. // add to middle OR head
  232. //
  233. // link to the next iso endpoint
  234. // ISOTD->INTQH
  235. // to
  236. // newISOTD->ISOTD->INTQH
  237. if (i == 0) {
  238. EHCI_ASSERT(DeviceData, NextEndpointData != NULL);
  239. EndpointData->NextEndpoint = NextEndpointData;
  240. NextEndpointData->PrevEndpoint = EndpointData;
  241. }
  242. // link to next
  243. nextSiTd = &NextEndpointData->SiTdList->Td[i&0x1f];
  244. phys = nextSiTd->PhysicalAddress;
  245. SET_SITD(phys);
  246. // link to the next iso endpoint
  247. siTd->HwTD.NextLink.HwAddress = phys;
  248. HW_PTR(siTd->NextLink) = (PUCHAR) nextSiTd;
  249. // link to prev
  250. if (PrevEndpointData != NULL) {
  251. // middle
  252. // ISOTD->ISOTD->INTQH, newISOTD->ISOTD->INTQH
  253. // to
  254. // ISOTD->newISOTD->ISOTD->INTQH
  255. if (i == 0) {
  256. PrevEndpointData->NextEndpoint = EndpointData;
  257. EndpointData->PrevEndpoint = PrevEndpointData;
  258. }
  259. if (HIGHSPEED(PrevEndpointData)) {
  260. PHCD_HSISO_TRANSFER_DESCRIPTOR previTd;
  261. previTd = &PrevEndpointData->HsIsoTdList->Td[i];
  262. ASSERT_ITD(DeviceData, previTd);
  263. siTd = &EndpointData->SiTdList->Td[i&0x1f];
  264. ASSERT_SITD(DeviceData, siTd);
  265. phys = siTd->PhysicalAddress;
  266. SET_SITD(phys);
  267. previTd->HwTD.NextLink.HwAddress = phys;
  268. HW_PTR(previTd->NextLink) = (PUCHAR) siTd;
  269. } else {
  270. PHCD_SI_TRANSFER_DESCRIPTOR prevSiTd;
  271. prevSiTd = &PrevEndpointData->SiTdList->Td[i&0x1f];
  272. ASSERT_SITD(DeviceData, prevSiTd);
  273. siTd = &EndpointData->SiTdList->Td[i&0x1f];
  274. ASSERT_SITD(DeviceData, siTd);
  275. phys = siTd->PhysicalAddress;
  276. SET_SITD(phys);
  277. prevSiTd->HwTD.NextLink.HwAddress = phys;
  278. HW_PTR(prevSiTd->NextLink) = (PUCHAR)siTd;
  279. }
  280. } else {
  281. // head of list, list not empty
  282. if (i == 0) {
  283. EHCI_ASSERT(DeviceData, NextEndpointData != NULL);
  284. EHCI_ASSERT(DeviceData, NextEndpointData ==
  285. DeviceData->IsoEndpointListHead);
  286. DeviceData->IsoEndpointListHead = EndpointData;
  287. EndpointData->PrevEndpoint = NULL;
  288. }
  289. phys = siTd->PhysicalAddress;
  290. SET_SITD(phys);
  291. // head of list, link to Dummy QH
  292. //
  293. // appropriate dummy should point to these TDs
  294. // DUMMY->ISOTD->INTQH, newISOTD->ISOTD->INTQH
  295. // to
  296. // DUMMY->newISOTD->ISOTD->INTQH
  297. dQh = EHCI_GetDummyQueueHeadForFrame(DeviceData, i);
  298. dQh->HwQH.HLink.HwAddress = phys;
  299. HW_PTR(dQh->NextLink) = (PUCHAR) siTd;
  300. }
  301. }
  302. } // not empty
  303. }
  304. }
  305. VOID
  306. EHCI_RemoveIsoTdsFromSchedule(
  307. PDEVICE_DATA DeviceData,
  308. PENDPOINT_DATA EndpointData
  309. )
  310. /*++
  311. Routine Description:
  312. unlink the iso TDs from the schedule
  313. Arguments:
  314. --*/
  315. {
  316. ULONG i;
  317. PENDPOINT_DATA prevEndpoint, nextEndpoint;
  318. PHCD_QUEUEHEAD_DESCRIPTOR dQh;
  319. prevEndpoint = EndpointData->PrevEndpoint;
  320. nextEndpoint = EndpointData->NextEndpoint;
  321. LOGENTRY(DeviceData, G, '_iRM', prevEndpoint,
  322. nextEndpoint, EndpointData);
  323. if (DeviceData->IsoEndpointListHead == EndpointData) {
  324. // this is the head
  325. for (i=0; i<USBEHCI_MAX_FRAME; i++) {
  326. PHCD_SI_TRANSFER_DESCRIPTOR siTd;
  327. ULONG phys;
  328. siTd = &EndpointData->SiTdList->Td[i&0x1f];
  329. phys = siTd->HwTD.NextLink.HwAddress;
  330. dQh = EHCI_GetDummyQueueHeadForFrame(DeviceData, i);
  331. dQh->HwQH.HLink.HwAddress = phys;
  332. HW_PTR(dQh->NextLink) = HW_PTR(siTd->NextLink);
  333. }
  334. DeviceData->IsoEndpointListHead =
  335. EndpointData->NextEndpoint;
  336. if (nextEndpoint != NULL) {
  337. EHCI_ASSERT(DeviceData,
  338. nextEndpoint->PrevEndpoint == EndpointData);
  339. nextEndpoint->PrevEndpoint = NULL;
  340. }
  341. } else {
  342. // middle or tail
  343. EHCI_ASSERT(DeviceData, prevEndpoint != NULL);
  344. if (HIGHSPEED(prevEndpoint)) {
  345. for (i=0; i<USBEHCI_MAX_FRAME; i++) {
  346. PHCD_HSISO_TRANSFER_DESCRIPTOR previTd;
  347. PHCD_SI_TRANSFER_DESCRIPTOR siTd;
  348. ULONG phys;
  349. siTd = &EndpointData->SiTdList->Td[i&0x1f];
  350. previTd = &prevEndpoint->HsIsoTdList->Td[i];
  351. phys = siTd->HwTD.NextLink.HwAddress;
  352. previTd->HwTD.NextLink.HwAddress = phys;
  353. HW_PTR(previTd->NextLink) = HW_PTR(siTd->NextLink);
  354. }
  355. prevEndpoint->NextEndpoint =
  356. EndpointData->NextEndpoint;
  357. if (nextEndpoint) {
  358. nextEndpoint->PrevEndpoint = prevEndpoint;
  359. }
  360. } else {
  361. for (i=0; i<ISO_SCHEDULE_SIZE; i++) {
  362. PHCD_SI_TRANSFER_DESCRIPTOR siTd, prevSiTd;
  363. ULONG phys;
  364. siTd = &EndpointData->SiTdList->Td[i];
  365. prevSiTd = &prevEndpoint->SiTdList->Td[i];
  366. phys = siTd->HwTD.NextLink.HwAddress;
  367. prevSiTd->HwTD.NextLink.HwAddress = phys;
  368. HW_PTR(prevSiTd->NextLink) = HW_PTR(siTd->NextLink);
  369. }
  370. prevEndpoint->NextEndpoint =
  371. EndpointData->NextEndpoint;
  372. if (nextEndpoint) {
  373. nextEndpoint->PrevEndpoint = prevEndpoint;
  374. }
  375. }
  376. }
  377. }
  378. USB_MINIPORT_STATUS
  379. EHCI_OpenIsochronousEndpoint(
  380. PDEVICE_DATA DeviceData,
  381. PENDPOINT_PARAMETERS EndpointParameters,
  382. PENDPOINT_DATA EndpointData
  383. )
  384. /*++
  385. Routine Description:
  386. Arguments:
  387. Return Value:
  388. --*/
  389. {
  390. PUCHAR buffer;
  391. HW_32BIT_PHYSICAL_ADDRESS phys;
  392. ULONG i;
  393. ULONG bytes;
  394. PHW_32BIT_PHYSICAL_ADDRESS frameBase;
  395. PENDPOINT_DATA prevEndpoint, nextEndpoint;
  396. LOGENTRY(DeviceData, G, '_opR', 0, 0, EndpointParameters);
  397. buffer = EndpointParameters->CommonBufferVa;
  398. phys = EndpointParameters->CommonBufferPhys;
  399. // how much did we get
  400. bytes = EndpointParameters->CommonBufferBytes;
  401. EndpointData->SiTdList = (PHCD_SITD_LIST) buffer;
  402. // bugbug use manifest
  403. EndpointData->TdCount = ISO_SCHEDULE_SIZE;
  404. EndpointData->LastFrame = 0;
  405. for (i=0; i<EndpointData->TdCount; i++) {
  406. EHCI_InitializeSiTD(DeviceData,
  407. EndpointData,
  408. EndpointParameters,
  409. &EndpointData->SiTdList->Td[i],
  410. i > 0 ?
  411. &EndpointData->SiTdList->Td[i-1] :
  412. &EndpointData->SiTdList->Td[EndpointData->TdCount-1],
  413. phys);
  414. phys += sizeof(HCD_SI_TRANSFER_DESCRIPTOR);
  415. }
  416. EndpointData->SiTdList->Td[0].HwTD.BackPointer.HwAddress =
  417. EndpointData->SiTdList->Td[EndpointData->TdCount-1].PhysicalAddress;
  418. // split iso eps are inserted after any high speed eps
  419. if (DeviceData->IsoEndpointListHead == NULL) {
  420. // empty list
  421. prevEndpoint = NULL;
  422. nextEndpoint = NULL;
  423. } else {
  424. prevEndpoint = NULL;
  425. nextEndpoint = DeviceData->IsoEndpointListHead;
  426. // walk the list to the first non HS ep or to
  427. // a NULL
  428. while (nextEndpoint != NULL &&
  429. HIGHSPEED(nextEndpoint)) {
  430. prevEndpoint = nextEndpoint;
  431. nextEndpoint = prevEndpoint->NextEndpoint;
  432. }
  433. if (nextEndpoint != NULL) {
  434. //
  435. // nextEndpoint is first non high speed endpoint
  436. // see what order it sould be added
  437. if (EndpointData->Parameters.Ordinal == 1) {
  438. // ordinal 1 add after this one
  439. prevEndpoint = nextEndpoint;
  440. nextEndpoint = prevEndpoint->NextEndpoint;
  441. }
  442. }
  443. }
  444. // insert this column of TDs thru the schedule
  445. EHCI_InsertIsoTdsInSchedule(DeviceData,
  446. EndpointData,
  447. prevEndpoint,
  448. nextEndpoint);
  449. // init endpoint structures
  450. InitializeListHead(&EndpointData->TransferList);
  451. EHCI_EnablePeriodicList(DeviceData);
  452. return USBMP_STATUS_SUCCESS;
  453. }
  454. VOID
  455. EHCI_MapIsoPacketToTd(
  456. PDEVICE_DATA DeviceData,
  457. PENDPOINT_DATA EndpointData,
  458. PMINIPORT_ISO_PACKET Packet,
  459. PHCD_SI_TRANSFER_DESCRIPTOR SiTd
  460. )
  461. /*++
  462. Routine Description:
  463. Arguments:
  464. Returns:
  465. --*/
  466. {
  467. ULONG length;
  468. LOGENTRY(DeviceData, G, '_mpI', SiTd, 0, Packet);
  469. SiTd->HwTD.State.ul = 0;
  470. SiTd->HwTD.BufferPointer0.ul = 0;
  471. SiTd->HwTD.BufferPointer1.ul = 0;
  472. SiTd->HwTD.BufferPointer0.ul =
  473. Packet->BufferPointer0.Hw32;
  474. length = Packet->BufferPointer0Length;
  475. SiTd->StartOffset = SiTd->HwTD.BufferPointer0.CurrentOffset;
  476. SiTd->HwTD.BufferPointer1.ul = 0;
  477. if (Packet->BufferPointerCount > 1) {
  478. EHCI_ASSERT(DeviceData,
  479. (Packet->BufferPointer1.Hw32 & 0xFFF) == 0);
  480. SiTd->HwTD.BufferPointer1.ul =
  481. Packet->BufferPointer1.Hw32;
  482. length += Packet->BufferPointer1Length;
  483. }
  484. // not sure if this is corrext for IN
  485. SiTd->HwTD.BufferPointer1.Tposition = TPOS_ALL;
  486. if (EndpointData->Parameters.TransferDirection == Out) {
  487. if (length == 0) {
  488. SiTd->HwTD.BufferPointer1.Tcount = 1;
  489. } else {
  490. SiTd->HwTD.BufferPointer1.Tcount = ((length -1) / 188) +1;
  491. }
  492. if (SiTd->HwTD.BufferPointer1.Tcount == 1) {
  493. SiTd->HwTD.BufferPointer1.Tposition = TPOS_ALL;
  494. } else {
  495. SiTd->HwTD.BufferPointer1.Tposition = TPOS_BEGIN;
  496. }
  497. EHCI_ASSERT(DeviceData, SiTd->HwTD.BufferPointer1.Tcount <= 6);
  498. } else {
  499. SiTd->HwTD.BufferPointer1.Tcount = 0;
  500. }
  501. SiTd->HwTD.State.BytesToTransfer = length;
  502. SiTd->HwTD.State.Active = 1;
  503. SiTd->HwTD.State.InterruptOnComplete = 1;
  504. EHCI_ASSERT(DeviceData, SiTd->HwTD.BackPointer.HwAddress != 0);
  505. }
  506. VOID
  507. EHCI_CompleteIsoPacket(
  508. PDEVICE_DATA DeviceData,
  509. PMINIPORT_ISO_PACKET Packet,
  510. PHCD_SI_TRANSFER_DESCRIPTOR SiTd
  511. )
  512. /*++
  513. Routine Description:
  514. Arguments:
  515. Returns:
  516. --*/
  517. {
  518. ULONG length;
  519. ULONG cf = EHCI_Get32BitFrameNumber(DeviceData);
  520. LOGENTRY(DeviceData, G, '_cpI', Packet, SiTd, cf);
  521. if (SiTd->HwTD.State.Active == 1) {
  522. // missed
  523. Packet->LengthTransferred = 0;
  524. LOGENTRY(DeviceData, G, '_cms',
  525. Packet,
  526. 0,
  527. Packet->FrameNumber);
  528. } else {
  529. //length = SiTd->HwTD.BufferPointer0.CurrentOffset -
  530. // SiTd->StartOffset;
  531. //LOGENTRY(DeviceData, G, '_cp2',
  532. // Packet->FrameNumber,
  533. // SiTd->HwTD.BufferPointer0.CurrentOffset,
  534. // SiTd->StartOffset);
  535. length = Packet->Length - SiTd->HwTD.State.BytesToTransfer;
  536. LOGENTRY(DeviceData, G, '_cp3',
  537. Packet->FrameNumber,
  538. Packet->Length ,
  539. SiTd->HwTD.State.BytesToTransfer);
  540. Packet->LengthTransferred = length;
  541. LOGENTRY(DeviceData, G, '_cpL', Packet, SiTd, length);
  542. }
  543. //Packet->LengthTransferred = 928;
  544. // map status
  545. LOGENTRY(DeviceData, G, '_cpS', Packet, SiTd->HwTD.State.ul,
  546. Packet->UsbdStatus);
  547. Packet->UsbdStatus = USBD_STATUS_SUCCESS;
  548. }
  549. PMINIPORT_ISO_PACKET
  550. EHCI_GetPacketForFrame(
  551. PDEVICE_DATA DeviceData,
  552. PENDPOINT_DATA EndpointData,
  553. PTRANSFER_CONTEXT *Transfer,
  554. ULONG Frame
  555. )
  556. /*++
  557. Routine Description:
  558. fetch the iso packet associated with the given frame
  559. if we have one in our current transfer list
  560. Arguments:
  561. Returns:
  562. --*/
  563. {
  564. ULONG i;
  565. PLIST_ENTRY listEntry;
  566. listEntry = EndpointData->TransferList.Flink;
  567. while (listEntry != &EndpointData->TransferList) {
  568. PTRANSFER_CONTEXT transfer;
  569. transfer = (PTRANSFER_CONTEXT) CONTAINING_RECORD(
  570. listEntry,
  571. struct _TRANSFER_CONTEXT,
  572. TransferLink);
  573. ASSERT_TRANSFER(DeviceData, transfer);
  574. if (Frame <= transfer->FrameComplete) {
  575. for(i=0; i<transfer->IsoTransfer->PacketCount; i++) {
  576. if (transfer->IsoTransfer->Packets[i].FrameNumber == Frame) {
  577. *Transfer = transfer;
  578. return &transfer->IsoTransfer->Packets[i];
  579. }
  580. }
  581. }
  582. listEntry = transfer->TransferLink.Flink;
  583. }
  584. return NULL;
  585. }
  586. ULONG xCount = 0;
  587. ULONG pCount = 0;
  588. VOID
  589. EHCI_InternalPollIsoEndpoint(
  590. PDEVICE_DATA DeviceData,
  591. PENDPOINT_DATA EndpointData,
  592. BOOLEAN Complete
  593. )
  594. /*++
  595. Routine Description:
  596. Called when the endpoint 'needs attention'
  597. static iso TD table
  598. --------------------
  599. 0 < -- (lastFrame & 0x1f)
  600. 1 {completed}
  601. 2 {completed}
  602. 3 {limbo}
  603. 4 < -- (currentframe & 0x1f)
  604. ...
  605. 31
  606. ---------------------
  607. Arguments:
  608. Return Value:
  609. --*/
  610. {
  611. ULONG x, i;
  612. ULONG currentFrame, lastFrame;
  613. PHCD_SI_TRANSFER_DESCRIPTOR siTd;
  614. PMINIPORT_ISO_PACKET packet;
  615. PLIST_ENTRY listEntry;
  616. PTRANSFER_CONTEXT transfer;
  617. ULONG transfersPending, fc;
  618. currentFrame = EHCI_Get32BitFrameNumber(DeviceData);
  619. lastFrame = EndpointData->LastFrame;
  620. LOGENTRY(DeviceData, G, '_pis', lastFrame, currentFrame,
  621. EndpointData);
  622. // if (pCount > 60) {
  623. // TEST_TRAP();
  624. // }
  625. if (currentFrame - lastFrame > ISO_SCHEDULE_SIZE) {
  626. // overrun
  627. lastFrame = currentFrame-1;
  628. LOGENTRY(DeviceData, G, '_ove', lastFrame, currentFrame, 0);
  629. // dump the current contents
  630. for (i = 0; i <ISO_SCHEDULE_SIZE; i++) {
  631. siTd = &EndpointData->SiTdList->Td[i];
  632. transfer = ISO_TRANSFER_PTR(siTd->Transfer);
  633. if (transfer != NULL) {
  634. ISO_PACKET_PTR(siTd->Packet) = NULL;
  635. ISO_TRANSFER_PTR(siTd->Transfer) = NULL;
  636. transfer->PendingPackets--;
  637. }
  638. }
  639. }
  640. if (lastFrame == currentFrame) {
  641. // too early to do anything
  642. LOGENTRY(DeviceData, G, '_ear', lastFrame, currentFrame, 0);
  643. return;
  644. }
  645. // TDs between lastframe and currentframe are complete,
  646. // complete the packets associated with them
  647. // f0
  648. // f1
  649. // f2 < ------- last frame }
  650. // f3 } these are complete
  651. // f4 <- backpointer may still be pointing here
  652. // f5 < ------- current frame
  653. // f6
  654. // f7
  655. // f8
  656. x = (lastFrame & (ISO_SCHEDULE_MASK));
  657. LOGENTRY(DeviceData, G, '_frm', lastFrame, x, currentFrame);
  658. while (x != ((currentFrame-1) & ISO_SCHEDULE_MASK)) {
  659. siTd = &EndpointData->SiTdList->Td[x];
  660. ASSERT_SITD(DeviceData, siTd);
  661. // complete this packet
  662. packet = ISO_PACKET_PTR(siTd->Packet);
  663. transfer = ISO_TRANSFER_PTR(siTd->Transfer);
  664. LOGENTRY(DeviceData, G, '_gpk', transfer, packet, x);
  665. if (packet != NULL) {
  666. transfer = ISO_TRANSFER_PTR(siTd->Transfer);
  667. ASSERT_TRANSFER(DeviceData, transfer);
  668. EHCI_CompleteIsoPacket(DeviceData, packet, siTd);
  669. ISO_PACKET_PTR(siTd->Packet) = NULL;
  670. ISO_TRANSFER_PTR(siTd->Transfer) = NULL;
  671. transfer->PendingPackets--;
  672. }
  673. lastFrame++;
  674. x++;
  675. x &= ISO_SCHEDULE_MASK;
  676. }
  677. // attempt to program what we can, if siTD is NULL
  678. // then we can program this frame
  679. // NOTE: No scheduling if paused!
  680. if (EndpointData->State != ENDPOINT_PAUSE) {
  681. LOGENTRY(DeviceData, G, '_psh', 0, 0, 0);
  682. for (i=0; i <ISO_SCHEDULE_SIZE; i++) {
  683. x = ((currentFrame+i) & ISO_SCHEDULE_MASK);
  684. siTd = &EndpointData->SiTdList->Td[x];
  685. ASSERT_SITD(DeviceData, siTd);
  686. LOGENTRY(DeviceData, G, '_gpf', siTd, x, currentFrame+i);
  687. // open slot?
  688. if (ISO_PACKET_PTR(siTd->Packet) != NULL) {
  689. // no, bail
  690. continue;
  691. }
  692. // yes, see if we have a packet
  693. packet = EHCI_GetPacketForFrame(DeviceData,
  694. EndpointData,
  695. &transfer,
  696. currentFrame+i);
  697. if (packet != NULL) {
  698. EHCI_ASSERT(DeviceData, ISO_PACKET_PTR(siTd->Packet) == NULL);
  699. EHCI_MapIsoPacketToTd(DeviceData, EndpointData,
  700. packet, siTd);
  701. ISO_PACKET_PTR(siTd->Packet) = packet;
  702. ASSERT_TRANSFER(DeviceData, transfer);
  703. ISO_TRANSFER_PTR(siTd->Transfer) = transfer;
  704. transfer->PendingPackets++;
  705. }
  706. }
  707. }
  708. EHCI_ASSERT(DeviceData, lastFrame < currentFrame);
  709. EndpointData->LastFrame = lastFrame;
  710. // walk our list of active iso transfers and see
  711. // if any are complete
  712. listEntry = EndpointData->TransferList.Flink;
  713. transfersPending = 0;
  714. while (listEntry != &EndpointData->TransferList && Complete) {
  715. PTRANSFER_CONTEXT transfer;
  716. transfer = (PTRANSFER_CONTEXT) CONTAINING_RECORD(
  717. listEntry,
  718. struct _TRANSFER_CONTEXT,
  719. TransferLink);
  720. LOGENTRY(DeviceData, G, '_ckt', transfer, transfer->FrameComplete+2
  721. , currentFrame);
  722. EHCI_ASSERT(DeviceData, transfer->Sig == SIG_EHCI_TRANSFER);
  723. if (currentFrame >= transfer->FrameComplete + 2 &&
  724. transfer->PendingPackets == 0) {
  725. listEntry = transfer->TransferLink.Flink;
  726. RemoveEntryList(&transfer->TransferLink);
  727. LOGENTRY(DeviceData, G, '_cpi', transfer, 0, 0);
  728. // if (xCount==2) {
  729. // TEST_TRAP();
  730. //}
  731. USBPORT_COMPLETE_ISO_TRANSFER(DeviceData,
  732. EndpointData,
  733. transfer->TransferParameters,
  734. transfer->IsoTransfer);
  735. } else {
  736. transfersPending++;
  737. fc = transfer->FrameComplete;
  738. listEntry = transfer->TransferLink.Flink;
  739. }
  740. }
  741. currentFrame = EHCI_Get32BitFrameNumber(DeviceData);
  742. if (transfersPending == 1 &&
  743. fc >= currentFrame &&
  744. (fc - currentFrame) < 2 ) {
  745. LOGENTRY(DeviceData, G, '_rei', fc, currentFrame, 0);
  746. EHCI_InterruptNextSOF(DeviceData);
  747. }
  748. }
  749. VOID
  750. EHCI_PollIsoEndpoint(
  751. PDEVICE_DATA DeviceData,
  752. PENDPOINT_DATA EndpointData
  753. )
  754. {
  755. LOGENTRY(DeviceData, G, '_ipl', 0, 0, 0);
  756. if (!IsListEmpty(&EndpointData->TransferList)) {
  757. LOGENTRY(DeviceData, G, '_III', 0, 0, 0);
  758. if (HIGHSPEED(EndpointData)) {
  759. EHCI_InternalPollHsIsoEndpoint(DeviceData, EndpointData, TRUE);
  760. } else {
  761. EHCI_InternalPollIsoEndpoint(DeviceData, EndpointData, TRUE);
  762. }
  763. }
  764. }
  765. USB_MINIPORT_STATUS
  766. EHCI_AbortIsoTransfer(
  767. PDEVICE_DATA DeviceData,
  768. PENDPOINT_DATA EndpointData,
  769. PTRANSFER_CONTEXT TransferContext
  770. )
  771. /*++
  772. Routine Description:
  773. Arguments:
  774. Return Value:
  775. --*/
  776. {
  777. ULONG i;
  778. // iso TD table should be idle at this point all we
  779. // need to do is make sure we have no TDs still pointing
  780. // at this transfer and remove it frome any internal
  781. // queues
  782. if (HIGHSPEED(EndpointData)) {
  783. for (i = 0; i <USBEHCI_MAX_FRAME; i++) {
  784. PHCD_HSISO_TRANSFER_DESCRIPTOR hsIsoTd;
  785. ULONG period = EndpointData->Parameters.Period;
  786. LOGENTRY(DeviceData, G, '_ibh', TransferContext,
  787. EndpointData, period);
  788. hsIsoTd = &EndpointData->HsIsoTdList->Td[i];
  789. if (ISO_TRANSFER_PTR(hsIsoTd->Transfer) == TransferContext) {
  790. ISO_TRANSFER_PTR(hsIsoTd->Transfer) = NULL;
  791. ISO_PACKET_PTR(hsIsoTd->FirstPacket) = NULL;
  792. TransferContext->PendingPackets -= (8/period);
  793. }
  794. }
  795. } else {
  796. for (i = 0; i <ISO_SCHEDULE_SIZE; i++) {
  797. PHCD_SI_TRANSFER_DESCRIPTOR siTd;
  798. LOGENTRY(DeviceData, G, '_ibi', TransferContext,
  799. EndpointData, 1);
  800. siTd = &EndpointData->SiTdList->Td[i];
  801. if (ISO_TRANSFER_PTR(siTd->Transfer) == TransferContext) {
  802. ISO_TRANSFER_PTR(siTd->Transfer) = NULL;
  803. ISO_PACKET_PTR(siTd->Packet) = NULL;
  804. TransferContext->PendingPackets--;
  805. }
  806. }
  807. }
  808. EHCI_ASSERT(DeviceData, TransferContext->TransferLink.Flink != NULL);
  809. EHCI_ASSERT(DeviceData, TransferContext->TransferLink.Blink != NULL);
  810. // remove this transfer from our lists
  811. RemoveEntryList(&TransferContext->TransferLink);
  812. TransferContext->TransferLink.Flink = NULL;
  813. TransferContext->TransferLink.Blink = NULL;
  814. return USBMP_STATUS_SUCCESS;
  815. }
  816. USB_MINIPORT_STATUS
  817. EHCI_SubmitIsoTransfer(
  818. PDEVICE_DATA DeviceData,
  819. PENDPOINT_DATA EndpointData,
  820. PTRANSFER_PARAMETERS TransferParameters,
  821. PTRANSFER_CONTEXT TransferContext,
  822. PMINIPORT_ISO_TRANSFER IsoTransfer
  823. )
  824. /*++
  825. Routine Description:
  826. Arguments:
  827. Return Value:
  828. --*/
  829. {
  830. // init the structures and queue the endpoint
  831. LOGENTRY(DeviceData, G, '_ISO', TransferContext, 0, 0);
  832. RtlZeroMemory(TransferContext, sizeof(TRANSFER_CONTEXT));
  833. TransferContext->Sig = SIG_EHCI_TRANSFER;
  834. TransferContext->IsoTransfer = IsoTransfer;
  835. TransferContext->EndpointData = EndpointData;
  836. TransferContext->TransferParameters = TransferParameters;
  837. if (HIGHSPEED(EndpointData)) {
  838. TransferContext->FrameComplete =
  839. IsoTransfer->Packets[0].FrameNumber + IsoTransfer->PacketCount/8;
  840. } else {
  841. TransferContext->FrameComplete =
  842. IsoTransfer->Packets[0].FrameNumber + IsoTransfer->PacketCount;
  843. }
  844. TransferContext->PendingPackets = 0;
  845. // if queues are empty the go ahead and reset the table
  846. // so we can fill now
  847. if (IsListEmpty(&EndpointData->TransferList)) {
  848. EndpointData->LastFrame = 0;
  849. LOGENTRY(DeviceData, G, '_rsi', 0, 0, 0);
  850. }
  851. InsertTailList(&EndpointData->TransferList,
  852. &TransferContext->TransferLink);
  853. // scehdule the initial part of the transfer if
  854. // possible
  855. if (HIGHSPEED(EndpointData)) {
  856. EHCI_InternalPollHsIsoEndpoint(DeviceData,
  857. EndpointData,
  858. FALSE);
  859. } else {
  860. EHCI_InternalPollIsoEndpoint(DeviceData,
  861. EndpointData,
  862. FALSE);
  863. }
  864. xCount++;
  865. //if (xCount==2) {
  866. // TEST_TRAP();
  867. //}
  868. return USBMP_STATUS_SUCCESS;
  869. }
  870. VOID
  871. EHCI_SetIsoEndpointState(
  872. PDEVICE_DATA DeviceData,
  873. PENDPOINT_DATA EndpointData,
  874. MP_ENDPOINT_STATE State
  875. )
  876. /*++
  877. Routine Description:
  878. Arguments:
  879. Return Value:
  880. --*/
  881. {
  882. ENDPOINT_TRANSFER_TYPE epType;
  883. ULONG i, j;
  884. epType = EndpointData->Parameters.TransferType;
  885. EHCI_ASSERT(DeviceData, epType == Isochronous);
  886. switch(State) {
  887. case ENDPOINT_ACTIVE:
  888. EndpointData->LastFrame = EHCI_Get32BitFrameNumber(DeviceData);
  889. break;
  890. case ENDPOINT_PAUSE:
  891. // clear the active bit on all TDs
  892. if (HIGHSPEED(EndpointData)) {
  893. for (i=0; i<EndpointData->TdCount; i++) {
  894. for(j=0; j<8; j++) {
  895. EndpointData->HsIsoTdList->Td[i].HwTD.Transaction[j].Active = 0;
  896. }
  897. }
  898. } else {
  899. for (i=0; i<EndpointData->TdCount; i++) {
  900. EndpointData->SiTdList->Td[i].HwTD.State.Active = 0;
  901. }
  902. }
  903. break;
  904. case ENDPOINT_REMOVE:
  905. if (HIGHSPEED(EndpointData)) {
  906. EHCI_RemoveHsIsoTdsFromSchedule(DeviceData,
  907. EndpointData);
  908. } else {
  909. EHCI_RemoveIsoTdsFromSchedule(DeviceData,
  910. EndpointData);
  911. }
  912. break;
  913. default:
  914. TEST_TRAP();
  915. }
  916. EndpointData->State = State;
  917. }
  918. /*
  919. High Speed Iso code
  920. We use a variation of the split Iso code here. We allocate 1024
  921. static TDs and insert them in the schedule. These TDs are then
  922. updated with the current transfers instead of inserted or removed.
  923. */
  924. VOID
  925. EHCI_Initialize_iTD(
  926. PDEVICE_DATA DeviceData,
  927. PENDPOINT_DATA EndpointData,
  928. PENDPOINT_PARAMETERS EndpointParameters,
  929. PHCD_HSISO_TRANSFER_DESCRIPTOR IsoTd,
  930. HW_32BIT_PHYSICAL_ADDRESS PhysicalAddress,
  931. ULONG Frame
  932. )
  933. /*++
  934. Routine Description:
  935. Initailze a static SiTD for an endpoint
  936. Arguments:
  937. Return Value:
  938. none
  939. --*/
  940. {
  941. ULONG i;
  942. IsoTd->Sig = SIG_HCD_ITD;
  943. IsoTd->PhysicalAddress = PhysicalAddress;
  944. ISO_PACKET_PTR(IsoTd->FirstPacket) = NULL;
  945. IsoTd->HostFrame = Frame;
  946. for (i=0; i< 8; i++) {
  947. IsoTd->HwTD.Transaction[i].ul = 0;
  948. }
  949. IsoTd->HwTD.BufferPointer0.DeviceAddress =
  950. EndpointParameters->DeviceAddress;
  951. IsoTd->HwTD.BufferPointer0.EndpointNumber =
  952. EndpointParameters->EndpointAddress;
  953. IsoTd->HwTD.BufferPointer1.MaxPacketSize =
  954. EndpointParameters->MuxPacketSize;
  955. // 1 = IN 0 = OUT
  956. IsoTd->HwTD.BufferPointer1.Direction =
  957. (EndpointParameters->TransferDirection == In) ? 1 : 0;
  958. IsoTd->HwTD.BufferPointer2.Multi =
  959. EndpointParameters->TransactionsPerMicroframe;
  960. }
  961. #define EHCI_OFFSET_MASK 0x00000FFF
  962. #define EHCI_PAGE_SHIFT 12
  963. VOID
  964. EHCI_MapHsIsoPacketsToTd(
  965. PDEVICE_DATA DeviceData,
  966. PENDPOINT_DATA EndpointData,
  967. PMINIPORT_ISO_PACKET FirstPacket,
  968. PHCD_HSISO_TRANSFER_DESCRIPTOR IsoTd,
  969. BOOLEAN InterruptOnComplete
  970. )
  971. /*++
  972. Routine Description:
  973. Arguments:
  974. Returns:
  975. --*/
  976. {
  977. PHC_ITD_BUFFER_POINTER currentBp;
  978. PMINIPORT_ISO_PACKET pkt = FirstPacket;
  979. ULONG page, offset, bpCount, i;
  980. ULONG frame = FirstPacket->FrameNumber;
  981. LOGENTRY(DeviceData, G, '_HHS', IsoTd, 0, FirstPacket);
  982. ASSERT_ITD(DeviceData, IsoTd);
  983. bpCount = 0;
  984. currentBp = (PHC_ITD_BUFFER_POINTER) &IsoTd->HwTD.BufferPointer0;
  985. // map the first packet
  986. page = (pkt->BufferPointer0.Hw32 >> EHCI_PAGE_SHIFT);
  987. currentBp->BufferPointer = page;
  988. // This Td will represent 8 packets
  989. for (i=0; i<8; i++) {
  990. EHCI_ASSERT(DeviceData, pkt->FrameNumber == frame);
  991. page = (pkt->BufferPointer0.Hw32 >> EHCI_PAGE_SHIFT);
  992. offset = pkt->BufferPointer0.Hw32 & EHCI_OFFSET_MASK;
  993. if (page != currentBp->BufferPointer) {
  994. currentBp++;
  995. bpCount++;
  996. currentBp->BufferPointer = page;
  997. }
  998. IsoTd->HwTD.Transaction[i].Offset = offset;
  999. IsoTd->HwTD.Transaction[i].Length = pkt->Length;
  1000. IsoTd->HwTD.Transaction[i].PageSelect = bpCount;
  1001. if (InterruptOnComplete && i==7) {
  1002. IsoTd->HwTD.Transaction[i].InterruptOnComplete = 1;
  1003. } else {
  1004. IsoTd->HwTD.Transaction[i].InterruptOnComplete = 0;
  1005. }
  1006. IsoTd->HwTD.Transaction[i].Active = 1;
  1007. if (pkt->BufferPointerCount > 1) {
  1008. page = (pkt->BufferPointer1.Hw32 >> EHCI_PAGE_SHIFT);
  1009. currentBp++;
  1010. bpCount++;
  1011. currentBp->BufferPointer = page;
  1012. EHCI_ASSERT(DeviceData, bpCount <= 6)
  1013. }
  1014. pkt++;
  1015. }
  1016. LOGENTRY(DeviceData, G, '_mhs', IsoTd, 0, bpCount);
  1017. }
  1018. VOID
  1019. EHCI_CompleteHsIsoPackets(
  1020. PDEVICE_DATA DeviceData,
  1021. PMINIPORT_ISO_PACKET FirstPacket,
  1022. PHCD_HSISO_TRANSFER_DESCRIPTOR IsoTd
  1023. )
  1024. /*++
  1025. Routine Description:
  1026. Complete the eight high speed packets associated with this
  1027. TD
  1028. Arguments:
  1029. Returns:
  1030. --*/
  1031. {
  1032. ULONG length, i;
  1033. ULONG cf = EHCI_Get32BitFrameNumber(DeviceData);
  1034. PMINIPORT_ISO_PACKET pkt = FirstPacket;
  1035. LOGENTRY(DeviceData, G, '_cpI', pkt, IsoTd, cf);
  1036. for (i=0; i<8; i++) {
  1037. if (IsoTd->HwTD.Transaction[i].Active == 1) {
  1038. // missed
  1039. pkt->LengthTransferred = 0;
  1040. LOGENTRY(DeviceData, G, '_cms',
  1041. pkt,
  1042. i,
  1043. pkt->FrameNumber);
  1044. pkt->UsbdStatus = USBD_STATUS_ISO_NOT_ACCESSED_BY_HW;
  1045. } else {
  1046. // if this is an out assume all data transferred
  1047. if (IsoTd->HwTD.BufferPointer1.Direction == 0) {
  1048. // out
  1049. length = pkt->Length;
  1050. LOGENTRY(DeviceData, G, '_cp3',
  1051. pkt->FrameNumber,
  1052. pkt->Length ,
  1053. pkt);
  1054. } else {
  1055. // in
  1056. length = IsoTd->HwTD.Transaction[i].Length;
  1057. LOGENTRY(DeviceData, G, '_cp4',
  1058. pkt->FrameNumber,
  1059. pkt->Length ,
  1060. pkt);
  1061. }
  1062. pkt->LengthTransferred = length;
  1063. // check the errubit
  1064. if (IsoTd->HwTD.Transaction[i].XactError) {
  1065. pkt->UsbdStatus = USBD_STATUS_XACT_ERROR;
  1066. //TEST_TRAP();
  1067. } else if (IsoTd->HwTD.Transaction[i].BabbleDetect) {
  1068. pkt->UsbdStatus = USBD_STATUS_BABBLE_DETECTED;
  1069. } else if (IsoTd->HwTD.Transaction[i].DataBufferError) {
  1070. pkt->UsbdStatus = USBD_STATUS_DATA_BUFFER_ERROR;
  1071. } else {
  1072. pkt->UsbdStatus = USBD_STATUS_SUCCESS;
  1073. }
  1074. LOGENTRY(DeviceData, G, '_cpL', pkt, IsoTd, length);
  1075. pkt++;
  1076. }
  1077. }
  1078. }
  1079. USB_MINIPORT_STATUS
  1080. EHCI_OpenHsIsochronousEndpoint(
  1081. PDEVICE_DATA DeviceData,
  1082. PENDPOINT_PARAMETERS EndpointParameters,
  1083. PENDPOINT_DATA EndpointData
  1084. )
  1085. /*++
  1086. Routine Description:
  1087. Arguments:
  1088. Return Value:
  1089. --*/
  1090. {
  1091. PUCHAR buffer;
  1092. HW_32BIT_PHYSICAL_ADDRESS phys;
  1093. ULONG i;
  1094. ULONG bytes;
  1095. PHW_32BIT_PHYSICAL_ADDRESS frameBase;
  1096. PENDPOINT_DATA prevEndpoint, nextEndpoint;
  1097. LOGENTRY(DeviceData, G, '_opS', 0, 0, EndpointParameters);
  1098. buffer = EndpointParameters->CommonBufferVa;
  1099. phys = EndpointParameters->CommonBufferPhys;
  1100. // how much did we get
  1101. bytes = EndpointParameters->CommonBufferBytes;
  1102. EndpointData->HsIsoTdList = (PHCD_HSISOTD_LIST) buffer;
  1103. // bugbug use manifest
  1104. EndpointData->TdCount = USBEHCI_MAX_FRAME;
  1105. EndpointData->LastFrame = 0;
  1106. for (i=0; i<EndpointData->TdCount; i++) {
  1107. EHCI_Initialize_iTD(DeviceData,
  1108. EndpointData,
  1109. EndpointParameters,
  1110. &EndpointData->HsIsoTdList->Td[i],
  1111. phys,
  1112. i);
  1113. phys += sizeof(HCD_HSISO_TRANSFER_DESCRIPTOR);
  1114. }
  1115. //
  1116. if (DeviceData->IsoEndpointListHead == NULL) {
  1117. // empty list, no iso endpoints
  1118. prevEndpoint = NULL;
  1119. nextEndpoint = NULL;
  1120. } else {
  1121. // currently we insert HS endpoints in front of split
  1122. // iso endpoints, so for high speed we just stick them
  1123. // on the head of the list
  1124. prevEndpoint = NULL;
  1125. nextEndpoint = DeviceData->IsoEndpointListHead;
  1126. }
  1127. // insert this column of TDs thru the schedule
  1128. EHCI_InsertHsIsoTdsInSchedule(DeviceData,
  1129. EndpointData,
  1130. prevEndpoint,
  1131. nextEndpoint);
  1132. // init endpoint structures
  1133. InitializeListHead(&EndpointData->TransferList);
  1134. EHCI_EnablePeriodicList(DeviceData);
  1135. return USBMP_STATUS_SUCCESS;
  1136. }
  1137. VOID
  1138. EHCI_RemoveHsIsoTdsFromSchedule(
  1139. PDEVICE_DATA DeviceData,
  1140. PENDPOINT_DATA EndpointData
  1141. )
  1142. /*++
  1143. Routine Description:
  1144. unlink the iso TDs from the schedule
  1145. Arguments:
  1146. --*/
  1147. {
  1148. //PHW_32BIT_PHYSICAL_ADDRESS frameBase;
  1149. ULONG i;
  1150. PENDPOINT_DATA prevEndpoint, nextEndpoint;
  1151. PHCD_QUEUEHEAD_DESCRIPTOR dQh;
  1152. prevEndpoint = EndpointData->PrevEndpoint;
  1153. nextEndpoint = EndpointData->NextEndpoint;
  1154. LOGENTRY(DeviceData, G, '_iRM', prevEndpoint,
  1155. nextEndpoint, EndpointData);
  1156. if (DeviceData->IsoEndpointListHead == EndpointData) {
  1157. // this is the head
  1158. //frameBase = DeviceData->FrameListBaseAddress;
  1159. for (i=0; i<USBEHCI_MAX_FRAME; i++) {
  1160. PHCD_HSISO_TRANSFER_DESCRIPTOR iTd;
  1161. ULONG phys;
  1162. iTd = &EndpointData->HsIsoTdList->Td[i];
  1163. phys = iTd->HwTD.NextLink.HwAddress;
  1164. dQh = EHCI_GetDummyQueueHeadForFrame(DeviceData, i);
  1165. dQh->HwQH.HLink.HwAddress = phys;
  1166. dQh->NextLink = iTd->NextLink;
  1167. //*frameBase = phys;
  1168. //frameBase++;
  1169. }
  1170. DeviceData->IsoEndpointListHead =
  1171. EndpointData->NextEndpoint;
  1172. if (nextEndpoint != NULL) {
  1173. EHCI_ASSERT(DeviceData,
  1174. nextEndpoint->PrevEndpoint == EndpointData);
  1175. nextEndpoint->PrevEndpoint = NULL;
  1176. }
  1177. } else {
  1178. // middle
  1179. TEST_TRAP();
  1180. EHCI_ASSERT(DeviceData, HIGHSPEED(prevEndpoint));
  1181. // link prev to next, prev will always be a HS ep
  1182. prevEndpoint->NextEndpoint = nextEndpoint;
  1183. if (nextEndpoint != NULL) {
  1184. nextEndpoint->PrevEndpoint = prevEndpoint;
  1185. }
  1186. for (i=0; i<USBEHCI_MAX_FRAME; i++) {
  1187. PHCD_HSISO_TRANSFER_DESCRIPTOR iTd, previTd;
  1188. ULONG phys;
  1189. iTd = &EndpointData->HsIsoTdList->Td[i];
  1190. previTd = &prevEndpoint->HsIsoTdList->Td[i];
  1191. phys = iTd->HwTD.NextLink.HwAddress;
  1192. previTd->HwTD.NextLink.HwAddress = phys;
  1193. }
  1194. }
  1195. }
  1196. VOID
  1197. EHCI_InsertHsIsoTdsInSchedule(
  1198. PDEVICE_DATA DeviceData,
  1199. PENDPOINT_DATA EndpointData,
  1200. PENDPOINT_DATA PrevEndpointData,
  1201. PENDPOINT_DATA NextEndpointData
  1202. )
  1203. /*++
  1204. Routine Description:
  1205. Insert an aync endpoint (queue head)
  1206. into the HW list
  1207. Arguments:
  1208. --*/
  1209. {
  1210. //PHW_32BIT_PHYSICAL_ADDRESS frameBase;
  1211. ULONG i;
  1212. LOGENTRY(DeviceData, G, '_iAH', PrevEndpointData,
  1213. NextEndpointData, EndpointData);
  1214. // always insert to head
  1215. EHCI_ASSERT(DeviceData, PrevEndpointData == NULL);
  1216. DeviceData->IsoEndpointListHead = EndpointData;
  1217. EndpointData->PrevEndpoint = NULL;
  1218. EndpointData->NextEndpoint =
  1219. NextEndpointData;
  1220. if (NextEndpointData != NULL) {
  1221. NextEndpointData->PrevEndpoint = EndpointData;
  1222. }
  1223. //frameBase = DeviceData->FrameListBaseAddress;
  1224. for (i=0; i<USBEHCI_MAX_FRAME; i++) {
  1225. PHCD_HSISO_TRANSFER_DESCRIPTOR iTd, nextiTd, previTd;
  1226. HW_32BIT_PHYSICAL_ADDRESS qh;
  1227. PHCD_QUEUEHEAD_DESCRIPTOR dQh;
  1228. ULONG phys;
  1229. iTd = &EndpointData->HsIsoTdList->Td[i];
  1230. ASSERT_ITD(DeviceData, iTd);
  1231. dQh = EHCI_GetDummyQueueHeadForFrame(DeviceData, i);
  1232. // fixup next link
  1233. if (NextEndpointData == NULL) {
  1234. // no iso endpoints, link to the interrupt
  1235. // queue heads via the dummy queue head
  1236. // qh = *frameBase;
  1237. qh = dQh->HwQH.HLink.HwAddress;
  1238. iTd->HwTD.NextLink.HwAddress = qh;
  1239. iTd->NextLink = dQh->NextLink;
  1240. } else {
  1241. // link to the next iso endpoint
  1242. if (HIGHSPEED(NextEndpointData)) {
  1243. PHCD_HSISO_TRANSFER_DESCRIPTOR tmp;
  1244. tmp = &NextEndpointData->HsIsoTdList->Td[i];
  1245. iTd->HwTD.NextLink.HwAddress =
  1246. tmp->PhysicalAddress;
  1247. HW_PTR(iTd->NextLink) = (PUCHAR) tmp;
  1248. } else {
  1249. PHCD_SI_TRANSFER_DESCRIPTOR tmp;
  1250. ULONG phys;
  1251. tmp = &NextEndpointData->SiTdList->Td[i%ISO_SCHEDULE_SIZE];
  1252. phys = tmp->PhysicalAddress;
  1253. SET_SITD(phys);
  1254. iTd->HwTD.NextLink.HwAddress = phys;
  1255. HW_PTR(iTd->NextLink) = (PUCHAR) tmp;
  1256. }
  1257. }
  1258. // fixup prev link
  1259. // since we always insert Hs iso on the head of the list
  1260. // prev endpoint should always be NULL
  1261. EHCI_ASSERT(DeviceData, PrevEndpointData == NULL);
  1262. phys = iTd->PhysicalAddress;
  1263. // link dummy QH to this TD
  1264. dQh->HwQH.HLink.HwAddress = phys;
  1265. HW_PTR(dQh->NextLink) = (PUCHAR) iTd;
  1266. //*frameBase = phys;
  1267. //frameBase++;
  1268. }
  1269. }
  1270. #define HSISO_SCHEDULE_MASK 0x3ff
  1271. VOID
  1272. EHCI_InternalPollHsIsoEndpoint(
  1273. PDEVICE_DATA DeviceData,
  1274. PENDPOINT_DATA EndpointData,
  1275. BOOLEAN Complete
  1276. )
  1277. /*++
  1278. Routine Description:
  1279. Called when the endpoint 'needs attention'
  1280. static iso TD table
  1281. --------------------
  1282. 0 < -- (lastFrame & 0x3ff)
  1283. 1 {completed}
  1284. 2 {completed}
  1285. 3 {completed}
  1286. 4 < -- (currentframe & 0x3ff)
  1287. ...
  1288. 1023
  1289. ---------------------
  1290. Arguments:
  1291. Return Value:
  1292. --*/
  1293. {
  1294. ULONG x, i;
  1295. ULONG currentFrame, lastFrame;
  1296. PHCD_HSISO_TRANSFER_DESCRIPTOR iTd;
  1297. PHCD_HSISO_TRANSFER_DESCRIPTOR lastiTd;
  1298. PMINIPORT_ISO_PACKET packet;
  1299. PLIST_ENTRY listEntry;
  1300. PTRANSFER_CONTEXT transfer;
  1301. currentFrame = EHCI_Get32BitFrameNumber(DeviceData);
  1302. lastFrame = EndpointData->LastFrame;
  1303. LOGENTRY(DeviceData, G, '_pis', lastFrame, currentFrame,
  1304. EndpointData);
  1305. if (currentFrame - lastFrame > USBEHCI_MAX_FRAME) {
  1306. // overrun
  1307. lastFrame = currentFrame-1;
  1308. LOGENTRY(DeviceData, G, '_ov1', lastFrame, currentFrame, 0);
  1309. // dump the current contents
  1310. for (i=0; i <USBEHCI_MAX_FRAME; i++) {
  1311. iTd = &EndpointData->HsIsoTdList->Td[i];
  1312. transfer = ISO_TRANSFER_PTR(iTd->Transfer);
  1313. if (transfer != NULL) {
  1314. ISO_PACKET_PTR(iTd->FirstPacket) = NULL;
  1315. ISO_TRANSFER_PTR(iTd->Transfer) = NULL;
  1316. transfer->PendingPackets-=8;
  1317. }
  1318. }
  1319. }
  1320. if (lastFrame == currentFrame) {
  1321. // too early to do anything
  1322. LOGENTRY(DeviceData, G, '_ear', lastFrame, currentFrame, 0);
  1323. return;
  1324. }
  1325. // TDs between lastframe and currentframe are complete,
  1326. // complete the packets associated with them
  1327. // f0
  1328. // f1
  1329. // f2 < ------- last frame }
  1330. // f3 } these are complete
  1331. // f4 }
  1332. // f5 < ------- current frame
  1333. // f6
  1334. // f7
  1335. // f8
  1336. x = (lastFrame & (HSISO_SCHEDULE_MASK));
  1337. lastiTd = NULL;
  1338. LOGENTRY(DeviceData, G, '_frh', lastFrame, x, currentFrame);
  1339. while (x != ((currentFrame-1) & HSISO_SCHEDULE_MASK)) {
  1340. iTd = &EndpointData->HsIsoTdList->Td[x];
  1341. ASSERT_ITD(DeviceData, iTd);
  1342. // complete this packet
  1343. packet = ISO_PACKET_PTR(iTd->FirstPacket);
  1344. transfer = ISO_TRANSFER_PTR(iTd->Transfer);
  1345. LOGENTRY(DeviceData, G, '_gpk', transfer, packet, x);
  1346. if (packet != NULL) {
  1347. transfer = ISO_TRANSFER_PTR(iTd->Transfer);
  1348. ASSERT_TRANSFER(DeviceData, transfer);
  1349. EHCI_CompleteHsIsoPackets(DeviceData, packet, iTd);
  1350. ISO_PACKET_PTR(iTd->FirstPacket) = NULL;
  1351. ISO_TRANSFER_PTR(iTd->Transfer) = NULL;
  1352. transfer->PendingPackets-=8;
  1353. }
  1354. lastFrame++;
  1355. x++;
  1356. x &= HSISO_SCHEDULE_MASK;
  1357. }
  1358. // attempt to program what we can, if iTD is NULL
  1359. // then we can program this frame
  1360. // NOTE: No scheduling if paused!
  1361. if (EndpointData->State != ENDPOINT_PAUSE) {
  1362. LOGENTRY(DeviceData, G, '_psh', 0, 0, 0);
  1363. for (i=0; i <USBEHCI_MAX_FRAME; i++) {
  1364. x = ((currentFrame+i) & HSISO_SCHEDULE_MASK);
  1365. iTd = &EndpointData->HsIsoTdList->Td[x];
  1366. ASSERT_ITD(DeviceData, iTd);
  1367. LOGENTRY(DeviceData, G, '_gpf', iTd, x, currentFrame+i);
  1368. // open slot?
  1369. if (ISO_PACKET_PTR(iTd->FirstPacket) != NULL) {
  1370. // no, bail
  1371. continue;
  1372. }
  1373. // yes, see if we have a packet
  1374. // this will fetch the first packet to transmit this frame
  1375. packet = EHCI_GetPacketForFrame(DeviceData,
  1376. EndpointData,
  1377. &transfer,
  1378. currentFrame+i);
  1379. if (packet != NULL) {
  1380. BOOLEAN ioc = FALSE;
  1381. ULONG sf, ef;
  1382. EHCI_ASSERT(DeviceData, ISO_PACKET_PTR(iTd->FirstPacket) == NULL);
  1383. if ((currentFrame+i) == transfer->FrameComplete) {
  1384. ioc = TRUE;
  1385. }
  1386. sf = transfer->FrameComplete -
  1387. transfer->IsoTransfer->PacketCount +5;
  1388. ef = transfer->FrameComplete -5;
  1389. // generate some interrupts on the first few frames of the
  1390. // transfer to help flush out any previous transfers
  1391. if (currentFrame+i <= sf ||
  1392. currentFrame+i >= ef) {
  1393. ioc = TRUE;
  1394. }
  1395. //interrupt every frame
  1396. //ioc = TRUE;
  1397. //if ((currentFrame % 2) == 0) {
  1398. // ioc = TRUE;
  1399. //}
  1400. // map 8 microframes
  1401. EHCI_MapHsIsoPacketsToTd(DeviceData, EndpointData,
  1402. packet, iTd, ioc);
  1403. lastiTd = iTd;
  1404. ISO_PACKET_PTR(iTd->FirstPacket) = packet;
  1405. ASSERT_TRANSFER(DeviceData, transfer);
  1406. ISO_TRANSFER_PTR(iTd->Transfer) = transfer;
  1407. transfer->PendingPackets+=8;
  1408. } else {
  1409. ULONG j;
  1410. // re-init itd
  1411. for (j=0; j<8; j++) {
  1412. iTd->HwTD.Transaction[j].InterruptOnComplete = 0;
  1413. }
  1414. }
  1415. }
  1416. // take a interrupt on the last TD programmed
  1417. if (lastiTd != NULL) {
  1418. lastiTd->HwTD.Transaction[7].InterruptOnComplete = 1;
  1419. }
  1420. }
  1421. EHCI_ASSERT(DeviceData, lastFrame < currentFrame);
  1422. EndpointData->LastFrame = lastFrame;
  1423. // walk our list of active iso transfers and see
  1424. // if any are complete
  1425. //restart:
  1426. listEntry = EndpointData->TransferList.Flink;
  1427. while (listEntry != &EndpointData->TransferList && Complete) {
  1428. PTRANSFER_CONTEXT transfer;
  1429. transfer = (PTRANSFER_CONTEXT) CONTAINING_RECORD(
  1430. listEntry,
  1431. struct _TRANSFER_CONTEXT,
  1432. TransferLink);
  1433. LOGENTRY(DeviceData, G, '_ckt', transfer, transfer->FrameComplete+2
  1434. , currentFrame);
  1435. EHCI_ASSERT(DeviceData, transfer->Sig == SIG_EHCI_TRANSFER);
  1436. if (currentFrame >= transfer->FrameComplete &&
  1437. transfer->PendingPackets == 0) {
  1438. listEntry = transfer->TransferLink.Flink;
  1439. RemoveEntryList(&transfer->TransferLink);
  1440. LOGENTRY(DeviceData, G, '_cpi', transfer, 0, 0);
  1441. USBPORT_COMPLETE_ISO_TRANSFER(DeviceData,
  1442. EndpointData,
  1443. transfer->TransferParameters,
  1444. transfer->IsoTransfer);
  1445. } else {
  1446. listEntry = transfer->TransferLink.Flink;
  1447. }
  1448. }
  1449. }
  1450. USB_MINIPORT_STATUS
  1451. EHCI_PokeIsoEndpoint(
  1452. PDEVICE_DATA DeviceData,
  1453. PENDPOINT_PARAMETERS EndpointParameters,
  1454. PENDPOINT_DATA EndpointData
  1455. )
  1456. /*++
  1457. Routine Description:
  1458. Arguments:
  1459. Return Value:
  1460. --*/
  1461. {
  1462. ULONG i;
  1463. if (HIGHSPEED(EndpointData)) {
  1464. TEST_TRAP();
  1465. } else {
  1466. PHCD_SI_TRANSFER_DESCRIPTOR siTd;
  1467. for (i=0; i<EndpointData->TdCount; i++) {
  1468. siTd = &EndpointData->SiTdList->Td[i];
  1469. ASSERT_SITD(DeviceData, siTd);
  1470. siTd->HwTD.Caps.DeviceAddress =
  1471. EndpointParameters->DeviceAddress;
  1472. siTd->HwTD.Caps.HubAddress =
  1473. EndpointParameters->TtDeviceAddress;
  1474. }
  1475. }
  1476. return USBMP_STATUS_SUCCESS;
  1477. }
  1478. PHCD_QUEUEHEAD_DESCRIPTOR
  1479. EHCI_GetDummyQueueHeadForFrame(
  1480. PDEVICE_DATA DeviceData,
  1481. ULONG Frame
  1482. )
  1483. /*++
  1484. Routine Description:
  1485. Arguments:
  1486. Return Value:
  1487. queue head
  1488. --*/
  1489. {
  1490. PUCHAR base;
  1491. base = DeviceData->DummyQueueHeads;
  1492. return (PHCD_QUEUEHEAD_DESCRIPTOR)
  1493. (base + sizeof(HCD_QUEUEHEAD_DESCRIPTOR) * Frame);
  1494. }
  1495. VOID
  1496. EHCI_AddDummyQueueHeads(
  1497. PDEVICE_DATA DeviceData
  1498. )
  1499. /*++
  1500. Routine Description:
  1501. NEC errata:
  1502. Insert a table of 1024 dummy queue heads in the schedule for
  1503. HW to access and point them at the interrupt queue heads.
  1504. These queue heads must be before any iso TDs
  1505. This is a workaround for a law ine the NEC B0' stepping version
  1506. of the controller. We must put 'dummy' QH at the front of the
  1507. peridoic list such that the first thing fetched is always a QH
  1508. even when ISO TDs are in the schedule.
  1509. Arguments:
  1510. Return Value:
  1511. --*/
  1512. {
  1513. PHCD_QUEUEHEAD_DESCRIPTOR dQh, stqh;
  1514. HW_32BIT_PHYSICAL_ADDRESS qhPhys;
  1515. PHW_32BIT_PHYSICAL_ADDRESS frameBase;
  1516. ULONG i;
  1517. HW_32BIT_PHYSICAL_ADDRESS phys;
  1518. frameBase = DeviceData->FrameListBaseAddress;
  1519. phys = DeviceData->DummyQueueHeadsPhys;
  1520. for (i=0; i<USBEHCI_MAX_FRAME; i++) {
  1521. // no iso endpoints should be in the schedule yet
  1522. qhPhys = *frameBase;
  1523. dQh = EHCI_GetDummyQueueHeadForFrame(DeviceData, i);
  1524. // init the dummy queue head
  1525. RtlZeroMemory(dQh, sizeof(*dQh));
  1526. dQh->PhysicalAddress = phys;
  1527. dQh->Sig = SIG_DUMMY_QH;
  1528. dQh->HwQH.EpChars.DeviceAddress = 128;
  1529. dQh->HwQH.EpChars.EndpointNumber = 0;
  1530. dQh->HwQH.EpChars.EndpointSpeed = HcEPCHAR_FullSpeed;
  1531. dQh->HwQH.EpChars.MaximumPacketLength = 64;
  1532. dQh->HwQH.EpCaps.InterruptScheduleMask = 0;
  1533. dQh->HwQH.EpCaps.SplitCompletionMask = 0;
  1534. dQh->HwQH.EpCaps.HubAddress = 0;
  1535. dQh->HwQH.EpCaps.PortNumber = 0;
  1536. dQh->HwQH.EpCaps.HighBWPipeMultiplier = 0;
  1537. dQh->HwQH.CurrentTD.HwAddress = 0;
  1538. dQh->HwQH.Overlay.qTD.AltNext_qTD.HwAddress = EHCI_TERMINATE_BIT;
  1539. dQh->HwQH.Overlay.qTD.Next_qTD.HwAddress = EHCI_TERMINATE_BIT;
  1540. dQh->HwQH.Overlay.qTD.Token.Active = 0;
  1541. phys += sizeof(HCD_QUEUEHEAD_DESCRIPTOR);
  1542. // link dummy to first interrupt queue head
  1543. dQh->HwQH.HLink.HwAddress = qhPhys;
  1544. stqh = EHCI_GetQueueHeadForFrame(DeviceData, i);
  1545. EHCI_ASSERT(DeviceData, (qhPhys & ~EHCI_DTYPE_Mask) ==
  1546. stqh->PhysicalAddress);
  1547. HW_PTR(dQh->NextLink) = (PUCHAR)stqh;
  1548. // add dummy queue head to frame list
  1549. qhPhys = dQh->PhysicalAddress;
  1550. SET_QH(qhPhys);
  1551. *frameBase = qhPhys;
  1552. frameBase++;
  1553. }
  1554. }