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.

264 lines
6.6 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. errata.c
  5. Abstract:
  6. documented errata for all of our favorite types of
  7. openhci USB controllers.
  8. Environment:
  9. Kernel mode
  10. Revision History:
  11. 12-31-99 : created jdunn
  12. --*/
  13. #include "common.h"
  14. /*
  15. Hydra Errata
  16. The folllowing code is specific for the COMPAQ Hydra OHCI hardware
  17. design -- it should not be executed on other controllers
  18. */
  19. // Hydra HighSpeed/LowSpeed Data Corruption Bug
  20. ULONG
  21. InitializeHydraHsLsFix(
  22. PDEVICE_DATA DeviceData,
  23. PUCHAR CommonBuffer,
  24. HW_32BIT_PHYSICAL_ADDRESS CommonBufferPhys
  25. )
  26. /*++
  27. Routine Description:
  28. Data corruption can occur on the Hydra part when iso and bulk
  29. transfers follow lowspeed interrupt transfers.
  30. The classic repro of this bug is playing 'dance of the surgar
  31. plum fairys' on USB speakers while moving the USB mouse. This
  32. generates low speed interrupt INs and High speed ISO OUTs.
  33. The 'fix' is to introduce a 'specific delay before the HS Iso
  34. transfers and after the LS interrupt transfers.
  35. <Interrupt Schedule>
  36. staticEd(period)
  37. (4) -\
  38. (2)-\
  39. (4) -/ \
  40. (1 )-><DELAY>->(Iso)->(Control and Bulk)
  41. (4) -\ /
  42. (2)-/
  43. (4) -/
  44. The <DELAY> is a predifined set of dummy EDs and TDs.
  45. Arguments:
  46. Return Value:
  47. returns the ammount of common buffer used for the 'hack'
  48. --*/
  49. {
  50. PHCD_ENDPOINT_DESCRIPTOR ed, tailEd;
  51. PHCD_TRANSFER_DESCRIPTOR td;
  52. PHC_STATIC_ED_DATA static1msEd;
  53. ULONG i;
  54. ULONG bufferUsed = 0;
  55. static1msEd = &DeviceData->StaticEDList[ED_INTERRUPT_1ms];
  56. /*
  57. To achieve the proper timming we must insert 17 dumy EDs
  58. each dummy ED must look like this:
  59. ED->TD->XXX
  60. XXX is bogus address = 0xABADBABE
  61. (HeadP points to TD)
  62. (TailP points to XXX)
  63. TD has CBP=0 and BE=0
  64. NextTD points to XXX
  65. The TD will never be retired by the hardware
  66. so we end up with:
  67. staticEd(1ms)->dED(1)->dED(2)....dED(17)->(1ms transferEds)
  68. NOTE: Since the problem only occurs with low speed, and
  69. low speed may not have a period < 8ms we don't need to
  70. worry about 1ms interrupt transfers.
  71. */
  72. //
  73. // add 17 dummy ED TD pairs
  74. //
  75. for (i=0; i< 17; i++) {
  76. ed = (PHCD_ENDPOINT_DESCRIPTOR) CommonBuffer;
  77. RtlZeroMemory(ed, sizeof(*ed));
  78. ed->PhysicalAddress = CommonBufferPhys;
  79. CommonBuffer += sizeof(HCD_TRANSFER_DESCRIPTOR);
  80. CommonBufferPhys += sizeof(HCD_TRANSFER_DESCRIPTOR);
  81. bufferUsed += sizeof(HCD_ENDPOINT_DESCRIPTOR);
  82. td = (PHCD_TRANSFER_DESCRIPTOR) CommonBuffer;
  83. RtlZeroMemory(td, sizeof(*td));
  84. td->PhysicalAddress = CommonBufferPhys;
  85. CommonBuffer += sizeof(HCD_ENDPOINT_DESCRIPTOR);
  86. CommonBufferPhys += sizeof(HCD_ENDPOINT_DESCRIPTOR);
  87. bufferUsed += sizeof(HCD_ENDPOINT_DESCRIPTOR);
  88. LOGENTRY(DeviceData, G, 'hyF', 0, ed, td);
  89. // initialize the ed and td
  90. ed->Sig = SIG_HCD_DUMMY_ED;
  91. ed->EdFlags = 0;
  92. // inint dummy HW ED
  93. ed->HwED.sKip = 1;
  94. ed->HwED.HeadP = td->PhysicalAddress;
  95. ed->HwED.TailP = 0xABADBABE;
  96. td->Sig = SIG_HCD_TD;
  97. td->Flags = 0;
  98. td->HwTD.NextTD = 0xABADBABE;
  99. // insert in the schedule on the 1ms list
  100. if (IsListEmpty(&static1msEd->TransferEdList)) {
  101. //
  102. // list is currently empty,
  103. // link it to the head of the hw queue
  104. //
  105. DeviceData->HydraLsHsHackEd = ed;
  106. InsertHeadList(&static1msEd->TransferEdList,
  107. &ed->SwLink.List);
  108. // PhysicaHead is the address of the
  109. // NextED entry in the static HwED for the list list,
  110. // (ie &HwED->nextEd == physicalHead)
  111. // so we end up with
  112. // StaticEd->TransferHwED->TransferHwED->NextStaticED
  113. //
  114. LOGENTRY(DeviceData, G, '_INh',
  115. static1msEd->PhysicalHead,
  116. ed,
  117. static1msEd);
  118. // tail points to old list head HW ed head
  119. ed->HwED.NextED = *static1msEd->PhysicalHead;
  120. // new head is this ed
  121. *static1msEd->PhysicalHead = ed->PhysicalAddress;
  122. } else {
  123. //
  124. // Something already on the list,
  125. // Link ED into tail of transferEd list
  126. //
  127. tailEd = CONTAINING_RECORD(static1msEd->TransferEdList.Blink,
  128. HCD_ENDPOINT_DESCRIPTOR,
  129. SwLink);
  130. LOGENTRY(DeviceData, G, '_Led', 0, tailEd, static1msEd);
  131. InsertTailList(&static1msEd->TransferEdList, &ed->SwLink.List);
  132. ed->HwED.NextED = 0;
  133. tailEd->HwED.NextED = ed->PhysicalAddress;
  134. }
  135. }
  136. return bufferUsed;
  137. }
  138. /*
  139. NEC Errata
  140. */
  141. /*
  142. AMD Errata
  143. */
  144. ULONG
  145. OHCI_ReadRhDescriptorA(
  146. PDEVICE_DATA DeviceData
  147. )
  148. /*++
  149. Routine Description:
  150. Read the number of downstream ports and other root hub characteristics
  151. from the HcRhDescriptorA register.
  152. If this register reads as all zero or any of the reserved bits are set
  153. then try reading the register again. This is a workaround for some
  154. early revs of the AMD K7 chipset, which can sometimes return bogus values
  155. if the root hub registers are read while the host controller is
  156. performing PCI bus master ED & TD reads.
  157. Attempt up to ten reads if a reserved bit is set. If a reserved bit is
  158. set on or register is zero on purpose we will still return the
  159. register after doing penece of ten reads thanks to AMD.
  160. Arguments:
  161. Return Value:
  162. descrA register (hopefully)
  163. --*/
  164. {
  165. HC_RH_DESCRIPTOR_A descrA;
  166. PHC_OPERATIONAL_REGISTER hc;
  167. ULONG i;
  168. hc = DeviceData->HC;
  169. for (i = 0; i < 10; i++) {
  170. descrA.ul = READ_REGISTER_ULONG(&hc->HcRhDescriptorA.ul);
  171. if ((descrA.ul) && (!(descrA.ul & HcDescA_RESERVED))) {
  172. break;
  173. } else {
  174. KeStallExecutionProcessor(5);
  175. }
  176. }
  177. return descrA.ul;
  178. }