]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.c
MdeModulePkg: Remove BootInRecoveryMode PPI
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusPei / HubPeim.c
CommitLineData
4b1bf81c 1/** @file\r
2Usb Hub Request Support In PEI Phase\r
3\r
72750e3b 4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
d1102dba 5\r
9d510e61 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
4b1bf81c 7\r
8**/\r
9\r
10#include "UsbPeim.h"\r
11#include "HubPeim.h"\r
12#include "PeiUsbLib.h"\r
13\r
14/**\r
15 Get a given hub port status.\r
16\r
17 @param PeiServices General-purpose services that are available to every PEIM.\r
18 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
19 @param Port Usb hub port number (starting from 1).\r
20 @param PortStatus Current Hub port status and change status.\r
21\r
22 @retval EFI_SUCCESS Port status is obtained successfully.\r
23 @retval EFI_DEVICE_ERROR Cannot get the port status due to a hardware error.\r
24 @retval Others Other failure occurs.\r
25\r
26**/\r
27EFI_STATUS\r
28PeiHubGetPortStatus (\r
29 IN EFI_PEI_SERVICES **PeiServices,\r
30 IN PEI_USB_IO_PPI *UsbIoPpi,\r
31 IN UINT8 Port,\r
32 OUT UINT32 *PortStatus\r
33 )\r
34{\r
35 EFI_USB_DEVICE_REQUEST DeviceRequest;\r
36\r
37 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));\r
38\r
39 //\r
40 // Fill Device request packet\r
41 //\r
42 DeviceRequest.RequestType = USB_HUB_GET_PORT_STATUS_REQ_TYPE;\r
43 DeviceRequest.Request = USB_HUB_GET_PORT_STATUS;\r
44 DeviceRequest.Index = Port;\r
45 DeviceRequest.Length = (UINT16) sizeof (UINT32);\r
46\r
47\r
48 return UsbIoPpi->UsbControlTransfer (\r
49 PeiServices,\r
50 UsbIoPpi,\r
51 &DeviceRequest,\r
52 EfiUsbDataIn,\r
53 PcdGet32 (PcdUsbTransferTimeoutValue),\r
54 PortStatus,\r
55 sizeof (UINT32)\r
56 );\r
57\r
58}\r
59\r
60/**\r
61 Set specified feature to a given hub port.\r
62\r
63 @param PeiServices General-purpose services that are available to every PEIM.\r
64 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
65 @param Port Usb hub port number (starting from 1).\r
66 @param Value New feature value.\r
67\r
68 @retval EFI_SUCCESS Port feature is set successfully.\r
69 @retval EFI_DEVICE_ERROR Cannot set the port feature due to a hardware error.\r
70 @retval Others Other failure occurs.\r
71\r
72**/\r
73EFI_STATUS\r
74PeiHubSetPortFeature (\r
75 IN EFI_PEI_SERVICES **PeiServices,\r
76 IN PEI_USB_IO_PPI *UsbIoPpi,\r
77 IN UINT8 Port,\r
78 IN UINT8 Value\r
79 )\r
80{\r
81 EFI_USB_DEVICE_REQUEST DeviceRequest;\r
82\r
83 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));\r
84\r
85 //\r
86 // Fill Device request packet\r
87 //\r
88 DeviceRequest.RequestType = USB_HUB_SET_PORT_FEATURE_REQ_TYPE;\r
89 DeviceRequest.Request = USB_HUB_SET_PORT_FEATURE;\r
90 DeviceRequest.Value = Value;\r
91 DeviceRequest.Index = Port;\r
92\r
93 return UsbIoPpi->UsbControlTransfer (\r
94 PeiServices,\r
95 UsbIoPpi,\r
96 &DeviceRequest,\r
97 EfiUsbNoData,\r
98 PcdGet32 (PcdUsbTransferTimeoutValue),\r
99 NULL,\r
100 0\r
101 );\r
102}\r
103\r
104/**\r
105 Clear specified feature on a given hub port.\r
106\r
107 @param PeiServices General-purpose services that are available to every PEIM.\r
108 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
109 @param Port Usb hub port number (starting from 1).\r
110 @param Value Feature value that will be cleared from the hub port.\r
111\r
112 @retval EFI_SUCCESS Port feature is cleared successfully.\r
113 @retval EFI_DEVICE_ERROR Cannot clear the port feature due to a hardware error.\r
114 @retval Others Other failure occurs.\r
115\r
116**/\r
117EFI_STATUS\r
118PeiHubClearPortFeature (\r
119 IN EFI_PEI_SERVICES **PeiServices,\r
120 IN PEI_USB_IO_PPI *UsbIoPpi,\r
121 IN UINT8 Port,\r
122 IN UINT8 Value\r
123 )\r
124{\r
125 EFI_USB_DEVICE_REQUEST DeviceRequest;\r
126\r
127 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));\r
128\r
129 //\r
130 // Fill Device request packet\r
131 //\r
132 DeviceRequest.RequestType = USB_HUB_CLEAR_FEATURE_PORT_REQ_TYPE;\r
133 DeviceRequest.Request = USB_HUB_CLEAR_FEATURE_PORT;\r
134 DeviceRequest.Value = Value;\r
135 DeviceRequest.Index = Port;\r
136\r
137 return UsbIoPpi->UsbControlTransfer (\r
138 PeiServices,\r
139 UsbIoPpi,\r
140 &DeviceRequest,\r
141 EfiUsbNoData,\r
142 PcdGet32 (PcdUsbTransferTimeoutValue),\r
143 NULL,\r
144 0\r
145 );\r
146}\r
147\r
148/**\r
149 Get a given hub status.\r
150\r
151 @param PeiServices General-purpose services that are available to every PEIM.\r
152 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
153 @param HubStatus Current Hub status and change status.\r
154\r
155 @retval EFI_SUCCESS Hub status is obtained successfully.\r
156 @retval EFI_DEVICE_ERROR Cannot get the hub status due to a hardware error.\r
157 @retval Others Other failure occurs.\r
158\r
159**/\r
160EFI_STATUS\r
161PeiHubGetHubStatus (\r
162 IN EFI_PEI_SERVICES **PeiServices,\r
163 IN PEI_USB_IO_PPI *UsbIoPpi,\r
164 OUT UINT32 *HubStatus\r
165 )\r
166{\r
167 EFI_USB_DEVICE_REQUEST DeviceRequest;\r
168\r
169 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));\r
170\r
171 //\r
172 // Fill Device request packet\r
173 //\r
174 DeviceRequest.RequestType = USB_HUB_GET_HUB_STATUS_REQ_TYPE;\r
175 DeviceRequest.Request = USB_HUB_GET_HUB_STATUS;\r
176 DeviceRequest.Length = (UINT16) sizeof (UINT32);\r
177\r
178 return UsbIoPpi->UsbControlTransfer (\r
179 PeiServices,\r
180 UsbIoPpi,\r
181 &DeviceRequest,\r
182 EfiUsbDataIn,\r
183 PcdGet32 (PcdUsbTransferTimeoutValue),\r
184 HubStatus,\r
185 sizeof (UINT32)\r
186 );\r
187}\r
188\r
4b1bf81c 189\r
4b1bf81c 190\r
191/**\r
192 Clear specified feature on a given hub.\r
193\r
194 @param PeiServices General-purpose services that are available to every PEIM.\r
195 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
196 @param Value Feature value that will be cleared from the hub port.\r
197\r
198 @retval EFI_SUCCESS Hub feature is cleared successfully.\r
199 @retval EFI_DEVICE_ERROR Cannot clear the hub feature due to a hardware error.\r
200 @retval Others Other failure occurs.\r
201\r
202**/\r
203EFI_STATUS\r
204PeiHubClearHubFeature (\r
205 IN EFI_PEI_SERVICES **PeiServices,\r
206 IN PEI_USB_IO_PPI *UsbIoPpi,\r
207 IN UINT8 Value\r
208 )\r
209{\r
210 EFI_USB_DEVICE_REQUEST DeviceRequest;\r
211\r
212 ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));\r
213\r
214 //\r
215 // Fill Device request packet\r
216 //\r
217 DeviceRequest.RequestType = USB_HUB_CLEAR_FEATURE_REQ_TYPE;\r
218 DeviceRequest.Request = USB_HUB_CLEAR_FEATURE;\r
219 DeviceRequest.Value = Value;\r
220\r
221 return UsbIoPpi->UsbControlTransfer (\r
222 PeiServices,\r
223 UsbIoPpi,\r
224 &DeviceRequest,\r
225 EfiUsbNoData,\r
226 PcdGet32 (PcdUsbTransferTimeoutValue),\r
227 NULL,\r
228 0\r
229 );\r
230}\r
231\r
232/**\r
72750e3b 233 Get a given (SuperSpeed) hub descriptor.\r
4b1bf81c 234\r
235 @param PeiServices General-purpose services that are available to every PEIM.\r
72750e3b 236 @param PeiUsbDevice Indicates the hub controller device.\r
4b1bf81c 237 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
238 @param DescriptorSize The length of Hub Descriptor buffer.\r
239 @param HubDescriptor Caller allocated buffer to store the hub descriptor if\r
240 successfully returned.\r
241\r
242 @retval EFI_SUCCESS Hub descriptor is obtained successfully.\r
243 @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.\r
244 @retval Others Other failure occurs.\r
245\r
246**/\r
247EFI_STATUS\r
248PeiGetHubDescriptor (\r
249 IN EFI_PEI_SERVICES **PeiServices,\r
72750e3b 250 IN PEI_USB_DEVICE *PeiUsbDevice,\r
4b1bf81c 251 IN PEI_USB_IO_PPI *UsbIoPpi,\r
252 IN UINTN DescriptorSize,\r
253 OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor\r
254 )\r
255{\r
256 EFI_USB_DEVICE_REQUEST DevReq;\r
72750e3b 257 UINT8 DescType;\r
d987459f 258\r
d987459f
SZ
259 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));\r
260\r
72750e3b
SZ
261 DescType = (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_SUPER) ?\r
262 USB_DT_SUPERSPEED_HUB :\r
263 USB_DT_HUB;\r
264\r
d987459f
SZ
265 //\r
266 // Fill Device request packet\r
267 //\r
268 DevReq.RequestType = USB_RT_HUB | 0x80;\r
269 DevReq.Request = USB_HUB_GET_DESCRIPTOR;\r
72750e3b
SZ
270 DevReq.Value = (UINT16) (DescType << 8);\r
271 DevReq.Length = (UINT16) DescriptorSize;\r
d987459f
SZ
272\r
273 return UsbIoPpi->UsbControlTransfer (\r
274 PeiServices,\r
275 UsbIoPpi,\r
276 &DevReq,\r
277 EfiUsbDataIn,\r
278 PcdGet32 (PcdUsbTransferTimeoutValue),\r
279 HubDescriptor,\r
72750e3b 280 (UINT16)DescriptorSize\r
d987459f
SZ
281 );\r
282}\r
283\r
284/**\r
285 Read the whole usb hub descriptor. It is necessary\r
286 to do it in two steps because hub descriptor is of\r
287 variable length.\r
288\r
289 @param PeiServices General-purpose services that are available to every PEIM.\r
290 @param PeiUsbDevice Indicates the hub controller device.\r
291 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
292 @param HubDescriptor Caller allocated buffer to store the hub descriptor if\r
293 successfully returned.\r
294\r
295 @retval EFI_SUCCESS Hub descriptor is obtained successfully.\r
296 @retval EFI_DEVICE_ERROR Cannot get the hub descriptor due to a hardware error.\r
297 @retval Others Other failure occurs.\r
298\r
299**/\r
300EFI_STATUS\r
301PeiUsbHubReadDesc (\r
302 IN EFI_PEI_SERVICES **PeiServices,\r
303 IN PEI_USB_DEVICE *PeiUsbDevice,\r
304 IN PEI_USB_IO_PPI *UsbIoPpi,\r
305 OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor\r
306 )\r
307{\r
308 EFI_STATUS Status;\r
309\r
72750e3b
SZ
310 //\r
311 // First get the hub descriptor length\r
312 //\r
313 Status = PeiGetHubDescriptor (PeiServices, PeiUsbDevice, UsbIoPpi, 2, HubDescriptor);\r
d987459f 314\r
72750e3b
SZ
315 if (EFI_ERROR (Status)) {\r
316 return Status;\r
d987459f
SZ
317 }\r
318\r
72750e3b
SZ
319 //\r
320 // Get the whole hub descriptor\r
321 //\r
322 return PeiGetHubDescriptor (PeiServices, PeiUsbDevice, UsbIoPpi, HubDescriptor->Length, HubDescriptor);\r
d987459f
SZ
323}\r
324\r
325/**\r
326 USB hub control transfer to set the hub depth.\r
327\r
328 @param PeiServices General-purpose services that are available to every PEIM.\r
329 @param PeiUsbDevice Indicates the hub controller device.\r
330 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
331\r
332 @retval EFI_SUCCESS Depth of the hub is set.\r
333 @retval Others Failed to set the depth.\r
334\r
335**/\r
336EFI_STATUS\r
337PeiUsbHubCtrlSetHubDepth (\r
338 IN EFI_PEI_SERVICES **PeiServices,\r
339 IN PEI_USB_DEVICE *PeiUsbDevice,\r
340 IN PEI_USB_IO_PPI *UsbIoPpi\r
341 )\r
342{\r
343 EFI_USB_DEVICE_REQUEST DevReq;\r
344 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));\r
345\r
346 //\r
347 // Fill Device request packet\r
348 //\r
349 DevReq.RequestType = USB_RT_HUB;\r
350 DevReq.Request = USB_HUB_REQ_SET_DEPTH;\r
351 DevReq.Value = PeiUsbDevice->Tier;\r
352 DevReq.Length = 0;\r
353\r
354 return UsbIoPpi->UsbControlTransfer (\r
355 PeiServices,\r
356 UsbIoPpi,\r
357 &DevReq,\r
358 EfiUsbNoData,\r
359 PcdGet32 (PcdUsbTransferTimeoutValue),\r
360 NULL,\r
361 0\r
362 );\r
363}\r
364\r
4b1bf81c 365/**\r
366 Configure a given hub.\r
367\r
368 @param PeiServices General-purpose services that are available to every PEIM.\r
369 @param PeiUsbDevice Indicating the hub controller device that will be configured\r
370\r
371 @retval EFI_SUCCESS Hub configuration is done successfully.\r
372 @retval EFI_DEVICE_ERROR Cannot configure the hub due to a hardware error.\r
373\r
374**/\r
375EFI_STATUS\r
376PeiDoHubConfig (\r
377 IN EFI_PEI_SERVICES **PeiServices,\r
378 IN PEI_USB_DEVICE *PeiUsbDevice\r
379 )\r
380{\r
72750e3b
SZ
381 UINT8 HubDescBuffer[256];\r
382 EFI_USB_HUB_DESCRIPTOR *HubDescriptor;\r
4b1bf81c 383 EFI_STATUS Status;\r
384 EFI_USB_HUB_STATUS HubStatus;\r
385 UINTN Index;\r
4b1bf81c 386 PEI_USB_IO_PPI *UsbIoPpi;\r
387\r
4b1bf81c 388 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;\r
389\r
72750e3b
SZ
390 //\r
391 // The length field of descriptor is UINT8 type, so the buffer\r
392 // with 256 bytes is enough to hold the descriptor data.\r
393 //\r
394 HubDescriptor = (EFI_USB_HUB_DESCRIPTOR *) HubDescBuffer;\r
395\r
4b1bf81c 396 //\r
d1102dba 397 // Get the hub descriptor\r
4b1bf81c 398 //\r
d987459f 399 Status = PeiUsbHubReadDesc (\r
4b1bf81c 400 PeiServices,\r
d987459f 401 PeiUsbDevice,\r
4b1bf81c 402 UsbIoPpi,\r
72750e3b 403 HubDescriptor\r
4b1bf81c 404 );\r
405 if (EFI_ERROR (Status)) {\r
406 return EFI_DEVICE_ERROR;\r
407 }\r
408\r
72750e3b 409 PeiUsbDevice->DownStreamPortNo = HubDescriptor->NbrPorts;\r
4b1bf81c 410\r
d987459f
SZ
411 if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_SUPER) {\r
412 DEBUG ((EFI_D_INFO, "PeiDoHubConfig: Set Hub Depth as 0x%x\n", PeiUsbDevice->Tier));\r
413 PeiUsbHubCtrlSetHubDepth (\r
414 PeiServices,\r
415 PeiUsbDevice,\r
416 UsbIoPpi\r
417 );\r
4b1bf81c 418 } else {\r
419 //\r
d987459f 420 // Power all the hub ports\r
4b1bf81c 421 //\r
d987459f
SZ
422 for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {\r
423 Status = PeiHubSetPortFeature (\r
424 PeiServices,\r
425 UsbIoPpi,\r
426 (UINT8) (Index + 1),\r
427 EfiUsbPortPower\r
428 );\r
429 if (EFI_ERROR (Status)) {\r
430 DEBUG (( EFI_D_ERROR, "PeiDoHubConfig: PeiHubSetPortFeature EfiUsbPortPower failed %x\n", Index));\r
431 continue;\r
432 }\r
4b1bf81c 433 }\r
d987459f 434\r
72750e3b
SZ
435 DEBUG (( EFI_D_INFO, "PeiDoHubConfig: HubDescriptor.PwrOn2PwrGood: 0x%x\n", HubDescriptor->PwrOn2PwrGood));\r
436 if (HubDescriptor->PwrOn2PwrGood > 0) {\r
437 MicroSecondDelay (HubDescriptor->PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);\r
d987459f
SZ
438 }\r
439\r
4b1bf81c 440 //\r
d987459f 441 // Clear Hub Status Change\r
4b1bf81c 442 //\r
d987459f
SZ
443 Status = PeiHubGetHubStatus (\r
444 PeiServices,\r
445 UsbIoPpi,\r
446 (UINT32 *) &HubStatus\r
447 );\r
448 if (EFI_ERROR (Status)) {\r
449 return EFI_DEVICE_ERROR;\r
450 } else {\r
451 //\r
452 // Hub power supply change happens\r
453 //\r
454 if ((HubStatus.HubChangeStatus & HUB_CHANGE_LOCAL_POWER) != 0) {\r
455 PeiHubClearHubFeature (\r
456 PeiServices,\r
457 UsbIoPpi,\r
458 C_HUB_LOCAL_POWER\r
459 );\r
460 }\r
461 //\r
462 // Hub change overcurrent happens\r
463 //\r
464 if ((HubStatus.HubChangeStatus & HUB_CHANGE_OVERCURRENT) != 0) {\r
465 PeiHubClearHubFeature (\r
466 PeiServices,\r
467 UsbIoPpi,\r
468 C_HUB_OVER_CURRENT\r
469 );\r
470 }\r
4b1bf81c 471 }\r
472 }\r
473\r
474 return EFI_SUCCESS;\r
475}\r
476\r
477/**\r
478 Send reset signal over the given root hub port.\r
479\r
480 @param PeiServices General-purpose services that are available to every PEIM.\r
481 @param UsbIoPpi Indicates the PEI_USB_IO_PPI instance.\r
482 @param PortNum Usb hub port number (starting from 1).\r
483\r
484**/\r
485VOID\r
486PeiResetHubPort (\r
487 IN EFI_PEI_SERVICES **PeiServices,\r
488 IN PEI_USB_IO_PPI *UsbIoPpi,\r
489 IN UINT8 PortNum\r
490 )\r
491{\r
d987459f
SZ
492 EFI_STATUS Status;\r
493 UINTN Index;\r
4b1bf81c 494 EFI_USB_PORT_STATUS HubPortStatus;\r
495\r
4b1bf81c 496 MicroSecondDelay (100 * 1000);\r
497\r
498 //\r
499 // reset root port\r
500 //\r
501 PeiHubSetPortFeature (\r
502 PeiServices,\r
503 UsbIoPpi,\r
504 PortNum,\r
505 EfiUsbPortReset\r
506 );\r
507\r
d987459f
SZ
508 //\r
509 // Drive the reset signal for worst 20ms. Check USB 2.0 Spec\r
510 // section 7.1.7.5 for timing requirements.\r
511 //\r
512 MicroSecondDelay (USB_SET_PORT_RESET_STALL);\r
4b1bf81c 513\r
d987459f
SZ
514 //\r
515 // Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done.\r
516 //\r
517 ZeroMem (&HubPortStatus, sizeof (EFI_USB_PORT_STATUS));\r
518\r
519 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
520 Status = PeiHubGetPortStatus (\r
521 PeiServices,\r
522 UsbIoPpi,\r
523 PortNum,\r
524 (UINT32 *) &HubPortStatus\r
525 );\r
526\r
527 if (EFI_ERROR (Status)) {\r
528 return;\r
529 }\r
530\r
531 if (USB_BIT_IS_SET (HubPortStatus.PortChangeStatus, USB_PORT_STAT_C_RESET)) {\r
532 break;\r
533 }\r
534\r
535 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);\r
536 }\r
537\r
538 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {\r
539 DEBUG ((EFI_D_ERROR, "PeiResetHubPort: reset not finished in time on port %d\n", PortNum));\r
540 return;\r
541 }\r
4b1bf81c 542\r
543 //\r
d987459f 544 // clear reset change root port\r
4b1bf81c 545 //\r
546 PeiHubClearPortFeature (\r
547 PeiServices,\r
548 UsbIoPpi,\r
549 PortNum,\r
d987459f 550 EfiUsbPortResetChange\r
4b1bf81c 551 );\r
552\r
553 MicroSecondDelay (1 * 1000);\r
554\r
555 PeiHubClearPortFeature (\r
556 PeiServices,\r
557 UsbIoPpi,\r
558 PortNum,\r
559 EfiUsbPortConnectChange\r
560 );\r
561\r
562 //\r
563 // Set port enable\r
564 //\r
565 PeiHubSetPortFeature (\r
566 PeiServices,\r
567 UsbIoPpi,\r
568 PortNum,\r
569 EfiUsbPortEnable\r
570 );\r
571\r
572 //\r
573 // Clear any change status\r
574 //\r
575\r
576 PeiHubClearPortFeature (\r
577 PeiServices,\r
578 UsbIoPpi,\r
579 PortNum,\r
580 EfiUsbPortEnableChange\r
581 );\r
582\r
583 MicroSecondDelay (10 * 1000);\r
584\r
585 return;\r
586}\r