Xhci.c 73 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296
  1. /** @file
  2. The XHCI controller driver.
  3. Copyright (c) 2011 - 2022, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "Xhci.h"
  7. //
  8. // Two arrays used to translate the XHCI port state (change)
  9. // to the UEFI protocol's port state (change).
  10. //
  11. USB_PORT_STATE_MAP mUsbPortStateMap[] = {
  12. { XHC_PORTSC_CCS, USB_PORT_STAT_CONNECTION },
  13. { XHC_PORTSC_PED, USB_PORT_STAT_ENABLE },
  14. { XHC_PORTSC_OCA, USB_PORT_STAT_OVERCURRENT },
  15. { XHC_PORTSC_RESET, USB_PORT_STAT_RESET }
  16. };
  17. USB_PORT_STATE_MAP mUsbPortChangeMap[] = {
  18. { XHC_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION },
  19. { XHC_PORTSC_PEC, USB_PORT_STAT_C_ENABLE },
  20. { XHC_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT },
  21. { XHC_PORTSC_PRC, USB_PORT_STAT_C_RESET }
  22. };
  23. USB_CLEAR_PORT_MAP mUsbClearPortChangeMap[] = {
  24. { XHC_PORTSC_CSC, EfiUsbPortConnectChange },
  25. { XHC_PORTSC_PEC, EfiUsbPortEnableChange },
  26. { XHC_PORTSC_OCC, EfiUsbPortOverCurrentChange },
  27. { XHC_PORTSC_PRC, EfiUsbPortResetChange }
  28. };
  29. USB_PORT_STATE_MAP mUsbHubPortStateMap[] = {
  30. { XHC_HUB_PORTSC_CCS, USB_PORT_STAT_CONNECTION },
  31. { XHC_HUB_PORTSC_PED, USB_PORT_STAT_ENABLE },
  32. { XHC_HUB_PORTSC_OCA, USB_PORT_STAT_OVERCURRENT },
  33. { XHC_HUB_PORTSC_RESET, USB_PORT_STAT_RESET }
  34. };
  35. USB_PORT_STATE_MAP mUsbHubPortChangeMap[] = {
  36. { XHC_HUB_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION },
  37. { XHC_HUB_PORTSC_PEC, USB_PORT_STAT_C_ENABLE },
  38. { XHC_HUB_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT },
  39. { XHC_HUB_PORTSC_PRC, USB_PORT_STAT_C_RESET }
  40. };
  41. USB_CLEAR_PORT_MAP mUsbHubClearPortChangeMap[] = {
  42. { XHC_HUB_PORTSC_CSC, EfiUsbPortConnectChange },
  43. { XHC_HUB_PORTSC_PEC, EfiUsbPortEnableChange },
  44. { XHC_HUB_PORTSC_OCC, EfiUsbPortOverCurrentChange },
  45. { XHC_HUB_PORTSC_PRC, EfiUsbPortResetChange },
  46. { XHC_HUB_PORTSC_BHRC, Usb3PortBHPortResetChange }
  47. };
  48. EFI_DRIVER_BINDING_PROTOCOL gXhciDriverBinding = {
  49. XhcDriverBindingSupported,
  50. XhcDriverBindingStart,
  51. XhcDriverBindingStop,
  52. 0x30,
  53. NULL,
  54. NULL
  55. };
  56. //
  57. // Template for Xhci's Usb2 Host Controller Protocol Instance.
  58. //
  59. EFI_USB2_HC_PROTOCOL gXhciUsb2HcTemplate = {
  60. XhcGetCapability,
  61. XhcReset,
  62. XhcGetState,
  63. XhcSetState,
  64. XhcControlTransfer,
  65. XhcBulkTransfer,
  66. XhcAsyncInterruptTransfer,
  67. XhcSyncInterruptTransfer,
  68. XhcIsochronousTransfer,
  69. XhcAsyncIsochronousTransfer,
  70. XhcGetRootHubPortStatus,
  71. XhcSetRootHubPortFeature,
  72. XhcClearRootHubPortFeature,
  73. 0x3,
  74. 0x0
  75. };
  76. /**
  77. Retrieves the capability of root hub ports.
  78. @param This The EFI_USB2_HC_PROTOCOL instance.
  79. @param MaxSpeed Max speed supported by the controller.
  80. @param PortNumber Number of the root hub ports.
  81. @param Is64BitCapable Whether the controller supports 64-bit memory
  82. addressing.
  83. @retval EFI_SUCCESS Host controller capability were retrieved successfully.
  84. @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.
  85. **/
  86. EFI_STATUS
  87. EFIAPI
  88. XhcGetCapability (
  89. IN EFI_USB2_HC_PROTOCOL *This,
  90. OUT UINT8 *MaxSpeed,
  91. OUT UINT8 *PortNumber,
  92. OUT UINT8 *Is64BitCapable
  93. )
  94. {
  95. USB_XHCI_INSTANCE *Xhc;
  96. EFI_TPL OldTpl;
  97. if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {
  98. return EFI_INVALID_PARAMETER;
  99. }
  100. OldTpl = gBS->RaiseTPL (XHC_TPL);
  101. Xhc = XHC_FROM_THIS (This);
  102. *MaxSpeed = EFI_USB_SPEED_SUPER;
  103. *PortNumber = (UINT8)(Xhc->HcSParams1.Data.MaxPorts);
  104. *Is64BitCapable = (UINT8)Xhc->Support64BitDma;
  105. DEBUG ((DEBUG_INFO, "XhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));
  106. gBS->RestoreTPL (OldTpl);
  107. return EFI_SUCCESS;
  108. }
  109. /**
  110. Provides software reset for the USB host controller.
  111. @param This This EFI_USB2_HC_PROTOCOL instance.
  112. @param Attributes A bit mask of the reset operation to perform.
  113. @retval EFI_SUCCESS The reset operation succeeded.
  114. @retval EFI_INVALID_PARAMETER Attributes is not valid.
  115. @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
  116. not currently supported by the host controller.
  117. @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
  118. **/
  119. EFI_STATUS
  120. EFIAPI
  121. XhcReset (
  122. IN EFI_USB2_HC_PROTOCOL *This,
  123. IN UINT16 Attributes
  124. )
  125. {
  126. USB_XHCI_INSTANCE *Xhc;
  127. EFI_STATUS Status;
  128. EFI_TPL OldTpl;
  129. Xhc = XHC_FROM_THIS (This);
  130. if (Xhc->DevicePath != NULL) {
  131. //
  132. // Report Status Code to indicate reset happens
  133. //
  134. REPORT_STATUS_CODE_WITH_DEVICE_PATH (
  135. EFI_PROGRESS_CODE,
  136. (EFI_IO_BUS_USB | EFI_IOB_PC_RESET),
  137. Xhc->DevicePath
  138. );
  139. }
  140. OldTpl = gBS->RaiseTPL (XHC_TPL);
  141. switch (Attributes) {
  142. case EFI_USB_HC_RESET_GLOBAL:
  143. //
  144. // Flow through, same behavior as Host Controller Reset
  145. //
  146. case EFI_USB_HC_RESET_HOST_CONTROLLER:
  147. if ((Xhc->DebugCapSupOffset != 0xFFFFFFFF) && ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset) & 0xFF) == XHC_CAP_USB_DEBUG) &&
  148. ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset + XHC_DC_DCCTRL) & BIT0) != 0))
  149. {
  150. Status = EFI_SUCCESS;
  151. goto ON_EXIT;
  152. }
  153. //
  154. // Host Controller must be Halt when Reset it
  155. //
  156. if (!XhcIsHalt (Xhc)) {
  157. Status = XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
  158. if (EFI_ERROR (Status)) {
  159. Status = EFI_DEVICE_ERROR;
  160. goto ON_EXIT;
  161. }
  162. }
  163. Status = XhcResetHC (Xhc, XHC_RESET_TIMEOUT);
  164. ASSERT (!(XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_CNR)));
  165. if (EFI_ERROR (Status)) {
  166. goto ON_EXIT;
  167. }
  168. //
  169. // Clean up the asynchronous transfers, currently only
  170. // interrupt supports asynchronous operation.
  171. //
  172. XhciDelAllAsyncIntTransfers (Xhc);
  173. XhcFreeSched (Xhc);
  174. XhcInitSched (Xhc);
  175. break;
  176. case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:
  177. case EFI_USB_HC_RESET_HOST_WITH_DEBUG:
  178. Status = EFI_UNSUPPORTED;
  179. break;
  180. default:
  181. Status = EFI_INVALID_PARAMETER;
  182. }
  183. ON_EXIT:
  184. DEBUG ((DEBUG_INFO, "XhcReset: status %r\n", Status));
  185. gBS->RestoreTPL (OldTpl);
  186. return Status;
  187. }
  188. /**
  189. Retrieve the current state of the USB host controller.
  190. @param This This EFI_USB2_HC_PROTOCOL instance.
  191. @param State Variable to return the current host controller
  192. state.
  193. @retval EFI_SUCCESS Host controller state was returned in State.
  194. @retval EFI_INVALID_PARAMETER State is NULL.
  195. @retval EFI_DEVICE_ERROR An error was encountered while attempting to
  196. retrieve the host controller's current state.
  197. **/
  198. EFI_STATUS
  199. EFIAPI
  200. XhcGetState (
  201. IN EFI_USB2_HC_PROTOCOL *This,
  202. OUT EFI_USB_HC_STATE *State
  203. )
  204. {
  205. USB_XHCI_INSTANCE *Xhc;
  206. EFI_TPL OldTpl;
  207. if (State == NULL) {
  208. return EFI_INVALID_PARAMETER;
  209. }
  210. OldTpl = gBS->RaiseTPL (XHC_TPL);
  211. Xhc = XHC_FROM_THIS (This);
  212. if (XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {
  213. *State = EfiUsbHcStateHalt;
  214. } else {
  215. *State = EfiUsbHcStateOperational;
  216. }
  217. DEBUG ((DEBUG_INFO, "XhcGetState: current state %d\n", *State));
  218. gBS->RestoreTPL (OldTpl);
  219. return EFI_SUCCESS;
  220. }
  221. /**
  222. Sets the USB host controller to a specific state.
  223. @param This This EFI_USB2_HC_PROTOCOL instance.
  224. @param State The state of the host controller that will be set.
  225. @retval EFI_SUCCESS The USB host controller was successfully placed
  226. in the state specified by State.
  227. @retval EFI_INVALID_PARAMETER State is invalid.
  228. @retval EFI_DEVICE_ERROR Failed to set the state due to device error.
  229. **/
  230. EFI_STATUS
  231. EFIAPI
  232. XhcSetState (
  233. IN EFI_USB2_HC_PROTOCOL *This,
  234. IN EFI_USB_HC_STATE State
  235. )
  236. {
  237. USB_XHCI_INSTANCE *Xhc;
  238. EFI_STATUS Status;
  239. EFI_USB_HC_STATE CurState;
  240. EFI_TPL OldTpl;
  241. Status = XhcGetState (This, &CurState);
  242. if (EFI_ERROR (Status)) {
  243. return EFI_DEVICE_ERROR;
  244. }
  245. if (CurState == State) {
  246. return EFI_SUCCESS;
  247. }
  248. OldTpl = gBS->RaiseTPL (XHC_TPL);
  249. Xhc = XHC_FROM_THIS (This);
  250. switch (State) {
  251. case EfiUsbHcStateHalt:
  252. Status = XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
  253. break;
  254. case EfiUsbHcStateOperational:
  255. if (XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HSE)) {
  256. Status = EFI_DEVICE_ERROR;
  257. break;
  258. }
  259. //
  260. // Software must not write a one to this field unless the host controller
  261. // is in the Halted state. Doing so will yield undefined results.
  262. // refers to Spec[XHCI1.0-2.3.1]
  263. //
  264. if (!XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {
  265. Status = EFI_DEVICE_ERROR;
  266. break;
  267. }
  268. Status = XhcRunHC (Xhc, XHC_GENERIC_TIMEOUT);
  269. break;
  270. case EfiUsbHcStateSuspend:
  271. Status = EFI_UNSUPPORTED;
  272. break;
  273. default:
  274. Status = EFI_INVALID_PARAMETER;
  275. }
  276. DEBUG ((DEBUG_INFO, "XhcSetState: status %r\n", Status));
  277. gBS->RestoreTPL (OldTpl);
  278. return Status;
  279. }
  280. /**
  281. Retrieves the current status of a USB root hub port.
  282. @param This This EFI_USB2_HC_PROTOCOL instance.
  283. @param PortNumber The root hub port to retrieve the state from.
  284. This value is zero-based.
  285. @param PortStatus Variable to receive the port state.
  286. @retval EFI_SUCCESS The status of the USB root hub port specified.
  287. by PortNumber was returned in PortStatus.
  288. @retval EFI_INVALID_PARAMETER PortNumber is invalid.
  289. @retval EFI_DEVICE_ERROR Can't read register.
  290. **/
  291. EFI_STATUS
  292. EFIAPI
  293. XhcGetRootHubPortStatus (
  294. IN EFI_USB2_HC_PROTOCOL *This,
  295. IN UINT8 PortNumber,
  296. OUT EFI_USB_PORT_STATUS *PortStatus
  297. )
  298. {
  299. USB_XHCI_INSTANCE *Xhc;
  300. UINT32 Offset;
  301. UINT32 State;
  302. UINT32 TotalPort;
  303. UINTN Index;
  304. UINTN MapSize;
  305. UINT8 PortSpeed;
  306. EFI_STATUS Status;
  307. USB_DEV_ROUTE ParentRouteChart;
  308. EFI_TPL OldTpl;
  309. if (PortStatus == NULL) {
  310. return EFI_INVALID_PARAMETER;
  311. }
  312. OldTpl = gBS->RaiseTPL (XHC_TPL);
  313. Xhc = XHC_FROM_THIS (This);
  314. Status = EFI_SUCCESS;
  315. TotalPort = Xhc->HcSParams1.Data.MaxPorts;
  316. if (PortNumber >= TotalPort) {
  317. Status = EFI_INVALID_PARAMETER;
  318. goto ON_EXIT;
  319. }
  320. Offset = (UINT32)(XHC_PORTSC_OFFSET + (0x10 * PortNumber));
  321. PortStatus->PortStatus = 0;
  322. PortStatus->PortChangeStatus = 0;
  323. State = XhcReadOpReg (Xhc, Offset);
  324. PortSpeed = (State & XHC_PORTSC_PS) >> 10;
  325. //
  326. // According to XHCI 1.1 spec November 2017,
  327. // Section 7.2 xHCI Support Protocol Capability
  328. //
  329. if (PortSpeed > 0) {
  330. PortStatus->PortStatus = XhcCheckUsbPortSpeedUsedPsic (Xhc, PortSpeed, PortNumber);
  331. // If no match found in ext cap reg, fall back to PORTSC
  332. if (PortStatus->PortStatus == 0) {
  333. //
  334. // According to XHCI 1.1 spec November 2017,
  335. // bit 10~13 of the root port status register identifies the speed of the attached device.
  336. //
  337. switch (PortSpeed) {
  338. case 2:
  339. PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
  340. break;
  341. case 3:
  342. PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
  343. break;
  344. case 4:
  345. case 5:
  346. PortStatus->PortStatus |= USB_PORT_STAT_SUPER_SPEED;
  347. break;
  348. default:
  349. break;
  350. }
  351. }
  352. }
  353. //
  354. // Convert the XHCI port/port change state to UEFI status
  355. //
  356. MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
  357. for (Index = 0; Index < MapSize; Index++) {
  358. if (XHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
  359. PortStatus->PortStatus = (UINT16)(PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);
  360. }
  361. }
  362. //
  363. // Bit5~8 reflects its current link state.
  364. //
  365. if ((State & XHC_PORTSC_PLS) >> 5 == 3) {
  366. PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
  367. }
  368. MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
  369. for (Index = 0; Index < MapSize; Index++) {
  370. if (XHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
  371. PortStatus->PortChangeStatus = (UINT16)(PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
  372. }
  373. }
  374. MapSize = sizeof (mUsbClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);
  375. for (Index = 0; Index < MapSize; Index++) {
  376. if (XHC_BIT_IS_SET (State, mUsbClearPortChangeMap[Index].HwState)) {
  377. XhcClearRootHubPortFeature (This, PortNumber, (EFI_USB_PORT_FEATURE)mUsbClearPortChangeMap[Index].Selector);
  378. }
  379. }
  380. //
  381. // Poll the root port status register to enable/disable corresponding device slot if there is a device attached/detached.
  382. // For those devices behind hub, we get its attach/detach event by hooking Get_Port_Status request at control transfer for those hub.
  383. //
  384. ParentRouteChart.Dword = 0;
  385. Status = XhcPollPortStatusChange (Xhc, ParentRouteChart, PortNumber, PortStatus);
  386. //
  387. // Force resetting the port by clearing the USB_PORT_STAT_C_RESET bit in PortChangeStatus
  388. // when XhcPollPortStatusChange fails
  389. //
  390. if (EFI_ERROR (Status)) {
  391. PortStatus->PortChangeStatus &= ~(USB_PORT_STAT_C_RESET);
  392. Status = EFI_SUCCESS;
  393. }
  394. ON_EXIT:
  395. gBS->RestoreTPL (OldTpl);
  396. return Status;
  397. }
  398. /**
  399. Sets a feature for the specified root hub port.
  400. @param This This EFI_USB2_HC_PROTOCOL instance.
  401. @param PortNumber Root hub port to set.
  402. @param PortFeature Feature to set.
  403. @retval EFI_SUCCESS The feature specified by PortFeature was set.
  404. @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
  405. @retval EFI_DEVICE_ERROR Can't read register.
  406. **/
  407. EFI_STATUS
  408. EFIAPI
  409. XhcSetRootHubPortFeature (
  410. IN EFI_USB2_HC_PROTOCOL *This,
  411. IN UINT8 PortNumber,
  412. IN EFI_USB_PORT_FEATURE PortFeature
  413. )
  414. {
  415. USB_XHCI_INSTANCE *Xhc;
  416. UINT32 Offset;
  417. UINT32 State;
  418. UINT32 TotalPort;
  419. EFI_STATUS Status;
  420. EFI_TPL OldTpl;
  421. OldTpl = gBS->RaiseTPL (XHC_TPL);
  422. Xhc = XHC_FROM_THIS (This);
  423. Status = EFI_SUCCESS;
  424. TotalPort = (Xhc->HcSParams1.Data.MaxPorts);
  425. if (PortNumber >= TotalPort) {
  426. Status = EFI_INVALID_PARAMETER;
  427. goto ON_EXIT;
  428. }
  429. Offset = (UINT32)(XHC_PORTSC_OFFSET + (0x10 * PortNumber));
  430. State = XhcReadOpReg (Xhc, Offset);
  431. //
  432. // Mask off the port status change bits, these bits are
  433. // write clean bit
  434. //
  435. State &= ~(BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);
  436. switch (PortFeature) {
  437. case EfiUsbPortEnable:
  438. //
  439. // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.
  440. // A port may be disabled by software writing a '1' to this flag.
  441. //
  442. Status = EFI_SUCCESS;
  443. break;
  444. case EfiUsbPortSuspend:
  445. State |= XHC_PORTSC_LWS;
  446. XhcWriteOpReg (Xhc, Offset, State);
  447. State &= ~XHC_PORTSC_PLS;
  448. State |= (3 << 5);
  449. XhcWriteOpReg (Xhc, Offset, State);
  450. break;
  451. case EfiUsbPortReset:
  452. DEBUG ((DEBUG_INFO, "XhcUsbPortReset!\n"));
  453. //
  454. // Make sure Host Controller not halt before reset it
  455. //
  456. if (XhcIsHalt (Xhc)) {
  457. Status = XhcRunHC (Xhc, XHC_GENERIC_TIMEOUT);
  458. if (EFI_ERROR (Status)) {
  459. DEBUG ((DEBUG_INFO, "XhcSetRootHubPortFeature :failed to start HC - %r\n", Status));
  460. break;
  461. }
  462. }
  463. //
  464. // 4.3.1 Resetting a Root Hub Port
  465. // 1) Write the PORTSC register with the Port Reset (PR) bit set to '1'.
  466. //
  467. State |= XHC_PORTSC_RESET;
  468. XhcWriteOpReg (Xhc, Offset, State);
  469. XhcWaitOpRegBit (Xhc, Offset, XHC_PORTSC_PRC, TRUE, XHC_GENERIC_TIMEOUT);
  470. break;
  471. case EfiUsbPortPower:
  472. //
  473. // Not supported, ignore the operation
  474. //
  475. Status = EFI_SUCCESS;
  476. break;
  477. case EfiUsbPortOwner:
  478. //
  479. // XHCI root hub port don't has the owner bit, ignore the operation
  480. //
  481. Status = EFI_SUCCESS;
  482. break;
  483. default:
  484. Status = EFI_INVALID_PARAMETER;
  485. }
  486. ON_EXIT:
  487. DEBUG ((DEBUG_INFO, "XhcSetRootHubPortFeature: status %r\n", Status));
  488. gBS->RestoreTPL (OldTpl);
  489. return Status;
  490. }
  491. /**
  492. Clears a feature for the specified root hub port.
  493. @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
  494. @param PortNumber Specifies the root hub port whose feature is
  495. requested to be cleared.
  496. @param PortFeature Indicates the feature selector associated with the
  497. feature clear request.
  498. @retval EFI_SUCCESS The feature specified by PortFeature was cleared
  499. for the USB root hub port specified by PortNumber.
  500. @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
  501. @retval EFI_DEVICE_ERROR Can't read register.
  502. **/
  503. EFI_STATUS
  504. EFIAPI
  505. XhcClearRootHubPortFeature (
  506. IN EFI_USB2_HC_PROTOCOL *This,
  507. IN UINT8 PortNumber,
  508. IN EFI_USB_PORT_FEATURE PortFeature
  509. )
  510. {
  511. USB_XHCI_INSTANCE *Xhc;
  512. UINT32 Offset;
  513. UINT32 State;
  514. UINT32 TotalPort;
  515. EFI_STATUS Status;
  516. EFI_TPL OldTpl;
  517. OldTpl = gBS->RaiseTPL (XHC_TPL);
  518. Xhc = XHC_FROM_THIS (This);
  519. Status = EFI_SUCCESS;
  520. TotalPort = (Xhc->HcSParams1.Data.MaxPorts);
  521. if (PortNumber >= TotalPort) {
  522. Status = EFI_INVALID_PARAMETER;
  523. goto ON_EXIT;
  524. }
  525. Offset = XHC_PORTSC_OFFSET + (0x10 * PortNumber);
  526. //
  527. // Mask off the port status change bits, these bits are
  528. // write clean bit
  529. //
  530. State = XhcReadOpReg (Xhc, Offset);
  531. State &= ~(BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);
  532. switch (PortFeature) {
  533. case EfiUsbPortEnable:
  534. //
  535. // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.
  536. // A port may be disabled by software writing a '1' to this flag.
  537. //
  538. State |= XHC_PORTSC_PED;
  539. State &= ~XHC_PORTSC_RESET;
  540. XhcWriteOpReg (Xhc, Offset, State);
  541. break;
  542. case EfiUsbPortSuspend:
  543. State |= XHC_PORTSC_LWS;
  544. XhcWriteOpReg (Xhc, Offset, State);
  545. State &= ~XHC_PORTSC_PLS;
  546. XhcWriteOpReg (Xhc, Offset, State);
  547. break;
  548. case EfiUsbPortReset:
  549. //
  550. // PORTSC_RESET BIT(4) bit is RW1S attribute, which means Write-1-to-set status:
  551. // Register bits indicate status when read, a clear bit may be set by
  552. // writing a '1'. Writing a '0' to RW1S bits has no effect.
  553. //
  554. break;
  555. case EfiUsbPortOwner:
  556. //
  557. // XHCI root hub port don't has the owner bit, ignore the operation
  558. //
  559. break;
  560. case EfiUsbPortConnectChange:
  561. //
  562. // Clear connect status change
  563. //
  564. State |= XHC_PORTSC_CSC;
  565. XhcWriteOpReg (Xhc, Offset, State);
  566. break;
  567. case EfiUsbPortEnableChange:
  568. //
  569. // Clear enable status change
  570. //
  571. State |= XHC_PORTSC_PEC;
  572. XhcWriteOpReg (Xhc, Offset, State);
  573. break;
  574. case EfiUsbPortOverCurrentChange:
  575. //
  576. // Clear PortOverCurrent change
  577. //
  578. State |= XHC_PORTSC_OCC;
  579. XhcWriteOpReg (Xhc, Offset, State);
  580. break;
  581. case EfiUsbPortResetChange:
  582. //
  583. // Clear Port Reset change
  584. //
  585. State |= XHC_PORTSC_PRC;
  586. XhcWriteOpReg (Xhc, Offset, State);
  587. break;
  588. case EfiUsbPortPower:
  589. case EfiUsbPortSuspendChange:
  590. //
  591. // Not supported or not related operation
  592. //
  593. break;
  594. default:
  595. Status = EFI_INVALID_PARAMETER;
  596. break;
  597. }
  598. ON_EXIT:
  599. DEBUG ((DEBUG_INFO, "XhcClearRootHubPortFeature: status %r\n", Status));
  600. gBS->RestoreTPL (OldTpl);
  601. return Status;
  602. }
  603. /**
  604. Submits a new transaction to a target USB device.
  605. @param Xhc The XHCI Instance.
  606. @param DeviceAddress The target device address.
  607. @param EndPointAddress Endpoint number and its direction encoded in bit 7
  608. @param DeviceSpeed Target device speed.
  609. @param MaximumPacketLength Maximum packet size the default control transfer
  610. endpoint is capable of sending or receiving.
  611. @param Type The transaction type.
  612. @param Request USB device request to send.
  613. @param Data Data buffer to be transmitted or received from USB
  614. device.
  615. @param DataLength The size (in bytes) of the data buffer.
  616. @param Timeout Indicates the maximum timeout, in millisecond.
  617. @param TransferResult Return the result of this control transfer.
  618. @retval EFI_SUCCESS Transfer was completed successfully.
  619. @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
  620. @retval EFI_INVALID_PARAMETER Some parameters are invalid.
  621. @retval EFI_TIMEOUT Transfer failed due to timeout.
  622. @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
  623. **/
  624. EFI_STATUS
  625. XhcTransfer (
  626. IN USB_XHCI_INSTANCE *Xhc,
  627. IN UINT8 DeviceAddress,
  628. IN UINT8 EndPointAddress,
  629. IN UINT8 DeviceSpeed,
  630. IN UINTN MaximumPacketLength,
  631. IN UINTN Type,
  632. IN EFI_USB_DEVICE_REQUEST *Request,
  633. IN OUT VOID *Data,
  634. IN OUT UINTN *DataLength,
  635. IN UINTN Timeout,
  636. OUT UINT32 *TransferResult
  637. )
  638. {
  639. EFI_STATUS Status;
  640. EFI_STATUS RecoveryStatus;
  641. URB *Urb;
  642. ASSERT ((Type == XHC_CTRL_TRANSFER) || (Type == XHC_BULK_TRANSFER) || (Type == XHC_INT_TRANSFER_SYNC));
  643. Urb = XhcCreateUrb (
  644. Xhc,
  645. DeviceAddress,
  646. EndPointAddress,
  647. DeviceSpeed,
  648. MaximumPacketLength,
  649. Type,
  650. Request,
  651. Data,
  652. *DataLength,
  653. NULL,
  654. NULL
  655. );
  656. if (Urb == NULL) {
  657. DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: failed to create URB!\n", Type));
  658. return EFI_OUT_OF_RESOURCES;
  659. }
  660. Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
  661. if (Status == EFI_TIMEOUT) {
  662. //
  663. // The transfer timed out. Abort the transfer by dequeueing of the TD.
  664. //
  665. RecoveryStatus = XhcDequeueTrbFromEndpoint (Xhc, Urb);
  666. if (RecoveryStatus == EFI_ALREADY_STARTED) {
  667. //
  668. // The URB is finished just before stopping endpoint.
  669. // Change returning status from EFI_TIMEOUT to EFI_SUCCESS.
  670. //
  671. ASSERT (Urb->Result == EFI_USB_NOERROR);
  672. Status = EFI_SUCCESS;
  673. DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: pending URB is finished, Length = %d.\n", Type, Urb->Completed));
  674. } else if (EFI_ERROR (RecoveryStatus)) {
  675. DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: XhcDequeueTrbFromEndpoint failed!\n", Type));
  676. }
  677. }
  678. *TransferResult = Urb->Result;
  679. *DataLength = Urb->Completed;
  680. if ((*TransferResult == EFI_USB_ERR_STALL) || (*TransferResult == EFI_USB_ERR_BABBLE)) {
  681. ASSERT (Status == EFI_DEVICE_ERROR);
  682. RecoveryStatus = XhcRecoverHaltedEndpoint (Xhc, Urb);
  683. if (EFI_ERROR (RecoveryStatus)) {
  684. DEBUG ((DEBUG_ERROR, "XhcTransfer[Type=%d]: XhcRecoverHaltedEndpoint failed!\n", Type));
  685. }
  686. }
  687. Xhc->PciIo->Flush (Xhc->PciIo);
  688. XhcFreeUrb (Xhc, Urb);
  689. return Status;
  690. }
  691. /**
  692. Submits control transfer to a target USB device.
  693. @param This This EFI_USB2_HC_PROTOCOL instance.
  694. @param DeviceAddress The target device address.
  695. @param DeviceSpeed Target device speed.
  696. @param MaximumPacketLength Maximum packet size the default control transfer
  697. endpoint is capable of sending or receiving.
  698. @param Request USB device request to send.
  699. @param TransferDirection Specifies the data direction for the data stage
  700. @param Data Data buffer to be transmitted or received from USB
  701. device.
  702. @param DataLength The size (in bytes) of the data buffer.
  703. @param Timeout Indicates the maximum timeout, in millisecond.
  704. @param Translator Transaction translator to be used by this device.
  705. @param TransferResult Return the result of this control transfer.
  706. @retval EFI_SUCCESS Transfer was completed successfully.
  707. @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
  708. @retval EFI_INVALID_PARAMETER Some parameters are invalid.
  709. @retval EFI_TIMEOUT Transfer failed due to timeout.
  710. @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
  711. **/
  712. EFI_STATUS
  713. EFIAPI
  714. XhcControlTransfer (
  715. IN EFI_USB2_HC_PROTOCOL *This,
  716. IN UINT8 DeviceAddress,
  717. IN UINT8 DeviceSpeed,
  718. IN UINTN MaximumPacketLength,
  719. IN EFI_USB_DEVICE_REQUEST *Request,
  720. IN EFI_USB_DATA_DIRECTION TransferDirection,
  721. IN OUT VOID *Data,
  722. IN OUT UINTN *DataLength,
  723. IN UINTN Timeout,
  724. IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
  725. OUT UINT32 *TransferResult
  726. )
  727. {
  728. USB_XHCI_INSTANCE *Xhc;
  729. UINT8 Endpoint;
  730. UINT8 Index;
  731. UINT8 DescriptorType;
  732. UINT8 SlotId;
  733. UINT8 TTT;
  734. UINT8 MTT;
  735. UINT32 MaxPacket0;
  736. EFI_USB_HUB_DESCRIPTOR *HubDesc;
  737. EFI_TPL OldTpl;
  738. EFI_STATUS Status;
  739. UINTN MapSize;
  740. EFI_USB_PORT_STATUS PortStatus;
  741. UINT32 State;
  742. EFI_USB_DEVICE_REQUEST ClearPortRequest;
  743. UINTN Len;
  744. //
  745. // Validate parameters
  746. //
  747. if ((Request == NULL) || (TransferResult == NULL)) {
  748. return EFI_INVALID_PARAMETER;
  749. }
  750. if ((TransferDirection != EfiUsbDataIn) &&
  751. (TransferDirection != EfiUsbDataOut) &&
  752. (TransferDirection != EfiUsbNoData))
  753. {
  754. return EFI_INVALID_PARAMETER;
  755. }
  756. if ((TransferDirection == EfiUsbNoData) &&
  757. ((Data != NULL) || (*DataLength != 0)))
  758. {
  759. return EFI_INVALID_PARAMETER;
  760. }
  761. if ((TransferDirection != EfiUsbNoData) &&
  762. ((Data == NULL) || (*DataLength == 0)))
  763. {
  764. return EFI_INVALID_PARAMETER;
  765. }
  766. if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&
  767. (MaximumPacketLength != 32) && (MaximumPacketLength != 64) &&
  768. (MaximumPacketLength != 512)
  769. )
  770. {
  771. return EFI_INVALID_PARAMETER;
  772. }
  773. if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {
  774. return EFI_INVALID_PARAMETER;
  775. }
  776. if ((DeviceSpeed == EFI_USB_SPEED_SUPER) && (MaximumPacketLength != 512)) {
  777. return EFI_INVALID_PARAMETER;
  778. }
  779. OldTpl = gBS->RaiseTPL (XHC_TPL);
  780. Xhc = XHC_FROM_THIS (This);
  781. Status = EFI_DEVICE_ERROR;
  782. *TransferResult = EFI_USB_ERR_SYSTEM;
  783. Len = 0;
  784. if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
  785. DEBUG ((DEBUG_ERROR, "XhcControlTransfer: HC halted at entrance\n"));
  786. goto ON_EXIT;
  787. }
  788. //
  789. // Check if the device is still enabled before every transaction.
  790. //
  791. SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
  792. if (SlotId == 0) {
  793. goto ON_EXIT;
  794. }
  795. //
  796. // Hook the Set_Address request from UsbBus.
  797. // According to XHCI 1.0 spec, the Set_Address request is replaced by XHCI's Address_Device cmd.
  798. //
  799. if ((Request->Request == USB_REQ_SET_ADDRESS) &&
  800. (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)))
  801. {
  802. //
  803. // Reset the BusDevAddr field of all disabled entries in UsbDevContext array firstly.
  804. // This way is used to clean the history to avoid using wrong device address by XhcAsyncInterruptTransfer().
  805. //
  806. for (Index = 0; Index < 255; Index++) {
  807. if (!Xhc->UsbDevContext[Index + 1].Enabled &&
  808. (Xhc->UsbDevContext[Index + 1].SlotId == 0) &&
  809. (Xhc->UsbDevContext[Index + 1].BusDevAddr == (UINT8)Request->Value))
  810. {
  811. Xhc->UsbDevContext[Index + 1].BusDevAddr = 0;
  812. }
  813. }
  814. if (Xhc->UsbDevContext[SlotId].XhciDevAddr == 0) {
  815. Status = EFI_DEVICE_ERROR;
  816. goto ON_EXIT;
  817. }
  818. //
  819. // The actual device address has been assigned by XHCI during initializing the device slot.
  820. // So we just need establish the mapping relationship between the device address requested from UsbBus
  821. // and the actual device address assigned by XHCI. The the following invocations through EFI_USB2_HC_PROTOCOL interface
  822. // can find out the actual device address by it.
  823. //
  824. Xhc->UsbDevContext[SlotId].BusDevAddr = (UINT8)Request->Value;
  825. Status = EFI_SUCCESS;
  826. goto ON_EXIT;
  827. }
  828. //
  829. // Create a new URB, insert it into the asynchronous
  830. // schedule list, then poll the execution status.
  831. // Note that we encode the direction in address although default control
  832. // endpoint is bidirectional. XhcCreateUrb expects this
  833. // combination of Ep addr and its direction.
  834. //
  835. Endpoint = (UINT8)(0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
  836. Status = XhcTransfer (
  837. Xhc,
  838. DeviceAddress,
  839. Endpoint,
  840. DeviceSpeed,
  841. MaximumPacketLength,
  842. XHC_CTRL_TRANSFER,
  843. Request,
  844. Data,
  845. DataLength,
  846. Timeout,
  847. TransferResult
  848. );
  849. if (EFI_ERROR (Status)) {
  850. goto ON_EXIT;
  851. }
  852. //
  853. // Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.
  854. // Hook Get_Status request form UsbBus as we need trace device attach/detach event happened at hub.
  855. // Hook Set_Config request from UsbBus as we need configure device endpoint.
  856. //
  857. if ((Request->Request == USB_REQ_GET_DESCRIPTOR) &&
  858. ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)) ||
  859. ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_DEVICE)))))
  860. {
  861. DescriptorType = (UINT8)(Request->Value >> 8);
  862. if ((DescriptorType == USB_DESC_TYPE_DEVICE) && ((*DataLength == sizeof (EFI_USB_DEVICE_DESCRIPTOR)) || ((DeviceSpeed == EFI_USB_SPEED_FULL) && (*DataLength == 8)))) {
  863. ASSERT (Data != NULL);
  864. //
  865. // Store a copy of device scriptor as hub device need this info to configure endpoint.
  866. //
  867. CopyMem (&Xhc->UsbDevContext[SlotId].DevDesc, Data, *DataLength);
  868. if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB >= 0x0300) {
  869. //
  870. // If it's a usb3.0 device, then its max packet size is a 2^n.
  871. //
  872. MaxPacket0 = 1 << Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;
  873. } else {
  874. MaxPacket0 = Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;
  875. }
  876. Xhc->UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));
  877. if (Xhc->HcCParams.Data.Csz == 0) {
  878. Status = XhcEvaluateContext (Xhc, SlotId, MaxPacket0);
  879. } else {
  880. Status = XhcEvaluateContext64 (Xhc, SlotId, MaxPacket0);
  881. }
  882. } else if (DescriptorType == USB_DESC_TYPE_CONFIG) {
  883. ASSERT (Data != NULL);
  884. if (*DataLength == ((UINT16 *)Data)[1]) {
  885. //
  886. // Get configuration value from request, Store the configuration descriptor for Configure_Endpoint cmd.
  887. //
  888. Index = (UINT8)Request->Value;
  889. ASSERT (Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations);
  890. Xhc->UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool (*DataLength);
  891. CopyMem (Xhc->UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLength);
  892. //
  893. // Default to use AlternateSetting 0 for all interfaces.
  894. //
  895. Xhc->UsbDevContext[SlotId].ActiveAlternateSetting = AllocateZeroPool (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->NumInterfaces * sizeof (UINT8));
  896. }
  897. } else if (((DescriptorType == USB_DESC_TYPE_HUB) ||
  898. (DescriptorType == USB_DESC_TYPE_HUB_SUPER_SPEED)) && (*DataLength > 2))
  899. {
  900. ASSERT (Data != NULL);
  901. HubDesc = (EFI_USB_HUB_DESCRIPTOR *)Data;
  902. ASSERT (HubDesc->NumPorts <= 15);
  903. //
  904. // The bit 5,6 of HubCharacter field of Hub Descriptor is TTT.
  905. //
  906. TTT = (UINT8)((HubDesc->HubCharacter & (BIT5 | BIT6)) >> 5);
  907. if (Xhc->UsbDevContext[SlotId].DevDesc.DeviceProtocol == 2) {
  908. //
  909. // Don't support multi-TT feature for super speed hub now.
  910. //
  911. MTT = 0;
  912. DEBUG ((DEBUG_ERROR, "XHCI: Don't support multi-TT feature for Hub now. (force to disable MTT)\n"));
  913. } else {
  914. MTT = 0;
  915. }
  916. if (Xhc->HcCParams.Data.Csz == 0) {
  917. Status = XhcConfigHubContext (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);
  918. } else {
  919. Status = XhcConfigHubContext64 (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);
  920. }
  921. }
  922. } else if ((Request->Request == USB_REQ_SET_CONFIG) &&
  923. (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)))
  924. {
  925. //
  926. // Hook Set_Config request from UsbBus as we need configure device endpoint.
  927. //
  928. for (Index = 0; Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {
  929. if (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->ConfigurationValue == (UINT8)Request->Value) {
  930. if (Xhc->HcCParams.Data.Csz == 0) {
  931. Status = XhcSetConfigCmd (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
  932. } else {
  933. Status = XhcSetConfigCmd64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
  934. }
  935. break;
  936. }
  937. }
  938. } else if ((Request->Request == USB_REQ_SET_INTERFACE) &&
  939. (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_INTERFACE)))
  940. {
  941. //
  942. // Hook Set_Interface request from UsbBus as we need configure interface setting.
  943. // Request->Value indicates AlterlateSetting to set
  944. // Request->Index indicates Interface to set
  945. //
  946. if (Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[(UINT8)Request->Index] != (UINT8)Request->Value) {
  947. if (Xhc->HcCParams.Data.Csz == 0) {
  948. Status = XhcSetInterface (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Xhc->UsbDevContext[SlotId].ActiveConfiguration - 1], Request);
  949. } else {
  950. Status = XhcSetInterface64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Xhc->UsbDevContext[SlotId].ActiveConfiguration - 1], Request);
  951. }
  952. }
  953. } else if ((Request->Request == USB_REQ_GET_STATUS) &&
  954. (Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER)))
  955. {
  956. ASSERT (Data != NULL);
  957. //
  958. // Hook Get_Status request from UsbBus to keep track of the port status change.
  959. //
  960. State = *(UINT32 *)Data;
  961. PortStatus.PortStatus = 0;
  962. PortStatus.PortChangeStatus = 0;
  963. if (DeviceSpeed == EFI_USB_SPEED_SUPER) {
  964. //
  965. // For super speed hub, its bit10~12 presents the attached device speed.
  966. //
  967. if ((State & XHC_PORTSC_PS) >> 10 == 0) {
  968. PortStatus.PortStatus |= USB_PORT_STAT_SUPER_SPEED;
  969. }
  970. } else {
  971. //
  972. // For high or full/low speed hub, its bit9~10 presents the attached device speed.
  973. //
  974. if (XHC_BIT_IS_SET (State, BIT9)) {
  975. PortStatus.PortStatus |= USB_PORT_STAT_LOW_SPEED;
  976. } else if (XHC_BIT_IS_SET (State, BIT10)) {
  977. PortStatus.PortStatus |= USB_PORT_STAT_HIGH_SPEED;
  978. }
  979. }
  980. //
  981. // Convert the XHCI port/port change state to UEFI status
  982. //
  983. MapSize = sizeof (mUsbHubPortStateMap) / sizeof (USB_PORT_STATE_MAP);
  984. for (Index = 0; Index < MapSize; Index++) {
  985. if (XHC_BIT_IS_SET (State, mUsbHubPortStateMap[Index].HwState)) {
  986. PortStatus.PortStatus = (UINT16)(PortStatus.PortStatus | mUsbHubPortStateMap[Index].UefiState);
  987. }
  988. }
  989. MapSize = sizeof (mUsbHubPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
  990. for (Index = 0; Index < MapSize; Index++) {
  991. if (XHC_BIT_IS_SET (State, mUsbHubPortChangeMap[Index].HwState)) {
  992. PortStatus.PortChangeStatus = (UINT16)(PortStatus.PortChangeStatus | mUsbHubPortChangeMap[Index].UefiState);
  993. }
  994. }
  995. MapSize = sizeof (mUsbHubClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);
  996. for (Index = 0; Index < MapSize; Index++) {
  997. if (XHC_BIT_IS_SET (State, mUsbHubClearPortChangeMap[Index].HwState)) {
  998. ZeroMem (&ClearPortRequest, sizeof (EFI_USB_DEVICE_REQUEST));
  999. ClearPortRequest.RequestType = USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER);
  1000. ClearPortRequest.Request = (UINT8)USB_REQ_CLEAR_FEATURE;
  1001. ClearPortRequest.Value = mUsbHubClearPortChangeMap[Index].Selector;
  1002. ClearPortRequest.Index = Request->Index;
  1003. ClearPortRequest.Length = 0;
  1004. XhcControlTransfer (
  1005. This,
  1006. DeviceAddress,
  1007. DeviceSpeed,
  1008. MaximumPacketLength,
  1009. &ClearPortRequest,
  1010. EfiUsbNoData,
  1011. NULL,
  1012. &Len,
  1013. Timeout,
  1014. Translator,
  1015. TransferResult
  1016. );
  1017. }
  1018. }
  1019. XhcPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);
  1020. *(UINT32 *)Data = *(UINT32 *)&PortStatus;
  1021. }
  1022. ON_EXIT:
  1023. if (EFI_ERROR (Status)) {
  1024. DEBUG ((DEBUG_ERROR, "XhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
  1025. }
  1026. gBS->RestoreTPL (OldTpl);
  1027. return Status;
  1028. }
  1029. /**
  1030. Submits bulk transfer to a bulk endpoint of a USB device.
  1031. @param This This EFI_USB2_HC_PROTOCOL instance.
  1032. @param DeviceAddress Target device address.
  1033. @param EndPointAddress Endpoint number and its direction in bit 7.
  1034. @param DeviceSpeed Device speed, Low speed device doesn't support bulk
  1035. transfer.
  1036. @param MaximumPacketLength Maximum packet size the endpoint is capable of
  1037. sending or receiving.
  1038. @param DataBuffersNumber Number of data buffers prepared for the transfer.
  1039. @param Data Array of pointers to the buffers of data to transmit
  1040. from or receive into.
  1041. @param DataLength The lenght of the data buffer.
  1042. @param DataToggle On input, the initial data toggle for the transfer;
  1043. On output, it is updated to to next data toggle to
  1044. use of the subsequent bulk transfer.
  1045. @param Timeout Indicates the maximum time, in millisecond, which
  1046. the transfer is allowed to complete.
  1047. @param Translator A pointr to the transaction translator data.
  1048. @param TransferResult A pointer to the detailed result information of the
  1049. bulk transfer.
  1050. @retval EFI_SUCCESS The transfer was completed successfully.
  1051. @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
  1052. @retval EFI_INVALID_PARAMETER Some parameters are invalid.
  1053. @retval EFI_TIMEOUT The transfer failed due to timeout.
  1054. @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
  1055. **/
  1056. EFI_STATUS
  1057. EFIAPI
  1058. XhcBulkTransfer (
  1059. IN EFI_USB2_HC_PROTOCOL *This,
  1060. IN UINT8 DeviceAddress,
  1061. IN UINT8 EndPointAddress,
  1062. IN UINT8 DeviceSpeed,
  1063. IN UINTN MaximumPacketLength,
  1064. IN UINT8 DataBuffersNumber,
  1065. IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
  1066. IN OUT UINTN *DataLength,
  1067. IN OUT UINT8 *DataToggle,
  1068. IN UINTN Timeout,
  1069. IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
  1070. OUT UINT32 *TransferResult
  1071. )
  1072. {
  1073. USB_XHCI_INSTANCE *Xhc;
  1074. UINT8 SlotId;
  1075. EFI_STATUS Status;
  1076. EFI_TPL OldTpl;
  1077. UINTN DebugErrorLevel;
  1078. //
  1079. // Validate the parameters
  1080. //
  1081. if ((DataLength == NULL) || (*DataLength == 0) ||
  1082. (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL))
  1083. {
  1084. return EFI_INVALID_PARAMETER;
  1085. }
  1086. if ((*DataToggle != 0) && (*DataToggle != 1)) {
  1087. return EFI_INVALID_PARAMETER;
  1088. }
  1089. if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
  1090. ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
  1091. ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512)) ||
  1092. ((EFI_USB_SPEED_SUPER == DeviceSpeed) && (MaximumPacketLength > 1024)))
  1093. {
  1094. return EFI_INVALID_PARAMETER;
  1095. }
  1096. OldTpl = gBS->RaiseTPL (XHC_TPL);
  1097. Xhc = XHC_FROM_THIS (This);
  1098. *TransferResult = EFI_USB_ERR_SYSTEM;
  1099. Status = EFI_DEVICE_ERROR;
  1100. if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
  1101. DEBUG ((DEBUG_ERROR, "XhcBulkTransfer: HC is halted\n"));
  1102. goto ON_EXIT;
  1103. }
  1104. //
  1105. // Check if the device is still enabled before every transaction.
  1106. //
  1107. SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
  1108. if (SlotId == 0) {
  1109. goto ON_EXIT;
  1110. }
  1111. //
  1112. // Create a new URB, insert it into the asynchronous
  1113. // schedule list, then poll the execution status.
  1114. //
  1115. Status = XhcTransfer (
  1116. Xhc,
  1117. DeviceAddress,
  1118. EndPointAddress,
  1119. DeviceSpeed,
  1120. MaximumPacketLength,
  1121. XHC_BULK_TRANSFER,
  1122. NULL,
  1123. Data[0],
  1124. DataLength,
  1125. Timeout,
  1126. TransferResult
  1127. );
  1128. ON_EXIT:
  1129. if (EFI_ERROR (Status)) {
  1130. if (Status == EFI_TIMEOUT) {
  1131. DebugErrorLevel = DEBUG_VERBOSE;
  1132. } else {
  1133. DebugErrorLevel = DEBUG_ERROR;
  1134. }
  1135. DEBUG ((DebugErrorLevel, "XhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
  1136. }
  1137. gBS->RestoreTPL (OldTpl);
  1138. return Status;
  1139. }
  1140. /**
  1141. Submits an asynchronous interrupt transfer to an
  1142. interrupt endpoint of a USB device.
  1143. @param This This EFI_USB2_HC_PROTOCOL instance.
  1144. @param DeviceAddress Target device address.
  1145. @param EndPointAddress Endpoint number and its direction encoded in bit 7
  1146. @param DeviceSpeed Indicates device speed.
  1147. @param MaximumPacketLength Maximum packet size the target endpoint is capable
  1148. @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt
  1149. transfer If FALSE, to remove the specified
  1150. asynchronous interrupt.
  1151. @param DataToggle On input, the initial data toggle to use; on output,
  1152. it is updated to indicate the next data toggle.
  1153. @param PollingInterval The he interval, in milliseconds, that the transfer
  1154. is polled.
  1155. @param DataLength The length of data to receive at the rate specified
  1156. by PollingInterval.
  1157. @param Translator Transaction translator to use.
  1158. @param CallBackFunction Function to call at the rate specified by
  1159. PollingInterval.
  1160. @param Context Context to CallBackFunction.
  1161. @retval EFI_SUCCESS The request has been successfully submitted or canceled.
  1162. @retval EFI_INVALID_PARAMETER Some parameters are invalid.
  1163. @retval EFI_OUT_OF_RESOURCES The request failed due to a lack of resources.
  1164. @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
  1165. **/
  1166. EFI_STATUS
  1167. EFIAPI
  1168. XhcAsyncInterruptTransfer (
  1169. IN EFI_USB2_HC_PROTOCOL *This,
  1170. IN UINT8 DeviceAddress,
  1171. IN UINT8 EndPointAddress,
  1172. IN UINT8 DeviceSpeed,
  1173. IN UINTN MaximumPacketLength,
  1174. IN BOOLEAN IsNewTransfer,
  1175. IN OUT UINT8 *DataToggle,
  1176. IN UINTN PollingInterval,
  1177. IN UINTN DataLength,
  1178. IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
  1179. IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
  1180. IN VOID *Context OPTIONAL
  1181. )
  1182. {
  1183. USB_XHCI_INSTANCE *Xhc;
  1184. URB *Urb;
  1185. EFI_STATUS Status;
  1186. UINT8 SlotId;
  1187. UINT8 Index;
  1188. EFI_TPL OldTpl;
  1189. //
  1190. // Validate parameters
  1191. //
  1192. if (!XHCI_IS_DATAIN (EndPointAddress)) {
  1193. return EFI_INVALID_PARAMETER;
  1194. }
  1195. if (IsNewTransfer) {
  1196. if (DataLength == 0) {
  1197. return EFI_INVALID_PARAMETER;
  1198. }
  1199. if ((*DataToggle != 1) && (*DataToggle != 0)) {
  1200. return EFI_INVALID_PARAMETER;
  1201. }
  1202. if ((PollingInterval > 255) || (PollingInterval < 1)) {
  1203. return EFI_INVALID_PARAMETER;
  1204. }
  1205. }
  1206. OldTpl = gBS->RaiseTPL (XHC_TPL);
  1207. Xhc = XHC_FROM_THIS (This);
  1208. //
  1209. // Delete Async interrupt transfer request.
  1210. //
  1211. if (!IsNewTransfer) {
  1212. //
  1213. // The delete request may happen after device is detached.
  1214. //
  1215. for (Index = 0; Index < 255; Index++) {
  1216. if (Xhc->UsbDevContext[Index + 1].BusDevAddr == DeviceAddress) {
  1217. break;
  1218. }
  1219. }
  1220. if (Index == 255) {
  1221. Status = EFI_INVALID_PARAMETER;
  1222. goto ON_EXIT;
  1223. }
  1224. Status = XhciDelAsyncIntTransfer (Xhc, DeviceAddress, EndPointAddress);
  1225. DEBUG ((DEBUG_INFO, "XhcAsyncInterruptTransfer: remove old transfer for addr %d, Status = %r\n", DeviceAddress, Status));
  1226. goto ON_EXIT;
  1227. }
  1228. Status = EFI_SUCCESS;
  1229. if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
  1230. DEBUG ((DEBUG_ERROR, "XhcAsyncInterruptTransfer: HC is halt\n"));
  1231. Status = EFI_DEVICE_ERROR;
  1232. goto ON_EXIT;
  1233. }
  1234. //
  1235. // Check if the device is still enabled before every transaction.
  1236. //
  1237. SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
  1238. if (SlotId == 0) {
  1239. goto ON_EXIT;
  1240. }
  1241. Urb = XhciInsertAsyncIntTransfer (
  1242. Xhc,
  1243. DeviceAddress,
  1244. EndPointAddress,
  1245. DeviceSpeed,
  1246. MaximumPacketLength,
  1247. DataLength,
  1248. CallBackFunction,
  1249. Context
  1250. );
  1251. if (Urb == NULL) {
  1252. Status = EFI_OUT_OF_RESOURCES;
  1253. goto ON_EXIT;
  1254. }
  1255. //
  1256. // Ring the doorbell
  1257. //
  1258. Status = RingIntTransferDoorBell (Xhc, Urb);
  1259. ON_EXIT:
  1260. Xhc->PciIo->Flush (Xhc->PciIo);
  1261. gBS->RestoreTPL (OldTpl);
  1262. return Status;
  1263. }
  1264. /**
  1265. Submits synchronous interrupt transfer to an interrupt endpoint
  1266. of a USB device.
  1267. @param This This EFI_USB2_HC_PROTOCOL instance.
  1268. @param DeviceAddress Target device address.
  1269. @param EndPointAddress Endpoint number and its direction encoded in bit 7
  1270. @param DeviceSpeed Indicates device speed.
  1271. @param MaximumPacketLength Maximum packet size the target endpoint is capable
  1272. of sending or receiving.
  1273. @param Data Buffer of data that will be transmitted to USB
  1274. device or received from USB device.
  1275. @param DataLength On input, the size, in bytes, of the data buffer; On
  1276. output, the number of bytes transferred.
  1277. @param DataToggle On input, the initial data toggle to use; on output,
  1278. it is updated to indicate the next data toggle.
  1279. @param Timeout Maximum time, in second, to complete.
  1280. @param Translator Transaction translator to use.
  1281. @param TransferResult Variable to receive the transfer result.
  1282. @return EFI_SUCCESS The transfer was completed successfully.
  1283. @return EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
  1284. @return EFI_INVALID_PARAMETER Some parameters are invalid.
  1285. @return EFI_TIMEOUT The transfer failed due to timeout.
  1286. @return EFI_DEVICE_ERROR The failed due to host controller or device error
  1287. **/
  1288. EFI_STATUS
  1289. EFIAPI
  1290. XhcSyncInterruptTransfer (
  1291. IN EFI_USB2_HC_PROTOCOL *This,
  1292. IN UINT8 DeviceAddress,
  1293. IN UINT8 EndPointAddress,
  1294. IN UINT8 DeviceSpeed,
  1295. IN UINTN MaximumPacketLength,
  1296. IN OUT VOID *Data,
  1297. IN OUT UINTN *DataLength,
  1298. IN OUT UINT8 *DataToggle,
  1299. IN UINTN Timeout,
  1300. IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
  1301. OUT UINT32 *TransferResult
  1302. )
  1303. {
  1304. USB_XHCI_INSTANCE *Xhc;
  1305. UINT8 SlotId;
  1306. EFI_STATUS Status;
  1307. EFI_TPL OldTpl;
  1308. //
  1309. // Validates parameters
  1310. //
  1311. if ((DataLength == NULL) || (*DataLength == 0) ||
  1312. (Data == NULL) || (TransferResult == NULL))
  1313. {
  1314. return EFI_INVALID_PARAMETER;
  1315. }
  1316. if ((*DataToggle != 1) && (*DataToggle != 0)) {
  1317. return EFI_INVALID_PARAMETER;
  1318. }
  1319. if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) ||
  1320. ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
  1321. ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072)))
  1322. {
  1323. return EFI_INVALID_PARAMETER;
  1324. }
  1325. OldTpl = gBS->RaiseTPL (XHC_TPL);
  1326. Xhc = XHC_FROM_THIS (This);
  1327. *TransferResult = EFI_USB_ERR_SYSTEM;
  1328. Status = EFI_DEVICE_ERROR;
  1329. if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) {
  1330. DEBUG ((DEBUG_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));
  1331. goto ON_EXIT;
  1332. }
  1333. //
  1334. // Check if the device is still enabled before every transaction.
  1335. //
  1336. SlotId = XhcBusDevAddrToSlotId (Xhc, DeviceAddress);
  1337. if (SlotId == 0) {
  1338. goto ON_EXIT;
  1339. }
  1340. Status = XhcTransfer (
  1341. Xhc,
  1342. DeviceAddress,
  1343. EndPointAddress,
  1344. DeviceSpeed,
  1345. MaximumPacketLength,
  1346. XHC_INT_TRANSFER_SYNC,
  1347. NULL,
  1348. Data,
  1349. DataLength,
  1350. Timeout,
  1351. TransferResult
  1352. );
  1353. ON_EXIT:
  1354. if (EFI_ERROR (Status)) {
  1355. DEBUG ((DEBUG_ERROR, "XhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
  1356. }
  1357. gBS->RestoreTPL (OldTpl);
  1358. return Status;
  1359. }
  1360. /**
  1361. Submits isochronous transfer to a target USB device.
  1362. @param This This EFI_USB2_HC_PROTOCOL instance.
  1363. @param DeviceAddress Target device address.
  1364. @param EndPointAddress End point address with its direction.
  1365. @param DeviceSpeed Device speed, Low speed device doesn't support this
  1366. type.
  1367. @param MaximumPacketLength Maximum packet size that the endpoint is capable of
  1368. sending or receiving.
  1369. @param DataBuffersNumber Number of data buffers prepared for the transfer.
  1370. @param Data Array of pointers to the buffers of data that will
  1371. be transmitted to USB device or received from USB
  1372. device.
  1373. @param DataLength The size, in bytes, of the data buffer.
  1374. @param Translator Transaction translator to use.
  1375. @param TransferResult Variable to receive the transfer result.
  1376. @return EFI_UNSUPPORTED Isochronous transfer is unsupported.
  1377. **/
  1378. EFI_STATUS
  1379. EFIAPI
  1380. XhcIsochronousTransfer (
  1381. IN EFI_USB2_HC_PROTOCOL *This,
  1382. IN UINT8 DeviceAddress,
  1383. IN UINT8 EndPointAddress,
  1384. IN UINT8 DeviceSpeed,
  1385. IN UINTN MaximumPacketLength,
  1386. IN UINT8 DataBuffersNumber,
  1387. IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
  1388. IN UINTN DataLength,
  1389. IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
  1390. OUT UINT32 *TransferResult
  1391. )
  1392. {
  1393. return EFI_UNSUPPORTED;
  1394. }
  1395. /**
  1396. Submits Async isochronous transfer to a target USB device.
  1397. @param This This EFI_USB2_HC_PROTOCOL instance.
  1398. @param DeviceAddress Target device address.
  1399. @param EndPointAddress End point address with its direction.
  1400. @param DeviceSpeed Device speed, Low speed device doesn't support this
  1401. type.
  1402. @param MaximumPacketLength Maximum packet size that the endpoint is capable of
  1403. sending or receiving.
  1404. @param DataBuffersNumber Number of data buffers prepared for the transfer.
  1405. @param Data Array of pointers to the buffers of data that will
  1406. be transmitted to USB device or received from USB
  1407. device.
  1408. @param DataLength The size, in bytes, of the data buffer.
  1409. @param Translator Transaction translator to use.
  1410. @param IsochronousCallBack Function to be called when the transfer complete.
  1411. @param Context Context passed to the call back function as
  1412. parameter.
  1413. @return EFI_UNSUPPORTED Isochronous transfer isn't supported.
  1414. **/
  1415. EFI_STATUS
  1416. EFIAPI
  1417. XhcAsyncIsochronousTransfer (
  1418. IN EFI_USB2_HC_PROTOCOL *This,
  1419. IN UINT8 DeviceAddress,
  1420. IN UINT8 EndPointAddress,
  1421. IN UINT8 DeviceSpeed,
  1422. IN UINTN MaximumPacketLength,
  1423. IN UINT8 DataBuffersNumber,
  1424. IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
  1425. IN UINTN DataLength,
  1426. IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
  1427. IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
  1428. IN VOID *Context
  1429. )
  1430. {
  1431. return EFI_UNSUPPORTED;
  1432. }
  1433. /**
  1434. Entry point for EFI drivers.
  1435. @param ImageHandle EFI_HANDLE.
  1436. @param SystemTable EFI_SYSTEM_TABLE.
  1437. @retval EFI_SUCCESS Success.
  1438. @retval Others Fail.
  1439. **/
  1440. EFI_STATUS
  1441. EFIAPI
  1442. XhcDriverEntryPoint (
  1443. IN EFI_HANDLE ImageHandle,
  1444. IN EFI_SYSTEM_TABLE *SystemTable
  1445. )
  1446. {
  1447. return EfiLibInstallDriverBindingComponentName2 (
  1448. ImageHandle,
  1449. SystemTable,
  1450. &gXhciDriverBinding,
  1451. ImageHandle,
  1452. &gXhciComponentName,
  1453. &gXhciComponentName2
  1454. );
  1455. }
  1456. /**
  1457. Test to see if this driver supports ControllerHandle. Any
  1458. ControllerHandle that has Usb2HcProtocol installed will
  1459. be supported.
  1460. @param This Protocol instance pointer.
  1461. @param Controller Handle of device to test.
  1462. @param RemainingDevicePath Not used.
  1463. @return EFI_SUCCESS This driver supports this device.
  1464. @return EFI_UNSUPPORTED This driver does not support this device.
  1465. **/
  1466. EFI_STATUS
  1467. EFIAPI
  1468. XhcDriverBindingSupported (
  1469. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  1470. IN EFI_HANDLE Controller,
  1471. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  1472. )
  1473. {
  1474. EFI_STATUS Status;
  1475. EFI_PCI_IO_PROTOCOL *PciIo;
  1476. USB_CLASSC UsbClassCReg;
  1477. //
  1478. // Test whether there is PCI IO Protocol attached on the controller handle.
  1479. //
  1480. Status = gBS->OpenProtocol (
  1481. Controller,
  1482. &gEfiPciIoProtocolGuid,
  1483. (VOID **)&PciIo,
  1484. This->DriverBindingHandle,
  1485. Controller,
  1486. EFI_OPEN_PROTOCOL_BY_DRIVER
  1487. );
  1488. if (EFI_ERROR (Status)) {
  1489. return EFI_UNSUPPORTED;
  1490. }
  1491. Status = PciIo->Pci.Read (
  1492. PciIo,
  1493. EfiPciIoWidthUint8,
  1494. PCI_CLASSCODE_OFFSET,
  1495. sizeof (USB_CLASSC) / sizeof (UINT8),
  1496. &UsbClassCReg
  1497. );
  1498. if (EFI_ERROR (Status)) {
  1499. Status = EFI_UNSUPPORTED;
  1500. goto ON_EXIT;
  1501. }
  1502. //
  1503. // Test whether the controller belongs to Xhci type
  1504. //
  1505. if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
  1506. (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
  1507. (UsbClassCReg.ProgInterface != PCI_IF_XHCI))
  1508. {
  1509. Status = EFI_UNSUPPORTED;
  1510. }
  1511. ON_EXIT:
  1512. gBS->CloseProtocol (
  1513. Controller,
  1514. &gEfiPciIoProtocolGuid,
  1515. This->DriverBindingHandle,
  1516. Controller
  1517. );
  1518. return Status;
  1519. }
  1520. /**
  1521. Create and initialize a USB_XHCI_INSTANCE structure.
  1522. @param PciIo The PciIo on this device.
  1523. @param DevicePath The device path of host controller.
  1524. @param OriginalPciAttributes Original PCI attributes.
  1525. @return The allocated and initialized USB_XHCI_INSTANCE structure if created,
  1526. otherwise NULL.
  1527. **/
  1528. USB_XHCI_INSTANCE *
  1529. XhcCreateUsbHc (
  1530. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1531. IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
  1532. IN UINT64 OriginalPciAttributes
  1533. )
  1534. {
  1535. USB_XHCI_INSTANCE *Xhc;
  1536. EFI_STATUS Status;
  1537. UINT32 PageSize;
  1538. UINT16 ExtCapReg;
  1539. UINT8 ReleaseNumber;
  1540. Xhc = AllocateZeroPool (sizeof (USB_XHCI_INSTANCE));
  1541. if (Xhc == NULL) {
  1542. return NULL;
  1543. }
  1544. //
  1545. // Initialize private data structure
  1546. //
  1547. Xhc->Signature = XHCI_INSTANCE_SIG;
  1548. Xhc->PciIo = PciIo;
  1549. Xhc->DevicePath = DevicePath;
  1550. Xhc->OriginalPciAttributes = OriginalPciAttributes;
  1551. CopyMem (&Xhc->Usb2Hc, &gXhciUsb2HcTemplate, sizeof (EFI_USB2_HC_PROTOCOL));
  1552. Status = PciIo->Pci.Read (
  1553. PciIo,
  1554. EfiPciIoWidthUint8,
  1555. XHC_PCI_SBRN_OFFSET,
  1556. 1,
  1557. &ReleaseNumber
  1558. );
  1559. if (!EFI_ERROR (Status)) {
  1560. Xhc->Usb2Hc.MajorRevision = (ReleaseNumber & 0xF0) >> 4;
  1561. Xhc->Usb2Hc.MinorRevision = (ReleaseNumber & 0x0F);
  1562. }
  1563. InitializeListHead (&Xhc->AsyncIntTransfers);
  1564. //
  1565. // Be caution that the Offset passed to XhcReadCapReg() should be Dword align
  1566. //
  1567. Xhc->CapLength = XhcReadCapReg8 (Xhc, XHC_CAPLENGTH_OFFSET);
  1568. Xhc->HcSParams1.Dword = XhcReadCapReg (Xhc, XHC_HCSPARAMS1_OFFSET);
  1569. Xhc->HcSParams2.Dword = XhcReadCapReg (Xhc, XHC_HCSPARAMS2_OFFSET);
  1570. Xhc->HcCParams.Dword = XhcReadCapReg (Xhc, XHC_HCCPARAMS_OFFSET);
  1571. Xhc->DBOff = XhcReadCapReg (Xhc, XHC_DBOFF_OFFSET);
  1572. Xhc->RTSOff = XhcReadCapReg (Xhc, XHC_RTSOFF_OFFSET);
  1573. //
  1574. // This PageSize field defines the page size supported by the xHC implementation.
  1575. // This xHC supports a page size of 2^(n+12) if bit n is Set. For example,
  1576. // if bit 0 is Set, the xHC supports 4k byte page sizes.
  1577. //
  1578. PageSize = XhcReadOpReg (Xhc, XHC_PAGESIZE_OFFSET);
  1579. if ((PageSize & (~XHC_PAGESIZE_MASK)) != 0) {
  1580. DEBUG ((DEBUG_ERROR, "XhcCreateUsb3Hc: Reserved bits are not 0 for PageSize\n"));
  1581. goto ON_ERROR;
  1582. }
  1583. PageSize &= XHC_PAGESIZE_MASK;
  1584. Xhc->PageSize = 1 << (HighBitSet32 (PageSize) + 12);
  1585. ExtCapReg = (UINT16)(Xhc->HcCParams.Data.ExtCapReg);
  1586. Xhc->ExtCapRegBase = ExtCapReg << 2;
  1587. Xhc->UsbLegSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_LEGACY);
  1588. Xhc->DebugCapSupOffset = XhcGetCapabilityAddr (Xhc, XHC_CAP_USB_DEBUG);
  1589. Xhc->Usb2SupOffset = XhcGetSupportedProtocolCapabilityAddr (Xhc, XHC_SUPPORTED_PROTOCOL_DW0_MAJOR_REVISION_USB2);
  1590. Xhc->Usb3SupOffset = XhcGetSupportedProtocolCapabilityAddr (Xhc, XHC_SUPPORTED_PROTOCOL_DW0_MAJOR_REVISION_USB3);
  1591. DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: Capability length 0x%x\n", Xhc->CapLength));
  1592. DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: HcSParams1 0x%x\n", Xhc->HcSParams1));
  1593. DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: HcSParams2 0x%x\n", Xhc->HcSParams2));
  1594. DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: HcCParams 0x%x\n", Xhc->HcCParams));
  1595. DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: DBOff 0x%x\n", Xhc->DBOff));
  1596. DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: RTSOff 0x%x\n", Xhc->RTSOff));
  1597. DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: UsbLegSupOffset 0x%x\n", Xhc->UsbLegSupOffset));
  1598. DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: DebugCapSupOffset 0x%x\n", Xhc->DebugCapSupOffset));
  1599. DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: Usb2SupOffset 0x%x\n", Xhc->Usb2SupOffset));
  1600. DEBUG ((DEBUG_INFO, "XhcCreateUsb3Hc: Usb3SupOffset 0x%x\n", Xhc->Usb3SupOffset));
  1601. //
  1602. // Create AsyncRequest Polling Timer
  1603. //
  1604. Status = gBS->CreateEvent (
  1605. EVT_TIMER | EVT_NOTIFY_SIGNAL,
  1606. TPL_NOTIFY,
  1607. XhcMonitorAsyncRequests,
  1608. Xhc,
  1609. &Xhc->PollTimer
  1610. );
  1611. if (EFI_ERROR (Status)) {
  1612. goto ON_ERROR;
  1613. }
  1614. return Xhc;
  1615. ON_ERROR:
  1616. FreePool (Xhc);
  1617. return NULL;
  1618. }
  1619. /**
  1620. One notified function to stop the Host Controller when gBS->ExitBootServices() called.
  1621. @param Event Pointer to this event
  1622. @param Context Event handler private data
  1623. **/
  1624. VOID
  1625. EFIAPI
  1626. XhcExitBootService (
  1627. EFI_EVENT Event,
  1628. VOID *Context
  1629. )
  1630. {
  1631. USB_XHCI_INSTANCE *Xhc;
  1632. EFI_PCI_IO_PROTOCOL *PciIo;
  1633. Xhc = (USB_XHCI_INSTANCE *)Context;
  1634. PciIo = Xhc->PciIo;
  1635. //
  1636. // Stop AsyncRequest Polling timer then stop the XHCI driver
  1637. // and uninstall the XHCI protocl.
  1638. //
  1639. gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0);
  1640. XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
  1641. if (Xhc->PollTimer != NULL) {
  1642. gBS->CloseEvent (Xhc->PollTimer);
  1643. }
  1644. XhcClearBiosOwnership (Xhc);
  1645. //
  1646. // Restore original PCI attributes
  1647. //
  1648. PciIo->Attributes (
  1649. PciIo,
  1650. EfiPciIoAttributeOperationSet,
  1651. Xhc->OriginalPciAttributes,
  1652. NULL
  1653. );
  1654. }
  1655. /**
  1656. Starting the Usb XHCI Driver.
  1657. @param This Protocol instance pointer.
  1658. @param Controller Handle of device to test.
  1659. @param RemainingDevicePath Not used.
  1660. @return EFI_SUCCESS supports this device.
  1661. @return EFI_UNSUPPORTED do not support this device.
  1662. @return EFI_DEVICE_ERROR cannot be started due to device Error.
  1663. @return EFI_OUT_OF_RESOURCES cannot allocate resources.
  1664. **/
  1665. EFI_STATUS
  1666. EFIAPI
  1667. XhcDriverBindingStart (
  1668. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  1669. IN EFI_HANDLE Controller,
  1670. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  1671. )
  1672. {
  1673. EFI_STATUS Status;
  1674. EFI_PCI_IO_PROTOCOL *PciIo;
  1675. UINT64 Supports;
  1676. UINT64 OriginalPciAttributes;
  1677. BOOLEAN PciAttributesSaved;
  1678. USB_XHCI_INSTANCE *Xhc;
  1679. EFI_DEVICE_PATH_PROTOCOL *HcDevicePath;
  1680. //
  1681. // Open the PciIo Protocol, then enable the USB host controller
  1682. //
  1683. Status = gBS->OpenProtocol (
  1684. Controller,
  1685. &gEfiPciIoProtocolGuid,
  1686. (VOID **)&PciIo,
  1687. This->DriverBindingHandle,
  1688. Controller,
  1689. EFI_OPEN_PROTOCOL_BY_DRIVER
  1690. );
  1691. if (EFI_ERROR (Status)) {
  1692. return Status;
  1693. }
  1694. //
  1695. // Open Device Path Protocol for on USB host controller
  1696. //
  1697. HcDevicePath = NULL;
  1698. Status = gBS->OpenProtocol (
  1699. Controller,
  1700. &gEfiDevicePathProtocolGuid,
  1701. (VOID **)&HcDevicePath,
  1702. This->DriverBindingHandle,
  1703. Controller,
  1704. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  1705. );
  1706. PciAttributesSaved = FALSE;
  1707. //
  1708. // Save original PCI attributes
  1709. //
  1710. Status = PciIo->Attributes (
  1711. PciIo,
  1712. EfiPciIoAttributeOperationGet,
  1713. 0,
  1714. &OriginalPciAttributes
  1715. );
  1716. if (EFI_ERROR (Status)) {
  1717. goto CLOSE_PCIIO;
  1718. }
  1719. PciAttributesSaved = TRUE;
  1720. Status = PciIo->Attributes (
  1721. PciIo,
  1722. EfiPciIoAttributeOperationSupported,
  1723. 0,
  1724. &Supports
  1725. );
  1726. if (!EFI_ERROR (Status)) {
  1727. Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
  1728. Status = PciIo->Attributes (
  1729. PciIo,
  1730. EfiPciIoAttributeOperationEnable,
  1731. Supports,
  1732. NULL
  1733. );
  1734. }
  1735. if (EFI_ERROR (Status)) {
  1736. DEBUG ((DEBUG_ERROR, "XhcDriverBindingStart: failed to enable controller\n"));
  1737. goto CLOSE_PCIIO;
  1738. }
  1739. //
  1740. // Create then install USB2_HC_PROTOCOL
  1741. //
  1742. Xhc = XhcCreateUsbHc (PciIo, HcDevicePath, OriginalPciAttributes);
  1743. if (Xhc == NULL) {
  1744. DEBUG ((DEBUG_ERROR, "XhcDriverBindingStart: failed to create USB2_HC\n"));
  1745. return EFI_OUT_OF_RESOURCES;
  1746. }
  1747. //
  1748. // Enable 64-bit DMA support in the PCI layer if this controller
  1749. // supports it.
  1750. //
  1751. if (Xhc->HcCParams.Data.Ac64 != 0) {
  1752. Status = PciIo->Attributes (
  1753. PciIo,
  1754. EfiPciIoAttributeOperationEnable,
  1755. EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
  1756. NULL
  1757. );
  1758. if (!EFI_ERROR (Status)) {
  1759. Xhc->Support64BitDma = TRUE;
  1760. } else {
  1761. DEBUG ((
  1762. DEBUG_WARN,
  1763. "%a: failed to enable 64-bit DMA on 64-bit capable controller @ %p (%r)\n",
  1764. __FUNCTION__,
  1765. Controller,
  1766. Status
  1767. ));
  1768. }
  1769. }
  1770. XhcSetBiosOwnership (Xhc);
  1771. XhcResetHC (Xhc, XHC_RESET_TIMEOUT);
  1772. ASSERT (XhcIsHalt (Xhc));
  1773. //
  1774. // After Chip Hardware Reset wait until the Controller Not Ready (CNR) flag
  1775. // in the USBSTS is '0' before writing any xHC Operational or Runtime registers.
  1776. //
  1777. ASSERT (!(XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_CNR)));
  1778. //
  1779. // Initialize the schedule
  1780. //
  1781. XhcInitSched (Xhc);
  1782. //
  1783. // Start the Host Controller
  1784. //
  1785. XhcRunHC (Xhc, XHC_GENERIC_TIMEOUT);
  1786. //
  1787. // Start the asynchronous interrupt monitor
  1788. //
  1789. Status = gBS->SetTimer (Xhc->PollTimer, TimerPeriodic, XHC_ASYNC_TIMER_INTERVAL);
  1790. if (EFI_ERROR (Status)) {
  1791. DEBUG ((DEBUG_ERROR, "XhcDriverBindingStart: failed to start async interrupt monitor\n"));
  1792. XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
  1793. goto FREE_POOL;
  1794. }
  1795. //
  1796. // Create event to stop the HC when exit boot service.
  1797. //
  1798. Status = gBS->CreateEventEx (
  1799. EVT_NOTIFY_SIGNAL,
  1800. TPL_NOTIFY,
  1801. XhcExitBootService,
  1802. Xhc,
  1803. &gEfiEventExitBootServicesGuid,
  1804. &Xhc->ExitBootServiceEvent
  1805. );
  1806. if (EFI_ERROR (Status)) {
  1807. goto FREE_POOL;
  1808. }
  1809. //
  1810. // Install the component name protocol, don't fail the start
  1811. // because of something for display.
  1812. //
  1813. AddUnicodeString2 (
  1814. "eng",
  1815. gXhciComponentName.SupportedLanguages,
  1816. &Xhc->ControllerNameTable,
  1817. L"eXtensible Host Controller (USB 3.0)",
  1818. TRUE
  1819. );
  1820. AddUnicodeString2 (
  1821. "en",
  1822. gXhciComponentName2.SupportedLanguages,
  1823. &Xhc->ControllerNameTable,
  1824. L"eXtensible Host Controller (USB 3.0)",
  1825. FALSE
  1826. );
  1827. Status = gBS->InstallProtocolInterface (
  1828. &Controller,
  1829. &gEfiUsb2HcProtocolGuid,
  1830. EFI_NATIVE_INTERFACE,
  1831. &Xhc->Usb2Hc
  1832. );
  1833. if (EFI_ERROR (Status)) {
  1834. DEBUG ((DEBUG_ERROR, "XhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
  1835. goto FREE_POOL;
  1836. }
  1837. DEBUG ((DEBUG_INFO, "XhcDriverBindingStart: XHCI started for controller @ %x\n", Controller));
  1838. return EFI_SUCCESS;
  1839. FREE_POOL:
  1840. gBS->CloseEvent (Xhc->PollTimer);
  1841. XhcFreeSched (Xhc);
  1842. FreePool (Xhc);
  1843. CLOSE_PCIIO:
  1844. if (PciAttributesSaved) {
  1845. //
  1846. // Restore original PCI attributes
  1847. //
  1848. PciIo->Attributes (
  1849. PciIo,
  1850. EfiPciIoAttributeOperationSet,
  1851. OriginalPciAttributes,
  1852. NULL
  1853. );
  1854. }
  1855. gBS->CloseProtocol (
  1856. Controller,
  1857. &gEfiPciIoProtocolGuid,
  1858. This->DriverBindingHandle,
  1859. Controller
  1860. );
  1861. return Status;
  1862. }
  1863. /**
  1864. Stop this driver on ControllerHandle. Support stopping any child handles
  1865. created by this driver.
  1866. @param This Protocol instance pointer.
  1867. @param Controller Handle of device to stop driver on.
  1868. @param NumberOfChildren Number of Children in the ChildHandleBuffer.
  1869. @param ChildHandleBuffer List of handles for the children we need to stop.
  1870. @return EFI_SUCCESS Success.
  1871. @return EFI_DEVICE_ERROR Fail.
  1872. **/
  1873. EFI_STATUS
  1874. EFIAPI
  1875. XhcDriverBindingStop (
  1876. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  1877. IN EFI_HANDLE Controller,
  1878. IN UINTN NumberOfChildren,
  1879. IN EFI_HANDLE *ChildHandleBuffer
  1880. )
  1881. {
  1882. EFI_STATUS Status;
  1883. EFI_USB2_HC_PROTOCOL *Usb2Hc;
  1884. EFI_PCI_IO_PROTOCOL *PciIo;
  1885. USB_XHCI_INSTANCE *Xhc;
  1886. UINT8 Index;
  1887. //
  1888. // Test whether the Controller handler passed in is a valid
  1889. // Usb controller handle that should be supported, if not,
  1890. // return the error status directly
  1891. //
  1892. Status = gBS->OpenProtocol (
  1893. Controller,
  1894. &gEfiUsb2HcProtocolGuid,
  1895. (VOID **)&Usb2Hc,
  1896. This->DriverBindingHandle,
  1897. Controller,
  1898. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  1899. );
  1900. if (EFI_ERROR (Status)) {
  1901. return Status;
  1902. }
  1903. Status = gBS->UninstallProtocolInterface (
  1904. Controller,
  1905. &gEfiUsb2HcProtocolGuid,
  1906. Usb2Hc
  1907. );
  1908. if (EFI_ERROR (Status)) {
  1909. return Status;
  1910. }
  1911. Xhc = XHC_FROM_THIS (Usb2Hc);
  1912. PciIo = Xhc->PciIo;
  1913. //
  1914. // Stop AsyncRequest Polling timer then stop the XHCI driver
  1915. // and uninstall the XHCI protocl.
  1916. //
  1917. gBS->SetTimer (Xhc->PollTimer, TimerCancel, 0);
  1918. //
  1919. // Disable the device slots occupied by these devices on its downstream ports.
  1920. // Entry 0 is reserved.
  1921. //
  1922. for (Index = 0; Index < 255; Index++) {
  1923. if (!Xhc->UsbDevContext[Index + 1].Enabled ||
  1924. (Xhc->UsbDevContext[Index + 1].SlotId == 0))
  1925. {
  1926. continue;
  1927. }
  1928. if (Xhc->HcCParams.Data.Csz == 0) {
  1929. XhcDisableSlotCmd (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);
  1930. } else {
  1931. XhcDisableSlotCmd64 (Xhc, Xhc->UsbDevContext[Index + 1].SlotId);
  1932. }
  1933. }
  1934. if (Xhc->PollTimer != NULL) {
  1935. gBS->CloseEvent (Xhc->PollTimer);
  1936. }
  1937. if (Xhc->ExitBootServiceEvent != NULL) {
  1938. gBS->CloseEvent (Xhc->ExitBootServiceEvent);
  1939. }
  1940. XhcHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
  1941. XhcClearBiosOwnership (Xhc);
  1942. XhciDelAllAsyncIntTransfers (Xhc);
  1943. XhcFreeSched (Xhc);
  1944. if (Xhc->ControllerNameTable) {
  1945. FreeUnicodeStringTable (Xhc->ControllerNameTable);
  1946. }
  1947. //
  1948. // Restore original PCI attributes
  1949. //
  1950. PciIo->Attributes (
  1951. PciIo,
  1952. EfiPciIoAttributeOperationSet,
  1953. Xhc->OriginalPciAttributes,
  1954. NULL
  1955. );
  1956. gBS->CloseProtocol (
  1957. Controller,
  1958. &gEfiPciIoProtocolGuid,
  1959. This->DriverBindingHandle,
  1960. Controller
  1961. );
  1962. FreePool (Xhc);
  1963. return EFI_SUCCESS;
  1964. }