]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / XhciPei / XhcPeim.c
CommitLineData
d987459f
SZ
1/** @file\r
2PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid\r
3which is used to enable recovery function from USB Drivers.\r
4\r
4a723d3d 5Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>\r
d987459f 6\r
9d510e61 7SPDX-License-Identifier: BSD-2-Clause-Patent\r
d987459f
SZ
8\r
9**/\r
10\r
11#include "XhcPeim.h"\r
12\r
13//\r
14// Two arrays used to translate the XHCI port state (change)\r
15// to the UEFI protocol's port state (change).\r
16//\r
17USB_PORT_STATE_MAP mUsbPortStateMap[] = {\r
1436aea4
MK
18 { XHC_PORTSC_CCS, USB_PORT_STAT_CONNECTION },\r
19 { XHC_PORTSC_PED, USB_PORT_STAT_ENABLE },\r
20 { XHC_PORTSC_OCA, USB_PORT_STAT_OVERCURRENT },\r
21 { XHC_PORTSC_PP, USB_PORT_STAT_POWER },\r
22 { XHC_PORTSC_RESET, USB_PORT_STAT_RESET }\r
d987459f
SZ
23};\r
24\r
25USB_PORT_STATE_MAP mUsbPortChangeMap[] = {\r
1436aea4
MK
26 { XHC_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION },\r
27 { XHC_PORTSC_PEC, USB_PORT_STAT_C_ENABLE },\r
28 { XHC_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT },\r
29 { XHC_PORTSC_PRC, USB_PORT_STAT_C_RESET }\r
d987459f
SZ
30};\r
31\r
1436aea4
MK
32USB_CLEAR_PORT_MAP mUsbClearPortChangeMap[] = {\r
33 { XHC_PORTSC_CSC, EfiUsbPortConnectChange },\r
34 { XHC_PORTSC_PEC, EfiUsbPortEnableChange },\r
35 { XHC_PORTSC_OCC, EfiUsbPortOverCurrentChange },\r
36 { XHC_PORTSC_PRC, EfiUsbPortResetChange }\r
d987459f
SZ
37};\r
38\r
39USB_PORT_STATE_MAP mUsbHubPortStateMap[] = {\r
1436aea4
MK
40 { XHC_HUB_PORTSC_CCS, USB_PORT_STAT_CONNECTION },\r
41 { XHC_HUB_PORTSC_PED, USB_PORT_STAT_ENABLE },\r
42 { XHC_HUB_PORTSC_OCA, USB_PORT_STAT_OVERCURRENT },\r
43 { XHC_HUB_PORTSC_PP, USB_PORT_STAT_POWER },\r
44 { XHC_HUB_PORTSC_RESET, USB_PORT_STAT_RESET }\r
d987459f
SZ
45};\r
46\r
47USB_PORT_STATE_MAP mUsbHubPortChangeMap[] = {\r
1436aea4
MK
48 { XHC_HUB_PORTSC_CSC, USB_PORT_STAT_C_CONNECTION },\r
49 { XHC_HUB_PORTSC_PEC, USB_PORT_STAT_C_ENABLE },\r
50 { XHC_HUB_PORTSC_OCC, USB_PORT_STAT_C_OVERCURRENT },\r
51 { XHC_HUB_PORTSC_PRC, USB_PORT_STAT_C_RESET }\r
d987459f
SZ
52};\r
53\r
1436aea4
MK
54USB_CLEAR_PORT_MAP mUsbHubClearPortChangeMap[] = {\r
55 { XHC_HUB_PORTSC_CSC, EfiUsbPortConnectChange },\r
56 { XHC_HUB_PORTSC_PEC, EfiUsbPortEnableChange },\r
57 { XHC_HUB_PORTSC_OCC, EfiUsbPortOverCurrentChange },\r
58 { XHC_HUB_PORTSC_PRC, EfiUsbPortResetChange },\r
59 { XHC_HUB_PORTSC_BHRC, Usb3PortBHPortResetChange }\r
d987459f
SZ
60};\r
61\r
62/**\r
63 Read XHCI Operation register.\r
64\r
65 @param Xhc The XHCI device.\r
66 @param Offset The operation register offset.\r
67\r
68 @retval the register content read.\r
69\r
70**/\r
71UINT32\r
72XhcPeiReadOpReg (\r
1436aea4
MK
73 IN PEI_XHC_DEV *Xhc,\r
74 IN UINT32 Offset\r
d987459f
SZ
75 )\r
76{\r
1436aea4 77 UINT32 Data;\r
d987459f
SZ
78\r
79 ASSERT (Xhc->CapLength != 0);\r
80\r
81 Data = MmioRead32 (Xhc->UsbHostControllerBaseAddress + Xhc->CapLength + Offset);\r
82 return Data;\r
83}\r
84\r
85/**\r
86 Write the data to the XHCI operation register.\r
87\r
88 @param Xhc The XHCI device.\r
89 @param Offset The operation register offset.\r
90 @param Data The data to write.\r
91\r
92**/\r
93VOID\r
94XhcPeiWriteOpReg (\r
1436aea4
MK
95 IN PEI_XHC_DEV *Xhc,\r
96 IN UINT32 Offset,\r
97 IN UINT32 Data\r
d987459f
SZ
98 )\r
99{\r
100 ASSERT (Xhc->CapLength != 0);\r
101\r
102 MmioWrite32 (Xhc->UsbHostControllerBaseAddress + Xhc->CapLength + Offset, Data);\r
103}\r
104\r
105/**\r
106 Set one bit of the operational register while keeping other bits.\r
107\r
108 @param Xhc The XHCI device.\r
109 @param Offset The offset of the operational register.\r
110 @param Bit The bit mask of the register to set.\r
111\r
112**/\r
113VOID\r
114XhcPeiSetOpRegBit (\r
1436aea4
MK
115 IN PEI_XHC_DEV *Xhc,\r
116 IN UINT32 Offset,\r
117 IN UINT32 Bit\r
d987459f
SZ
118 )\r
119{\r
1436aea4 120 UINT32 Data;\r
d987459f
SZ
121\r
122 Data = XhcPeiReadOpReg (Xhc, Offset);\r
123 Data |= Bit;\r
124 XhcPeiWriteOpReg (Xhc, Offset, Data);\r
125}\r
126\r
127/**\r
128 Clear one bit of the operational register while keeping other bits.\r
129\r
130 @param Xhc The XHCI device.\r
131 @param Offset The offset of the operational register.\r
132 @param Bit The bit mask of the register to clear.\r
133\r
134**/\r
135VOID\r
136XhcPeiClearOpRegBit (\r
1436aea4
MK
137 IN PEI_XHC_DEV *Xhc,\r
138 IN UINT32 Offset,\r
139 IN UINT32 Bit\r
d987459f
SZ
140 )\r
141{\r
1436aea4 142 UINT32 Data;\r
d987459f
SZ
143\r
144 Data = XhcPeiReadOpReg (Xhc, Offset);\r
145 Data &= ~Bit;\r
146 XhcPeiWriteOpReg (Xhc, Offset, Data);\r
147}\r
148\r
149/**\r
150 Wait the operation register's bit as specified by Bit\r
151 to become set (or clear).\r
152\r
153 @param Xhc The XHCI device.\r
154 @param Offset The offset of the operational register.\r
155 @param Bit The bit mask of the register to wait for.\r
156 @param WaitToSet Wait the bit to set or clear.\r
26cd2d6d 157 @param Timeout The time to wait before abort (in millisecond, ms).\r
d987459f
SZ
158\r
159 @retval EFI_SUCCESS The bit successfully changed by host controller.\r
160 @retval EFI_TIMEOUT The time out occurred.\r
161\r
162**/\r
163EFI_STATUS\r
164XhcPeiWaitOpRegBit (\r
1436aea4
MK
165 IN PEI_XHC_DEV *Xhc,\r
166 IN UINT32 Offset,\r
167 IN UINT32 Bit,\r
168 IN BOOLEAN WaitToSet,\r
169 IN UINT32 Timeout\r
d987459f
SZ
170 )\r
171{\r
1436aea4 172 UINT64 Index;\r
d987459f 173\r
26cd2d6d 174 for (Index = 0; Index < Timeout * XHC_1_MILLISECOND; Index++) {\r
d987459f
SZ
175 if (XHC_REG_BIT_IS_SET (Xhc, Offset, Bit) == WaitToSet) {\r
176 return EFI_SUCCESS;\r
177 }\r
178\r
26cd2d6d 179 MicroSecondDelay (XHC_1_MICROSECOND);\r
d987459f
SZ
180 }\r
181\r
182 return EFI_TIMEOUT;\r
183}\r
184\r
185/**\r
186 Read XHCI capability register.\r
187\r
188 @param Xhc The XHCI device.\r
189 @param Offset Capability register address.\r
190\r
191 @retval the register content read.\r
192\r
193**/\r
194UINT32\r
195XhcPeiReadCapRegister (\r
1436aea4
MK
196 IN PEI_XHC_DEV *Xhc,\r
197 IN UINT32 Offset\r
d987459f
SZ
198 )\r
199{\r
1436aea4 200 UINT32 Data;\r
d987459f
SZ
201\r
202 Data = MmioRead32 (Xhc->UsbHostControllerBaseAddress + Offset);\r
203\r
204 return Data;\r
205}\r
206\r
d987459f
SZ
207/**\r
208 Write the data to the XHCI door bell register.\r
209\r
210 @param Xhc The XHCI device.\r
211 @param Offset The offset of the door bell register.\r
212 @param Data The data to write.\r
213\r
214**/\r
215VOID\r
216XhcPeiWriteDoorBellReg (\r
1436aea4
MK
217 IN PEI_XHC_DEV *Xhc,\r
218 IN UINT32 Offset,\r
219 IN UINT32 Data\r
d987459f
SZ
220 )\r
221{\r
222 ASSERT (Xhc->DBOff != 0);\r
223\r
224 MmioWrite32 (Xhc->UsbHostControllerBaseAddress + Xhc->DBOff + Offset, Data);\r
225}\r
226\r
227/**\r
228 Read XHCI runtime register.\r
229\r
230 @param Xhc The XHCI device.\r
231 @param Offset The offset of the runtime register.\r
232\r
233 @return The register content read\r
234\r
235**/\r
236UINT32\r
237XhcPeiReadRuntimeReg (\r
1436aea4
MK
238 IN PEI_XHC_DEV *Xhc,\r
239 IN UINT32 Offset\r
d987459f
SZ
240 )\r
241{\r
1436aea4 242 UINT32 Data;\r
d987459f
SZ
243\r
244 ASSERT (Xhc->RTSOff != 0);\r
245\r
246 Data = MmioRead32 (Xhc->UsbHostControllerBaseAddress + Xhc->RTSOff + Offset);\r
247\r
248 return Data;\r
249}\r
250\r
251/**\r
252 Write the data to the XHCI runtime register.\r
253\r
254 @param Xhc The XHCI device.\r
255 @param Offset The offset of the runtime register.\r
256 @param Data The data to write.\r
257\r
258**/\r
259VOID\r
260XhcPeiWriteRuntimeReg (\r
1436aea4
MK
261 IN PEI_XHC_DEV *Xhc,\r
262 IN UINT32 Offset,\r
263 IN UINT32 Data\r
d987459f
SZ
264 )\r
265{\r
266 ASSERT (Xhc->RTSOff != 0);\r
267\r
268 MmioWrite32 (Xhc->UsbHostControllerBaseAddress + Xhc->RTSOff + Offset, Data);\r
269}\r
270\r
271/**\r
272 Set one bit of the runtime register while keeping other bits.\r
273\r
274 @param Xhc The XHCI device.\r
275 @param Offset The offset of the runtime register.\r
276 @param Bit The bit mask of the register to set.\r
277\r
278**/\r
279VOID\r
280XhcPeiSetRuntimeRegBit (\r
1436aea4
MK
281 IN PEI_XHC_DEV *Xhc,\r
282 IN UINT32 Offset,\r
283 IN UINT32 Bit\r
d987459f
SZ
284 )\r
285{\r
1436aea4 286 UINT32 Data;\r
d987459f
SZ
287\r
288 Data = XhcPeiReadRuntimeReg (Xhc, Offset);\r
289 Data |= Bit;\r
290 XhcPeiWriteRuntimeReg (Xhc, Offset, Data);\r
291}\r
292\r
293/**\r
294 Clear one bit of the runtime register while keeping other bits.\r
295\r
296 @param Xhc The XHCI device.\r
297 @param Offset The offset of the runtime register.\r
298 @param Bit The bit mask of the register to set.\r
299\r
300**/\r
301VOID\r
302XhcPeiClearRuntimeRegBit (\r
1436aea4
MK
303 IN PEI_XHC_DEV *Xhc,\r
304 IN UINT32 Offset,\r
305 IN UINT32 Bit\r
d987459f
SZ
306 )\r
307{\r
1436aea4 308 UINT32 Data;\r
d987459f
SZ
309\r
310 Data = XhcPeiReadRuntimeReg (Xhc, Offset);\r
311 Data &= ~Bit;\r
312 XhcPeiWriteRuntimeReg (Xhc, Offset, Data);\r
313}\r
314\r
315/**\r
316 Check whether Xhc is halted.\r
317\r
318 @param Xhc The XHCI device.\r
319\r
320 @retval TRUE The controller is halted.\r
321 @retval FALSE The controller isn't halted.\r
322\r
323**/\r
324BOOLEAN\r
325XhcPeiIsHalt (\r
1436aea4 326 IN PEI_XHC_DEV *Xhc\r
d987459f
SZ
327 )\r
328{\r
329 return XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT);\r
330}\r
331\r
332/**\r
333 Check whether system error occurred.\r
334\r
335 @param Xhc The XHCI device.\r
336\r
337 @retval TRUE System error happened.\r
338 @retval FALSE No system error.\r
339\r
340**/\r
341BOOLEAN\r
342XhcPeiIsSysError (\r
1436aea4 343 IN PEI_XHC_DEV *Xhc\r
d987459f
SZ
344 )\r
345{\r
346 return XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HSE);\r
347}\r
348\r
349/**\r
350 Reset the host controller.\r
351\r
352 @param Xhc The XHCI device.\r
26cd2d6d 353 @param Timeout Time to wait before abort (in millisecond, ms).\r
d987459f
SZ
354\r
355 @retval EFI_TIMEOUT The transfer failed due to time out.\r
356 @retval Others Failed to reset the host.\r
357\r
358**/\r
359EFI_STATUS\r
360XhcPeiResetHC (\r
1436aea4
MK
361 IN PEI_XHC_DEV *Xhc,\r
362 IN UINT32 Timeout\r
d987459f
SZ
363 )\r
364{\r
1436aea4 365 EFI_STATUS Status;\r
d987459f
SZ
366\r
367 //\r
368 // Host can only be reset when it is halt. If not so, halt it\r
369 //\r
370 if (!XhcPeiIsHalt (Xhc)) {\r
371 Status = XhcPeiHaltHC (Xhc, Timeout);\r
372\r
373 if (EFI_ERROR (Status)) {\r
374 goto ON_EXIT;\r
375 }\r
376 }\r
377\r
378 XhcPeiSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET);\r
1f87985a
FT
379 //\r
380 // Some XHCI host controllers require to have extra 1ms delay before accessing any MMIO register during reset.\r
381 // Otherwise there may have the timeout case happened.\r
382 // The below is a workaround to solve such problem.\r
383 //\r
384 MicroSecondDelay (1000);\r
d987459f
SZ
385 Status = XhcPeiWaitOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET, FALSE, Timeout);\r
386ON_EXIT:\r
87000d77 387 DEBUG ((DEBUG_INFO, "XhcPeiResetHC: %r\n", Status));\r
d987459f
SZ
388 return Status;\r
389}\r
390\r
391/**\r
392 Halt the host controller.\r
393\r
394 @param Xhc The XHCI device.\r
395 @param Timeout Time to wait before abort.\r
396\r
397 @retval EFI_TIMEOUT Failed to halt the controller before Timeout.\r
398 @retval EFI_SUCCESS The XHCI is halt.\r
399\r
400**/\r
401EFI_STATUS\r
402XhcPeiHaltHC (\r
1436aea4
MK
403 IN PEI_XHC_DEV *Xhc,\r
404 IN UINT32 Timeout\r
d987459f
SZ
405 )\r
406{\r
1436aea4 407 EFI_STATUS Status;\r
d987459f
SZ
408\r
409 XhcPeiClearOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);\r
410 Status = XhcPeiWaitOpRegBit (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT, TRUE, Timeout);\r
87000d77 411 DEBUG ((DEBUG_INFO, "XhcPeiHaltHC: %r\n", Status));\r
d987459f
SZ
412 return Status;\r
413}\r
414\r
415/**\r
416 Set the XHCI to run.\r
417\r
418 @param Xhc The XHCI device.\r
419 @param Timeout Time to wait before abort.\r
420\r
421 @retval EFI_SUCCESS The XHCI is running.\r
422 @retval Others Failed to set the XHCI to run.\r
423\r
424**/\r
425EFI_STATUS\r
426XhcPeiRunHC (\r
1436aea4
MK
427 IN PEI_XHC_DEV *Xhc,\r
428 IN UINT32 Timeout\r
d987459f
SZ
429 )\r
430{\r
1436aea4 431 EFI_STATUS Status;\r
d987459f
SZ
432\r
433 XhcPeiSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);\r
434 Status = XhcPeiWaitOpRegBit (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT, FALSE, Timeout);\r
87000d77 435 DEBUG ((DEBUG_INFO, "XhcPeiRunHC: %r\n", Status));\r
d987459f
SZ
436 return Status;\r
437}\r
438\r
439/**\r
440 Submits control transfer to a target USB device.\r
441\r
442 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
443 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.\r
444 @param DeviceAddress The target device address.\r
445 @param DeviceSpeed Target device speed.\r
446 @param MaximumPacketLength Maximum packet size the default control transfer\r
447 endpoint is capable of sending or receiving.\r
448 @param Request USB device request to send.\r
449 @param TransferDirection Specifies the data direction for the data stage.\r
450 @param Data Data buffer to be transmitted or received from USB device.\r
451 @param DataLength The size (in bytes) of the data buffer.\r
452 @param TimeOut Indicates the maximum timeout, in millisecond.\r
453 If Timeout is 0, then the caller must wait for the function\r
454 to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.\r
455 @param Translator Transaction translator to be used by this device.\r
456 @param TransferResult Return the result of this control transfer.\r
457\r
458 @retval EFI_SUCCESS Transfer was completed successfully.\r
459 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.\r
460 @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
461 @retval EFI_TIMEOUT Transfer failed due to timeout.\r
462 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.\r
463\r
464**/\r
465EFI_STATUS\r
466EFIAPI\r
467XhcPeiControlTransfer (\r
1436aea4
MK
468 IN EFI_PEI_SERVICES **PeiServices,\r
469 IN PEI_USB2_HOST_CONTROLLER_PPI *This,\r
470 IN UINT8 DeviceAddress,\r
471 IN UINT8 DeviceSpeed,\r
472 IN UINTN MaximumPacketLength,\r
473 IN EFI_USB_DEVICE_REQUEST *Request,\r
474 IN EFI_USB_DATA_DIRECTION TransferDirection,\r
475 IN OUT VOID *Data,\r
476 IN OUT UINTN *DataLength,\r
477 IN UINTN TimeOut,\r
478 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
479 OUT UINT32 *TransferResult\r
d987459f
SZ
480 )\r
481{\r
1436aea4
MK
482 PEI_XHC_DEV *Xhc;\r
483 URB *Urb;\r
484 UINT8 Endpoint;\r
485 UINT8 Index;\r
486 UINT8 DescriptorType;\r
487 UINT8 SlotId;\r
488 UINT8 TTT;\r
489 UINT8 MTT;\r
490 UINT32 MaxPacket0;\r
491 EFI_USB_HUB_DESCRIPTOR *HubDesc;\r
492 EFI_STATUS Status;\r
493 EFI_STATUS RecoveryStatus;\r
494 UINTN MapSize;\r
495 EFI_USB_PORT_STATUS PortStatus;\r
496 UINT32 State;\r
497 EFI_USB_DEVICE_REQUEST ClearPortRequest;\r
498 UINTN Len;\r
d987459f
SZ
499\r
500 //\r
501 // Validate parameters\r
502 //\r
503 if ((Request == NULL) || (TransferResult == NULL)) {\r
504 return EFI_INVALID_PARAMETER;\r
505 }\r
506\r
507 if ((TransferDirection != EfiUsbDataIn) &&\r
508 (TransferDirection != EfiUsbDataOut) &&\r
1436aea4
MK
509 (TransferDirection != EfiUsbNoData))\r
510 {\r
d987459f
SZ
511 return EFI_INVALID_PARAMETER;\r
512 }\r
513\r
514 if ((TransferDirection == EfiUsbNoData) &&\r
1436aea4
MK
515 ((Data != NULL) || (*DataLength != 0)))\r
516 {\r
d987459f
SZ
517 return EFI_INVALID_PARAMETER;\r
518 }\r
519\r
520 if ((TransferDirection != EfiUsbNoData) &&\r
1436aea4
MK
521 ((Data == NULL) || (*DataLength == 0)))\r
522 {\r
d987459f
SZ
523 return EFI_INVALID_PARAMETER;\r
524 }\r
525\r
526 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&\r
527 (MaximumPacketLength != 32) && (MaximumPacketLength != 64) &&\r
528 (MaximumPacketLength != 512)\r
1436aea4
MK
529 )\r
530 {\r
d987459f
SZ
531 return EFI_INVALID_PARAMETER;\r
532 }\r
533\r
534 if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {\r
535 return EFI_INVALID_PARAMETER;\r
536 }\r
537\r
538 if ((DeviceSpeed == EFI_USB_SPEED_SUPER) && (MaximumPacketLength != 512)) {\r
539 return EFI_INVALID_PARAMETER;\r
540 }\r
541\r
1436aea4 542 Xhc = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This);\r
d987459f
SZ
543\r
544 Status = EFI_DEVICE_ERROR;\r
545 *TransferResult = EFI_USB_ERR_SYSTEM;\r
546 Len = 0;\r
547\r
548 if (XhcPeiIsHalt (Xhc) || XhcPeiIsSysError (Xhc)) {\r
87000d77 549 DEBUG ((DEBUG_ERROR, "XhcPeiControlTransfer: HC is halted or has system error\n"));\r
d987459f
SZ
550 goto ON_EXIT;\r
551 }\r
552\r
553 //\r
554 // Check if the device is still enabled before every transaction.\r
555 //\r
556 SlotId = XhcPeiBusDevAddrToSlotId (Xhc, DeviceAddress);\r
557 if (SlotId == 0) {\r
558 goto ON_EXIT;\r
559 }\r
560\r
561 //\r
562 // Hook the Set_Address request from UsbBus.\r
563 // According to XHCI 1.0 spec, the Set_Address request is replaced by XHCI's Address_Device cmd.\r
564 //\r
565 if ((Request->Request == USB_REQ_SET_ADDRESS) &&\r
1436aea4
MK
566 (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)))\r
567 {\r
d987459f
SZ
568 //\r
569 // Reset the BusDevAddr field of all disabled entries in UsbDevContext array firstly.\r
570 // This way is used to clean the history to avoid using wrong device address afterwards.\r
571 //\r
572 for (Index = 0; Index < 255; Index++) {\r
573 if (!Xhc->UsbDevContext[Index + 1].Enabled &&\r
574 (Xhc->UsbDevContext[Index + 1].SlotId == 0) &&\r
1436aea4
MK
575 (Xhc->UsbDevContext[Index + 1].BusDevAddr == (UINT8)Request->Value))\r
576 {\r
d987459f
SZ
577 Xhc->UsbDevContext[Index + 1].BusDevAddr = 0;\r
578 }\r
579 }\r
580\r
581 if (Xhc->UsbDevContext[SlotId].XhciDevAddr == 0) {\r
582 goto ON_EXIT;\r
583 }\r
1436aea4 584\r
d987459f
SZ
585 //\r
586 // The actual device address has been assigned by XHCI during initializing the device slot.\r
587 // So we just need establish the mapping relationship between the device address requested from UsbBus\r
588 // and the actual device address assigned by XHCI. The following invocations through EFI_USB2_HC_PROTOCOL interface\r
589 // can find out the actual device address by it.\r
590 //\r
1436aea4
MK
591 Xhc->UsbDevContext[SlotId].BusDevAddr = (UINT8)Request->Value;\r
592 Status = EFI_SUCCESS;\r
d987459f
SZ
593 goto ON_EXIT;\r
594 }\r
595\r
596 //\r
597 // Create a new URB, insert it into the asynchronous\r
598 // schedule list, then poll the execution status.\r
599 // Note that we encode the direction in address although default control\r
600 // endpoint is bidirectional. XhcPeiCreateUrb expects this\r
601 // combination of Ep addr and its direction.\r
602 //\r
1436aea4
MK
603 Endpoint = (UINT8)(0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));\r
604 Urb = XhcPeiCreateUrb (\r
605 Xhc,\r
606 DeviceAddress,\r
607 Endpoint,\r
608 DeviceSpeed,\r
609 MaximumPacketLength,\r
610 XHC_CTRL_TRANSFER,\r
611 Request,\r
612 Data,\r
613 *DataLength,\r
614 NULL,\r
615 NULL\r
616 );\r
d987459f
SZ
617\r
618 if (Urb == NULL) {\r
87000d77 619 DEBUG ((DEBUG_ERROR, "XhcPeiControlTransfer: failed to create URB"));\r
d987459f
SZ
620 Status = EFI_OUT_OF_RESOURCES;\r
621 goto ON_EXIT;\r
622 }\r
623\r
624 Status = XhcPeiExecTransfer (Xhc, FALSE, Urb, TimeOut);\r
625\r
626 //\r
627 // Get the status from URB. The result is updated in XhcPeiCheckUrbResult\r
628 // which is called by XhcPeiExecTransfer\r
629 //\r
630 *TransferResult = Urb->Result;\r
631 *DataLength = Urb->Completed;\r
632\r
12e6c738
FT
633 if (Status == EFI_TIMEOUT) {\r
634 //\r
635 // The transfer timed out. Abort the transfer by dequeueing of the TD.\r
636 //\r
1436aea4
MK
637 RecoveryStatus = XhcPeiDequeueTrbFromEndpoint (Xhc, Urb);\r
638 if (EFI_ERROR (RecoveryStatus)) {\r
639 DEBUG ((DEBUG_ERROR, "XhcPeiControlTransfer: XhcPeiDequeueTrbFromEndpoint failed\n"));\r
d987459f 640 }\r
1436aea4 641\r
b575ca32
JY
642 XhcPeiFreeUrb (Xhc, Urb);\r
643 goto ON_EXIT;\r
d987459f 644 } else {\r
12e6c738
FT
645 if (*TransferResult == EFI_USB_NOERROR) {\r
646 Status = EFI_SUCCESS;\r
958a8181 647 } else if ((*TransferResult == EFI_USB_ERR_STALL) || (*TransferResult == EFI_USB_ERR_BABBLE)) {\r
1436aea4 648 RecoveryStatus = XhcPeiRecoverHaltedEndpoint (Xhc, Urb);\r
12e6c738 649 if (EFI_ERROR (RecoveryStatus)) {\r
87000d77 650 DEBUG ((DEBUG_ERROR, "XhcPeiControlTransfer: XhcPeiRecoverHaltedEndpoint failed\n"));\r
12e6c738 651 }\r
1436aea4 652\r
12e6c738 653 Status = EFI_DEVICE_ERROR;\r
b575ca32
JY
654 XhcPeiFreeUrb (Xhc, Urb);\r
655 goto ON_EXIT;\r
12e6c738 656 } else {\r
b575ca32
JY
657 XhcPeiFreeUrb (Xhc, Urb);\r
658 goto ON_EXIT;\r
12e6c738 659 }\r
d987459f 660 }\r
1436aea4 661\r
b575ca32
JY
662 //\r
663 // Unmap data before consume.\r
664 //\r
665 XhcPeiFreeUrb (Xhc, Urb);\r
d987459f
SZ
666\r
667 //\r
668 // Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.\r
669 // Hook Get_Status request form UsbBus as we need trace device attach/detach event happened at hub.\r
670 // Hook Set_Config request from UsbBus as we need configure device endpoint.\r
671 //\r
672 if ((Request->Request == USB_REQ_GET_DESCRIPTOR) &&\r
673 ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)) ||\r
1436aea4
MK
674 ((Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_DEVICE)))))\r
675 {\r
676 DescriptorType = (UINT8)(Request->Value >> 8);\r
d987459f
SZ
677 if ((DescriptorType == USB_DESC_TYPE_DEVICE) && ((*DataLength == sizeof (EFI_USB_DEVICE_DESCRIPTOR)) || ((DeviceSpeed == EFI_USB_SPEED_FULL) && (*DataLength == 8)))) {\r
678 ASSERT (Data != NULL);\r
679 //\r
680 // Store a copy of device scriptor as hub device need this info to configure endpoint.\r
681 //\r
682 CopyMem (&Xhc->UsbDevContext[SlotId].DevDesc, Data, *DataLength);\r
b9953b65 683 if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB >= 0x0300) {\r
d987459f
SZ
684 //\r
685 // If it's a usb3.0 device, then its max packet size is a 2^n.\r
686 //\r
687 MaxPacket0 = 1 << Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;\r
688 } else {\r
689 MaxPacket0 = Xhc->UsbDevContext[SlotId].DevDesc.MaxPacketSize0;\r
690 }\r
1436aea4 691\r
d987459f
SZ
692 Xhc->UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));\r
693 if (Xhc->UsbDevContext[SlotId].ConfDesc == NULL) {\r
694 Status = EFI_OUT_OF_RESOURCES;\r
b575ca32 695 goto ON_EXIT;\r
d987459f 696 }\r
1436aea4 697\r
d987459f
SZ
698 if (Xhc->HcCParams.Data.Csz == 0) {\r
699 Status = XhcPeiEvaluateContext (Xhc, SlotId, MaxPacket0);\r
700 } else {\r
701 Status = XhcPeiEvaluateContext64 (Xhc, SlotId, MaxPacket0);\r
702 }\r
703 } else if (DescriptorType == USB_DESC_TYPE_CONFIG) {\r
704 ASSERT (Data != NULL);\r
1436aea4 705 if (*DataLength == ((UINT16 *)Data)[1]) {\r
d987459f
SZ
706 //\r
707 // Get configuration value from request, store the configuration descriptor for Configure_Endpoint cmd.\r
708 //\r
1436aea4 709 Index = (UINT8)Request->Value;\r
d987459f
SZ
710 ASSERT (Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations);\r
711 Xhc->UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool (*DataLength);\r
712 if (Xhc->UsbDevContext[SlotId].ConfDesc[Index] == NULL) {\r
713 Status = EFI_OUT_OF_RESOURCES;\r
b575ca32 714 goto ON_EXIT;\r
d987459f 715 }\r
1436aea4 716\r
d987459f
SZ
717 CopyMem (Xhc->UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLength);\r
718 }\r
719 } else if (((DescriptorType == USB_DESC_TYPE_HUB) ||\r
1436aea4
MK
720 (DescriptorType == USB_DESC_TYPE_HUB_SUPER_SPEED)) && (*DataLength > 2))\r
721 {\r
d987459f 722 ASSERT (Data != NULL);\r
1436aea4 723 HubDesc = (EFI_USB_HUB_DESCRIPTOR *)Data;\r
d987459f
SZ
724 ASSERT (HubDesc->NumPorts <= 15);\r
725 //\r
726 // The bit 5,6 of HubCharacter field of Hub Descriptor is TTT.\r
727 //\r
1436aea4 728 TTT = (UINT8)((HubDesc->HubCharacter & (BIT5 | BIT6)) >> 5);\r
d987459f
SZ
729 if (Xhc->UsbDevContext[SlotId].DevDesc.DeviceProtocol == 2) {\r
730 //\r
731 // Don't support multi-TT feature for super speed hub now.\r
732 //\r
733 MTT = 0;\r
87000d77 734 DEBUG ((DEBUG_ERROR, "XHCI: Don't support multi-TT feature for Hub now. (force to disable MTT)\n"));\r
d987459f
SZ
735 } else {\r
736 MTT = 0;\r
737 }\r
738\r
739 if (Xhc->HcCParams.Data.Csz == 0) {\r
740 Status = XhcPeiConfigHubContext (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);\r
741 } else {\r
742 Status = XhcPeiConfigHubContext64 (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);\r
743 }\r
744 }\r
745 } else if ((Request->Request == USB_REQ_SET_CONFIG) &&\r
1436aea4
MK
746 (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE)))\r
747 {\r
d987459f
SZ
748 //\r
749 // Hook Set_Config request from UsbBus as we need configure device endpoint.\r
750 //\r
751 for (Index = 0; Index < Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations; Index++) {\r
752 if (Xhc->UsbDevContext[SlotId].ConfDesc[Index]->ConfigurationValue == (UINT8)Request->Value) {\r
753 if (Xhc->HcCParams.Data.Csz == 0) {\r
754 Status = XhcPeiSetConfigCmd (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);\r
755 } else {\r
756 Status = XhcPeiSetConfigCmd64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);\r
757 }\r
1436aea4 758\r
d987459f
SZ
759 break;\r
760 }\r
761 }\r
762 } else if ((Request->Request == USB_REQ_GET_STATUS) &&\r
1436aea4
MK
763 (Request->RequestType == USB_REQUEST_TYPE (EfiUsbDataIn, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER)))\r
764 {\r
d987459f
SZ
765 ASSERT (Data != NULL);\r
766 //\r
767 // Hook Get_Status request from UsbBus to keep track of the port status change.\r
768 //\r
1436aea4 769 State = *(UINT32 *)Data;\r
d987459f
SZ
770 PortStatus.PortStatus = 0;\r
771 PortStatus.PortChangeStatus = 0;\r
772\r
773 if (DeviceSpeed == EFI_USB_SPEED_SUPER) {\r
774 //\r
775 // For super speed hub, its bit10~12 presents the attached device speed.\r
776 //\r
777 if ((State & XHC_PORTSC_PS) >> 10 == 0) {\r
778 PortStatus.PortStatus |= USB_PORT_STAT_SUPER_SPEED;\r
779 }\r
780 } else {\r
781 //\r
782 // For high or full/low speed hub, its bit9~10 presents the attached device speed.\r
783 //\r
784 if (XHC_BIT_IS_SET (State, BIT9)) {\r
785 PortStatus.PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
786 } else if (XHC_BIT_IS_SET (State, BIT10)) {\r
787 PortStatus.PortStatus |= USB_PORT_STAT_HIGH_SPEED;\r
788 }\r
789 }\r
790\r
791 //\r
792 // Convert the XHCI port/port change state to UEFI status\r
793 //\r
794 MapSize = sizeof (mUsbHubPortStateMap) / sizeof (USB_PORT_STATE_MAP);\r
795 for (Index = 0; Index < MapSize; Index++) {\r
796 if (XHC_BIT_IS_SET (State, mUsbHubPortStateMap[Index].HwState)) {\r
1436aea4 797 PortStatus.PortStatus = (UINT16)(PortStatus.PortStatus | mUsbHubPortStateMap[Index].UefiState);\r
d987459f
SZ
798 }\r
799 }\r
800\r
801 MapSize = sizeof (mUsbHubPortChangeMap) / sizeof (USB_PORT_STATE_MAP);\r
802 for (Index = 0; Index < MapSize; Index++) {\r
803 if (XHC_BIT_IS_SET (State, mUsbHubPortChangeMap[Index].HwState)) {\r
1436aea4 804 PortStatus.PortChangeStatus = (UINT16)(PortStatus.PortChangeStatus | mUsbHubPortChangeMap[Index].UefiState);\r
d987459f
SZ
805 }\r
806 }\r
807\r
808 MapSize = sizeof (mUsbHubClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);\r
809\r
810 for (Index = 0; Index < MapSize; Index++) {\r
811 if (XHC_BIT_IS_SET (State, mUsbHubClearPortChangeMap[Index].HwState)) {\r
812 ZeroMem (&ClearPortRequest, sizeof (EFI_USB_DEVICE_REQUEST));\r
1436aea4
MK
813 ClearPortRequest.RequestType = USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER);\r
814 ClearPortRequest.Request = (UINT8)USB_REQ_CLEAR_FEATURE;\r
815 ClearPortRequest.Value = mUsbHubClearPortChangeMap[Index].Selector;\r
816 ClearPortRequest.Index = Request->Index;\r
817 ClearPortRequest.Length = 0;\r
d987459f
SZ
818\r
819 XhcPeiControlTransfer (\r
820 PeiServices,\r
821 This,\r
822 DeviceAddress,\r
823 DeviceSpeed,\r
824 MaximumPacketLength,\r
825 &ClearPortRequest,\r
826 EfiUsbNoData,\r
827 NULL,\r
828 &Len,\r
829 TimeOut,\r
830 Translator,\r
831 TransferResult\r
832 );\r
833 }\r
834 }\r
835\r
836 XhcPeiPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);\r
837\r
1436aea4 838 *(UINT32 *)Data = *(UINT32 *)&PortStatus;\r
d987459f
SZ
839 }\r
840\r
d987459f
SZ
841ON_EXIT:\r
842\r
843 if (EFI_ERROR (Status)) {\r
87000d77 844 DEBUG ((DEBUG_ERROR, "XhcPeiControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
d987459f
SZ
845 }\r
846\r
847 return Status;\r
848}\r
849\r
850/**\r
851 Submits bulk transfer to a bulk endpoint of a USB device.\r
852\r
853 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
854 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.\r
855 @param DeviceAddress Target device address.\r
856 @param EndPointAddress Endpoint number and its direction in bit 7.\r
857 @param DeviceSpeed Device speed, Low speed device doesn't support\r
858 bulk transfer.\r
859 @param MaximumPacketLength Maximum packet size the endpoint is capable of\r
860 sending or receiving.\r
861 @param Data Array of pointers to the buffers of data to transmit\r
862 from or receive into.\r
863 @param DataLength The lenght of the data buffer.\r
864 @param DataToggle On input, the initial data toggle for the transfer;\r
865 On output, it is updated to to next data toggle to use of\r
866 the subsequent bulk transfer.\r
867 @param TimeOut Indicates the maximum time, in millisecond, which the\r
868 transfer is allowed to complete.\r
869 If Timeout is 0, then the caller must wait for the function\r
870 to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.\r
871 @param Translator A pointr to the transaction translator data.\r
872 @param TransferResult A pointer to the detailed result information of the\r
873 bulk transfer.\r
874\r
875 @retval EFI_SUCCESS The transfer was completed successfully.\r
876 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.\r
877 @retval EFI_INVALID_PARAMETER Parameters are invalid.\r
878 @retval EFI_TIMEOUT The transfer failed due to timeout.\r
879 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.\r
880\r
881**/\r
882EFI_STATUS\r
883EFIAPI\r
884XhcPeiBulkTransfer (\r
1436aea4
MK
885 IN EFI_PEI_SERVICES **PeiServices,\r
886 IN PEI_USB2_HOST_CONTROLLER_PPI *This,\r
887 IN UINT8 DeviceAddress,\r
888 IN UINT8 EndPointAddress,\r
889 IN UINT8 DeviceSpeed,\r
890 IN UINTN MaximumPacketLength,\r
891 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
892 IN OUT UINTN *DataLength,\r
893 IN OUT UINT8 *DataToggle,\r
894 IN UINTN TimeOut,\r
895 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
896 OUT UINT32 *TransferResult\r
d987459f
SZ
897 )\r
898{\r
1436aea4
MK
899 PEI_XHC_DEV *Xhc;\r
900 URB *Urb;\r
901 UINT8 SlotId;\r
902 EFI_STATUS Status;\r
903 EFI_STATUS RecoveryStatus;\r
d987459f
SZ
904\r
905 //\r
906 // Validate the parameters\r
907 //\r
908 if ((DataLength == NULL) || (*DataLength == 0) ||\r
1436aea4
MK
909 (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL))\r
910 {\r
d987459f
SZ
911 return EFI_INVALID_PARAMETER;\r
912 }\r
913\r
914 if ((*DataToggle != 0) && (*DataToggle != 1)) {\r
915 return EFI_INVALID_PARAMETER;\r
916 }\r
917\r
918 if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||\r
919 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||\r
920 ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 512)) ||\r
1436aea4
MK
921 ((DeviceSpeed == EFI_USB_SPEED_SUPER) && (MaximumPacketLength > 1024)))\r
922 {\r
d987459f
SZ
923 return EFI_INVALID_PARAMETER;\r
924 }\r
925\r
1436aea4 926 Xhc = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This);\r
d987459f
SZ
927\r
928 *TransferResult = EFI_USB_ERR_SYSTEM;\r
929 Status = EFI_DEVICE_ERROR;\r
930\r
931 if (XhcPeiIsHalt (Xhc) || XhcPeiIsSysError (Xhc)) {\r
87000d77 932 DEBUG ((DEBUG_ERROR, "XhcPeiBulkTransfer: HC is halted or has system error\n"));\r
d987459f
SZ
933 goto ON_EXIT;\r
934 }\r
935\r
936 //\r
937 // Check if the device is still enabled before every transaction.\r
938 //\r
939 SlotId = XhcPeiBusDevAddrToSlotId (Xhc, DeviceAddress);\r
940 if (SlotId == 0) {\r
941 goto ON_EXIT;\r
942 }\r
943\r
944 //\r
945 // Create a new URB, insert it into the asynchronous\r
946 // schedule list, then poll the execution status.\r
947 //\r
948 Urb = XhcPeiCreateUrb (\r
949 Xhc,\r
950 DeviceAddress,\r
951 EndPointAddress,\r
952 DeviceSpeed,\r
953 MaximumPacketLength,\r
954 XHC_BULK_TRANSFER,\r
955 NULL,\r
956 Data[0],\r
957 *DataLength,\r
958 NULL,\r
959 NULL\r
960 );\r
961\r
962 if (Urb == NULL) {\r
87000d77 963 DEBUG ((DEBUG_ERROR, "XhcPeiBulkTransfer: failed to create URB\n"));\r
d987459f
SZ
964 Status = EFI_OUT_OF_RESOURCES;\r
965 goto ON_EXIT;\r
966 }\r
967\r
968 Status = XhcPeiExecTransfer (Xhc, FALSE, Urb, TimeOut);\r
969\r
970 *TransferResult = Urb->Result;\r
971 *DataLength = Urb->Completed;\r
972\r
12e6c738
FT
973 if (Status == EFI_TIMEOUT) {\r
974 //\r
975 // The transfer timed out. Abort the transfer by dequeueing of the TD.\r
976 //\r
1436aea4
MK
977 RecoveryStatus = XhcPeiDequeueTrbFromEndpoint (Xhc, Urb);\r
978 if (EFI_ERROR (RecoveryStatus)) {\r
979 DEBUG ((DEBUG_ERROR, "XhcPeiBulkTransfer: XhcPeiDequeueTrbFromEndpoint failed\n"));\r
12e6c738
FT
980 }\r
981 } else {\r
982 if (*TransferResult == EFI_USB_NOERROR) {\r
983 Status = EFI_SUCCESS;\r
958a8181 984 } else if ((*TransferResult == EFI_USB_ERR_STALL) || (*TransferResult == EFI_USB_ERR_BABBLE)) {\r
1436aea4 985 RecoveryStatus = XhcPeiRecoverHaltedEndpoint (Xhc, Urb);\r
12e6c738 986 if (EFI_ERROR (RecoveryStatus)) {\r
87000d77 987 DEBUG ((DEBUG_ERROR, "XhcPeiBulkTransfer: XhcPeiRecoverHaltedEndpoint failed\n"));\r
12e6c738 988 }\r
1436aea4 989\r
12e6c738 990 Status = EFI_DEVICE_ERROR;\r
d987459f 991 }\r
d987459f
SZ
992 }\r
993\r
994 XhcPeiFreeUrb (Xhc, Urb);\r
995\r
996ON_EXIT:\r
997\r
998 if (EFI_ERROR (Status)) {\r
87000d77 999 DEBUG ((DEBUG_ERROR, "XhcPeiBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
d987459f
SZ
1000 }\r
1001\r
1002 return Status;\r
1003}\r
1004\r
1005/**\r
1006 Retrieves the number of root hub ports.\r
1007\r
1008 @param[in] PeiServices The pointer to the PEI Services Table.\r
1009 @param[in] This The pointer to this instance of the\r
1010 PEI_USB2_HOST_CONTROLLER_PPI.\r
1011 @param[out] PortNumber The pointer to the number of the root hub ports.\r
1012\r
1013 @retval EFI_SUCCESS The port number was retrieved successfully.\r
1014 @retval EFI_INVALID_PARAMETER PortNumber is NULL.\r
1015\r
1016**/\r
1017EFI_STATUS\r
1018EFIAPI\r
1019XhcPeiGetRootHubPortNumber (\r
1436aea4
MK
1020 IN EFI_PEI_SERVICES **PeiServices,\r
1021 IN PEI_USB2_HOST_CONTROLLER_PPI *This,\r
1022 OUT UINT8 *PortNumber\r
d987459f
SZ
1023 )\r
1024{\r
1436aea4
MK
1025 PEI_XHC_DEV *XhcDev;\r
1026\r
d987459f
SZ
1027 XhcDev = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This);\r
1028\r
1029 if (PortNumber == NULL) {\r
1030 return EFI_INVALID_PARAMETER;\r
1031 }\r
1032\r
1033 *PortNumber = XhcDev->HcSParams1.Data.MaxPorts;\r
87000d77 1034 DEBUG ((DEBUG_INFO, "XhcPeiGetRootHubPortNumber: PortNumber = %x\n", *PortNumber));\r
d987459f
SZ
1035 return EFI_SUCCESS;\r
1036}\r
1037\r
1038/**\r
1039 Clears a feature for the specified root hub port.\r
1040\r
1041 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
1042 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.\r
1043 @param PortNumber Specifies the root hub port whose feature\r
1044 is requested to be cleared.\r
1045 @param PortFeature Indicates the feature selector associated with the\r
1046 feature clear request.\r
1047\r
1048 @retval EFI_SUCCESS The feature specified by PortFeature was cleared\r
1049 for the USB root hub port specified by PortNumber.\r
1050 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
1051\r
1052**/\r
1053EFI_STATUS\r
1054EFIAPI\r
1055XhcPeiClearRootHubPortFeature (\r
1436aea4
MK
1056 IN EFI_PEI_SERVICES **PeiServices,\r
1057 IN PEI_USB2_HOST_CONTROLLER_PPI *This,\r
1058 IN UINT8 PortNumber,\r
1059 IN EFI_USB_PORT_FEATURE PortFeature\r
d987459f
SZ
1060 )\r
1061{\r
1436aea4
MK
1062 PEI_XHC_DEV *Xhc;\r
1063 UINT32 Offset;\r
1064 UINT32 State;\r
1065 EFI_STATUS Status;\r
d987459f 1066\r
1436aea4 1067 Xhc = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This);\r
d987459f
SZ
1068 Status = EFI_SUCCESS;\r
1069\r
1070 if (PortNumber >= Xhc->HcSParams1.Data.MaxPorts) {\r
1071 Status = EFI_INVALID_PARAMETER;\r
1072 goto ON_EXIT;\r
1073 }\r
1074\r
1436aea4
MK
1075 Offset = (UINT32)(XHC_PORTSC_OFFSET + (0x10 * PortNumber));\r
1076 State = XhcPeiReadOpReg (Xhc, Offset);\r
87000d77 1077 DEBUG ((DEBUG_INFO, "XhcPeiClearRootHubPortFeature: Port: %x State: %x\n", PortNumber, State));\r
d987459f
SZ
1078\r
1079 //\r
1080 // Mask off the port status change bits, these bits are\r
1081 // write clean bits\r
1082 //\r
1436aea4 1083 State &= ~(BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);\r
d987459f
SZ
1084\r
1085 switch (PortFeature) {\r
1086 case EfiUsbPortEnable:\r
1087 //\r
1088 // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.\r
1089 // A port may be disabled by software writing a '1' to this flag.\r
1090 //\r
1091 State |= XHC_PORTSC_PED;\r
1092 State &= ~XHC_PORTSC_RESET;\r
1093 XhcPeiWriteOpReg (Xhc, Offset, State);\r
1094 break;\r
1095\r
1096 case EfiUsbPortSuspend:\r
1097 State |= XHC_PORTSC_LWS;\r
1098 XhcPeiWriteOpReg (Xhc, Offset, State);\r
1099 State &= ~XHC_PORTSC_PLS;\r
1100 XhcPeiWriteOpReg (Xhc, Offset, State);\r
1101 break;\r
1102\r
1103 case EfiUsbPortReset:\r
1104 //\r
1105 // PORTSC_RESET BIT(4) bit is RW1S attribute, which means Write-1-to-set status:\r
1106 // Register bits indicate status when read, a clear bit may be set by\r
1107 // writing a '1'. Writing a '0' to RW1S bits has no effect.\r
1108 //\r
1109 break;\r
1110\r
1111 case EfiUsbPortPower:\r
1112 if (Xhc->HcCParams.Data.Ppc) {\r
1113 //\r
1114 // Port Power Control supported\r
1115 //\r
1116 State &= ~XHC_PORTSC_PP;\r
1117 XhcPeiWriteOpReg (Xhc, Offset, State);\r
1118 }\r
1436aea4 1119\r
d987459f
SZ
1120 break;\r
1121\r
1122 case EfiUsbPortOwner:\r
1123 //\r
1124 // XHCI root hub port don't has the owner bit, ignore the operation\r
1125 //\r
1126 break;\r
1127\r
1128 case EfiUsbPortConnectChange:\r
1129 //\r
1130 // Clear connect status change\r
1131 //\r
1132 State |= XHC_PORTSC_CSC;\r
1133 XhcPeiWriteOpReg (Xhc, Offset, State);\r
1134 break;\r
1135\r
1136 case EfiUsbPortEnableChange:\r
1137 //\r
1138 // Clear enable status change\r
1139 //\r
1140 State |= XHC_PORTSC_PEC;\r
1141 XhcPeiWriteOpReg (Xhc, Offset, State);\r
1142 break;\r
1143\r
1144 case EfiUsbPortOverCurrentChange:\r
1145 //\r
1146 // Clear PortOverCurrent change\r
1147 //\r
1148 State |= XHC_PORTSC_OCC;\r
1149 XhcPeiWriteOpReg (Xhc, Offset, State);\r
1150 break;\r
1151\r
1152 case EfiUsbPortResetChange:\r
1153 //\r
1154 // Clear Port Reset change\r
1155 //\r
1156 State |= XHC_PORTSC_PRC;\r
1157 XhcPeiWriteOpReg (Xhc, Offset, State);\r
1158 break;\r
1159\r
1160 case EfiUsbPortSuspendChange:\r
1161 //\r
1162 // Not supported or not related operation\r
1163 //\r
1164 break;\r
1165\r
1166 default:\r
1167 Status = EFI_INVALID_PARAMETER;\r
1168 break;\r
1169 }\r
1170\r
1171ON_EXIT:\r
87000d77 1172 DEBUG ((DEBUG_INFO, "XhcPeiClearRootHubPortFeature: PortFeature: %x Status = %r\n", PortFeature, Status));\r
d987459f
SZ
1173 return Status;\r
1174}\r
1175\r
1176/**\r
1177 Sets a feature for the specified root hub port.\r
1178\r
1179 @param PeiServices The pointer of EFI_PEI_SERVICES\r
1180 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI\r
1181 @param PortNumber Root hub port to set.\r
1182 @param PortFeature Feature to set.\r
1183\r
1184 @retval EFI_SUCCESS The feature specified by PortFeature was set.\r
1185 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
1186 @retval EFI_TIMEOUT The time out occurred.\r
1187\r
1188**/\r
1189EFI_STATUS\r
1190EFIAPI\r
1191XhcPeiSetRootHubPortFeature (\r
1436aea4
MK
1192 IN EFI_PEI_SERVICES **PeiServices,\r
1193 IN PEI_USB2_HOST_CONTROLLER_PPI *This,\r
1194 IN UINT8 PortNumber,\r
1195 IN EFI_USB_PORT_FEATURE PortFeature\r
d987459f
SZ
1196 )\r
1197{\r
1436aea4
MK
1198 PEI_XHC_DEV *Xhc;\r
1199 UINT32 Offset;\r
1200 UINT32 State;\r
1201 EFI_STATUS Status;\r
d987459f 1202\r
1436aea4 1203 Xhc = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This);\r
d987459f
SZ
1204 Status = EFI_SUCCESS;\r
1205\r
1206 if (PortNumber >= Xhc->HcSParams1.Data.MaxPorts) {\r
1207 Status = EFI_INVALID_PARAMETER;\r
1208 goto ON_EXIT;\r
1209 }\r
1210\r
1436aea4
MK
1211 Offset = (UINT32)(XHC_PORTSC_OFFSET + (0x10 * PortNumber));\r
1212 State = XhcPeiReadOpReg (Xhc, Offset);\r
87000d77 1213 DEBUG ((DEBUG_INFO, "XhcPeiSetRootHubPortFeature: Port: %x State: %x\n", PortNumber, State));\r
d987459f
SZ
1214\r
1215 //\r
1216 // Mask off the port status change bits, these bits are\r
1217 // write clean bits\r
1218 //\r
1436aea4 1219 State &= ~(BIT1 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23);\r
d987459f
SZ
1220\r
1221 switch (PortFeature) {\r
1222 case EfiUsbPortEnable:\r
1223 //\r
1224 // Ports may only be enabled by the xHC. Software cannot enable a port by writing a '1' to this flag.\r
1225 // A port may be disabled by software writing a '1' to this flag.\r
1226 //\r
1227 break;\r
1228\r
1229 case EfiUsbPortSuspend:\r
1230 State |= XHC_PORTSC_LWS;\r
1231 XhcPeiWriteOpReg (Xhc, Offset, State);\r
1232 State &= ~XHC_PORTSC_PLS;\r
1436aea4 1233 State |= (3 << 5);\r
d987459f
SZ
1234 XhcPeiWriteOpReg (Xhc, Offset, State);\r
1235 break;\r
1236\r
1237 case EfiUsbPortReset:\r
1238 //\r
1239 // Make sure Host Controller not halt before reset it\r
1240 //\r
1241 if (XhcPeiIsHalt (Xhc)) {\r
1242 Status = XhcPeiRunHC (Xhc, XHC_GENERIC_TIMEOUT);\r
1243 if (EFI_ERROR (Status)) {\r
1244 break;\r
1245 }\r
1246 }\r
1247\r
1248 //\r
1249 // 4.3.1 Resetting a Root Hub Port\r
1250 // 1) Write the PORTSC register with the Port Reset (PR) bit set to '1'.\r
1251 // 2) Wait for a successful Port Status Change Event for the port, where the Port Reset Change (PRC)\r
1252 // bit in the PORTSC field is set to '1'.\r
1253 //\r
1254 State |= XHC_PORTSC_RESET;\r
1255 XhcPeiWriteOpReg (Xhc, Offset, State);\r
1436aea4 1256 XhcPeiWaitOpRegBit (Xhc, Offset, XHC_PORTSC_PRC, TRUE, XHC_GENERIC_TIMEOUT);\r
d987459f
SZ
1257 break;\r
1258\r
1259 case EfiUsbPortPower:\r
1260 if (Xhc->HcCParams.Data.Ppc) {\r
1261 //\r
1262 // Port Power Control supported\r
1263 //\r
1264 State |= XHC_PORTSC_PP;\r
1265 XhcPeiWriteOpReg (Xhc, Offset, State);\r
1266 }\r
1436aea4 1267\r
d987459f
SZ
1268 break;\r
1269\r
1270 case EfiUsbPortOwner:\r
1271 //\r
1272 // XHCI root hub port don't has the owner bit, ignore the operation\r
1273 //\r
1274 break;\r
1275\r
1276 default:\r
1277 Status = EFI_INVALID_PARAMETER;\r
1278 }\r
1279\r
1280ON_EXIT:\r
87000d77 1281 DEBUG ((DEBUG_INFO, "XhcPeiSetRootHubPortFeature: PortFeature: %x Status = %r\n", PortFeature, Status));\r
d987459f
SZ
1282 return Status;\r
1283}\r
1284\r
1285/**\r
1286 Retrieves the current status of a USB root hub port.\r
1287\r
1288 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
1289 @param This The pointer of PEI_USB2_HOST_CONTROLLER_PPI.\r
1290 @param PortNumber The root hub port to retrieve the state from.\r
1291 @param PortStatus Variable to receive the port state.\r
1292\r
1293 @retval EFI_SUCCESS The status of the USB root hub port specified.\r
1294 by PortNumber was returned in PortStatus.\r
1295 @retval EFI_INVALID_PARAMETER PortNumber is invalid.\r
1296\r
1297**/\r
1298EFI_STATUS\r
1299EFIAPI\r
1300XhcPeiGetRootHubPortStatus (\r
1436aea4
MK
1301 IN EFI_PEI_SERVICES **PeiServices,\r
1302 IN PEI_USB2_HOST_CONTROLLER_PPI *This,\r
1303 IN UINT8 PortNumber,\r
1304 OUT EFI_USB_PORT_STATUS *PortStatus\r
d987459f
SZ
1305 )\r
1306{\r
1436aea4
MK
1307 PEI_XHC_DEV *Xhc;\r
1308 UINT32 Offset;\r
1309 UINT32 State;\r
1310 UINTN Index;\r
1311 UINTN MapSize;\r
1312 USB_DEV_ROUTE ParentRouteChart;\r
d987459f
SZ
1313\r
1314 if (PortStatus == NULL) {\r
1315 return EFI_INVALID_PARAMETER;\r
1316 }\r
1317\r
1318 Xhc = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS (This);\r
1319\r
1320 if (PortNumber >= Xhc->HcSParams1.Data.MaxPorts) {\r
1321 return EFI_INVALID_PARAMETER;\r
1322 }\r
1323\r
1324 //\r
1325 // Clear port status.\r
1326 //\r
1436aea4
MK
1327 PortStatus->PortStatus = 0;\r
1328 PortStatus->PortChangeStatus = 0;\r
d987459f 1329\r
1436aea4
MK
1330 Offset = (UINT32)(XHC_PORTSC_OFFSET + (0x10 * PortNumber));\r
1331 State = XhcPeiReadOpReg (Xhc, Offset);\r
87000d77 1332 DEBUG ((DEBUG_INFO, "XhcPeiGetRootHubPortStatus: Port: %x State: %x\n", PortNumber, State));\r
d987459f
SZ
1333\r
1334 //\r
4a723d3d
SZ
1335 // According to XHCI 1.1 spec November 2017,\r
1336 // bit 10~13 of the root port status register identifies the speed of the attached device.\r
d987459f
SZ
1337 //\r
1338 switch ((State & XHC_PORTSC_PS) >> 10) {\r
1339 case 2:\r
1340 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
1341 break;\r
1342\r
1343 case 3:\r
1344 PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;\r
1345 break;\r
1346\r
1347 case 4:\r
4a723d3d 1348 case 5:\r
d987459f
SZ
1349 PortStatus->PortStatus |= USB_PORT_STAT_SUPER_SPEED;\r
1350 break;\r
1351\r
1352 default:\r
1353 break;\r
1354 }\r
1355\r
1356 //\r
1357 // Convert the XHCI port/port change state to UEFI status\r
1358 //\r
1359 MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);\r
1360\r
1361 for (Index = 0; Index < MapSize; Index++) {\r
1362 if (XHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {\r
1436aea4 1363 PortStatus->PortStatus = (UINT16)(PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);\r
d987459f
SZ
1364 }\r
1365 }\r
1436aea4 1366\r
d987459f
SZ
1367 //\r
1368 // Bit5~8 reflects its current link state.\r
1369 //\r
1370 if ((State & XHC_PORTSC_PLS) >> 5 == 3) {\r
1371 PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;\r
1372 }\r
1373\r
1374 MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);\r
1375\r
1376 for (Index = 0; Index < MapSize; Index++) {\r
1377 if (XHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {\r
1436aea4 1378 PortStatus->PortChangeStatus = (UINT16)(PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);\r
d987459f
SZ
1379 }\r
1380 }\r
1381\r
1382 MapSize = sizeof (mUsbClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);\r
1383\r
1384 for (Index = 0; Index < MapSize; Index++) {\r
1385 if (XHC_BIT_IS_SET (State, mUsbClearPortChangeMap[Index].HwState)) {\r
1386 XhcPeiClearRootHubPortFeature (PeiServices, This, PortNumber, (EFI_USB_PORT_FEATURE)mUsbClearPortChangeMap[Index].Selector);\r
1387 }\r
1388 }\r
1389\r
1390 //\r
1391 // Poll the root port status register to enable/disable corresponding device slot if there is a device attached/detached.\r
1392 // For those devices behind hub, we get its attach/detach event by hooking Get_Port_Status request at control transfer for those hub.\r
1393 //\r
1394 ParentRouteChart.Dword = 0;\r
1395 XhcPeiPollPortStatusChange (Xhc, ParentRouteChart, PortNumber, PortStatus);\r
1396\r
87000d77 1397 DEBUG ((DEBUG_INFO, "XhcPeiGetRootHubPortStatus: PortChangeStatus: %x PortStatus: %x\n", PortStatus->PortChangeStatus, PortStatus->PortStatus));\r
d987459f
SZ
1398 return EFI_SUCCESS;\r
1399}\r
1400\r
b575ca32
JY
1401/**\r
1402 One notified function to stop the Host Controller at the end of PEI\r
1403\r
1404 @param[in] PeiServices Pointer to PEI Services Table.\r
1405 @param[in] NotifyDescriptor Pointer to the descriptor for the Notification event that\r
1406 caused this function to execute.\r
1407 @param[in] Ppi Pointer to the PPI data associated with this function.\r
1408\r
1409 @retval EFI_SUCCESS The function completes successfully\r
1410 @retval others\r
1411**/\r
1412EFI_STATUS\r
1413EFIAPI\r
1414XhcEndOfPei (\r
1415 IN EFI_PEI_SERVICES **PeiServices,\r
1416 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
1417 IN VOID *Ppi\r
1418 )\r
1419{\r
1436aea4 1420 PEI_XHC_DEV *Xhc;\r
b575ca32 1421\r
1436aea4 1422 Xhc = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS_NOTIFY (NotifyDescriptor);\r
b575ca32
JY
1423\r
1424 XhcPeiHaltHC (Xhc, XHC_GENERIC_TIMEOUT);\r
1425\r
0aa17941
SZ
1426 XhcPeiFreeSched (Xhc);\r
1427\r
b575ca32
JY
1428 return EFI_SUCCESS;\r
1429}\r
1430\r
d987459f
SZ
1431/**\r
1432 @param FileHandle Handle of the file being invoked.\r
1433 @param PeiServices Describes the list of possible PEI Services.\r
1434\r
1435 @retval EFI_SUCCESS PPI successfully installed.\r
1436\r
1437**/\r
1438EFI_STATUS\r
1439EFIAPI\r
1440XhcPeimEntry (\r
1436aea4
MK
1441 IN EFI_PEI_FILE_HANDLE FileHandle,\r
1442 IN CONST EFI_PEI_SERVICES **PeiServices\r
d987459f
SZ
1443 )\r
1444{\r
1436aea4
MK
1445 PEI_USB_CONTROLLER_PPI *UsbControllerPpi;\r
1446 EFI_STATUS Status;\r
1447 UINT8 Index;\r
1448 UINTN ControllerType;\r
1449 UINTN BaseAddress;\r
1450 UINTN MemPages;\r
1451 PEI_XHC_DEV *XhcDev;\r
1452 EFI_PHYSICAL_ADDRESS TempPtr;\r
1453 UINT32 PageSize;\r
d987459f
SZ
1454\r
1455 //\r
1456 // Shadow this PEIM to run from memory.\r
1457 //\r
1458 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {\r
1459 return EFI_SUCCESS;\r
1460 }\r
1461\r
1462 Status = PeiServicesLocatePpi (\r
1463 &gPeiUsbControllerPpiGuid,\r
1464 0,\r
1465 NULL,\r
1436aea4 1466 (VOID **)&UsbControllerPpi\r
d987459f
SZ
1467 );\r
1468 if (EFI_ERROR (Status)) {\r
1469 return EFI_UNSUPPORTED;\r
1470 }\r
1471\r
0aa17941
SZ
1472 IoMmuInit ();\r
1473\r
d987459f
SZ
1474 Index = 0;\r
1475 while (TRUE) {\r
1476 Status = UsbControllerPpi->GetUsbController (\r
1436aea4 1477 (EFI_PEI_SERVICES **)PeiServices,\r
d987459f
SZ
1478 UsbControllerPpi,\r
1479 Index,\r
1480 &ControllerType,\r
1481 &BaseAddress\r
1482 );\r
1483 //\r
1484 // When status is error, it means no controller is found.\r
1485 //\r
1486 if (EFI_ERROR (Status)) {\r
1487 break;\r
1488 }\r
1489\r
1490 //\r
1491 // This PEIM is for XHC type controller.\r
1492 //\r
1493 if (ControllerType != PEI_XHCI_CONTROLLER) {\r
1494 Index++;\r
1495 continue;\r
1496 }\r
1497\r
1498 MemPages = EFI_SIZE_TO_PAGES (sizeof (PEI_XHC_DEV));\r
1436aea4
MK
1499 Status = PeiServicesAllocatePages (\r
1500 EfiBootServicesData,\r
1501 MemPages,\r
1502 &TempPtr\r
1503 );\r
d987459f
SZ
1504 if (EFI_ERROR (Status)) {\r
1505 return EFI_OUT_OF_RESOURCES;\r
1506 }\r
1436aea4
MK
1507\r
1508 ZeroMem ((VOID *)(UINTN)TempPtr, EFI_PAGES_TO_SIZE (MemPages));\r
1509 XhcDev = (PEI_XHC_DEV *)((UINTN)TempPtr);\r
1510\r
1511 XhcDev->Signature = USB_XHC_DEV_SIGNATURE;\r
1512 XhcDev->UsbHostControllerBaseAddress = (UINT32)BaseAddress;\r
1513 XhcDev->CapLength = (UINT8)(XhcPeiReadCapRegister (XhcDev, XHC_CAPLENGTH_OFFSET) & 0x0FF);\r
1514 XhcDev->HcSParams1.Dword = XhcPeiReadCapRegister (XhcDev, XHC_HCSPARAMS1_OFFSET);\r
1515 XhcDev->HcSParams2.Dword = XhcPeiReadCapRegister (XhcDev, XHC_HCSPARAMS2_OFFSET);\r
1516 XhcDev->HcCParams.Dword = XhcPeiReadCapRegister (XhcDev, XHC_HCCPARAMS_OFFSET);\r
1517 XhcDev->DBOff = XhcPeiReadCapRegister (XhcDev, XHC_DBOFF_OFFSET);\r
1518 XhcDev->RTSOff = XhcPeiReadCapRegister (XhcDev, XHC_RTSOFF_OFFSET);\r
d987459f
SZ
1519\r
1520 //\r
1521 // This PageSize field defines the page size supported by the xHC implementation.\r
1522 // This xHC supports a page size of 2^(n+12) if bit n is Set. For example,\r
1523 // if bit 0 is Set, the xHC supports 4k byte page sizes.\r
1524 //\r
1525 PageSize = XhcPeiReadOpReg (XhcDev, XHC_PAGESIZE_OFFSET) & XHC_PAGESIZE_MASK;\r
1526 XhcDev->PageSize = 1 << (HighBitSet32 (PageSize) + 12);\r
1527\r
87000d77
MK
1528 DEBUG ((DEBUG_INFO, "XhciPei: UsbHostControllerBaseAddress: %x\n", XhcDev->UsbHostControllerBaseAddress));\r
1529 DEBUG ((DEBUG_INFO, "XhciPei: CapLength: %x\n", XhcDev->CapLength));\r
1530 DEBUG ((DEBUG_INFO, "XhciPei: HcSParams1: %x\n", XhcDev->HcSParams1.Dword));\r
1531 DEBUG ((DEBUG_INFO, "XhciPei: HcSParams2: %x\n", XhcDev->HcSParams2.Dword));\r
1532 DEBUG ((DEBUG_INFO, "XhciPei: HcCParams: %x\n", XhcDev->HcCParams.Dword));\r
1533 DEBUG ((DEBUG_INFO, "XhciPei: DBOff: %x\n", XhcDev->DBOff));\r
1534 DEBUG ((DEBUG_INFO, "XhciPei: RTSOff: %x\n", XhcDev->RTSOff));\r
1535 DEBUG ((DEBUG_INFO, "XhciPei: PageSize: %x\n", XhcDev->PageSize));\r
d987459f
SZ
1536\r
1537 XhcPeiResetHC (XhcDev, XHC_RESET_TIMEOUT);\r
1538 ASSERT (XhcPeiIsHalt (XhcDev));\r
1539\r
1540 //\r
1541 // Initialize the schedule\r
1542 //\r
1543 XhcPeiInitSched (XhcDev);\r
1544\r
1545 //\r
1546 // Start the Host Controller\r
1547 //\r
1548 XhcPeiRunHC (XhcDev, XHC_GENERIC_TIMEOUT);\r
1549\r
1550 //\r
1551 // Wait for root port state stable\r
1552 //\r
1553 MicroSecondDelay (XHC_ROOT_PORT_STATE_STABLE);\r
1554\r
1436aea4
MK
1555 XhcDev->Usb2HostControllerPpi.ControlTransfer = XhcPeiControlTransfer;\r
1556 XhcDev->Usb2HostControllerPpi.BulkTransfer = XhcPeiBulkTransfer;\r
1557 XhcDev->Usb2HostControllerPpi.GetRootHubPortNumber = XhcPeiGetRootHubPortNumber;\r
1558 XhcDev->Usb2HostControllerPpi.GetRootHubPortStatus = XhcPeiGetRootHubPortStatus;\r
1559 XhcDev->Usb2HostControllerPpi.SetRootHubPortFeature = XhcPeiSetRootHubPortFeature;\r
1560 XhcDev->Usb2HostControllerPpi.ClearRootHubPortFeature = XhcPeiClearRootHubPortFeature;\r
d987459f
SZ
1561\r
1562 XhcDev->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
1436aea4
MK
1563 XhcDev->PpiDescriptor.Guid = &gPeiUsb2HostControllerPpiGuid;\r
1564 XhcDev->PpiDescriptor.Ppi = &XhcDev->Usb2HostControllerPpi;\r
d987459f 1565\r
1436aea4
MK
1566 XhcDev->EndOfPeiNotifyList.Flags = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
1567 XhcDev->EndOfPeiNotifyList.Guid = &gEfiEndOfPeiSignalPpiGuid;\r
b575ca32
JY
1568 XhcDev->EndOfPeiNotifyList.Notify = XhcEndOfPei;\r
1569\r
d987459f 1570 PeiServicesInstallPpi (&XhcDev->PpiDescriptor);\r
b575ca32 1571 PeiServicesNotifyPpi (&XhcDev->EndOfPeiNotifyList);\r
d987459f
SZ
1572\r
1573 Index++;\r
1574 }\r
1575\r
1576 return EFI_SUCCESS;\r
1577}\r