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.

1019 lines
27 KiB

  1. /*++
  2. Copyright (c) 1999, 2000 Microsoft Corporation
  3. Module Name:
  4. roothub.c
  5. Abstract:
  6. miniport root hub
  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-00 : created, jdunn
  17. implements the following miniport functions:
  18. MINIPORT_RH_GetStatus
  19. MINIPORT_RH_GetPortStatus
  20. MINIPORT_RH_GethubStatus
  21. MINIPORT_RH_SetFeaturePortReset
  22. MINIPORT_RH_SetFeaturePortSuspend
  23. MINIPORT_RH_SetFeaturePortPower
  24. MINIPORT_RH_ClearFeaturePortEnable
  25. MINIPORT_RH_ClearFeaturePortSuspend
  26. MINIPORT_RH_ClearFeaturePortPower
  27. MINIPORT_RH_ClearFeaturePortConnectChange
  28. MINIPORT_RH_ClearFeaturePortResetChange
  29. MINIPORT_RH_ClearFeaturePortEnableChange
  30. MINIPORT_RH_ClearFeaturePortSuspendChange
  31. MINIPORT_RH_ClearFeaturePortOvercurrentChange
  32. --*/
  33. #include "common.h"
  34. #include "usbpriv.h"
  35. typedef struct _EHCI_PORT_EVENT_CONTEXT {
  36. USHORT PortNumber;
  37. } EHCI_PORT_EVENT_CONTEXT, *PEHCI_PORT_EVENT_CONTEXT;
  38. VOID
  39. EHCI_RH_GetRootHubData(
  40. PDEVICE_DATA DeviceData,
  41. OUT PROOTHUB_DATA HubData
  42. )
  43. /*++
  44. return info about the root hub
  45. --*/
  46. {
  47. HubData->NumberOfPorts =
  48. DeviceData->NumberOfPorts;
  49. if (DeviceData->PortPowerControl == 1) {
  50. HubData->HubCharacteristics.PowerSwitchType =
  51. USBPORT_RH_POWER_SWITCH_PORT;
  52. } else {
  53. HubData->HubCharacteristics.PowerSwitchType =
  54. USBPORT_RH_POWER_SWITCH_GANG;
  55. }
  56. HubData->HubCharacteristics.Reserved = 0;
  57. HubData->HubCharacteristics.OverCurrentProtection = 0;
  58. HubData->HubCharacteristics.CompoundDevice = 0;
  59. HubData->PowerOnToPowerGood = 2;
  60. // this value is the current consumed by the hub
  61. // brains, for the embeded hub this doesn't make
  62. // much sense.
  63. //
  64. // so we report zero
  65. HubData->HubControlCurrent = 0;
  66. LOGENTRY(DeviceData, G, '_hub', HubData->NumberOfPorts,
  67. DeviceData->PortPowerControl, 0);
  68. }
  69. USB_MINIPORT_STATUS
  70. EHCI_RH_GetStatus(
  71. PDEVICE_DATA DeviceData,
  72. OUT PUSHORT Status
  73. )
  74. /*++
  75. get the device status
  76. --*/
  77. {
  78. // the root hub is self powered
  79. *Status = USB_GETSTATUS_SELF_POWERED;
  80. return USBMP_STATUS_SUCCESS;
  81. }
  82. USB_MINIPORT_STATUS
  83. EHCI_RH_ClearFeaturePortEnable (
  84. PDEVICE_DATA DeviceData,
  85. USHORT PortNumber
  86. )
  87. {
  88. PHC_OPERATIONAL_REGISTER hcOp;
  89. PORTSC port;
  90. hcOp = DeviceData->OperationalRegisters;
  91. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  92. EHCI_KdPrint((DeviceData, 0, "port[%d] disable (1) %x\n", PortNumber, port.ul));
  93. port.PortEnable = 0;
  94. MASK_CHANGE_BITS(port);
  95. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul,
  96. port.ul);
  97. return USBMP_STATUS_SUCCESS;
  98. }
  99. USB_MINIPORT_STATUS
  100. EHCI_RH_ClearFeaturePortPower (
  101. PDEVICE_DATA DeviceData,
  102. USHORT PortNumber
  103. )
  104. {
  105. PHC_OPERATIONAL_REGISTER hcOp;
  106. PORTSC port;
  107. // turn power off
  108. hcOp = DeviceData->OperationalRegisters;
  109. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  110. port.PortPower = 0;
  111. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul,
  112. port.ul);
  113. return USBMP_STATUS_SUCCESS;
  114. }
  115. VOID
  116. EHCI_RH_PortResumeComplete(
  117. PDEVICE_DATA DeviceData,
  118. PVOID Context
  119. )
  120. /*++
  121. complete a port resume
  122. --*/
  123. {
  124. PHC_OPERATIONAL_REGISTER hcOp;
  125. PORTSC port;
  126. PEHCI_PORT_EVENT_CONTEXT portResumeContext = Context;
  127. USHORT portNumber;
  128. hcOp = DeviceData->OperationalRegisters;
  129. portNumber = portResumeContext->PortNumber;
  130. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[portNumber-1].ul);
  131. LOGENTRY(DeviceData, G, '_pRS', port.ul,
  132. DeviceData->PortSuspendChange, portNumber);
  133. EHCI_KdPrint((DeviceData, 1, "port[%d] resume (1) %x\n", portNumber, port.ul));
  134. // writing a 0 stops resume
  135. MASK_CHANGE_BITS(port);
  136. port.ForcePortResume = 0;
  137. port.PortSuspend = 0;
  138. WRITE_REGISTER_ULONG(&hcOp->PortRegister[portNumber-1].ul,
  139. port.ul);
  140. // indicate a change to suspend state ie resume complete
  141. SET_BIT(DeviceData->PortSuspendChange, portNumber-1);
  142. }
  143. USB_MINIPORT_STATUS
  144. EHCI_RH_ClearFeaturePortSuspend (
  145. PDEVICE_DATA DeviceData,
  146. USHORT PortNumber
  147. )
  148. {
  149. PHC_OPERATIONAL_REGISTER hcOp;
  150. PORTSC port;
  151. EHCI_PORT_EVENT_CONTEXT portResumeContext;
  152. // resume the port
  153. hcOp = DeviceData->OperationalRegisters;
  154. // mask off CC chirping on this port
  155. SET_BIT(DeviceData->PortPMChirp, PortNumber-1);
  156. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  157. // writing a 1 generates resume signalling
  158. port.ForcePortResume = 1;
  159. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul,
  160. port.ul);
  161. // time it
  162. portResumeContext.PortNumber = PortNumber;
  163. // some hubs require us to wait longer if the downstream
  164. // device drivers resume for > 10 ms. Looks like we need
  165. // 50 for the NEC B1 hub.
  166. USBPORT_REQUEST_ASYNC_CALLBACK(DeviceData,
  167. 50, // callback in ms,
  168. &portResumeContext,
  169. sizeof(portResumeContext),
  170. EHCI_RH_PortResumeComplete);
  171. return USBMP_STATUS_SUCCESS;
  172. }
  173. USB_MINIPORT_STATUS
  174. EHCI_RH_ClearFeaturePortSuspendChange (
  175. PDEVICE_DATA DeviceData,
  176. USHORT PortNumber
  177. )
  178. {
  179. PHC_OPERATIONAL_REGISTER hcOp;
  180. PORTSC port;
  181. hcOp = DeviceData->OperationalRegisters;
  182. CLEAR_BIT(DeviceData->PortSuspendChange, PortNumber-1);
  183. return USBMP_STATUS_SUCCESS;
  184. }
  185. USB_MINIPORT_STATUS
  186. EHCI_RH_ClearFeaturePortOvercurrentChange (
  187. PDEVICE_DATA DeviceData,
  188. USHORT PortNumber
  189. )
  190. {
  191. PHC_OPERATIONAL_REGISTER hcOp;
  192. PORTSC port;
  193. EHCI_KdPrint((DeviceData, 1,
  194. "'EHCI_RH_ClearFeatureOvercurrentChange\n"));
  195. hcOp = DeviceData->OperationalRegisters;
  196. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  197. MASK_CHANGE_BITS(port);
  198. port.OvercurrentChange = 1;
  199. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul,
  200. port.ul);
  201. return USBMP_STATUS_SUCCESS;
  202. }
  203. USB_MINIPORT_STATUS
  204. EHCI_RH_GetPortStatus(
  205. PDEVICE_DATA DeviceData,
  206. USHORT PortNumber,
  207. PRH_PORT_STATUS portStatus
  208. )
  209. /*++
  210. get the status of a partuclar port
  211. --*/
  212. {
  213. PHC_OPERATIONAL_REGISTER hcOp;
  214. PORTSC port;
  215. hcOp = DeviceData->OperationalRegisters;
  216. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  217. portStatus->ul = 0;
  218. LOGENTRY(DeviceData, G, '_Pp1', PortNumber, port.ul, 0);
  219. // low speed detect, if low speed then do an immediate
  220. // handoff to the CC
  221. // This field is only valid if enable status is 0 and
  222. // connect status is 1
  223. if ((port.LineStatus == 1) &&
  224. port.PortOwnedByCC == 0 &&
  225. port.PortSuspend == 0 &&
  226. port.PortEnable == 0 &&
  227. port.PortConnect == 1 ) {
  228. EHCI_KdPrint((DeviceData, 1, "'low speed device detected\n"));
  229. // low speed device detected
  230. port.PortOwnedByCC = 1;
  231. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul,
  232. port.ul);
  233. return USBMP_STATUS_SUCCESS;
  234. }
  235. // map the bits to the port status structure
  236. portStatus->Connected =
  237. port.PortConnect;
  238. portStatus->Enabled =
  239. port.PortEnable;
  240. portStatus->Suspended =
  241. port.PortSuspend;
  242. portStatus->OverCurrent =
  243. port.OvercurrentActive;
  244. portStatus->Reset =
  245. port.PortReset;
  246. portStatus->PowerOn =
  247. port.PortPower;
  248. portStatus->OwnedByCC =
  249. port.PortOwnedByCC;
  250. if (portStatus->Connected == 1) {
  251. portStatus->HighSpeed = 1;
  252. portStatus->LowSpeed = 0;
  253. } else {
  254. // report high speed when no device connected
  255. // this should work around a bug in the usbhub
  256. // driver -- the hub driver does not refresh the
  257. // port status register if the first reset attempt
  258. // fails.
  259. portStatus->HighSpeed = 1;
  260. }
  261. // chirping support allows us to use the
  262. // port change status bit
  263. if (port.PortConnectChange == 1) {
  264. SET_BIT(DeviceData->PortConnectChange, PortNumber-1);
  265. }
  266. portStatus->EnableChange =
  267. port.PortEnableChange;
  268. portStatus->OverCurrentChange =
  269. port.OvercurrentChange;
  270. // these change bits must be emulated
  271. if (TEST_BIT(DeviceData->PortResetChange, PortNumber-1)) {
  272. portStatus->ResetChange = 1;
  273. }
  274. if (TEST_BIT(DeviceData->PortConnectChange, PortNumber-1)) {
  275. portStatus->ConnectChange = 1;
  276. }
  277. if (TEST_BIT(DeviceData->PortSuspendChange, PortNumber-1)) {
  278. portStatus->SuspendChange = 1;
  279. }
  280. LOGENTRY(DeviceData, G, '_gps',
  281. PortNumber, portStatus->ul, port.ul);
  282. return USBMP_STATUS_SUCCESS;
  283. }
  284. VOID
  285. EHCI_RH_FinishReset(
  286. PDEVICE_DATA DeviceData,
  287. PVOID Context
  288. )
  289. /*++
  290. complete a port reset
  291. --*/
  292. {
  293. PHC_OPERATIONAL_REGISTER hcOp;
  294. PORTSC port;
  295. PEHCI_PORT_EVENT_CONTEXT portResetContext = Context;
  296. USHORT portNumber;
  297. ULONG NecUsb2HubHack = 0;
  298. hcOp = DeviceData->OperationalRegisters;
  299. portNumber = portResetContext->PortNumber;
  300. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[portNumber-1].ul);
  301. EHCI_KdPrint((DeviceData, 0, "port[%d] reset (4) %x\n", portNumber, port.ul));
  302. if (port.ul == 0xFFFFFFFF) {
  303. // just bail if hardware disappears
  304. return;
  305. }
  306. // at this point we will know if this is a high speed
  307. // device -- if it is not then we need to hand the port
  308. // to the CC
  309. // port enable of zero means we have a full or low speed
  310. // device (ie not chirping).
  311. #if DBG
  312. if (port.PortConnect == 0) {
  313. EHCI_KdPrint((DeviceData, 0, "HS device dropped\n"));
  314. }
  315. #endif
  316. if (port.PortEnable == 0 &&
  317. port.PortConnect == 1 &&
  318. port.PortConnectChange == 0) {
  319. // do the handoff
  320. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[portNumber-1].ul);
  321. port.PortOwnedByCC = 1;
  322. WRITE_REGISTER_ULONG(&hcOp->PortRegister[portNumber-1].ul,
  323. port.ul);
  324. // do not indicate a reset change, this will cause the
  325. // hub driver to timeout the reset and detect that
  326. // no device is connected. when this occurs on a USB 2
  327. // controller the hub driver will ignore the error.
  328. //CLEAR_BIT(DeviceData->PortResetChange, portNumber-1);
  329. SET_BIT(DeviceData->PortResetChange, portNumber-1);
  330. } else {
  331. // we have a USB 2.0 device, indicate the reset change
  332. // NOTE if the device dropped off the bus (NEC USB 2 hub or
  333. // user removed it) we still indicate a reset change on high
  334. // speed
  335. SET_BIT(DeviceData->PortResetChange, portNumber-1);
  336. USBPORT_INVALIDATE_ROOTHUB(DeviceData);
  337. }
  338. CLEAR_BIT(DeviceData->PortPMChirp, portNumber-1);
  339. }
  340. VOID
  341. EHCI_RH_PortResetComplete(
  342. PDEVICE_DATA DeviceData,
  343. PVOID Context
  344. )
  345. /*++
  346. complete a port reset
  347. --*/
  348. {
  349. PHC_OPERATIONAL_REGISTER hcOp;
  350. PORTSC port;
  351. PEHCI_PORT_EVENT_CONTEXT portResetContext = Context;
  352. USHORT portNumber;
  353. BOOLEAN forceHighSpeed = FALSE;
  354. ULONG microsecs;
  355. hcOp = DeviceData->OperationalRegisters;
  356. portNumber = portResetContext->PortNumber;
  357. EHCI_RH_PortResetComplete_Retry:
  358. microsecs = 0;
  359. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[portNumber-1].ul);
  360. LOGENTRY(DeviceData, G, '_prC', port.ul,
  361. DeviceData->PortResetChange, portNumber);
  362. EHCI_KdPrint((DeviceData, 0, "port[%d] reset (1) %x\n", portNumber, port.ul));
  363. // writing a 0 stops reset
  364. MASK_CHANGE_BITS(port);
  365. port.PortReset = 0;
  366. WRITE_REGISTER_ULONG(&hcOp->PortRegister[portNumber-1].ul,
  367. port.ul);
  368. // wait for reset to go low -- this should be on the order of
  369. // microseconds
  370. do {
  371. KeStallExecutionProcessor(20); // spec says 10 microseconds
  372. // Intel controller needs 20
  373. microsecs+=20;
  374. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[portNumber-1].ul);
  375. EHCI_KdPrint((DeviceData, 1, "port[%d] reset (2) %x\n",
  376. portNumber, port.ul));
  377. if (microsecs > USBEHCI_MAX_RESET_TIME) {
  378. // > 1 microframe (125 us) has passed, retry
  379. EHCI_KdPrint((DeviceData, 0, "port[%d] reset (timeout) %x\n", portNumber, port.ul));
  380. goto EHCI_RH_PortResetComplete_Retry;
  381. }
  382. // bail if HW is gone
  383. } while (port.PortReset == 1 && port.ul != 0xFFFFFFFF);
  384. EHCI_KdPrint((DeviceData, 0, "port[%d] reset (3) %x\n", portNumber, port.ul));
  385. USBPORT_REQUEST_ASYNC_CALLBACK(DeviceData,
  386. 50, // callback in 10 ms,
  387. portResetContext,
  388. sizeof(*portResetContext),
  389. EHCI_RH_FinishReset);
  390. }
  391. USB_MINIPORT_STATUS
  392. EHCI_RH_SetFeaturePortReset(
  393. PDEVICE_DATA DeviceData,
  394. USHORT PortNumber
  395. )
  396. /*++
  397. Put a port in reset
  398. --*/
  399. {
  400. PHC_OPERATIONAL_REGISTER hcOp;
  401. PORTSC port;
  402. EHCI_PORT_EVENT_CONTEXT portResetContext;
  403. hcOp = DeviceData->OperationalRegisters;
  404. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  405. LOGENTRY(DeviceData, G, '_spr', port.ul,
  406. 0, PortNumber);
  407. // mask off CC chirping on this port
  408. SET_BIT(DeviceData->PortPMChirp, PortNumber-1);
  409. // do a normal reset sequence
  410. LOGENTRY(DeviceData, G, '_res', port.ul, 0, PortNumber);
  411. MASK_CHANGE_BITS(port);
  412. port.PortEnable = 0;
  413. port.PortReset = 1;
  414. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul, port.ul);
  415. // schedule a callback
  416. portResetContext.PortNumber = PortNumber;
  417. // note that usbport calls us back with a copy of this
  418. // structure not the pointer to the original structure
  419. USBPORT_REQUEST_ASYNC_CALLBACK(DeviceData,
  420. 50, // callback in x ms,
  421. &portResetContext,
  422. sizeof(portResetContext),
  423. EHCI_RH_PortResetComplete);
  424. return USBMP_STATUS_SUCCESS;
  425. }
  426. USB_MINIPORT_STATUS
  427. EHCI_RH_SetFeaturePortSuspend(
  428. PDEVICE_DATA DeviceData,
  429. USHORT PortNumber
  430. )
  431. /*++
  432. Put a port in suspend
  433. --*/
  434. {
  435. PHC_OPERATIONAL_REGISTER hcOp;
  436. PORTSC port;
  437. hcOp = DeviceData->OperationalRegisters;
  438. // NOTE:
  439. // there should be no transactions in progress at the
  440. // time we suspend the port.
  441. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  442. LOGENTRY(DeviceData, G, '_sps', port.ul,
  443. 0, PortNumber);
  444. // writing a 1 suspends the port
  445. MASK_CHANGE_BITS(port);
  446. port.PortSuspend = 1;
  447. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul,
  448. port.ul);
  449. // wiat 1 microframe for current transaction to finish
  450. KeStallExecutionProcessor(125);
  451. return USBMP_STATUS_SUCCESS;
  452. }
  453. USB_MINIPORT_STATUS
  454. EHCI_RH_SetFeaturePortPower(
  455. PDEVICE_DATA DeviceData,
  456. USHORT PortNumber
  457. )
  458. /*++
  459. --*/
  460. {
  461. PHC_OPERATIONAL_REGISTER hcOp;
  462. PORTSC port;
  463. hcOp = DeviceData->OperationalRegisters;
  464. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  465. LOGENTRY(DeviceData, G, '_spp', port.ul,
  466. 0, PortNumber);
  467. // writing a 1 turns on power
  468. MASK_CHANGE_BITS(port);
  469. port.PortPower = 1;
  470. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul,
  471. port.ul);
  472. return USBMP_STATUS_SUCCESS;
  473. }
  474. USB_MINIPORT_STATUS
  475. EHCI_RH_SetFeaturePortEnable(
  476. PDEVICE_DATA DeviceData,
  477. USHORT PortNumber
  478. )
  479. /*++
  480. --*/
  481. {
  482. // do nothing, independent enable not supported
  483. return USBMP_STATUS_SUCCESS;
  484. }
  485. USB_MINIPORT_STATUS
  486. EHCI_RH_ClearFeaturePortConnectChange(
  487. PDEVICE_DATA DeviceData,
  488. USHORT PortNumber
  489. )
  490. /*++
  491. --*/
  492. {
  493. PHC_OPERATIONAL_REGISTER hcOp;
  494. PORTSC port;
  495. hcOp = DeviceData->OperationalRegisters;
  496. //
  497. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  498. LOGENTRY(DeviceData, G, '_pcc', port.ul,
  499. 0, PortNumber);
  500. // writing a 1 zeros the change bit
  501. if (port.PortConnectChange == 1) {
  502. // mask off other change bits
  503. MASK_CHANGE_BITS(port);
  504. port.PortConnectChange = 1;
  505. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul,
  506. port.ul);
  507. }
  508. CLEAR_BIT(DeviceData->PortConnectChange, PortNumber-1);
  509. return USBMP_STATUS_SUCCESS;
  510. }
  511. USB_MINIPORT_STATUS
  512. EHCI_RH_ClearFeaturePortEnableChange(
  513. PDEVICE_DATA DeviceData,
  514. USHORT PortNumber
  515. )
  516. /*++
  517. --*/
  518. {
  519. PHC_OPERATIONAL_REGISTER hcOp;
  520. PORTSC port;
  521. LOGENTRY(DeviceData, G, '_cpe', PortNumber, 0, 0);
  522. hcOp = DeviceData->OperationalRegisters;
  523. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  524. MASK_CHANGE_BITS(port);
  525. port.PortEnableChange = 1;
  526. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul, port.ul);
  527. return USBMP_STATUS_SUCCESS;
  528. }
  529. USB_MINIPORT_STATUS
  530. EHCI_RH_GetHubStatus(
  531. PDEVICE_DATA DeviceData,
  532. OUT PRH_HUB_STATUS HubStatus
  533. )
  534. /*++
  535. --*/
  536. {
  537. // nothing intersting for the root
  538. // hub to report
  539. HubStatus->ul = 0;
  540. return USBMP_STATUS_SUCCESS;
  541. }
  542. USB_MINIPORT_STATUS
  543. EHCI_RH_ClearFeaturePortResetChange(
  544. PDEVICE_DATA DeviceData,
  545. USHORT PortNumber
  546. )
  547. /*++
  548. --*/
  549. {
  550. CLEAR_BIT(DeviceData->PortResetChange, PortNumber-1);
  551. return USBMP_STATUS_SUCCESS;
  552. }
  553. VOID
  554. EHCI_OptumtuseratePort(
  555. PDEVICE_DATA DeviceData,
  556. USHORT PortNumber
  557. )
  558. /*++
  559. Forces the port to high speed mode.
  560. NOTE:
  561. Current mechanism only works on the NEC controller.
  562. --*/
  563. {
  564. PHC_OPERATIONAL_REGISTER hcOp;
  565. PORTSC port;
  566. LOGENTRY(DeviceData, G, '_obt', PortNumber, 0, 0);
  567. hcOp = DeviceData->OperationalRegisters;
  568. port.ul = 0x5100a;
  569. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul,
  570. port.ul);
  571. KeStallExecutionProcessor(10); //stall for 10 microseconds
  572. // force high speed mode on the port
  573. port.ul = 0x01005;
  574. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul,
  575. port.ul);
  576. KeStallExecutionProcessor(100); //stall for 10 microseconds
  577. }
  578. USB_MINIPORT_STATUS
  579. EHCI_RH_UsbprivRootPortStatus(
  580. PDEVICE_DATA DeviceData,
  581. ULONG ParameterLength,
  582. PVOID Parameters
  583. )
  584. {
  585. PUSBPRIV_ROOTPORT_STATUS portStatusParams;
  586. PHC_OPERATIONAL_REGISTER hcOp;
  587. PRH_PORT_STATUS portStatus;
  588. PORTSC port;
  589. USHORT portNumber;
  590. if (ParameterLength < sizeof(USBPRIV_ROOTPORT_STATUS))
  591. {
  592. return (USBMP_STATUS_FAILURE);
  593. }
  594. //
  595. // Read the port status for this port from the registers
  596. //
  597. hcOp = DeviceData->OperationalRegisters;
  598. portStatusParams = (PUSBPRIV_ROOTPORT_STATUS) Parameters;
  599. portNumber = portStatusParams->PortNumber;
  600. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[portNumber-1].ul);
  601. LOGENTRY(DeviceData, G, '_Up1', portNumber, port.ul, 0);
  602. //
  603. // Check to see if the port is resuming. If so, clear the bit and
  604. // reenable the port.
  605. //
  606. if (port.ForcePortResume)
  607. {
  608. //
  609. // Clear the port resume
  610. //
  611. USBPORT_WAIT(DeviceData, 50);
  612. MASK_CHANGE_BITS(port);
  613. port.ForcePortResume = 0;
  614. port.PortSuspend = 0;
  615. WRITE_REGISTER_ULONG(&hcOp->PortRegister[portNumber-1].ul, port.ul);
  616. //
  617. // Reread the port status
  618. //
  619. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[portNumber-1].ul);
  620. SET_BIT(DeviceData->PortSuspendChange, portNumber-1);
  621. LOGENTRY(DeviceData, G, '_Up2', portNumber, port.ul, 0);
  622. }
  623. //
  624. // Map the current port information to the port status
  625. //
  626. portStatus = &portStatusParams->PortStatus;
  627. portStatus->ul = 0;
  628. portStatus->Connected =
  629. port.PortConnect;
  630. portStatus->Enabled =
  631. port.PortEnable;
  632. portStatus->Suspended =
  633. port.PortSuspend;
  634. portStatus->OverCurrent =
  635. port.OvercurrentActive;
  636. portStatus->Reset =
  637. port.PortReset;
  638. portStatus->PowerOn =
  639. port.PortPower;
  640. portStatus->OwnedByCC =
  641. port.PortOwnedByCC;
  642. if (portStatus->Connected == 1) {
  643. portStatus->HighSpeed = 1;
  644. portStatus->LowSpeed = 0;
  645. } else {
  646. // report high speed when no device connected
  647. // this should work around a bug in the usbhub
  648. // driver -- the hub driver does not refresh the
  649. // port status register if the first reset attempt
  650. // fails.
  651. portStatus->HighSpeed = 1;
  652. }
  653. portStatus->ConnectChange =
  654. port.PortConnectChange;
  655. portStatus->EnableChange =
  656. port.PortEnableChange;
  657. portStatus->OverCurrentChange =
  658. port.OvercurrentChange;
  659. // these change bits must be emulated
  660. if (TEST_BIT(DeviceData->PortResetChange, portNumber-1)) {
  661. portStatus->ResetChange = 1;
  662. }
  663. if (TEST_BIT(DeviceData->PortConnectChange, portNumber-1)) {
  664. portStatus->ConnectChange = 1;
  665. }
  666. if (TEST_BIT(DeviceData->PortSuspendChange, portNumber-1)) {
  667. portStatus->SuspendChange = 1;
  668. }
  669. LOGENTRY(DeviceData, G, '_Ups',
  670. portNumber, portStatus->ul, port.ul);
  671. return USBMP_STATUS_SUCCESS;
  672. }
  673. USB_MINIPORT_STATUS
  674. EHCI_RH_ChirpRootPort(
  675. PDEVICE_DATA DeviceData,
  676. USHORT PortNumber
  677. )
  678. {
  679. PHC_OPERATIONAL_REGISTER hcOp;
  680. PORTSC port;
  681. EHCI_PORT_EVENT_CONTEXT portResetContext;
  682. ULONG mics;
  683. hcOp = DeviceData->OperationalRegisters;
  684. #if DBG
  685. {
  686. USBCMD cmd;
  687. cmd.ul = READ_REGISTER_ULONG(&hcOp->UsbCommand.ul);
  688. EHCI_ASSERT(DeviceData, cmd.HostControllerRun == 1);
  689. }
  690. #endif
  691. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  692. LOGENTRY(DeviceData, G, '_chr', port.ul,
  693. 0, PortNumber);
  694. EHCI_KdPrint((DeviceData, 0, ">port[%d] chirp %x\n", PortNumber, port.ul));
  695. if (TEST_BIT(DeviceData->PortPMChirp, PortNumber-1)) {
  696. // skip the chirp if we have already done this
  697. EHCI_KdPrint((DeviceData, 0, "<skip port chirp[%d] %x\n", PortNumber, port.ul));
  698. return USBMP_STATUS_SUCCESS;
  699. }
  700. if (!port.PortPower) {
  701. // skip if not powered, this will cause us to
  702. // bypass the chirp if the controller has not initialized
  703. // such as in the case of BOOT
  704. EHCI_KdPrint((DeviceData, 0, "<skip port chirp[%d] %x, no power\n", PortNumber, port.ul));
  705. return USBMP_STATUS_SUCCESS;
  706. }
  707. // port is connect and not enabled and not owned by CC
  708. // therefore we should probably chirp it
  709. if (port.PortConnect &&
  710. !port.PortEnable &&
  711. !port.PortOwnedByCC) {
  712. //TEST_TRAP();
  713. // quick check for handoff of LS devices
  714. if ((port.LineStatus == 1) &&
  715. port.PortOwnedByCC == 0 &&
  716. port.PortSuspend == 0 &&
  717. port.PortEnable == 0 &&
  718. port.PortConnect == 1 ) {
  719. // low speed device detected
  720. port.PortOwnedByCC = 1;
  721. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul,
  722. port.ul);
  723. EHCI_KdPrint((DeviceData, 0, ">port chirp[%d] %x, ->cc(1)\n", PortNumber,
  724. port.ul));
  725. return USBMP_STATUS_SUCCESS;
  726. }
  727. // do a normal reset sequence
  728. LOGENTRY(DeviceData, G, '_rss', port.ul, 0, PortNumber);
  729. // set reset and clear connect change
  730. port.PortEnable = 0;
  731. port.PortReset = 1;
  732. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul, port.ul);
  733. USBPORT_WAIT(DeviceData, 10);
  734. EHCI_RH_ChirpRootPort_Retry:
  735. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  736. MASK_CHANGE_BITS(port);
  737. port.PortReset = 0;
  738. mics = 0;
  739. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul, port.ul);
  740. // wait for reset to go low -- this should be on the order of
  741. // microseconds
  742. do {
  743. // writing a 0 stops reset
  744. KeStallExecutionProcessor(20); // spec says 10 microseconds
  745. // Intel controller needs 20
  746. mics +=20;
  747. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  748. EHCI_KdPrint((DeviceData, 1, "port reset (2) %x\n", port.ul));
  749. if (mics > USBEHCI_MAX_RESET_TIME) {
  750. // reset did not clear in 1 microframe, try again to clear it
  751. goto EHCI_RH_ChirpRootPort_Retry;
  752. }
  753. } while (port.PortReset == 1);
  754. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  755. if (port.PortEnable == 0) {
  756. // do the handoff
  757. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  758. port.PortOwnedByCC = 1;
  759. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul,
  760. port.ul);
  761. EHCI_KdPrint((DeviceData, 0, "<port chirp[%d] %x, ->cc(2)\n", PortNumber,
  762. port.ul));
  763. } else {
  764. // clear the enable bit so the device does not listen
  765. // on address 0
  766. port.ul = READ_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul);
  767. port.PortEnable = 0;
  768. MASK_CHANGE_BITS(port);
  769. // allow some SOFs before we disable
  770. // The Cypress USB 2 device will drop off the bus if it doen't see
  771. // any SOFs
  772. USBPORT_WAIT(DeviceData, 10);
  773. SET_BIT(DeviceData->PortPMChirp, PortNumber-1);
  774. WRITE_REGISTER_ULONG(&hcOp->PortRegister[PortNumber-1].ul,
  775. port.ul);
  776. EHCI_KdPrint((DeviceData, 0, "<chirp port[%d] disable %x\n",
  777. PortNumber, port.ul));
  778. }
  779. } else {
  780. EHCI_KdPrint((DeviceData, 0, "<no port chirp[%d] %x\n", PortNumber, port.ul));
  781. }
  782. return USBMP_STATUS_SUCCESS;
  783. }