Xhci.c 73 KB

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