]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusPei / UsbPeim.c
CommitLineData
4b1bf81c 1/** @file\r
2The module to produce Usb Bus PPI.\r
3\r
d1102dba
LG
4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
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// UsbIo PPI interface function\r
16//\r
17PEI_USB_IO_PPI mUsbIoPpi = {\r
18 PeiUsbControlTransfer,\r
19 PeiUsbBulkTransfer,\r
20 PeiUsbGetInterfaceDescriptor,\r
21 PeiUsbGetEndpointDescriptor,\r
22 PeiUsbPortReset\r
23};\r
24\r
25EFI_PEI_PPI_DESCRIPTOR mUsbIoPpiList = {\r
26 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
27 &gPeiUsbIoPpiGuid,\r
28 NULL\r
29};\r
30\r
31/**\r
32 The enumeration routine to detect device change.\r
d1102dba 33\r
4b1bf81c 34 @param PeiServices Describes the list of possible PEI Services.\r
35 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.\r
36 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.\r
37\r
38 @retval EFI_SUCCESS The usb is enumerated successfully.\r
39 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
40 @retval Others Other failure occurs.\r
41\r
42**/\r
43EFI_STATUS\r
44PeiUsbEnumeration (\r
45 IN EFI_PEI_SERVICES **PeiServices,\r
46 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,\r
47 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi\r
48 );\r
49\r
50/**\r
51 Configure new detected usb device.\r
d1102dba 52\r
4b1bf81c 53 @param PeiServices Describes the list of possible PEI Services.\r
54 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
55 @param Port The port to be configured.\r
56 @param DeviceAddress The device address to be configured.\r
57\r
58 @retval EFI_SUCCESS The new detected usb device is configured successfully.\r
59 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
60 @retval Others Other failure occurs.\r
61\r
62**/\r
63EFI_STATUS\r
64PeiConfigureUsbDevice (\r
65 IN EFI_PEI_SERVICES **PeiServices,\r
66 IN PEI_USB_DEVICE *PeiUsbDevice,\r
67 IN UINT8 Port,\r
68 IN OUT UINT8 *DeviceAddress\r
69 );\r
70\r
71/**\r
72 Get all configurations from a detected usb device.\r
d1102dba 73\r
4b1bf81c 74 @param PeiServices Describes the list of possible PEI Services.\r
75 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
76\r
77 @retval EFI_SUCCESS The new detected usb device is configured successfully.\r
78 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
79 @retval Others Other failure occurs.\r
80\r
81**/\r
82EFI_STATUS\r
83PeiUsbGetAllConfiguration (\r
84 IN EFI_PEI_SERVICES **PeiServices,\r
85 IN PEI_USB_DEVICE *PeiUsbDevice\r
86 );\r
87\r
88/**\r
89 Get the start position of next wanted descriptor.\r
d1102dba 90\r
4b1bf81c 91 @param Buffer Buffer containing data to parse.\r
92 @param Length Buffer length.\r
93 @param DescType Descriptor type.\r
94 @param DescLength Descriptor length.\r
95 @param ParsedBytes Bytes has been parsed.\r
96\r
97 @retval EFI_SUCCESS Get wanted descriptor successfully.\r
98 @retval EFI_DEVICE_ERROR Error occurred.\r
99\r
100**/\r
101EFI_STATUS\r
102GetExpectedDescriptor (\r
103 IN UINT8 *Buffer,\r
104 IN UINTN Length,\r
105 IN UINT8 DescType,\r
106 IN UINT8 DescLength,\r
107 OUT UINTN *ParsedBytes\r
108 );\r
109\r
110/**\r
111 The entrypoint of the module, it will enumerate all HCs.\r
d1102dba 112\r
4b1bf81c 113 @param FileHandle Handle of the file being invoked.\r
114 @param PeiServices Describes the list of possible PEI Services.\r
115\r
116 @retval EFI_SUCCESS Usb initialization is done successfully.\r
117 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
118 @retval EFI_UNSUPPORTED Can't find required PPI.\r
119\r
120**/\r
121EFI_STATUS\r
122EFIAPI\r
123PeimInitializeUsb (\r
124 IN EFI_PEI_FILE_HANDLE FileHandle,\r
125 IN CONST EFI_PEI_SERVICES **PeiServices\r
126 )\r
127{\r
128 EFI_STATUS Status;\r
129 UINTN Index;\r
130 PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;\r
131 PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi;\r
132\r
133 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {\r
134 return EFI_SUCCESS;\r
135 }\r
136\r
137 //\r
d1102dba 138 // gPeiUsbHostControllerPpiGuid and gPeiUsb2HostControllerPpiGuid should not\r
4b1bf81c 139 // be produced at the same time\r
140 //\r
141 Index = 0;\r
142 while (TRUE) {\r
143 //\r
144 // Get UsbHcPpi at first.\r
145 //\r
146 Status = PeiServicesLocatePpi (\r
147 &gPeiUsbHostControllerPpiGuid,\r
148 Index,\r
149 NULL,\r
150 (VOID **) &UsbHcPpi\r
151 );\r
152 if (EFI_ERROR (Status)) {\r
153 //\r
154 // No more host controller, break out\r
155 //\r
156 break;\r
157 }\r
158 PeiUsbEnumeration ((EFI_PEI_SERVICES **) PeiServices, UsbHcPpi, NULL);\r
159 Index++;\r
160 }\r
161\r
162 if (Index == 0) {\r
163 //\r
164 // Then try to get Usb2HcPpi.\r
165 //\r
166 while (TRUE) {\r
167 Status = PeiServicesLocatePpi (\r
168 &gPeiUsb2HostControllerPpiGuid,\r
169 Index,\r
170 NULL,\r
171 (VOID **) &Usb2HcPpi\r
d1102dba 172 );\r
4b1bf81c 173 if (EFI_ERROR (Status)) {\r
174 //\r
175 // No more host controller, break out\r
176 //\r
177 break;\r
d1102dba
LG
178 }\r
179 PeiUsbEnumeration ((EFI_PEI_SERVICES **) PeiServices, NULL, Usb2HcPpi);\r
4b1bf81c 180 Index++;\r
181 }\r
182 }\r
d1102dba 183\r
4b1bf81c 184 if (Index == 0) {\r
185 return EFI_UNSUPPORTED;\r
186 }\r
187\r
188 return EFI_SUCCESS;\r
189}\r
190\r
191/**\r
192 The Hub Enumeration just scans the hub ports one time. It also\r
193 doesn't support hot-plug.\r
d1102dba 194\r
4b1bf81c 195 @param PeiServices Describes the list of possible PEI Services.\r
196 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
197 @param CurrentAddress The DeviceAddress of usb device.\r
198\r
199 @retval EFI_SUCCESS The usb hub is enumerated successfully.\r
200 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
201 @retval Others Other failure occurs.\r
202\r
203**/\r
204EFI_STATUS\r
205PeiHubEnumeration (\r
206 IN EFI_PEI_SERVICES **PeiServices,\r
207 IN PEI_USB_DEVICE *PeiUsbDevice,\r
208 IN UINT8 *CurrentAddress\r
209 )\r
210{\r
211 UINTN Index;\r
212 EFI_STATUS Status;\r
213 PEI_USB_IO_PPI *UsbIoPpi;\r
214 EFI_USB_PORT_STATUS PortStatus;\r
215 UINTN MemPages;\r
216 EFI_PHYSICAL_ADDRESS AllocateAddress;\r
217 PEI_USB_DEVICE *NewPeiUsbDevice;\r
8a718ba9
SZ
218 UINTN InterfaceIndex;\r
219 UINTN EndpointIndex;\r
4b1bf81c 220\r
221\r
222 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;\r
223\r
d987459f
SZ
224 DEBUG ((EFI_D_INFO, "PeiHubEnumeration: DownStreamPortNo: %x\n", PeiUsbDevice->DownStreamPortNo));\r
225\r
4b1bf81c 226 for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {\r
227\r
228 Status = PeiHubGetPortStatus (\r
229 PeiServices,\r
230 UsbIoPpi,\r
231 (UINT8) (Index + 1),\r
232 (UINT32 *) &PortStatus\r
233 );\r
234\r
235 if (EFI_ERROR (Status)) {\r
236 continue;\r
237 }\r
238\r
d987459f
SZ
239 DEBUG ((EFI_D_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));\r
240 //\r
241 // Only handle connection/enable/overcurrent/reset change.\r
242 //\r
243 if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {\r
244 continue;\r
245 } else {\r
4b1bf81c 246 if (IsPortConnect (PortStatus.PortStatus)) {\r
4b1bf81c 247 //\r
248 // Begin to deal with the new device\r
249 //\r
250 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;\r
251 Status = PeiServicesAllocatePages (\r
252 EfiBootServicesCode,\r
253 MemPages,\r
254 &AllocateAddress\r
255 );\r
256 if (EFI_ERROR (Status)) {\r
257 return EFI_OUT_OF_RESOURCES;\r
258 }\r
259\r
260 NewPeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);\r
261 ZeroMem (NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));\r
262\r
263 NewPeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;\r
264 NewPeiUsbDevice->DeviceAddress = 0;\r
265 NewPeiUsbDevice->MaxPacketSize0 = 8;\r
266 NewPeiUsbDevice->DataToggle = 0;\r
267 CopyMem (\r
268 &(NewPeiUsbDevice->UsbIoPpi),\r
269 &mUsbIoPpi,\r
270 sizeof (PEI_USB_IO_PPI)\r
271 );\r
272 CopyMem (\r
273 &(NewPeiUsbDevice->UsbIoPpiList),\r
274 &mUsbIoPpiList,\r
275 sizeof (EFI_PEI_PPI_DESCRIPTOR)\r
276 );\r
277 NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;\r
278 NewPeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;\r
279 NewPeiUsbDevice->UsbHcPpi = PeiUsbDevice->UsbHcPpi;\r
280 NewPeiUsbDevice->Usb2HcPpi = PeiUsbDevice->Usb2HcPpi;\r
d987459f 281 NewPeiUsbDevice->Tier = (UINT8) (PeiUsbDevice->Tier + 1);\r
4b1bf81c 282 NewPeiUsbDevice->IsHub = 0x0;\r
283 NewPeiUsbDevice->DownStreamPortNo = 0x0;\r
284\r
d1102dba 285 if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||\r
d987459f
SZ
286 ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0)) {\r
287 //\r
d1102dba 288 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.\r
d987459f
SZ
289 //\r
290 PeiResetHubPort (PeiServices, UsbIoPpi, (UINT8)(Index + 1));\r
d1102dba 291\r
d987459f
SZ
292 PeiHubGetPortStatus (\r
293 PeiServices,\r
294 UsbIoPpi,\r
295 (UINT8) (Index + 1),\r
296 (UINT32 *) &PortStatus\r
297 );\r
298 } else {\r
299 PeiHubClearPortFeature (\r
300 PeiServices,\r
301 UsbIoPpi,\r
302 (UINT8) (Index + 1),\r
303 EfiUsbPortResetChange\r
304 );\r
305 }\r
4b1bf81c 306\r
d987459f
SZ
307 NewPeiUsbDevice->DeviceSpeed = (UINT8) PeiUsbGetDeviceSpeed (PortStatus.PortStatus);\r
308 DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));\r
4b1bf81c 309\r
d987459f
SZ
310 if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)){\r
311 NewPeiUsbDevice->MaxPacketSize0 = 512;\r
312 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {\r
313 NewPeiUsbDevice->MaxPacketSize0 = 64;\r
314 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {\r
315 NewPeiUsbDevice->MaxPacketSize0 = 8;\r
316 } else {\r
317 NewPeiUsbDevice->MaxPacketSize0 = 8;\r
318 }\r
4b1bf81c 319\r
320 if(NewPeiUsbDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {\r
d12c6a78 321 if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_HIGH) {\r
322 NewPeiUsbDevice->Translator.TranslatorPortNumber = (UINT8)Index;\r
323 NewPeiUsbDevice->Translator.TranslatorHubAddress = *CurrentAddress;\r
324 } else {\r
325 CopyMem(&(NewPeiUsbDevice->Translator), &(PeiUsbDevice->Translator), sizeof(EFI_USB2_HC_TRANSACTION_TRANSLATOR));\r
4b1bf81c 326 }\r
d12c6a78 327 }\r
4b1bf81c 328\r
329 //\r
330 // Configure that Usb Device\r
331 //\r
332 Status = PeiConfigureUsbDevice (\r
333 PeiServices,\r
334 NewPeiUsbDevice,\r
335 (UINT8) (Index + 1),\r
336 CurrentAddress\r
337 );\r
338\r
339 if (EFI_ERROR (Status)) {\r
340 continue;\r
341 }\r
d987459f 342 DEBUG ((EFI_D_INFO, "PeiHubEnumeration: PeiConfigureUsbDevice Success\n"));\r
4b1bf81c 343\r
344 Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);\r
345\r
346 if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {\r
347 NewPeiUsbDevice->IsHub = 0x1;\r
348\r
349 Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);\r
350 if (EFI_ERROR (Status)) {\r
351 return Status;\r
352 }\r
353\r
354 PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);\r
355 }\r
4b1bf81c 356\r
8a718ba9
SZ
357 for (InterfaceIndex = 1; InterfaceIndex < NewPeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {\r
358 //\r
359 // Begin to deal with the new device\r
360 //\r
361 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;\r
362 Status = PeiServicesAllocatePages (\r
363 EfiBootServicesCode,\r
364 MemPages,\r
365 &AllocateAddress\r
366 );\r
367 if (EFI_ERROR (Status)) {\r
368 return EFI_OUT_OF_RESOURCES;\r
369 }\r
370 CopyMem ((VOID *)(UINTN)AllocateAddress, NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));\r
371 NewPeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);\r
372 NewPeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;\r
373 NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;\r
374 NewPeiUsbDevice->InterfaceDesc = NewPeiUsbDevice->InterfaceDescList[InterfaceIndex];\r
375 for (EndpointIndex = 0; EndpointIndex < NewPeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {\r
376 NewPeiUsbDevice->EndpointDesc[EndpointIndex] = NewPeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];\r
377 }\r
378\r
379 Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);\r
380\r
381 if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {\r
382 NewPeiUsbDevice->IsHub = 0x1;\r
383\r
384 Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);\r
385 if (EFI_ERROR (Status)) {\r
386 return Status;\r
387 }\r
388\r
389 PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);\r
390 }\r
391 }\r
392 }\r
4b1bf81c 393 }\r
394 }\r
395\r
396\r
397 return EFI_SUCCESS;\r
398}\r
399\r
400/**\r
401 The enumeration routine to detect device change.\r
d1102dba 402\r
4b1bf81c 403 @param PeiServices Describes the list of possible PEI Services.\r
404 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.\r
405 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.\r
406\r
407 @retval EFI_SUCCESS The usb is enumerated successfully.\r
408 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
409 @retval Others Other failure occurs.\r
410\r
411**/\r
412EFI_STATUS\r
413PeiUsbEnumeration (\r
414 IN EFI_PEI_SERVICES **PeiServices,\r
415 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,\r
416 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi\r
417 )\r
418{\r
419 UINT8 NumOfRootPort;\r
420 EFI_STATUS Status;\r
421 UINT8 Index;\r
422 EFI_USB_PORT_STATUS PortStatus;\r
423 PEI_USB_DEVICE *PeiUsbDevice;\r
424 UINTN MemPages;\r
425 EFI_PHYSICAL_ADDRESS AllocateAddress;\r
426 UINT8 CurrentAddress;\r
8a718ba9
SZ
427 UINTN InterfaceIndex;\r
428 UINTN EndpointIndex;\r
4b1bf81c 429\r
430 CurrentAddress = 0;\r
d12c6a78 431 if (Usb2HcPpi != NULL) {\r
4b1bf81c 432 Usb2HcPpi->GetRootHubPortNumber (\r
433 PeiServices,\r
434 Usb2HcPpi,\r
435 (UINT8 *) &NumOfRootPort\r
d1102dba 436 );\r
d12c6a78 437 } else if (UsbHcPpi != NULL) {\r
4b1bf81c 438 UsbHcPpi->GetRootHubPortNumber (\r
439 PeiServices,\r
440 UsbHcPpi,\r
441 (UINT8 *) &NumOfRootPort\r
442 );\r
d12c6a78 443 } else {\r
444 ASSERT (FALSE);\r
445 return EFI_INVALID_PARAMETER;\r
4b1bf81c 446 }\r
447\r
d987459f
SZ
448 DEBUG ((EFI_D_INFO, "PeiUsbEnumeration: NumOfRootPort: %x\n", NumOfRootPort));\r
449\r
4b1bf81c 450 for (Index = 0; Index < NumOfRootPort; Index++) {\r
451 //\r
452 // First get root port status to detect changes happen\r
453 //\r
454 if (Usb2HcPpi != NULL) {\r
455 Usb2HcPpi->GetRootHubPortStatus (\r
456 PeiServices,\r
457 Usb2HcPpi,\r
458 (UINT8) Index,\r
459 &PortStatus\r
d1102dba 460 );\r
4b1bf81c 461 } else {\r
462 UsbHcPpi->GetRootHubPortStatus (\r
463 PeiServices,\r
464 UsbHcPpi,\r
465 (UINT8) Index,\r
466 &PortStatus\r
467 );\r
468 }\r
d987459f
SZ
469 DEBUG ((EFI_D_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));\r
470 //\r
471 // Only handle connection/enable/overcurrent/reset change.\r
472 //\r
473 if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {\r
474 continue;\r
475 } else {\r
4b1bf81c 476 if (IsPortConnect (PortStatus.PortStatus)) {\r
4b1bf81c 477 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;\r
478 Status = PeiServicesAllocatePages (\r
479 EfiBootServicesCode,\r
480 MemPages,\r
481 &AllocateAddress\r
482 );\r
483 if (EFI_ERROR (Status)) {\r
484 return EFI_OUT_OF_RESOURCES;\r
485 }\r
486\r
487 PeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);\r
488 ZeroMem (PeiUsbDevice, sizeof (PEI_USB_DEVICE));\r
489\r
490 PeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;\r
491 PeiUsbDevice->DeviceAddress = 0;\r
492 PeiUsbDevice->MaxPacketSize0 = 8;\r
493 PeiUsbDevice->DataToggle = 0;\r
494 CopyMem (\r
495 &(PeiUsbDevice->UsbIoPpi),\r
496 &mUsbIoPpi,\r
497 sizeof (PEI_USB_IO_PPI)\r
498 );\r
499 CopyMem (\r
500 &(PeiUsbDevice->UsbIoPpiList),\r
501 &mUsbIoPpiList,\r
502 sizeof (EFI_PEI_PPI_DESCRIPTOR)\r
503 );\r
504 PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;\r
505 PeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;\r
506 PeiUsbDevice->UsbHcPpi = UsbHcPpi;\r
507 PeiUsbDevice->Usb2HcPpi = Usb2HcPpi;\r
508 PeiUsbDevice->IsHub = 0x0;\r
509 PeiUsbDevice->DownStreamPortNo = 0x0;\r
510\r
d1102dba 511 if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||\r
d987459f
SZ
512 ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0)) {\r
513 //\r
d1102dba 514 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.\r
d987459f
SZ
515 //\r
516 ResetRootPort (\r
517 PeiServices,\r
518 PeiUsbDevice->UsbHcPpi,\r
519 PeiUsbDevice->Usb2HcPpi,\r
520 Index,\r
521 0\r
522 );\r
4b1bf81c 523\r
d987459f
SZ
524 if (Usb2HcPpi != NULL) {\r
525 Usb2HcPpi->GetRootHubPortStatus (\r
526 PeiServices,\r
527 Usb2HcPpi,\r
528 (UINT8) Index,\r
529 &PortStatus\r
530 );\r
531 } else {\r
532 UsbHcPpi->GetRootHubPortStatus (\r
533 PeiServices,\r
534 UsbHcPpi,\r
535 (UINT8) Index,\r
536 &PortStatus\r
537 );\r
538 }\r
4b1bf81c 539 } else {\r
d987459f
SZ
540 if (Usb2HcPpi != NULL) {\r
541 Usb2HcPpi->ClearRootHubPortFeature (\r
542 PeiServices,\r
543 Usb2HcPpi,\r
544 (UINT8) Index,\r
545 EfiUsbPortResetChange\r
d1102dba 546 );\r
d987459f
SZ
547 } else {\r
548 UsbHcPpi->ClearRootHubPortFeature (\r
549 PeiServices,\r
550 UsbHcPpi,\r
551 (UINT8) Index,\r
552 EfiUsbPortResetChange\r
553 );\r
554 }\r
4b1bf81c 555 }\r
556\r
d987459f 557 PeiUsbDevice->DeviceSpeed = (UINT8) PeiUsbGetDeviceSpeed (PortStatus.PortStatus);\r
4b1bf81c 558 DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));\r
559\r
d987459f
SZ
560 if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)){\r
561 PeiUsbDevice->MaxPacketSize0 = 512;\r
562 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {\r
563 PeiUsbDevice->MaxPacketSize0 = 64;\r
564 } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {\r
565 PeiUsbDevice->MaxPacketSize0 = 8;\r
566 } else {\r
567 PeiUsbDevice->MaxPacketSize0 = 8;\r
568 }\r
569\r
4b1bf81c 570 //\r
571 // Configure that Usb Device\r
572 //\r
573 Status = PeiConfigureUsbDevice (\r
574 PeiServices,\r
575 PeiUsbDevice,\r
576 Index,\r
577 &CurrentAddress\r
578 );\r
579\r
580 if (EFI_ERROR (Status)) {\r
581 continue;\r
582 }\r
d987459f 583 DEBUG ((EFI_D_INFO, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n"));\r
4b1bf81c 584\r
585 Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);\r
586\r
587 if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {\r
588 PeiUsbDevice->IsHub = 0x1;\r
589\r
590 Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);\r
591 if (EFI_ERROR (Status)) {\r
592 return Status;\r
593 }\r
594\r
595 PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);\r
596 }\r
8a718ba9
SZ
597\r
598 for (InterfaceIndex = 1; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {\r
599 //\r
600 // Begin to deal with the new device\r
601 //\r
602 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;\r
603 Status = PeiServicesAllocatePages (\r
604 EfiBootServicesCode,\r
605 MemPages,\r
606 &AllocateAddress\r
607 );\r
608 if (EFI_ERROR (Status)) {\r
609 return EFI_OUT_OF_RESOURCES;\r
610 }\r
611 CopyMem ((VOID *)(UINTN)AllocateAddress, PeiUsbDevice, sizeof (PEI_USB_DEVICE));\r
612 PeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);\r
613 PeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;\r
614 PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;\r
615 PeiUsbDevice->InterfaceDesc = PeiUsbDevice->InterfaceDescList[InterfaceIndex];\r
616 for (EndpointIndex = 0; EndpointIndex < PeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {\r
617 PeiUsbDevice->EndpointDesc[EndpointIndex] = PeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];\r
618 }\r
619\r
620 Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);\r
621\r
622 if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {\r
623 PeiUsbDevice->IsHub = 0x1;\r
624\r
625 Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);\r
626 if (EFI_ERROR (Status)) {\r
627 return Status;\r
628 }\r
629\r
630 PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);\r
631 }\r
632 }\r
4b1bf81c 633 } else {\r
634 //\r
635 // Disconnect change happen, currently we don't support\r
636 //\r
637 }\r
638 }\r
639 }\r
640\r
641 return EFI_SUCCESS;\r
642}\r
643\r
644/**\r
645 Configure new detected usb device.\r
d1102dba 646\r
4b1bf81c 647 @param PeiServices Describes the list of possible PEI Services.\r
648 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
649 @param Port The port to be configured.\r
650 @param DeviceAddress The device address to be configured.\r
651\r
652 @retval EFI_SUCCESS The new detected usb device is configured successfully.\r
653 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
654 @retval Others Other failure occurs.\r
655\r
656**/\r
657EFI_STATUS\r
658PeiConfigureUsbDevice (\r
659 IN EFI_PEI_SERVICES **PeiServices,\r
660 IN PEI_USB_DEVICE *PeiUsbDevice,\r
661 IN UINT8 Port,\r
662 IN OUT UINT8 *DeviceAddress\r
663 )\r
664{\r
665 EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;\r
666 EFI_STATUS Status;\r
667 PEI_USB_IO_PPI *UsbIoPpi;\r
668 UINT8 Retry;\r
669\r
670 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;\r
671 Status = EFI_SUCCESS;\r
672 ZeroMem (&DeviceDescriptor, sizeof (EFI_USB_DEVICE_DESCRIPTOR));\r
673 //\r
674 // Get USB device descriptor\r
675 //\r
676\r
677 for (Retry = 0; Retry < 3; Retry ++) {\r
4b1bf81c 678 Status = PeiUsbGetDescriptor (\r
679 PeiServices,\r
680 UsbIoPpi,\r
681 (USB_DT_DEVICE << 8),\r
682 0,\r
683 8,\r
684 &DeviceDescriptor\r
685 );\r
686\r
687 if (!EFI_ERROR (Status)) {\r
d987459f 688 DEBUG ((EFI_D_INFO, "PeiUsbGet Device Descriptor the %d time Success\n", Retry));\r
4b1bf81c 689 break;\r
690 }\r
691 }\r
692\r
693 if (Retry == 3) {\r
d987459f 694 DEBUG ((EFI_D_ERROR, "PeiUsbGet Device Descriptor fail: %x %r\n", Retry, Status));\r
4b1bf81c 695 return Status;\r
696 }\r
697\r
b9953b65 698 if ((DeviceDescriptor.BcdUSB >= 0x0300) && (DeviceDescriptor.MaxPacketSize0 == 9)) {\r
d987459f
SZ
699 PeiUsbDevice->MaxPacketSize0 = 1 << 9;\r
700 } else {\r
701 PeiUsbDevice->MaxPacketSize0 = DeviceDescriptor.MaxPacketSize0;\r
702 }\r
4b1bf81c 703\r
704 (*DeviceAddress) ++;\r
705\r
706 Status = PeiUsbSetDeviceAddress (\r
707 PeiServices,\r
708 UsbIoPpi,\r
709 *DeviceAddress\r
710 );\r
711\r
712 if (EFI_ERROR (Status)) {\r
d987459f 713 DEBUG ((EFI_D_ERROR, "PeiUsbSetDeviceAddress Failed: %r\n", Status));\r
4b1bf81c 714 return Status;\r
715 }\r
04910ceb 716 MicroSecondDelay (USB_SET_DEVICE_ADDRESS_STALL);\r
4b1bf81c 717\r
718 PeiUsbDevice->DeviceAddress = *DeviceAddress;\r
719\r
720 //\r
721 // Get whole USB device descriptor\r
722 //\r
723 Status = PeiUsbGetDescriptor (\r
724 PeiServices,\r
725 UsbIoPpi,\r
726 (USB_DT_DEVICE << 8),\r
727 0,\r
728 (UINT16) sizeof (EFI_USB_DEVICE_DESCRIPTOR),\r
729 &DeviceDescriptor\r
730 );\r
731\r
732 if (EFI_ERROR (Status)) {\r
733 DEBUG ((EFI_D_ERROR, "PeiUsbGetDescriptor First Failed\n"));\r
734 return Status;\r
735 }\r
8a718ba9 736\r
4b1bf81c 737 //\r
738 // Get its default configuration and its first interface\r
739 //\r
740 Status = PeiUsbGetAllConfiguration (\r
741 PeiServices,\r
742 PeiUsbDevice\r
743 );\r
4b1bf81c 744 if (EFI_ERROR (Status)) {\r
745 return Status;\r
746 }\r
04910ceb 747 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL);\r
4b1bf81c 748\r
749 Status = PeiUsbSetConfiguration (\r
750 PeiServices,\r
751 UsbIoPpi\r
752 );\r
753\r
754 if (EFI_ERROR (Status)) {\r
755 return Status;\r
756 }\r
757\r
758 return EFI_SUCCESS;\r
759}\r
760\r
761/**\r
762 Get all configurations from a detected usb device.\r
d1102dba 763\r
4b1bf81c 764 @param PeiServices Describes the list of possible PEI Services.\r
765 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
766\r
767 @retval EFI_SUCCESS The new detected usb device is configured successfully.\r
768 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
769 @retval Others Other failure occurs.\r
770\r
771**/\r
772EFI_STATUS\r
773PeiUsbGetAllConfiguration (\r
774 IN EFI_PEI_SERVICES **PeiServices,\r
775 IN PEI_USB_DEVICE *PeiUsbDevice\r
776 )\r
777{\r
778 EFI_STATUS Status;\r
779 EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc;\r
780 PEI_USB_IO_PPI *UsbIoPpi;\r
781 UINT16 ConfigDescLength;\r
782 UINT8 *Ptr;\r
783 UINTN SkipBytes;\r
784 UINTN LengthLeft;\r
8a718ba9 785 UINTN InterfaceIndex;\r
4b1bf81c 786 UINTN Index;\r
787 UINTN NumOfEndpoint;\r
788\r
789 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;\r
790\r
791 //\r
792 // First get its 4-byte configuration descriptor\r
793 //\r
794 Status = PeiUsbGetDescriptor (\r
795 PeiServices,\r
796 UsbIoPpi,\r
797 (USB_DT_CONFIG << 8), // Value\r
798 0, // Index\r
799 4, // Length\r
800 PeiUsbDevice->ConfigurationData\r
801 );\r
802\r
803 if (EFI_ERROR (Status)) {\r
804 DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor First Failed\n"));\r
805 return Status;\r
806 }\r
04910ceb 807 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL);\r
4b1bf81c 808\r
809 ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) PeiUsbDevice->ConfigurationData;\r
810 ConfigDescLength = ConfigDesc->TotalLength;\r
811\r
70425456
RN
812 //\r
813 // Reject if TotalLength even cannot cover itself.\r
814 //\r
815 if (ConfigDescLength < OFFSET_OF (EFI_USB_CONFIG_DESCRIPTOR, TotalLength) + sizeof (ConfigDesc->TotalLength)) {\r
816 return EFI_DEVICE_ERROR;\r
817 }\r
818\r
819 //\r
820 // Reject if TotalLength exceeds the PeiUsbDevice->ConfigurationData.\r
821 //\r
822 if (ConfigDescLength > sizeof (PeiUsbDevice->ConfigurationData)) {\r
823 return EFI_DEVICE_ERROR;\r
824 }\r
825\r
4b1bf81c 826 //\r
827 // Then we get the total descriptors for this configuration\r
828 //\r
829 Status = PeiUsbGetDescriptor (\r
830 PeiServices,\r
831 UsbIoPpi,\r
832 (USB_DT_CONFIG << 8),\r
833 0,\r
834 ConfigDescLength,\r
835 PeiUsbDevice->ConfigurationData\r
836 );\r
837\r
838 if (EFI_ERROR (Status)) {\r
839 DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor all Failed\n"));\r
840 return Status;\r
841 }\r
842 //\r
843 // Parse this configuration descriptor\r
844 // First get the current config descriptor;\r
845 //\r
846 Status = GetExpectedDescriptor (\r
847 PeiUsbDevice->ConfigurationData,\r
848 ConfigDescLength,\r
849 USB_DT_CONFIG,\r
850 (UINT8) sizeof (EFI_USB_CONFIG_DESCRIPTOR),\r
851 &SkipBytes\r
852 );\r
853\r
854 if (EFI_ERROR (Status)) {\r
855 return Status;\r
856 }\r
857\r
858 Ptr = PeiUsbDevice->ConfigurationData + SkipBytes;\r
859 PeiUsbDevice->ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) Ptr;\r
860\r
861 Ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR);\r
862 LengthLeft = ConfigDescLength - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR);\r
863\r
8a718ba9 864 for (InterfaceIndex = 0; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {\r
4b1bf81c 865\r
4b1bf81c 866 //\r
8a718ba9 867 // Get the interface descriptor\r
4b1bf81c 868 //\r
869 Status = GetExpectedDescriptor (\r
870 Ptr,\r
871 LengthLeft,\r
8a718ba9
SZ
872 USB_DT_INTERFACE,\r
873 (UINT8) sizeof (EFI_USB_INTERFACE_DESCRIPTOR),\r
4b1bf81c 874 &SkipBytes\r
875 );\r
876\r
877 if (EFI_ERROR (Status)) {\r
878 return Status;\r
879 }\r
880\r
881 Ptr += SkipBytes;\r
8a718ba9
SZ
882 if (InterfaceIndex == 0) {\r
883 PeiUsbDevice->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;\r
884 }\r
885 PeiUsbDevice->InterfaceDescList[InterfaceIndex] = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;\r
4b1bf81c 886\r
8a718ba9 887 Ptr += sizeof (EFI_USB_INTERFACE_DESCRIPTOR);\r
4b1bf81c 888 LengthLeft -= SkipBytes;\r
8a718ba9
SZ
889 LengthLeft -= sizeof (EFI_USB_INTERFACE_DESCRIPTOR);\r
890\r
891 //\r
892 // Parse all the endpoint descriptor within this interface\r
893 //\r
894 NumOfEndpoint = PeiUsbDevice->InterfaceDescList[InterfaceIndex]->NumEndpoints;\r
895 ASSERT (NumOfEndpoint <= MAX_ENDPOINT);\r
896\r
897 for (Index = 0; Index < NumOfEndpoint; Index++) {\r
898 //\r
899 // Get the endpoint descriptor\r
900 //\r
901 Status = GetExpectedDescriptor (\r
902 Ptr,\r
903 LengthLeft,\r
904 USB_DT_ENDPOINT,\r
905 (UINT8) sizeof (EFI_USB_ENDPOINT_DESCRIPTOR),\r
906 &SkipBytes\r
907 );\r
908\r
909 if (EFI_ERROR (Status)) {\r
910 return Status;\r
911 }\r
912\r
913 Ptr += SkipBytes;\r
914 if (InterfaceIndex == 0) {\r
915 PeiUsbDevice->EndpointDesc[Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;\r
916 }\r
917 PeiUsbDevice->EndpointDescList[InterfaceIndex][Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;\r
918\r
919 Ptr += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);\r
920 LengthLeft -= SkipBytes;\r
921 LengthLeft -= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);\r
922 }\r
4b1bf81c 923 }\r
924\r
925 return EFI_SUCCESS;\r
926}\r
927\r
928/**\r
929 Get the start position of next wanted descriptor.\r
d1102dba 930\r
4b1bf81c 931 @param Buffer Buffer containing data to parse.\r
932 @param Length Buffer length.\r
933 @param DescType Descriptor type.\r
934 @param DescLength Descriptor length.\r
935 @param ParsedBytes Bytes has been parsed.\r
936\r
937 @retval EFI_SUCCESS Get wanted descriptor successfully.\r
938 @retval EFI_DEVICE_ERROR Error occurred.\r
939\r
940**/\r
941EFI_STATUS\r
942GetExpectedDescriptor (\r
943 IN UINT8 *Buffer,\r
944 IN UINTN Length,\r
945 IN UINT8 DescType,\r
946 IN UINT8 DescLength,\r
947 OUT UINTN *ParsedBytes\r
948 )\r
949{\r
c96de1db
RN
950 USB_DESC_HEAD *Head;\r
951 UINTN Offset;\r
4b1bf81c 952\r
c96de1db 953 //\r
dbeaf585 954 // Total length is too small that cannot hold the single descriptor header plus data.\r
c96de1db
RN
955 //\r
956 if (Length <= sizeof (USB_DESC_HEAD)) {\r
957 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, total length = %d!\n", Length));\r
958 return EFI_DEVICE_ERROR;\r
959 }\r
4b1bf81c 960\r
c96de1db
RN
961 //\r
962 // All the descriptor has a common LTV (Length, Type, Value)\r
963 // format. Skip the descriptor that isn't of this Type\r
964 //\r
965 Offset = 0;\r
966 Head = (USB_DESC_HEAD *)Buffer;\r
967 while (Offset < Length - sizeof (USB_DESC_HEAD)) {\r
4b1bf81c 968 //\r
c96de1db 969 // Above condition make sure Head->Len and Head->Type are safe to access\r
4b1bf81c 970 //\r
c96de1db 971 Head = (USB_DESC_HEAD *)&Buffer[Offset];\r
4b1bf81c 972\r
c96de1db
RN
973 if (Head->Len == 0) {\r
974 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = 0!\n"));\r
975 return EFI_DEVICE_ERROR;\r
4b1bf81c 976 }\r
977\r
4b1bf81c 978 //\r
c96de1db 979 // Make sure no overflow when adding Head->Len to Offset.\r
4b1bf81c 980 //\r
c96de1db
RN
981 if (Head->Len > MAX_UINTN - Offset) {\r
982 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = %d!\n", Head->Len));\r
4b1bf81c 983 return EFI_DEVICE_ERROR;\r
984 }\r
985\r
c96de1db
RN
986 if (Head->Type == DescType) {\r
987 break;\r
4b1bf81c 988 }\r
c96de1db
RN
989\r
990 Offset += Head->Len;\r
991 }\r
992\r
993 //\r
994 // Head->Len is invalid resulting data beyond boundary, or\r
995 // Descriptor cannot be found: No such type.\r
996 //\r
997 if (Length < Offset) {\r
998 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Offset/Len = %d/%d!\n", Offset, Length));\r
999 return EFI_DEVICE_ERROR;\r
4b1bf81c 1000 }\r
1001\r
c96de1db
RN
1002 if ((Head->Type != DescType) || (Head->Len < DescLength)) {\r
1003 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: descriptor cannot be found, Header(T/L) = %d/%d!\n", Head->Type, Head->Len));\r
1004 return EFI_DEVICE_ERROR;\r
1005 }\r
4b1bf81c 1006\r
c96de1db 1007 *ParsedBytes = Offset;\r
4b1bf81c 1008 return EFI_SUCCESS;\r
1009}\r
1010\r
1011/**\r
1012 Send reset signal over the given root hub port.\r
d1102dba 1013\r
4b1bf81c 1014 @param PeiServices Describes the list of possible PEI Services.\r
1015 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.\r
1016 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.\r
1017 @param PortNum The port to be reset.\r
1018 @param RetryIndex The retry times.\r
1019\r
1020**/\r
1021VOID\r
1022ResetRootPort (\r
1023 IN EFI_PEI_SERVICES **PeiServices,\r
1024 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,\r
1025 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi,\r
1026 IN UINT8 PortNum,\r
1027 IN UINT8 RetryIndex\r
1028 )\r
1029{\r
1030 EFI_STATUS Status;\r
d987459f
SZ
1031 UINTN Index;\r
1032 EFI_USB_PORT_STATUS PortStatus;\r
4b1bf81c 1033\r
1034\r
1035 if (Usb2HcPpi != NULL) {\r
1036 MicroSecondDelay (200 * 1000);\r
d1102dba 1037\r
4b1bf81c 1038 //\r
1039 // reset root port\r
1040 //\r
1041 Status = Usb2HcPpi->SetRootHubPortFeature (\r
1042 PeiServices,\r
1043 Usb2HcPpi,\r
1044 PortNum,\r
1045 EfiUsbPortReset\r
1046 );\r
d1102dba 1047\r
4b1bf81c 1048 if (EFI_ERROR (Status)) {\r
1049 DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));\r
1050 return;\r
1051 }\r
d1102dba 1052\r
d987459f
SZ
1053 //\r
1054 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec\r
1055 // section 7.1.7.5 for timing requirements.\r
1056 //\r
1057 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);\r
1058\r
4b1bf81c 1059 //\r
1060 // clear reset root port\r
1061 //\r
1062 Status = Usb2HcPpi->ClearRootHubPortFeature (\r
1063 PeiServices,\r
1064 Usb2HcPpi,\r
1065 PortNum,\r
1066 EfiUsbPortReset\r
1067 );\r
d1102dba 1068\r
4b1bf81c 1069 if (EFI_ERROR (Status)) {\r
1070 DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));\r
1071 return;\r
1072 }\r
d987459f
SZ
1073\r
1074 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);\r
1075\r
1076 //\r
1077 // USB host controller won't clear the RESET bit until\r
1078 // reset is actually finished.\r
1079 //\r
1080 ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));\r
1081\r
1082 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
1083 Status = Usb2HcPpi->GetRootHubPortStatus (\r
1084 PeiServices,\r
1085 Usb2HcPpi,\r
1086 PortNum,\r
1087 &PortStatus\r
d1102dba 1088 );\r
d987459f
SZ
1089 if (EFI_ERROR (Status)) {\r
1090 return;\r
1091 }\r
1092\r
1093 if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {\r
1094 break;\r
1095 }\r
1096\r
1097 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);\r
1098 }\r
1099\r
1100 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {\r
1101 DEBUG ((EFI_D_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));\r
1102 return;\r
1103 }\r
1104\r
1105 Usb2HcPpi->ClearRootHubPortFeature (\r
1106 PeiServices,\r
1107 Usb2HcPpi,\r
1108 PortNum,\r
1109 EfiUsbPortResetChange\r
1110 );\r
1111\r
4b1bf81c 1112 Usb2HcPpi->ClearRootHubPortFeature (\r
1113 PeiServices,\r
1114 Usb2HcPpi,\r
1115 PortNum,\r
1116 EfiUsbPortConnectChange\r
1117 );\r
d1102dba 1118\r
4b1bf81c 1119 //\r
1120 // Set port enable\r
1121 //\r
1122 Usb2HcPpi->SetRootHubPortFeature(\r
1123 PeiServices,\r
1124 Usb2HcPpi,\r
1125 PortNum,\r
1126 EfiUsbPortEnable\r
1127 );\r
d1102dba 1128\r
4b1bf81c 1129 Usb2HcPpi->ClearRootHubPortFeature (\r
1130 PeiServices,\r
1131 Usb2HcPpi,\r
1132 PortNum,\r
1133 EfiUsbPortEnableChange\r
1134 );\r
d1102dba 1135\r
4b1bf81c 1136 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);\r
1137 } else {\r
1138 MicroSecondDelay (200 * 1000);\r
d1102dba 1139\r
4b1bf81c 1140 //\r
1141 // reset root port\r
1142 //\r
1143 Status = UsbHcPpi->SetRootHubPortFeature (\r
1144 PeiServices,\r
1145 UsbHcPpi,\r
1146 PortNum,\r
1147 EfiUsbPortReset\r
1148 );\r
d1102dba 1149\r
4b1bf81c 1150 if (EFI_ERROR (Status)) {\r
1151 DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));\r
1152 return;\r
1153 }\r
d1102dba 1154\r
d987459f
SZ
1155 //\r
1156 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec\r
1157 // section 7.1.7.5 for timing requirements.\r
1158 //\r
1159 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);\r
d1102dba 1160\r
4b1bf81c 1161 //\r
1162 // clear reset root port\r
1163 //\r
1164 Status = UsbHcPpi->ClearRootHubPortFeature (\r
1165 PeiServices,\r
1166 UsbHcPpi,\r
1167 PortNum,\r
1168 EfiUsbPortReset\r
1169 );\r
d1102dba 1170\r
4b1bf81c 1171 if (EFI_ERROR (Status)) {\r
1172 DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));\r
1173 return;\r
1174 }\r
d1102dba 1175\r
d987459f
SZ
1176 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);\r
1177\r
1178 //\r
1179 // USB host controller won't clear the RESET bit until\r
1180 // reset is actually finished.\r
1181 //\r
1182 ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));\r
1183\r
1184 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
1185 Status = UsbHcPpi->GetRootHubPortStatus (\r
1186 PeiServices,\r
1187 UsbHcPpi,\r
1188 PortNum,\r
1189 &PortStatus\r
d1102dba 1190 );\r
d987459f
SZ
1191 if (EFI_ERROR (Status)) {\r
1192 return;\r
1193 }\r
1194\r
1195 if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {\r
1196 break;\r
1197 }\r
1198\r
1199 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);\r
1200 }\r
1201\r
1202 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {\r
1203 DEBUG ((EFI_D_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));\r
1204 return;\r
1205 }\r
1206\r
1207 UsbHcPpi->ClearRootHubPortFeature (\r
1208 PeiServices,\r
1209 UsbHcPpi,\r
1210 PortNum,\r
1211 EfiUsbPortResetChange\r
1212 );\r
1213\r
4b1bf81c 1214 UsbHcPpi->ClearRootHubPortFeature (\r
1215 PeiServices,\r
1216 UsbHcPpi,\r
1217 PortNum,\r
1218 EfiUsbPortConnectChange\r
1219 );\r
d1102dba 1220\r
4b1bf81c 1221 //\r
1222 // Set port enable\r
1223 //\r
1224 UsbHcPpi->SetRootHubPortFeature(\r
1225 PeiServices,\r
1226 UsbHcPpi,\r
1227 PortNum,\r
1228 EfiUsbPortEnable\r
1229 );\r
d1102dba 1230\r
4b1bf81c 1231 UsbHcPpi->ClearRootHubPortFeature (\r
1232 PeiServices,\r
1233 UsbHcPpi,\r
1234 PortNum,\r
1235 EfiUsbPortEnableChange\r
1236 );\r
d1102dba 1237\r
4b1bf81c 1238 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);\r
1239 }\r
1240 return;\r
1241}\r
1242\r
1243\r