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