]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
MdeModulePkg XhciPei/UsbBusPei: Enhance code for better device compatibility.
[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
04910ceb 723 MicroSecondDelay (USB_SET_DEVICE_ADDRESS_STALL);\r
4b1bf81c 724\r
725 PeiUsbDevice->DeviceAddress = *DeviceAddress;\r
726\r
727 //\r
728 // Get whole USB device descriptor\r
729 //\r
730 Status = PeiUsbGetDescriptor (\r
731 PeiServices,\r
732 UsbIoPpi,\r
733 (USB_DT_DEVICE << 8),\r
734 0,\r
735 (UINT16) sizeof (EFI_USB_DEVICE_DESCRIPTOR),\r
736 &DeviceDescriptor\r
737 );\r
738\r
739 if (EFI_ERROR (Status)) {\r
740 DEBUG ((EFI_D_ERROR, "PeiUsbGetDescriptor First Failed\n"));\r
741 return Status;\r
742 }\r
8a718ba9 743\r
4b1bf81c 744 //\r
745 // Get its default configuration and its first interface\r
746 //\r
747 Status = PeiUsbGetAllConfiguration (\r
748 PeiServices,\r
749 PeiUsbDevice\r
750 );\r
4b1bf81c 751 if (EFI_ERROR (Status)) {\r
752 return Status;\r
753 }\r
04910ceb 754 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL);\r
4b1bf81c 755\r
756 Status = PeiUsbSetConfiguration (\r
757 PeiServices,\r
758 UsbIoPpi\r
759 );\r
760\r
761 if (EFI_ERROR (Status)) {\r
762 return Status;\r
763 }\r
764\r
765 return EFI_SUCCESS;\r
766}\r
767\r
768/**\r
769 Get all configurations from a detected usb device.\r
770 \r
771 @param PeiServices Describes the list of possible PEI Services.\r
772 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
773\r
774 @retval EFI_SUCCESS The new detected usb device is configured successfully.\r
775 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
776 @retval Others Other failure occurs.\r
777\r
778**/\r
779EFI_STATUS\r
780PeiUsbGetAllConfiguration (\r
781 IN EFI_PEI_SERVICES **PeiServices,\r
782 IN PEI_USB_DEVICE *PeiUsbDevice\r
783 )\r
784{\r
785 EFI_STATUS Status;\r
786 EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc;\r
787 PEI_USB_IO_PPI *UsbIoPpi;\r
788 UINT16 ConfigDescLength;\r
789 UINT8 *Ptr;\r
790 UINTN SkipBytes;\r
791 UINTN LengthLeft;\r
8a718ba9 792 UINTN InterfaceIndex;\r
4b1bf81c 793 UINTN Index;\r
794 UINTN NumOfEndpoint;\r
795\r
796 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;\r
797\r
798 //\r
799 // First get its 4-byte configuration descriptor\r
800 //\r
801 Status = PeiUsbGetDescriptor (\r
802 PeiServices,\r
803 UsbIoPpi,\r
804 (USB_DT_CONFIG << 8), // Value\r
805 0, // Index\r
806 4, // Length\r
807 PeiUsbDevice->ConfigurationData\r
808 );\r
809\r
810 if (EFI_ERROR (Status)) {\r
811 DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor First Failed\n"));\r
812 return Status;\r
813 }\r
04910ceb 814 MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL);\r
4b1bf81c 815\r
816 ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) PeiUsbDevice->ConfigurationData;\r
817 ConfigDescLength = ConfigDesc->TotalLength;\r
818\r
819 //\r
820 // Then we get the total descriptors for this configuration\r
821 //\r
822 Status = PeiUsbGetDescriptor (\r
823 PeiServices,\r
824 UsbIoPpi,\r
825 (USB_DT_CONFIG << 8),\r
826 0,\r
827 ConfigDescLength,\r
828 PeiUsbDevice->ConfigurationData\r
829 );\r
830\r
831 if (EFI_ERROR (Status)) {\r
832 DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor all Failed\n"));\r
833 return Status;\r
834 }\r
835 //\r
836 // Parse this configuration descriptor\r
837 // First get the current config descriptor;\r
838 //\r
839 Status = GetExpectedDescriptor (\r
840 PeiUsbDevice->ConfigurationData,\r
841 ConfigDescLength,\r
842 USB_DT_CONFIG,\r
843 (UINT8) sizeof (EFI_USB_CONFIG_DESCRIPTOR),\r
844 &SkipBytes\r
845 );\r
846\r
847 if (EFI_ERROR (Status)) {\r
848 return Status;\r
849 }\r
850\r
851 Ptr = PeiUsbDevice->ConfigurationData + SkipBytes;\r
852 PeiUsbDevice->ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) Ptr;\r
853\r
854 Ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR);\r
855 LengthLeft = ConfigDescLength - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR);\r
856\r
8a718ba9 857 for (InterfaceIndex = 0; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {\r
4b1bf81c 858\r
4b1bf81c 859 //\r
8a718ba9 860 // Get the interface descriptor\r
4b1bf81c 861 //\r
862 Status = GetExpectedDescriptor (\r
863 Ptr,\r
864 LengthLeft,\r
8a718ba9
SZ
865 USB_DT_INTERFACE,\r
866 (UINT8) sizeof (EFI_USB_INTERFACE_DESCRIPTOR),\r
4b1bf81c 867 &SkipBytes\r
868 );\r
869\r
870 if (EFI_ERROR (Status)) {\r
871 return Status;\r
872 }\r
873\r
874 Ptr += SkipBytes;\r
8a718ba9
SZ
875 if (InterfaceIndex == 0) {\r
876 PeiUsbDevice->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;\r
877 }\r
878 PeiUsbDevice->InterfaceDescList[InterfaceIndex] = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;\r
4b1bf81c 879\r
8a718ba9 880 Ptr += sizeof (EFI_USB_INTERFACE_DESCRIPTOR);\r
4b1bf81c 881 LengthLeft -= SkipBytes;\r
8a718ba9
SZ
882 LengthLeft -= sizeof (EFI_USB_INTERFACE_DESCRIPTOR);\r
883\r
884 //\r
885 // Parse all the endpoint descriptor within this interface\r
886 //\r
887 NumOfEndpoint = PeiUsbDevice->InterfaceDescList[InterfaceIndex]->NumEndpoints;\r
888 ASSERT (NumOfEndpoint <= MAX_ENDPOINT);\r
889\r
890 for (Index = 0; Index < NumOfEndpoint; Index++) {\r
891 //\r
892 // Get the endpoint descriptor\r
893 //\r
894 Status = GetExpectedDescriptor (\r
895 Ptr,\r
896 LengthLeft,\r
897 USB_DT_ENDPOINT,\r
898 (UINT8) sizeof (EFI_USB_ENDPOINT_DESCRIPTOR),\r
899 &SkipBytes\r
900 );\r
901\r
902 if (EFI_ERROR (Status)) {\r
903 return Status;\r
904 }\r
905\r
906 Ptr += SkipBytes;\r
907 if (InterfaceIndex == 0) {\r
908 PeiUsbDevice->EndpointDesc[Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;\r
909 }\r
910 PeiUsbDevice->EndpointDescList[InterfaceIndex][Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;\r
911\r
912 Ptr += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);\r
913 LengthLeft -= SkipBytes;\r
914 LengthLeft -= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);\r
915 }\r
4b1bf81c 916 }\r
917\r
918 return EFI_SUCCESS;\r
919}\r
920\r
921/**\r
922 Get the start position of next wanted descriptor.\r
923 \r
924 @param Buffer Buffer containing data to parse.\r
925 @param Length Buffer length.\r
926 @param DescType Descriptor type.\r
927 @param DescLength Descriptor length.\r
928 @param ParsedBytes Bytes has been parsed.\r
929\r
930 @retval EFI_SUCCESS Get wanted descriptor successfully.\r
931 @retval EFI_DEVICE_ERROR Error occurred.\r
932\r
933**/\r
934EFI_STATUS\r
935GetExpectedDescriptor (\r
936 IN UINT8 *Buffer,\r
937 IN UINTN Length,\r
938 IN UINT8 DescType,\r
939 IN UINT8 DescLength,\r
940 OUT UINTN *ParsedBytes\r
941 )\r
942{\r
943 UINT16 DescriptorHeader;\r
944 UINT8 Len;\r
945 UINT8 *Ptr;\r
946 UINTN Parsed;\r
947\r
948 Parsed = 0;\r
949 Ptr = Buffer;\r
950\r
951 while (TRUE) {\r
952 //\r
953 // Buffer length should not less than Desc length\r
954 //\r
955 if (Length < DescLength) {\r
956 return EFI_DEVICE_ERROR;\r
957 }\r
958\r
959 DescriptorHeader = (UINT16) (*Ptr + ((*(Ptr + 1)) << 8));\r
960\r
961 Len = Buffer[0];\r
962\r
963 //\r
964 // Check to see if it is a start of expected descriptor\r
965 //\r
966 if (DescriptorHeader == ((DescType << 8) | DescLength)) {\r
967 break;\r
968 }\r
969\r
970 if ((UINT8) (DescriptorHeader >> 8) == DescType) {\r
971 if (Len > DescLength) {\r
972 return EFI_DEVICE_ERROR;\r
973 }\r
974 }\r
975 //\r
976 // Descriptor length should be at least 2\r
977 // and should not exceed the buffer length\r
978 //\r
979 if (Len < 2) {\r
980 return EFI_DEVICE_ERROR;\r
981 }\r
982\r
983 if (Len > Length) {\r
984 return EFI_DEVICE_ERROR;\r
985 }\r
986 //\r
987 // Skip this mismatch descriptor\r
988 //\r
989 Length -= Len;\r
990 Ptr += Len;\r
991 Parsed += Len;\r
992 }\r
993\r
994 *ParsedBytes = Parsed;\r
995\r
996 return EFI_SUCCESS;\r
997}\r
998\r
999/**\r
1000 Send reset signal over the given root hub port.\r
1001 \r
1002 @param PeiServices Describes the list of possible PEI Services.\r
1003 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.\r
1004 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.\r
1005 @param PortNum The port to be reset.\r
1006 @param RetryIndex The retry times.\r
1007\r
1008**/\r
1009VOID\r
1010ResetRootPort (\r
1011 IN EFI_PEI_SERVICES **PeiServices,\r
1012 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,\r
1013 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi,\r
1014 IN UINT8 PortNum,\r
1015 IN UINT8 RetryIndex\r
1016 )\r
1017{\r
1018 EFI_STATUS Status;\r
d987459f
SZ
1019 UINTN Index;\r
1020 EFI_USB_PORT_STATUS PortStatus;\r
4b1bf81c 1021\r
1022\r
1023 if (Usb2HcPpi != NULL) {\r
1024 MicroSecondDelay (200 * 1000);\r
1025 \r
1026 //\r
1027 // reset root port\r
1028 //\r
1029 Status = Usb2HcPpi->SetRootHubPortFeature (\r
1030 PeiServices,\r
1031 Usb2HcPpi,\r
1032 PortNum,\r
1033 EfiUsbPortReset\r
1034 );\r
1035 \r
1036 if (EFI_ERROR (Status)) {\r
1037 DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));\r
1038 return;\r
1039 }\r
1040 \r
d987459f
SZ
1041 //\r
1042 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec\r
1043 // section 7.1.7.5 for timing requirements.\r
1044 //\r
1045 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);\r
1046\r
4b1bf81c 1047 //\r
1048 // clear reset root port\r
1049 //\r
1050 Status = Usb2HcPpi->ClearRootHubPortFeature (\r
1051 PeiServices,\r
1052 Usb2HcPpi,\r
1053 PortNum,\r
1054 EfiUsbPortReset\r
1055 );\r
1056 \r
1057 if (EFI_ERROR (Status)) {\r
1058 DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));\r
1059 return;\r
1060 }\r
d987459f
SZ
1061\r
1062 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);\r
1063\r
1064 //\r
1065 // USB host controller won't clear the RESET bit until\r
1066 // reset is actually finished.\r
1067 //\r
1068 ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));\r
1069\r
1070 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
1071 Status = Usb2HcPpi->GetRootHubPortStatus (\r
1072 PeiServices,\r
1073 Usb2HcPpi,\r
1074 PortNum,\r
1075 &PortStatus\r
1076 ); \r
1077 if (EFI_ERROR (Status)) {\r
1078 return;\r
1079 }\r
1080\r
1081 if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {\r
1082 break;\r
1083 }\r
1084\r
1085 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);\r
1086 }\r
1087\r
1088 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {\r
1089 DEBUG ((EFI_D_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));\r
1090 return;\r
1091 }\r
1092\r
1093 Usb2HcPpi->ClearRootHubPortFeature (\r
1094 PeiServices,\r
1095 Usb2HcPpi,\r
1096 PortNum,\r
1097 EfiUsbPortResetChange\r
1098 );\r
1099\r
4b1bf81c 1100 Usb2HcPpi->ClearRootHubPortFeature (\r
1101 PeiServices,\r
1102 Usb2HcPpi,\r
1103 PortNum,\r
1104 EfiUsbPortConnectChange\r
1105 );\r
1106 \r
1107 //\r
1108 // Set port enable\r
1109 //\r
1110 Usb2HcPpi->SetRootHubPortFeature(\r
1111 PeiServices,\r
1112 Usb2HcPpi,\r
1113 PortNum,\r
1114 EfiUsbPortEnable\r
1115 );\r
1116 \r
1117 Usb2HcPpi->ClearRootHubPortFeature (\r
1118 PeiServices,\r
1119 Usb2HcPpi,\r
1120 PortNum,\r
1121 EfiUsbPortEnableChange\r
1122 );\r
1123 \r
1124 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);\r
1125 } else {\r
1126 MicroSecondDelay (200 * 1000);\r
1127 \r
1128 //\r
1129 // reset root port\r
1130 //\r
1131 Status = UsbHcPpi->SetRootHubPortFeature (\r
1132 PeiServices,\r
1133 UsbHcPpi,\r
1134 PortNum,\r
1135 EfiUsbPortReset\r
1136 );\r
1137 \r
1138 if (EFI_ERROR (Status)) {\r
1139 DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));\r
1140 return;\r
1141 }\r
1142 \r
d987459f
SZ
1143 //\r
1144 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec\r
1145 // section 7.1.7.5 for timing requirements.\r
1146 //\r
1147 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);\r
4b1bf81c 1148 \r
1149 //\r
1150 // clear reset root port\r
1151 //\r
1152 Status = UsbHcPpi->ClearRootHubPortFeature (\r
1153 PeiServices,\r
1154 UsbHcPpi,\r
1155 PortNum,\r
1156 EfiUsbPortReset\r
1157 );\r
1158 \r
1159 if (EFI_ERROR (Status)) {\r
1160 DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));\r
1161 return;\r
1162 }\r
1163 \r
d987459f
SZ
1164 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);\r
1165\r
1166 //\r
1167 // USB host controller won't clear the RESET bit until\r
1168 // reset is actually finished.\r
1169 //\r
1170 ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));\r
1171\r
1172 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
1173 Status = UsbHcPpi->GetRootHubPortStatus (\r
1174 PeiServices,\r
1175 UsbHcPpi,\r
1176 PortNum,\r
1177 &PortStatus\r
1178 ); \r
1179 if (EFI_ERROR (Status)) {\r
1180 return;\r
1181 }\r
1182\r
1183 if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {\r
1184 break;\r
1185 }\r
1186\r
1187 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);\r
1188 }\r
1189\r
1190 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {\r
1191 DEBUG ((EFI_D_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));\r
1192 return;\r
1193 }\r
1194\r
1195 UsbHcPpi->ClearRootHubPortFeature (\r
1196 PeiServices,\r
1197 UsbHcPpi,\r
1198 PortNum,\r
1199 EfiUsbPortResetChange\r
1200 );\r
1201\r
4b1bf81c 1202 UsbHcPpi->ClearRootHubPortFeature (\r
1203 PeiServices,\r
1204 UsbHcPpi,\r
1205 PortNum,\r
1206 EfiUsbPortConnectChange\r
1207 );\r
1208 \r
1209 //\r
1210 // Set port enable\r
1211 //\r
1212 UsbHcPpi->SetRootHubPortFeature(\r
1213 PeiServices,\r
1214 UsbHcPpi,\r
1215 PortNum,\r
1216 EfiUsbPortEnable\r
1217 );\r
1218 \r
1219 UsbHcPpi->ClearRootHubPortFeature (\r
1220 PeiServices,\r
1221 UsbHcPpi,\r
1222 PortNum,\r
1223 EfiUsbPortEnableChange\r
1224 );\r
1225 \r
1226 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);\r
1227 }\r
1228 return;\r
1229}\r
1230\r
1231\r