]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
MdeModulePkg: Remove the trailing space in three source files.
[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
4b1bf81c 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
d1102dba 40\r
4b1bf81c 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
d1102dba 59\r
4b1bf81c 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
d1102dba 80\r
4b1bf81c 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
d1102dba 97\r
4b1bf81c 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
d1102dba 119\r
4b1bf81c 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
d1102dba 145 // gPeiUsbHostControllerPpiGuid and gPeiUsb2HostControllerPpiGuid should not\r
4b1bf81c 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
d1102dba 179 );\r
4b1bf81c 180 if (EFI_ERROR (Status)) {\r
181 //\r
182 // No more host controller, break out\r
183 //\r
184 break;\r
d1102dba
LG
185 }\r
186 PeiUsbEnumeration ((EFI_PEI_SERVICES **) PeiServices, NULL, Usb2HcPpi);\r
4b1bf81c 187 Index++;\r
188 }\r
189 }\r
d1102dba 190\r
4b1bf81c 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
d1102dba 201\r
4b1bf81c 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
d1102dba 292 if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||\r
d987459f
SZ
293 ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0)) {\r
294 //\r
d1102dba 295 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.\r
d987459f
SZ
296 //\r
297 PeiResetHubPort (PeiServices, UsbIoPpi, (UINT8)(Index + 1));\r
d1102dba 298\r
d987459f
SZ
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
d1102dba 409\r
4b1bf81c 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
d1102dba 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
d1102dba 467 );\r
4b1bf81c 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
d1102dba 518 if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||\r
d987459f
SZ
519 ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0)) {\r
520 //\r
d1102dba 521 // If the port already has reset change flag and is connected and enabled, skip the port reset logic.\r
d987459f
SZ
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
d1102dba 553 );\r
d987459f
SZ
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
d1102dba 653\r
4b1bf81c 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
b9953b65 705 if ((DeviceDescriptor.BcdUSB >= 0x0300) && (DeviceDescriptor.MaxPacketSize0 == 9)) {\r
d987459f
SZ
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
d1102dba 770\r
4b1bf81c 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
70425456
RN
819 //\r
820 // Reject if TotalLength even cannot cover itself.\r
821 //\r
822 if (ConfigDescLength < OFFSET_OF (EFI_USB_CONFIG_DESCRIPTOR, TotalLength) + sizeof (ConfigDesc->TotalLength)) {\r
823 return EFI_DEVICE_ERROR;\r
824 }\r
825\r
826 //\r
827 // Reject if TotalLength exceeds the PeiUsbDevice->ConfigurationData.\r
828 //\r
829 if (ConfigDescLength > sizeof (PeiUsbDevice->ConfigurationData)) {\r
830 return EFI_DEVICE_ERROR;\r
831 }\r
832\r
4b1bf81c 833 //\r
834 // Then we get the total descriptors for this configuration\r
835 //\r
836 Status = PeiUsbGetDescriptor (\r
837 PeiServices,\r
838 UsbIoPpi,\r
839 (USB_DT_CONFIG << 8),\r
840 0,\r
841 ConfigDescLength,\r
842 PeiUsbDevice->ConfigurationData\r
843 );\r
844\r
845 if (EFI_ERROR (Status)) {\r
846 DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor all Failed\n"));\r
847 return Status;\r
848 }\r
849 //\r
850 // Parse this configuration descriptor\r
851 // First get the current config descriptor;\r
852 //\r
853 Status = GetExpectedDescriptor (\r
854 PeiUsbDevice->ConfigurationData,\r
855 ConfigDescLength,\r
856 USB_DT_CONFIG,\r
857 (UINT8) sizeof (EFI_USB_CONFIG_DESCRIPTOR),\r
858 &SkipBytes\r
859 );\r
860\r
861 if (EFI_ERROR (Status)) {\r
862 return Status;\r
863 }\r
864\r
865 Ptr = PeiUsbDevice->ConfigurationData + SkipBytes;\r
866 PeiUsbDevice->ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) Ptr;\r
867\r
868 Ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR);\r
869 LengthLeft = ConfigDescLength - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR);\r
870\r
8a718ba9 871 for (InterfaceIndex = 0; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {\r
4b1bf81c 872\r
4b1bf81c 873 //\r
8a718ba9 874 // Get the interface descriptor\r
4b1bf81c 875 //\r
876 Status = GetExpectedDescriptor (\r
877 Ptr,\r
878 LengthLeft,\r
8a718ba9
SZ
879 USB_DT_INTERFACE,\r
880 (UINT8) sizeof (EFI_USB_INTERFACE_DESCRIPTOR),\r
4b1bf81c 881 &SkipBytes\r
882 );\r
883\r
884 if (EFI_ERROR (Status)) {\r
885 return Status;\r
886 }\r
887\r
888 Ptr += SkipBytes;\r
8a718ba9
SZ
889 if (InterfaceIndex == 0) {\r
890 PeiUsbDevice->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;\r
891 }\r
892 PeiUsbDevice->InterfaceDescList[InterfaceIndex] = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;\r
4b1bf81c 893\r
8a718ba9 894 Ptr += sizeof (EFI_USB_INTERFACE_DESCRIPTOR);\r
4b1bf81c 895 LengthLeft -= SkipBytes;\r
8a718ba9
SZ
896 LengthLeft -= sizeof (EFI_USB_INTERFACE_DESCRIPTOR);\r
897\r
898 //\r
899 // Parse all the endpoint descriptor within this interface\r
900 //\r
901 NumOfEndpoint = PeiUsbDevice->InterfaceDescList[InterfaceIndex]->NumEndpoints;\r
902 ASSERT (NumOfEndpoint <= MAX_ENDPOINT);\r
903\r
904 for (Index = 0; Index < NumOfEndpoint; Index++) {\r
905 //\r
906 // Get the endpoint descriptor\r
907 //\r
908 Status = GetExpectedDescriptor (\r
909 Ptr,\r
910 LengthLeft,\r
911 USB_DT_ENDPOINT,\r
912 (UINT8) sizeof (EFI_USB_ENDPOINT_DESCRIPTOR),\r
913 &SkipBytes\r
914 );\r
915\r
916 if (EFI_ERROR (Status)) {\r
917 return Status;\r
918 }\r
919\r
920 Ptr += SkipBytes;\r
921 if (InterfaceIndex == 0) {\r
922 PeiUsbDevice->EndpointDesc[Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;\r
923 }\r
924 PeiUsbDevice->EndpointDescList[InterfaceIndex][Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;\r
925\r
926 Ptr += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);\r
927 LengthLeft -= SkipBytes;\r
928 LengthLeft -= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);\r
929 }\r
4b1bf81c 930 }\r
931\r
932 return EFI_SUCCESS;\r
933}\r
934\r
935/**\r
936 Get the start position of next wanted descriptor.\r
d1102dba 937\r
4b1bf81c 938 @param Buffer Buffer containing data to parse.\r
939 @param Length Buffer length.\r
940 @param DescType Descriptor type.\r
941 @param DescLength Descriptor length.\r
942 @param ParsedBytes Bytes has been parsed.\r
943\r
944 @retval EFI_SUCCESS Get wanted descriptor successfully.\r
945 @retval EFI_DEVICE_ERROR Error occurred.\r
946\r
947**/\r
948EFI_STATUS\r
949GetExpectedDescriptor (\r
950 IN UINT8 *Buffer,\r
951 IN UINTN Length,\r
952 IN UINT8 DescType,\r
953 IN UINT8 DescLength,\r
954 OUT UINTN *ParsedBytes\r
955 )\r
956{\r
c96de1db
RN
957 USB_DESC_HEAD *Head;\r
958 UINTN Offset;\r
4b1bf81c 959\r
c96de1db 960 //\r
dbeaf585 961 // Total length is too small that cannot hold the single descriptor header plus data.\r
c96de1db
RN
962 //\r
963 if (Length <= sizeof (USB_DESC_HEAD)) {\r
964 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, total length = %d!\n", Length));\r
965 return EFI_DEVICE_ERROR;\r
966 }\r
4b1bf81c 967\r
c96de1db
RN
968 //\r
969 // All the descriptor has a common LTV (Length, Type, Value)\r
970 // format. Skip the descriptor that isn't of this Type\r
971 //\r
972 Offset = 0;\r
973 Head = (USB_DESC_HEAD *)Buffer;\r
974 while (Offset < Length - sizeof (USB_DESC_HEAD)) {\r
4b1bf81c 975 //\r
c96de1db 976 // Above condition make sure Head->Len and Head->Type are safe to access\r
4b1bf81c 977 //\r
c96de1db 978 Head = (USB_DESC_HEAD *)&Buffer[Offset];\r
4b1bf81c 979\r
c96de1db
RN
980 if (Head->Len == 0) {\r
981 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = 0!\n"));\r
982 return EFI_DEVICE_ERROR;\r
4b1bf81c 983 }\r
984\r
4b1bf81c 985 //\r
c96de1db 986 // Make sure no overflow when adding Head->Len to Offset.\r
4b1bf81c 987 //\r
c96de1db
RN
988 if (Head->Len > MAX_UINTN - Offset) {\r
989 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = %d!\n", Head->Len));\r
4b1bf81c 990 return EFI_DEVICE_ERROR;\r
991 }\r
992\r
c96de1db
RN
993 if (Head->Type == DescType) {\r
994 break;\r
4b1bf81c 995 }\r
c96de1db
RN
996\r
997 Offset += Head->Len;\r
998 }\r
999\r
1000 //\r
1001 // Head->Len is invalid resulting data beyond boundary, or\r
1002 // Descriptor cannot be found: No such type.\r
1003 //\r
1004 if (Length < Offset) {\r
1005 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Offset/Len = %d/%d!\n", Offset, Length));\r
1006 return EFI_DEVICE_ERROR;\r
4b1bf81c 1007 }\r
1008\r
c96de1db
RN
1009 if ((Head->Type != DescType) || (Head->Len < DescLength)) {\r
1010 DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: descriptor cannot be found, Header(T/L) = %d/%d!\n", Head->Type, Head->Len));\r
1011 return EFI_DEVICE_ERROR;\r
1012 }\r
4b1bf81c 1013\r
c96de1db 1014 *ParsedBytes = Offset;\r
4b1bf81c 1015 return EFI_SUCCESS;\r
1016}\r
1017\r
1018/**\r
1019 Send reset signal over the given root hub port.\r
d1102dba 1020\r
4b1bf81c 1021 @param PeiServices Describes the list of possible PEI Services.\r
1022 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.\r
1023 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.\r
1024 @param PortNum The port to be reset.\r
1025 @param RetryIndex The retry times.\r
1026\r
1027**/\r
1028VOID\r
1029ResetRootPort (\r
1030 IN EFI_PEI_SERVICES **PeiServices,\r
1031 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,\r
1032 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi,\r
1033 IN UINT8 PortNum,\r
1034 IN UINT8 RetryIndex\r
1035 )\r
1036{\r
1037 EFI_STATUS Status;\r
d987459f
SZ
1038 UINTN Index;\r
1039 EFI_USB_PORT_STATUS PortStatus;\r
4b1bf81c 1040\r
1041\r
1042 if (Usb2HcPpi != NULL) {\r
1043 MicroSecondDelay (200 * 1000);\r
d1102dba 1044\r
4b1bf81c 1045 //\r
1046 // reset root port\r
1047 //\r
1048 Status = Usb2HcPpi->SetRootHubPortFeature (\r
1049 PeiServices,\r
1050 Usb2HcPpi,\r
1051 PortNum,\r
1052 EfiUsbPortReset\r
1053 );\r
d1102dba 1054\r
4b1bf81c 1055 if (EFI_ERROR (Status)) {\r
1056 DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));\r
1057 return;\r
1058 }\r
d1102dba 1059\r
d987459f
SZ
1060 //\r
1061 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec\r
1062 // section 7.1.7.5 for timing requirements.\r
1063 //\r
1064 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);\r
1065\r
4b1bf81c 1066 //\r
1067 // clear reset root port\r
1068 //\r
1069 Status = Usb2HcPpi->ClearRootHubPortFeature (\r
1070 PeiServices,\r
1071 Usb2HcPpi,\r
1072 PortNum,\r
1073 EfiUsbPortReset\r
1074 );\r
d1102dba 1075\r
4b1bf81c 1076 if (EFI_ERROR (Status)) {\r
1077 DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));\r
1078 return;\r
1079 }\r
d987459f
SZ
1080\r
1081 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);\r
1082\r
1083 //\r
1084 // USB host controller won't clear the RESET bit until\r
1085 // reset is actually finished.\r
1086 //\r
1087 ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));\r
1088\r
1089 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
1090 Status = Usb2HcPpi->GetRootHubPortStatus (\r
1091 PeiServices,\r
1092 Usb2HcPpi,\r
1093 PortNum,\r
1094 &PortStatus\r
d1102dba 1095 );\r
d987459f
SZ
1096 if (EFI_ERROR (Status)) {\r
1097 return;\r
1098 }\r
1099\r
1100 if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {\r
1101 break;\r
1102 }\r
1103\r
1104 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);\r
1105 }\r
1106\r
1107 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {\r
1108 DEBUG ((EFI_D_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));\r
1109 return;\r
1110 }\r
1111\r
1112 Usb2HcPpi->ClearRootHubPortFeature (\r
1113 PeiServices,\r
1114 Usb2HcPpi,\r
1115 PortNum,\r
1116 EfiUsbPortResetChange\r
1117 );\r
1118\r
4b1bf81c 1119 Usb2HcPpi->ClearRootHubPortFeature (\r
1120 PeiServices,\r
1121 Usb2HcPpi,\r
1122 PortNum,\r
1123 EfiUsbPortConnectChange\r
1124 );\r
d1102dba 1125\r
4b1bf81c 1126 //\r
1127 // Set port enable\r
1128 //\r
1129 Usb2HcPpi->SetRootHubPortFeature(\r
1130 PeiServices,\r
1131 Usb2HcPpi,\r
1132 PortNum,\r
1133 EfiUsbPortEnable\r
1134 );\r
d1102dba 1135\r
4b1bf81c 1136 Usb2HcPpi->ClearRootHubPortFeature (\r
1137 PeiServices,\r
1138 Usb2HcPpi,\r
1139 PortNum,\r
1140 EfiUsbPortEnableChange\r
1141 );\r
d1102dba 1142\r
4b1bf81c 1143 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);\r
1144 } else {\r
1145 MicroSecondDelay (200 * 1000);\r
d1102dba 1146\r
4b1bf81c 1147 //\r
1148 // reset root port\r
1149 //\r
1150 Status = UsbHcPpi->SetRootHubPortFeature (\r
1151 PeiServices,\r
1152 UsbHcPpi,\r
1153 PortNum,\r
1154 EfiUsbPortReset\r
1155 );\r
d1102dba 1156\r
4b1bf81c 1157 if (EFI_ERROR (Status)) {\r
1158 DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));\r
1159 return;\r
1160 }\r
d1102dba 1161\r
d987459f
SZ
1162 //\r
1163 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec\r
1164 // section 7.1.7.5 for timing requirements.\r
1165 //\r
1166 MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);\r
d1102dba 1167\r
4b1bf81c 1168 //\r
1169 // clear reset root port\r
1170 //\r
1171 Status = UsbHcPpi->ClearRootHubPortFeature (\r
1172 PeiServices,\r
1173 UsbHcPpi,\r
1174 PortNum,\r
1175 EfiUsbPortReset\r
1176 );\r
d1102dba 1177\r
4b1bf81c 1178 if (EFI_ERROR (Status)) {\r
1179 DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));\r
1180 return;\r
1181 }\r
d1102dba 1182\r
d987459f
SZ
1183 MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);\r
1184\r
1185 //\r
1186 // USB host controller won't clear the RESET bit until\r
1187 // reset is actually finished.\r
1188 //\r
1189 ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));\r
1190\r
1191 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
1192 Status = UsbHcPpi->GetRootHubPortStatus (\r
1193 PeiServices,\r
1194 UsbHcPpi,\r
1195 PortNum,\r
1196 &PortStatus\r
d1102dba 1197 );\r
d987459f
SZ
1198 if (EFI_ERROR (Status)) {\r
1199 return;\r
1200 }\r
1201\r
1202 if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {\r
1203 break;\r
1204 }\r
1205\r
1206 MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);\r
1207 }\r
1208\r
1209 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {\r
1210 DEBUG ((EFI_D_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));\r
1211 return;\r
1212 }\r
1213\r
1214 UsbHcPpi->ClearRootHubPortFeature (\r
1215 PeiServices,\r
1216 UsbHcPpi,\r
1217 PortNum,\r
1218 EfiUsbPortResetChange\r
1219 );\r
1220\r
4b1bf81c 1221 UsbHcPpi->ClearRootHubPortFeature (\r
1222 PeiServices,\r
1223 UsbHcPpi,\r
1224 PortNum,\r
1225 EfiUsbPortConnectChange\r
1226 );\r
d1102dba 1227\r
4b1bf81c 1228 //\r
1229 // Set port enable\r
1230 //\r
1231 UsbHcPpi->SetRootHubPortFeature(\r
1232 PeiServices,\r
1233 UsbHcPpi,\r
1234 PortNum,\r
1235 EfiUsbPortEnable\r
1236 );\r
d1102dba 1237\r
4b1bf81c 1238 UsbHcPpi->ClearRootHubPortFeature (\r
1239 PeiServices,\r
1240 UsbHcPpi,\r
1241 PortNum,\r
1242 EfiUsbPortEnableChange\r
1243 );\r
d1102dba 1244\r
4b1bf81c 1245 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);\r
1246 }\r
1247 return;\r
1248}\r
1249\r
1250\r