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.

1575 lines
38 KiB

  1. /*++
  2. Copyright (c) 1999, 2000 Microsoft Corporation
  3. Module Name:
  4. hydramp.c
  5. Abstract:
  6. USB 2.0 EHCI driver
  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. 2-19-99 : created, jdunn
  17. --*/
  18. #include "common.h"
  19. #include <initguid.h>
  20. #include "usbpriv.h"
  21. //implements the following miniport functions:
  22. //EHCI_StartController
  23. //EHCI_StopController
  24. //EHCI_DisableInterrupts
  25. //EHCI_EnableInterrupts
  26. USB_MINIPORT_STATUS
  27. EHCI_InitializeHardware(
  28. PDEVICE_DATA DeviceData
  29. )
  30. /*++
  31. Routine Description:
  32. Initializes the hardware registers for the host controller.
  33. Arguments:
  34. Return Value:
  35. --*/
  36. {
  37. PHC_OPERATIONAL_REGISTER hcOp;
  38. PHC_CAPABILITIES_REGISTER hcCap;
  39. USBCMD cmd;
  40. HCSPARAMS hcSparms;
  41. LARGE_INTEGER finishTime, currentTime;
  42. hcCap = DeviceData->CapabilitiesRegisters;
  43. hcOp = DeviceData->OperationalRegisters;
  44. // reset the controller
  45. cmd.ul = READ_REGISTER_ULONG(&hcOp->UsbCommand.ul);
  46. LOGENTRY(DeviceData, G, '_res', cmd.ul, 0, 0);
  47. cmd.HostControllerReset = 1;
  48. WRITE_REGISTER_ULONG(&hcOp->UsbCommand.ul, cmd.ul);
  49. KeQuerySystemTime(&finishTime);
  50. // no spec'ed time -- we will graciously grant 0.1 sec.
  51. //
  52. // figure when we quit (.1 seconds later)
  53. finishTime.QuadPart += 1000000;
  54. // wait for reset bit to got to zero
  55. cmd.ul = READ_REGISTER_ULONG(&hcOp->UsbCommand.ul);
  56. while (cmd.HostControllerReset) {
  57. KeQuerySystemTime(&currentTime);
  58. if (currentTime.QuadPart >= finishTime.QuadPart) {
  59. EHCI_KdPrint((DeviceData, 0,
  60. "'EHCI controller failed to reset in .1 sec!\n"));
  61. return USBMP_STATUS_HARDWARE_FAILURE;
  62. }
  63. cmd.ul = READ_REGISTER_ULONG(&hcOp->UsbCommand.ul);
  64. }
  65. hcSparms.ul =
  66. READ_REGISTER_ULONG(&hcCap->HcStructuralParameters.ul);
  67. DeviceData->NumberOfPorts =
  68. (USHORT) hcSparms.NumberOfPorts;
  69. DeviceData->PortPowerControl =
  70. (USHORT) hcSparms.PortPowerControl;
  71. // inialize operational registers
  72. WRITE_REGISTER_ULONG(&hcOp->AsyncListAddr, 0);
  73. WRITE_REGISTER_ULONG(&hcOp->PeriodicListBase, 0);
  74. // set the enabled interrupts cache, we'll enable
  75. // these interrupts when asked
  76. DeviceData->EnabledInterrupts.UsbInterrupt = 1;
  77. DeviceData->EnabledInterrupts.UsbError = 1;
  78. DeviceData->EnabledInterrupts.FrameListRollover = 1;
  79. DeviceData->EnabledInterrupts.HostSystemError = 1;
  80. DeviceData->EnabledInterrupts.IntOnAsyncAdvance = 1;
  81. return USBMP_STATUS_SUCCESS;
  82. }
  83. USB_MINIPORT_STATUS
  84. EHCI_InitializeSchedule(
  85. PDEVICE_DATA DeviceData,
  86. PUCHAR StaticQHs,
  87. HW_32BIT_PHYSICAL_ADDRESS StaticQHsPhys
  88. )
  89. /*++
  90. Routine Description:
  91. Build the schedule of static Eds
  92. Arguments:
  93. Return Value:
  94. --*/
  95. {
  96. USB_MINIPORT_STATUS mpStatus;
  97. ULONG length;
  98. ULONG i;
  99. PHC_OPERATIONAL_REGISTER hcOp;
  100. PHCD_QUEUEHEAD_DESCRIPTOR qh;
  101. HW_LINK_POINTER asyncHwQh;
  102. PHW_32BIT_PHYSICAL_ADDRESS frameBase;
  103. hcOp = DeviceData->OperationalRegisters;
  104. // allocate a frame list
  105. frameBase = DeviceData->FrameListBaseAddress =
  106. (PHW_32BIT_PHYSICAL_ADDRESS) StaticQHs;
  107. DeviceData->FrameListBasePhys =
  108. StaticQHsPhys;
  109. StaticQHs += USBEHCI_MAX_FRAME*sizeof(HW_32BIT_PHYSICAL_ADDRESS);
  110. StaticQHsPhys += USBEHCI_MAX_FRAME*sizeof(HW_32BIT_PHYSICAL_ADDRESS);
  111. // allocate a 'Dummy' QH for the Async list
  112. qh = (PHCD_QUEUEHEAD_DESCRIPTOR) StaticQHs;
  113. RtlZeroMemory(qh, sizeof(*qh));
  114. asyncHwQh.HwAddress =
  115. qh->PhysicalAddress = StaticQHsPhys;
  116. // no current TD
  117. // t-bit set on next TD
  118. SET_T_BIT(qh->HwQH.Overlay.qTD.Next_qTD.HwAddress);
  119. qh->HwQH.Overlay.qTD.Token.Halted = 1;
  120. qh->HwQH.EpChars.HeadOfReclimationList = 1;
  121. qh->Sig = SIG_HCD_AQH;
  122. SET_QH(asyncHwQh.HwAddress);
  123. // link to ourselves
  124. qh->HwQH.HLink.HwAddress = asyncHwQh.HwAddress;
  125. QH_DESCRIPTOR_PTR(qh->NextQh) = qh;
  126. QH_DESCRIPTOR_PTR(qh->PrevQh) = qh;
  127. DeviceData->AsyncQueueHead = qh;
  128. StaticQHs += sizeof(HCD_QUEUEHEAD_DESCRIPTOR);
  129. StaticQHsPhys += sizeof(HCD_QUEUEHEAD_DESCRIPTOR);
  130. // allocate 64 static interrupt queue heads
  131. for (i=0; i<64; i++) {
  132. qh = (PHCD_QUEUEHEAD_DESCRIPTOR) StaticQHs;
  133. qh->PhysicalAddress = StaticQHsPhys;
  134. DeviceData->StaticInterruptQH[i] = qh;
  135. StaticQHs += sizeof(HCD_QUEUEHEAD_DESCRIPTOR);
  136. StaticQHsPhys += sizeof(HCD_QUEUEHEAD_DESCRIPTOR);
  137. }
  138. EHCI_InitailizeInterruptSchedule(DeviceData);
  139. for (i=0; i<USBEHCI_MAX_FRAME; i++) {
  140. PHCD_QUEUEHEAD_DESCRIPTOR qh;
  141. HW_32BIT_PHYSICAL_ADDRESS qhPhys;
  142. qh = EHCI_GetQueueHeadForFrame(DeviceData, i);
  143. qhPhys = qh->PhysicalAddress;
  144. SET_QH(qhPhys);
  145. *frameBase = qhPhys;
  146. frameBase++;
  147. }
  148. DeviceData->DummyQueueHeads = StaticQHs;
  149. DeviceData->DummyQueueHeadsPhys = StaticQHsPhys;
  150. StaticQHs+= sizeof(HCD_QUEUEHEAD_DESCRIPTOR)*USBEHCI_MAX_FRAME;
  151. StaticQHsPhys+= sizeof(HCD_QUEUEHEAD_DESCRIPTOR)*USBEHCI_MAX_FRAME;
  152. EHCI_AddDummyQueueHeads(DeviceData);
  153. // program the frame list
  154. WRITE_REGISTER_ULONG(&hcOp->PeriodicListBase,
  155. DeviceData->FrameListBasePhys);
  156. // write the async qh to the controller
  157. WRITE_REGISTER_ULONG(&hcOp->AsyncListAddr, asyncHwQh.HwAddress);
  158. mpStatus = USBMP_STATUS_SUCCESS;
  159. return mpStatus;
  160. }
  161. VOID
  162. EHCI_ReadUlongRegFlag(
  163. PDEVICE_DATA DeviceData,
  164. PUCHAR DebugString,
  165. PWCHAR FlagName,
  166. ULONG FlagNameSize,
  167. ULONG FlagBit
  168. )
  169. /*++
  170. Routine Description:
  171. Arguments:
  172. Return Value:
  173. --*/
  174. {
  175. USB_MINIPORT_STATUS mpStatus;
  176. ULONG flag;
  177. // get SOF modify value from registry
  178. mpStatus =
  179. USBPORT_GET_REGISTRY_KEY_VALUE(DeviceData,
  180. TRUE, // software branch
  181. FlagName,
  182. FlagNameSize,
  183. &flag,
  184. sizeof(flag));
  185. // if this call fails we just use the default
  186. if (mpStatus == USBMP_STATUS_SUCCESS) {
  187. if (flag) {
  188. SET_FLAG(DeviceData->Flags, FlagBit);
  189. }
  190. EHCI_KdPrint((DeviceData, 1, "'%s: %d \n",
  191. DebugString, flag));
  192. }
  193. }
  194. VOID
  195. EHCI_GetRegistryParameters(
  196. PDEVICE_DATA DeviceData
  197. )
  198. /*++
  199. Routine Description:
  200. Arguments:
  201. Return Value:
  202. --*/
  203. {
  204. EHCI_ReadUlongRegFlag(DeviceData,
  205. "Enable Idle Endpoint Support",
  206. EN_IDLE_ENDPOINT_SUPPORT,
  207. sizeof(EN_IDLE_ENDPOINT_SUPPORT),
  208. EHCI_DD_EN_IDLE_EP_SUPPORT);
  209. }
  210. VOID
  211. USBMPFN
  212. EHCI_StopController(
  213. PDEVICE_DATA DeviceData,
  214. BOOLEAN HwPresent
  215. )
  216. /*++
  217. Routine Description:
  218. Arguments:
  219. Return Value:
  220. --*/
  221. {
  222. USBCMD cmd;
  223. PHC_OPERATIONAL_REGISTER hcOp = NULL;
  224. CONFIGFLAG configFlag;
  225. hcOp = DeviceData->OperationalRegisters;
  226. // clear the run bit
  227. cmd.ul = READ_REGISTER_ULONG(&hcOp->UsbCommand.ul);
  228. LOGENTRY(DeviceData, G, '_stp', cmd.ul, 0, 0);
  229. cmd.HostControllerRun = 0;
  230. WRITE_REGISTER_ULONG(&hcOp->UsbCommand.ul, cmd.ul);
  231. // mask off all interrupts
  232. WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul,
  233. 0);
  234. // set cc control of the hc ports to the companion
  235. // controllers
  236. configFlag.ul = 0;
  237. configFlag.RoutePortsToEHCI = 0;
  238. WRITE_REGISTER_ULONG(&hcOp->ConfigFlag.ul, configFlag.ul);
  239. }
  240. VOID
  241. USBMPFN
  242. EHCI_TakePortControl(
  243. PDEVICE_DATA DeviceData
  244. )
  245. /*++
  246. Routine Description:
  247. Arguments:
  248. Return Value:
  249. --*/
  250. {
  251. PHC_OPERATIONAL_REGISTER hcOp = NULL;
  252. CONFIGFLAG configFlag;
  253. hcOp = DeviceData->OperationalRegisters;
  254. configFlag.ul = READ_REGISTER_ULONG(&hcOp->ConfigFlag.ul);
  255. EHCI_KdPrint((DeviceData, 0, "'EHCI - configflag %x\n", configFlag.ul));
  256. DeviceData->LastConfigFlag.ul = configFlag.ul;
  257. // set default port routing
  258. configFlag.ul = 0;
  259. configFlag.RoutePortsToEHCI = 1;
  260. WRITE_REGISTER_ULONG(&hcOp->ConfigFlag.ul, configFlag.ul);
  261. }
  262. USB_MINIPORT_STATUS
  263. USBMPFN
  264. EHCI_StartController(
  265. PDEVICE_DATA DeviceData,
  266. PHC_RESOURCES HcResources
  267. )
  268. /*++
  269. Routine Description:
  270. Arguments:
  271. Return Value:
  272. --*/
  273. {
  274. USB_MINIPORT_STATUS mpStatus;
  275. PHC_OPERATIONAL_REGISTER hcOp = NULL;
  276. PHC_CAPABILITIES_REGISTER hcCap = NULL;
  277. PUCHAR base;
  278. USBCMD cmd;
  279. HCLENGTHVERSION hcLengthVersion;
  280. ULONG capLength;
  281. ULONG hciVersion;
  282. CONFIGFLAG configFlag;
  283. UCHAR fladj; // fBIOS set frame length adjustment
  284. DeviceData->Sig = SIG_EHCI_DD;
  285. DeviceData->ControllerFlavor =
  286. HcResources->ControllerFlavor;
  287. DeviceData->DeviceStarted = FALSE;
  288. USBPORT_READ_CONFIG_SPACE(
  289. DeviceData,
  290. &DeviceData->Vid,
  291. 0,
  292. sizeof(DeviceData->Vid));
  293. USBPORT_READ_CONFIG_SPACE(
  294. DeviceData,
  295. &DeviceData->Dev,
  296. 2,
  297. sizeof(DeviceData->Dev));
  298. #if DBG
  299. if (AGERE(DeviceData)) {
  300. EHCI_KdPrint((DeviceData, 0, "'EHCI Agere Controller Detected\n"));
  301. } else if (NEC(DeviceData)) {
  302. EHCI_KdPrint((DeviceData, 0, "'EHCI NEC Controller Detected\n"));
  303. } else {
  304. EHCI_KdPrint((DeviceData, 0, "'EHCI Generic Controller Detected\n"));
  305. }
  306. #endif
  307. // get the frame length adjustment value set by the BIOS
  308. USBPORT_READ_CONFIG_SPACE(
  309. DeviceData,
  310. &fladj,
  311. 0x61,
  312. sizeof(fladj));
  313. DeviceData->SavedFladj = fladj;
  314. DeviceData->IsoEndpointListHead = NULL;
  315. if (EHCI_PastExpirationDate(DeviceData)) {
  316. return USBMP_STATUS_INIT_FAILURE;
  317. }
  318. // assume success
  319. mpStatus = USBMP_STATUS_SUCCESS;
  320. EHCI_ASSERT(DeviceData, HcResources->CommonBufferVa != NULL);
  321. // validate our resources
  322. if ((HcResources->Flags & (HCR_MEM_REGS | HCR_IRQ)) !=
  323. (HCR_MEM_REGS | HCR_IRQ)) {
  324. mpStatus = USBMP_STATUS_INIT_FAILURE;
  325. }
  326. base = HcResources->DeviceRegisters;
  327. hcCap = DeviceData->CapabilitiesRegisters =
  328. (PHC_CAPABILITIES_REGISTER) base;
  329. hcLengthVersion.ul = READ_REGISTER_ULONG(&hcCap->HcLengthVersion.ul);
  330. capLength = hcLengthVersion.HcCapLength;
  331. hciVersion = hcLengthVersion.HcVersion;
  332. EHCI_KdPrint((DeviceData, 1, "'EHCI CAPLENGTH = 0x%x\n", capLength));
  333. EHCI_KdPrint((DeviceData, 1, "'EHCI HCIVERSION = 0x%x\n", hciVersion));
  334. // set up or device data structure
  335. hcOp = DeviceData->OperationalRegisters =
  336. (PHC_OPERATIONAL_REGISTER) (base + capLength);
  337. EHCI_KdPrint((DeviceData, 1, "'EHCI mapped Operational Regs = %x\n", hcOp));
  338. EHCI_KdPrint((DeviceData, 1, "'EHCI mapped Capabilities Regs = %x\n", hcCap));
  339. EHCI_GetRegistryParameters(DeviceData);
  340. // if (mpStatus == USBMP_STATUS_SUCCESS) {
  341. // mpStatus = EHCI_StopBIOS(DeviceData);
  342. // }
  343. if (mpStatus == USBMP_STATUS_SUCCESS) {
  344. // got resources and schedule
  345. // init the controller
  346. mpStatus = EHCI_InitializeHardware(DeviceData);
  347. }
  348. if (mpStatus == USBMP_STATUS_SUCCESS) {
  349. // inialize static Queue Heads
  350. PUCHAR staticQHs;
  351. HW_32BIT_PHYSICAL_ADDRESS staticQHsPhys;
  352. // carve the common buffer block in to
  353. // static QueueHeads
  354. //
  355. // set up the schedule
  356. staticQHs = HcResources->CommonBufferVa;
  357. staticQHsPhys = HcResources->CommonBufferPhys;
  358. // set up the schedule
  359. mpStatus = EHCI_InitializeSchedule(DeviceData,
  360. staticQHs,
  361. staticQHsPhys);
  362. }
  363. if (mpStatus == USBMP_STATUS_SUCCESS) {
  364. USBPORT_READ_CONFIG_SPACE(
  365. DeviceData,
  366. &fladj,
  367. 0x61,
  368. sizeof(fladj));
  369. if (fladj != DeviceData->SavedFladj) {
  370. TEST_TRAP();
  371. fladj = DeviceData->SavedFladj;
  372. USBPORT_WRITE_CONFIG_SPACE(
  373. DeviceData,
  374. &fladj,
  375. 0x61,
  376. sizeof(fladj));
  377. }
  378. // set default port routing
  379. configFlag.ul = 0;
  380. configFlag.RoutePortsToEHCI = 1;
  381. WRITE_REGISTER_ULONG(&hcOp->ConfigFlag.ul, configFlag.ul);
  382. DeviceData->LastConfigFlag.ul = configFlag.ul;
  383. // set the interrupt threshold to maximum
  384. cmd.ul = READ_REGISTER_ULONG(&hcOp->UsbCommand.ul);
  385. cmd.InterruptThreshold = 1;
  386. WRITE_REGISTER_ULONG(&hcOp->UsbCommand.ul, cmd.ul);
  387. // start the controller
  388. cmd.ul = READ_REGISTER_ULONG(&hcOp->UsbCommand.ul);
  389. LOGENTRY(DeviceData, G, '_run', cmd.ul, 0, 0);
  390. cmd.HostControllerRun = 1;
  391. WRITE_REGISTER_ULONG(&hcOp->UsbCommand.ul, cmd.ul);
  392. DeviceData->DeviceStarted = TRUE;
  393. if (HcResources->Restart) {
  394. USHORT p;
  395. // we have a restart, re-power the ports here so that
  396. // we can hand of devices that are on the 1.1 bus
  397. EHCI_KdPrint((DeviceData, 0, "'Restart, power chirpable ports\n"));
  398. // power the ports
  399. for (p = 1; p <= DeviceData->NumberOfPorts; p++) {
  400. EHCI_RH_SetFeaturePortPower(DeviceData, p);
  401. }
  402. // no poweron2powergood for EHCI root ports, wait
  403. // 100 ms for port power stabilization
  404. // 100 ms minimum debiunce time
  405. USBPORT_WAIT(DeviceData, 200);
  406. // bugbug this will keep some HS mass storage devices from failing after
  407. // hibernate, however it will significantly increase resume from hibernate
  408. // time. see bug #586818
  409. // USBPORT_WAIT(DeviceData, 500);
  410. for (p = 1; p <= DeviceData->NumberOfPorts; p++) {
  411. EHCI_RH_ChirpRootPort(DeviceData, p);
  412. }
  413. }
  414. } else {
  415. DEBUG_BREAK(DeviceData);
  416. }
  417. return mpStatus;
  418. }
  419. VOID
  420. EHCI_SuspendController(
  421. PDEVICE_DATA DeviceData
  422. )
  423. {
  424. USBCMD cmd;
  425. USBSTS status;
  426. USBINTR intr;
  427. PHC_OPERATIONAL_REGISTER hcOp = NULL;
  428. ULONG i,p;
  429. USBSTS irqStatus;
  430. hcOp = DeviceData->OperationalRegisters;
  431. // save all volatile regs from the core power well
  432. // since we may loose power on the controller chip (not bus)
  433. // the miniport is resposnible for saving HW state
  434. DeviceData->PeriodicListBaseSave =
  435. READ_REGISTER_ULONG(&hcOp->PeriodicListBase);
  436. DeviceData->AsyncListAddrSave =
  437. READ_REGISTER_ULONG(&hcOp->AsyncListAddr);
  438. DeviceData->SegmentSelectorSave =
  439. READ_REGISTER_ULONG(&hcOp->SegmentSelector);
  440. // preserve the state of the list enable bits
  441. DeviceData->CmdSave.ul =
  442. READ_REGISTER_ULONG(&hcOp->UsbCommand.ul);
  443. // reset the PM chirp state flags for another pass at power
  444. // management
  445. DeviceData, DeviceData->PortPMChirp == 0;
  446. // Save away the command register
  447. // DeviceData->SuspendCommandReg.us =
  448. // command.us = READ_PORT_USHORT(&reg->UsbCommand.us);
  449. // clear the int on async advance doorbell
  450. cmd.ul = READ_REGISTER_ULONG(&hcOp->UsbCommand.ul);
  451. cmd.IntOnAsyncAdvanceDoorbell = 0;
  452. WRITE_REGISTER_ULONG(&hcOp->UsbCommand.ul,
  453. cmd.ul);
  454. // Stop the controller
  455. cmd.ul = READ_REGISTER_ULONG(&hcOp->UsbCommand.ul);
  456. LOGENTRY(DeviceData, G, '_st1', cmd.ul, 0, 0);
  457. cmd.HostControllerRun = 0;
  458. WRITE_REGISTER_ULONG(&hcOp->UsbCommand.ul, cmd.ul);
  459. // ack any interrupts that may be left over from the halt
  460. // process. The controller should not generate any new
  461. // interrupts when it is stopped. For some reason the NEC
  462. // controller generates a doorbel interrupt on halt.
  463. // wait 1 microframe
  464. KeStallExecutionProcessor(125);
  465. irqStatus.ul = READ_REGISTER_ULONG(&hcOp->UsbStatus.ul);
  466. // just look at the IRQ status bits
  467. irqStatus.ul &= HcInterruptStatusMask;
  468. if (irqStatus.ul != 0) {
  469. WRITE_REGISTER_ULONG(&hcOp->UsbStatus.ul,
  470. irqStatus.ul);
  471. }
  472. // mask off all interrupts now
  473. WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul,
  474. 0);
  475. // Wait for the HC to halt
  476. // Note that according to the sepc if we don't halt in ms
  477. // (16ms) the hardware is busted.
  478. for (i=0; i<10; i++) {
  479. status.ul = READ_REGISTER_ULONG(&hcOp->UsbStatus.ul);
  480. if (status.HcHalted) {
  481. break;
  482. }
  483. USBPORT_WAIT(DeviceData, 1);
  484. }
  485. if (status.HcHalted != 1) {
  486. // hardware is f'ed up
  487. TEST_TRAP();
  488. }
  489. //if (!status.HCHalted) {
  490. //
  491. // // Can't get the HCHalted bit to stick, so reset the controller.
  492. // command.GlobalReset = 1;
  493. // WRITE_PORT_USHORT(&reg->UsbCommand.us, command.us);
  494. //
  495. // USBPORT_WAIT(DeviceData, 10);
  496. //
  497. // command.GlobalReset = 0;
  498. // WRITE_PORT_USHORT(&reg->UsbCommand.us, command.us);
  499. // // Re-enable interrupts, since they are zero'd out on reset.
  500. // WRITE_PORT_USHORT(&reg->UsbInterruptEnable.us, DeviceData->EnabledInterrupts.us);
  501. //
  502. //}
  503. // enable the port chage interrupt, this allows us to wake
  504. // in the selective suspend case
  505. intr.ul = READ_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul);
  506. intr.PortChangeDetect = 1;
  507. WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul, intr.ul);
  508. }
  509. USB_MINIPORT_STATUS
  510. EHCI_ResumeController(
  511. PDEVICE_DATA DeviceData
  512. )
  513. {
  514. USBCMD cmd;
  515. PHC_OPERATIONAL_REGISTER hcOp = NULL;
  516. CONFIGFLAG configFlag;
  517. hcOp = DeviceData->OperationalRegisters;
  518. EHCI_KdPrint((DeviceData, 1, "'>EHCI_ResumeController\n"));
  519. // don't mess with handoff regs for now
  520. //configFlag.ul = 0;
  521. //configFlag.RoutePortsToEHCI = 1;
  522. //WRITE_REGISTER_ULONG(&hcOp->ConfigFlag.ul, configFlag.ul);
  523. // restore volitile regs
  524. //configFlag.ul = READ_REGISTER_ULONG(&hcOp->ConfigFlag.ul);
  525. configFlag.ul = DeviceData->LastConfigFlag.ul;
  526. if (configFlag.RoutePortsToEHCI == 0) {
  527. // we have a reset
  528. EHCI_KdPrint((DeviceData, 1, "'Routing bit has reset to 0\n"));
  529. configFlag.RoutePortsToEHCI = 1;
  530. DeviceData->LastConfigFlag.ul = configFlag.ul;
  531. WRITE_REGISTER_ULONG(&hcOp->ConfigFlag.ul, configFlag.ul);
  532. return USBMP_STATUS_HARDWARE_FAILURE;
  533. }
  534. // restore volitile regs
  535. WRITE_REGISTER_ULONG(&hcOp->SegmentSelector, DeviceData->SegmentSelectorSave);
  536. WRITE_REGISTER_ULONG(&hcOp->PeriodicListBase, DeviceData->PeriodicListBaseSave);
  537. WRITE_REGISTER_ULONG(&hcOp->AsyncListAddr, DeviceData->AsyncListAddrSave);
  538. // start the controller
  539. cmd.ul = READ_REGISTER_ULONG(&hcOp->UsbCommand.ul);
  540. LOGENTRY(DeviceData, G, '_run', cmd.ul, 0, 0);
  541. cmd.HostControllerRun = 1;
  542. // restore volatile cmd bits
  543. cmd.AsyncScheduleEnable = DeviceData->CmdSave.AsyncScheduleEnable;
  544. cmd.PeriodicScheduleEnable = DeviceData->CmdSave.PeriodicScheduleEnable;
  545. cmd.InterruptThreshold = DeviceData->CmdSave.InterruptThreshold;
  546. WRITE_REGISTER_ULONG(&hcOp->UsbCommand.ul, cmd.ul);
  547. WRITE_REGISTER_ULONG(&hcOp->UsbInterruptEnable.ul,
  548. DeviceData->EnabledInterrupts.ul);
  549. EHCI_KdPrint((DeviceData, 1, "'<EHCI_ResumeController\n"));
  550. return USBMP_STATUS_SUCCESS;
  551. }
  552. USB_MINIPORT_STATUS
  553. EHCI_OpenEndpoint(
  554. PDEVICE_DATA DeviceData,
  555. PENDPOINT_PARAMETERS EndpointParameters,
  556. PENDPOINT_DATA EndpointData
  557. )
  558. /*++
  559. Routine Description:
  560. Arguments:
  561. Return Value:
  562. --*/
  563. {
  564. USB_MINIPORT_STATUS mpStatus;
  565. EndpointData->Sig = SIG_EP_DATA;
  566. // save a copy of the parameters
  567. EndpointData->Parameters = *EndpointParameters;
  568. EndpointData->Flags = 0;
  569. EndpointData->PendingTransfers = 0;
  570. switch (EndpointParameters->TransferType) {
  571. case Control:
  572. EndpointData->MaxPendingTransfers = 1;
  573. mpStatus = EHCI_OpenBulkOrControlEndpoint(
  574. DeviceData,
  575. TRUE,
  576. EndpointParameters,
  577. EndpointData);
  578. break;
  579. case Interrupt:
  580. mpStatus = EHCI_OpenInterruptEndpoint(
  581. DeviceData,
  582. EndpointParameters,
  583. EndpointData);
  584. break;
  585. case Bulk:
  586. EndpointData->MaxPendingTransfers = 1;
  587. mpStatus = EHCI_OpenBulkOrControlEndpoint(
  588. DeviceData,
  589. FALSE,
  590. EndpointParameters,
  591. EndpointData);
  592. break;
  593. case Isochronous:
  594. if (EndpointParameters->DeviceSpeed == HighSpeed) {
  595. mpStatus = EHCI_OpenHsIsochronousEndpoint(
  596. DeviceData,
  597. EndpointParameters,
  598. EndpointData);
  599. } else {
  600. mpStatus = EHCI_OpenIsochronousEndpoint(
  601. DeviceData,
  602. EndpointParameters,
  603. EndpointData);
  604. }
  605. break;
  606. default:
  607. TEST_TRAP();
  608. mpStatus = USBMP_STATUS_NOT_SUPPORTED;
  609. }
  610. return mpStatus;
  611. }
  612. VOID
  613. EHCI_CloseEndpoint(
  614. PDEVICE_DATA DeviceData,
  615. PENDPOINT_DATA EndpointData
  616. )
  617. /*++
  618. Routine Description:
  619. Arguments:
  620. Return Value:
  621. --*/
  622. {
  623. // nothing to do here
  624. }
  625. USB_MINIPORT_STATUS
  626. EHCI_PokeEndpoint(
  627. PDEVICE_DATA DeviceData,
  628. PENDPOINT_PARAMETERS EndpointParameters,
  629. PENDPOINT_DATA EndpointData
  630. )
  631. /*++
  632. Routine Description:
  633. Arguments:
  634. Return Value:
  635. --*/
  636. {
  637. PHCD_QUEUEHEAD_DESCRIPTOR qh;
  638. ULONG oldBandwidth;
  639. LOGENTRY(DeviceData, G, '_Pok', EndpointData,
  640. EndpointParameters, 0);
  641. switch(EndpointData->Parameters.TransferType) {
  642. case Interrupt:
  643. case Control:
  644. case Bulk:
  645. return EHCI_PokeAsyncEndpoint(DeviceData,
  646. EndpointParameters,
  647. EndpointData);
  648. case Isochronous:
  649. return EHCI_PokeIsoEndpoint(DeviceData,
  650. EndpointParameters,
  651. EndpointData);
  652. }
  653. return USBMP_STATUS_SUCCESS;
  654. }
  655. VOID
  656. EHCI_RebalanceEndpoint(
  657. PDEVICE_DATA DeviceData,
  658. PENDPOINT_PARAMETERS EndpointParameters,
  659. PENDPOINT_DATA EndpointData
  660. )
  661. /*++
  662. Routine Description:
  663. compute how much common buffer we will need
  664. for this endpoint
  665. Arguments:
  666. Return Value:
  667. --*/
  668. {
  669. switch (EndpointParameters->TransferType) {
  670. case Interrupt:
  671. EHCI_RebalanceInterruptEndpoint(DeviceData,
  672. EndpointParameters,
  673. EndpointData);
  674. break;
  675. case Isochronous:
  676. EHCI_RebalanceIsoEndpoint(DeviceData,
  677. EndpointParameters,
  678. EndpointData);
  679. break;
  680. }
  681. }
  682. USB_MINIPORT_STATUS
  683. EHCI_QueryEndpointRequirements(
  684. PDEVICE_DATA DeviceData,
  685. PENDPOINT_PARAMETERS EndpointParameters,
  686. OUT PENDPOINT_REQUIREMENTS EndpointRequirements
  687. )
  688. /*++
  689. Routine Description:
  690. compute how much common buffer we will need
  691. for this endpoint
  692. Arguments:
  693. Return Value:
  694. --*/
  695. {
  696. switch (EndpointParameters->TransferType) {
  697. case Control:
  698. EndpointRequirements->MinCommonBufferBytes =
  699. sizeof(HCD_QUEUEHEAD_DESCRIPTOR) +
  700. TDS_PER_CONTROL_ENDPOINT*sizeof(HCD_TRANSFER_DESCRIPTOR);
  701. EndpointRequirements->MaximumTransferSize =
  702. MAX_CONTROL_TRANSFER_SIZE;
  703. break;
  704. case Interrupt:
  705. EndpointRequirements->MinCommonBufferBytes =
  706. sizeof(HCD_QUEUEHEAD_DESCRIPTOR) +
  707. TDS_PER_INTERRUPT_ENDPOINT*sizeof(HCD_TRANSFER_DESCRIPTOR);
  708. EndpointRequirements->MaximumTransferSize =
  709. MAX_INTERRUPT_TRANSFER_SIZE;
  710. break;
  711. case Bulk:
  712. //
  713. // TDS_PER_ENDPOINT limits the largest transfer we
  714. // can handle.
  715. //
  716. // TDS_PER_ENDPOINT TDs plus an ED
  717. EndpointRequirements->MinCommonBufferBytes =
  718. sizeof(HCD_QUEUEHEAD_DESCRIPTOR) +
  719. TDS_PER_BULK_ENDPOINT*sizeof(HCD_TRANSFER_DESCRIPTOR);
  720. EndpointRequirements->MaximumTransferSize =
  721. MAX_BULK_TRANSFER_SIZE;
  722. break;
  723. case Isochronous:
  724. if (EndpointParameters->DeviceSpeed == HighSpeed) {
  725. EndpointRequirements->MinCommonBufferBytes =
  726. USBEHCI_MAX_FRAME*sizeof(HCD_HSISO_TRANSFER_DESCRIPTOR);
  727. EndpointRequirements->MaximumTransferSize =
  728. MAX_HSISO_TRANSFER_SIZE;
  729. } else {
  730. // TDS_PER_ENDPOINT TDs plus an ED
  731. EndpointRequirements->MinCommonBufferBytes =
  732. TDS_PER_ISO_ENDPOINT*sizeof(HCD_SI_TRANSFER_DESCRIPTOR);
  733. EndpointRequirements->MaximumTransferSize =
  734. MAX_ISO_TRANSFER_SIZE;
  735. }
  736. break;
  737. default:
  738. USBPORT_BUGCHECK(DeviceData);
  739. }
  740. return USBMP_STATUS_SUCCESS;
  741. }
  742. VOID
  743. EHCI_PollEndpoint(
  744. PDEVICE_DATA DeviceData,
  745. PENDPOINT_DATA EndpointData
  746. )
  747. /*++
  748. Routine Description:
  749. Arguments:
  750. Return Value:
  751. --*/
  752. {
  753. switch(EndpointData->Parameters.TransferType) {
  754. case Control:
  755. case Bulk:
  756. case Interrupt:
  757. EHCI_PollAsyncEndpoint(DeviceData, EndpointData);
  758. break;
  759. case Isochronous:
  760. EHCI_PollIsoEndpoint(DeviceData, EndpointData);
  761. break;
  762. }
  763. }
  764. PHCD_TRANSFER_DESCRIPTOR
  765. EHCI_AllocTd(
  766. PDEVICE_DATA DeviceData,
  767. PENDPOINT_DATA EndpointData
  768. )
  769. /*++
  770. Routine Description:
  771. Allocate a TD from an endpoints pool
  772. Arguments:
  773. Return Value:
  774. --*/
  775. {
  776. ULONG i;
  777. PHCD_TRANSFER_DESCRIPTOR td;
  778. for (i=0; i<EndpointData->TdCount; i++) {
  779. td = &EndpointData->TdList->Td[i];
  780. if (!TEST_FLAG(td->Flags, TD_FLAG_BUSY)) {
  781. SET_FLAG(td->Flags, TD_FLAG_BUSY);
  782. LOGENTRY(DeviceData, G, '_aTD', td, 0, 0);
  783. EndpointData->FreeTds--;
  784. return td;
  785. }
  786. }
  787. // we should always find one
  788. EHCI_ASSERT(DeviceData, FALSE);
  789. USBPORT_BUGCHECK(DeviceData);
  790. return NULL;
  791. }
  792. VOID
  793. EHCI_SetEndpointStatus(
  794. PDEVICE_DATA DeviceData,
  795. PENDPOINT_DATA EndpointData,
  796. MP_ENDPOINT_STATUS Status
  797. )
  798. /*++
  799. Routine Description:
  800. Arguments:
  801. Return Value:
  802. --*/
  803. {
  804. switch (EndpointData->Parameters.TransferType) {
  805. case Control:
  806. case Bulk:
  807. case Interrupt:
  808. EHCI_SetAsyncEndpointStatus(DeviceData,
  809. EndpointData,
  810. Status);
  811. break;
  812. case Isochronous:
  813. // nothing to do for iso
  814. break;
  815. default:
  816. USBPORT_BUGCHECK(DeviceData);
  817. }
  818. }
  819. MP_ENDPOINT_STATUS
  820. EHCI_GetEndpointStatus(
  821. PDEVICE_DATA DeviceData,
  822. PENDPOINT_DATA EndpointData
  823. )
  824. /*++
  825. Routine Description:
  826. Arguments:
  827. Return Value:
  828. --*/
  829. {
  830. switch (EndpointData->Parameters.TransferType) {
  831. case Control:
  832. case Bulk:
  833. case Interrupt:
  834. return EHCI_GetAsyncEndpointStatus(DeviceData,
  835. EndpointData);
  836. break;
  837. }
  838. // return RUNNING for iso
  839. return ENDPOINT_STATUS_RUN;
  840. }
  841. VOID
  842. EHCI_SetEndpointState(
  843. PDEVICE_DATA DeviceData,
  844. PENDPOINT_DATA EndpointData,
  845. MP_ENDPOINT_STATE State
  846. )
  847. /*++
  848. Routine Description:
  849. Arguments:
  850. Return Value:
  851. --*/
  852. {
  853. LOGENTRY(DeviceData, G, '_ses', EndpointData, 0, State);
  854. switch (EndpointData->Parameters.TransferType) {
  855. case Control:
  856. case Bulk:
  857. case Interrupt:
  858. EHCI_SetAsyncEndpointState(DeviceData,
  859. EndpointData,
  860. State);
  861. break;
  862. case Isochronous:
  863. EHCI_SetIsoEndpointState(DeviceData,
  864. EndpointData,
  865. State);
  866. break;
  867. default:
  868. USBPORT_BUGCHECK(DeviceData);
  869. }
  870. }
  871. MP_ENDPOINT_STATE
  872. EHCI_GetEndpointState(
  873. PDEVICE_DATA DeviceData,
  874. PENDPOINT_DATA EndpointData
  875. )
  876. /*++
  877. Routine Description:
  878. Arguments:
  879. Return Value:
  880. --*/
  881. {
  882. MP_ENDPOINT_STATE currentState;
  883. PHCD_QUEUEHEAD_DESCRIPTOR qh;
  884. // assume we are active
  885. currentState = ENDPOINT_ACTIVE;
  886. qh = EndpointData->QueueHead;
  887. // removed from schedule?
  888. if (!TEST_FLAG(qh->QhFlags, EHCI_QH_FLAG_IN_SCHEDULE)) {
  889. // yes
  890. currentState = TEST_FLAG(qh->QhFlags, EHCI_QH_FLAG_QH_REMOVED) ?
  891. ENDPOINT_REMOVE : ENDPOINT_PAUSE;
  892. }
  893. LOGENTRY(DeviceData, G, '_ges', EndpointData, 0, currentState);
  894. return currentState;
  895. }
  896. VOID
  897. EHCI_PollController(
  898. PDEVICE_DATA DeviceData
  899. )
  900. /*++
  901. Routine Description:
  902. Arguments:
  903. Return Value:
  904. --*/
  905. {
  906. USBPORT_INVALIDATE_ROOTHUB(DeviceData);
  907. }
  908. USB_MINIPORT_STATUS
  909. EHCI_SubmitTransfer(
  910. PDEVICE_DATA DeviceData,
  911. PENDPOINT_DATA EndpointData,
  912. PTRANSFER_PARAMETERS TransferParameters,
  913. PTRANSFER_CONTEXT TransferContext,
  914. PTRANSFER_SG_LIST TransferSGList
  915. )
  916. {
  917. USB_MINIPORT_STATUS mpStatus;
  918. // init the context
  919. RtlZeroMemory(TransferContext, sizeof(*TransferContext));
  920. TransferContext->Sig = SIG_EHCI_TRANSFER;
  921. TransferContext->UsbdStatus = USBD_STATUS_SUCCESS;
  922. TransferContext->EndpointData = EndpointData;
  923. TransferContext->TransferParameters = TransferParameters;
  924. switch (EndpointData->Parameters.TransferType) {
  925. case Control:
  926. mpStatus =
  927. EHCI_ControlTransfer(DeviceData,
  928. EndpointData,
  929. TransferParameters,
  930. TransferContext,
  931. TransferSGList);
  932. break;
  933. case Interrupt:
  934. mpStatus =
  935. EHCI_InterruptTransfer(DeviceData,
  936. EndpointData,
  937. TransferParameters,
  938. TransferContext,
  939. TransferSGList);
  940. break;
  941. case Bulk:
  942. mpStatus =
  943. EHCI_BulkTransfer(DeviceData,
  944. EndpointData,
  945. TransferParameters,
  946. TransferContext,
  947. TransferSGList);
  948. break;
  949. default:
  950. TEST_TRAP();
  951. }
  952. return mpStatus;
  953. }
  954. VOID
  955. EHCI_AbortTransfer(
  956. PDEVICE_DATA DeviceData,
  957. PENDPOINT_DATA EndpointData,
  958. PTRANSFER_CONTEXT TransferContext,
  959. OUT PULONG BytesTransferred
  960. )
  961. {
  962. switch (EndpointData->Parameters.TransferType) {
  963. case Control:
  964. case Interrupt:
  965. case Bulk:
  966. EHCI_AbortAsyncTransfer(DeviceData,
  967. EndpointData,
  968. TransferContext);
  969. break;
  970. default:
  971. EHCI_AbortIsoTransfer(DeviceData,
  972. EndpointData,
  973. TransferContext);
  974. }
  975. }
  976. USB_MINIPORT_STATUS
  977. EHCI_PassThru (
  978. PDEVICE_DATA DeviceData,
  979. GUID *FunctionGuid,
  980. ULONG ParameterLength,
  981. OUT PVOID Parameters
  982. )
  983. {
  984. PUCHAR p = Parameters;
  985. UCHAR pdkApi;
  986. ULONG portNumber;
  987. USB_MINIPORT_STATUS mpStatus;
  988. mpStatus = USBMP_STATUS_NOT_SUPPORTED;
  989. if (RtlEqualMemory(FunctionGuid, &GUID_USBPRIV_ROOTPORT_STATUS, sizeof(GUID)))
  990. {
  991. mpStatus = EHCI_RH_UsbprivRootPortStatus(DeviceData,
  992. ParameterLength,
  993. Parameters);
  994. }
  995. #if 0
  996. portNumber = *(p+1);
  997. mpStatus = USBMP_STATUS_NOT_SUPPORTED;
  998. // pdkApi - force full speed
  999. pdkApi = *p;
  1000. switch (pdkApi) {
  1001. // obtumtuserate the port as requested
  1002. case 0:
  1003. {
  1004. PHC_OPERATIONAL_REGISTER hcOp;
  1005. USHORT portNumber;
  1006. PORTSC port;
  1007. portNumber = *(p+1);
  1008. hcOp = DeviceData->OperationalRegisters;
  1009. // first power the port up
  1010. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[portNumber-1].ul);
  1011. port.PortPower = 1;
  1012. WRITE_REGISTER_ULONG(&hcOp->PortRegister[portNumber-1].ul,
  1013. port.ul);
  1014. KeStallExecutionProcessor(10); //stall for 10 microseconds
  1015. EHCI_OptumtuseratePort(DeviceData, portNumber);
  1016. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[portNumber-1].ul);
  1017. SET_BIT(DeviceData->HighSpeedDeviceAttached, portNumber-1);
  1018. // see if it worked
  1019. if (port.ul == 0x1205) {
  1020. mpStatus = USBMP_STATUS_SUCCESS;
  1021. } else {
  1022. mpStatus = USBMP_STATUS_FAILURE;
  1023. }
  1024. LOGENTRY(DeviceData, G, '_hsE', portNumber, mpStatus, port.ul);
  1025. TEST_TRAP();
  1026. }
  1027. break;
  1028. case 1:
  1029. // force a connect change
  1030. // indicate a port change condition to the hub
  1031. SET_BIT(DeviceData->PortConnectChange, portNumber-1);
  1032. break;
  1033. }
  1034. #endif
  1035. return mpStatus;
  1036. }
  1037. VOID
  1038. EHCI_SetEndpointDataToggle(
  1039. PDEVICE_DATA DeviceData,
  1040. PENDPOINT_DATA EndpointData,
  1041. ULONG Toggle
  1042. )
  1043. /*++
  1044. Routine Description:
  1045. Arguments:
  1046. Toggle is 0 or 1
  1047. Return Value:
  1048. --*/
  1049. {
  1050. PHCD_QUEUEHEAD_DESCRIPTOR qh;
  1051. if (EndpointData->Parameters.TransferType == Control ||
  1052. EndpointData->Parameters.TransferType == Isochronous) {
  1053. // nothing to do for control and iso
  1054. return;
  1055. }
  1056. qh = EndpointData->QueueHead;
  1057. qh->HwQH.Overlay.qTD.Token.DataToggle = Toggle;
  1058. LOGENTRY(DeviceData, G, '_stg', EndpointData, 0, Toggle);
  1059. }
  1060. VOID
  1061. EHCI_CheckController(
  1062. PDEVICE_DATA DeviceData
  1063. )
  1064. {
  1065. if (DeviceData->DeviceStarted) {
  1066. EHCI_HardwarePresent(DeviceData, TRUE);
  1067. }
  1068. }
  1069. // Beta versions of our miniport driver have a hard coded exp date
  1070. #ifdef NO_EXP_DATE
  1071. #define EXPIRATION_DATE 0
  1072. #else
  1073. //Sep 1, 2001
  1074. //#define EXPIRATION_DATE 0x01c133406ab2406c
  1075. //Oct 24, 2001
  1076. //#define EXPIRATION_DATE 0x01c15cd5887bc884
  1077. //Dec 31, 2001
  1078. //#define EXPIRATION_DATE 0x01c19251a68bfac0
  1079. #endif
  1080. BOOLEAN
  1081. EHCI_PastExpirationDate(
  1082. PDEVICE_DATA DeviceData
  1083. )
  1084. {
  1085. LARGE_INTEGER systemTime;
  1086. KeQuerySystemTime(&systemTime);
  1087. EHCI_KdPrint((DeviceData, 1, "system time: %x %x\n", systemTime.QuadPart));
  1088. EHCI_KdPrint((DeviceData, 1, "exp system time: %x %x\n", EXPIRATION_DATE));
  1089. if (EXPIRATION_DATE &&
  1090. systemTime.QuadPart > EXPIRATION_DATE) {
  1091. EHCI_KdPrint((DeviceData, 1, "driver expired"));
  1092. return TRUE;
  1093. }
  1094. return FALSE;
  1095. }
  1096. UCHAR
  1097. EHCI_GetEECP(
  1098. PDEVICE_DATA DeviceData,
  1099. UCHAR CapabilityId
  1100. )
  1101. /*
  1102. returns the offset of a specific EECP in config space
  1103. given a cap id
  1104. returns 0 if no EECP or Id not found
  1105. */
  1106. {
  1107. UCHAR eecpOffset;
  1108. HC_EECP eecp;
  1109. PHC_CAPABILITIES_REGISTER hcCap;
  1110. hcCap = DeviceData->CapabilitiesRegisters;
  1111. eecpOffset = (UCHAR) hcCap->HcCapabilityParameters.EECP;
  1112. if (eecpOffset == 0) {
  1113. return eecpOffset;
  1114. }
  1115. EHCI_KdPrint((DeviceData, 1, "EECP offset found @ 0x%x\n", eecpOffset));
  1116. do {
  1117. USBPORT_READ_CONFIG_SPACE(
  1118. DeviceData,
  1119. &eecp,
  1120. eecpOffset,
  1121. sizeof(eecp));
  1122. EHCI_KdPrint((DeviceData, 1, "EECP cap 0x%x Next 0x%x (%08.8x)\n",
  1123. eecp.CapId, eecp.NextCap, eecp.ul));
  1124. if (eecp.CapId == CapabilityId) {
  1125. return eecpOffset;
  1126. }
  1127. eecpOffset = (UCHAR) eecp.NextCap;
  1128. } while (eecpOffset);
  1129. return eecpOffset;
  1130. }
  1131. USB_MINIPORT_STATUS
  1132. EHCI_StopBIOS(
  1133. PDEVICE_DATA DeviceData
  1134. )
  1135. /*++
  1136. Routine Description:
  1137. Stop Legacy BIOS
  1138. Arguments:
  1139. Return Value:
  1140. --*/
  1141. {
  1142. UCHAR biosOffset;
  1143. USB_LEGACYBIOS_REGISTERS hcLegs;
  1144. biosOffset = EHCI_GetEECP(DeviceData, EECP_PRE_OS_HANDOFF);
  1145. // do we have BIOS
  1146. if (biosOffset) {
  1147. // hey! nice Legs.
  1148. EHCI_KdPrint((DeviceData, 1, "EHCI Legacy BIOS EECP registers detected\n"));
  1149. // read the legacy registers
  1150. USBPORT_READ_CONFIG_SPACE(DeviceData, &hcLegs, biosOffset, sizeof(hcLegs));
  1151. // see if BIOS is enabled
  1152. if (hcLegs.Caps.HcBIOSowned) {
  1153. USBLEGSUP legSup;
  1154. EHCI_KdPrint((DeviceData, 0, "EHCI Legacy BIOS detected\n"));
  1155. TEST_TRAP();
  1156. // take ownership,
  1157. // set OS owned
  1158. legSup.ul = hcLegs.Caps.ul;
  1159. legSup.HcOSowned = 1;
  1160. USBPORT_WRITE_CONFIG_SPACE(DeviceData, &legSup, biosOffset, sizeof(legSup));
  1161. // wait on Bios owned to go to zero
  1162. do {
  1163. USBPORT_READ_CONFIG_SPACE(DeviceData, &legSup, biosOffset, sizeof(legSup));
  1164. } while (legSup.HcBIOSowned);
  1165. }
  1166. }
  1167. return USBMP_STATUS_SUCCESS;
  1168. }