]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
Roll back r12434.
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusPei / UsbPeim.c
CommitLineData
4b1bf81c 1/** @file\r
2The module to produce Usb Bus PPI.\r
3\r
2256f1f7 4Copyright (c) 2006 - 2010, 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
225\r
226\r
227 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;\r
228\r
229 for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {\r
230\r
231 Status = PeiHubGetPortStatus (\r
232 PeiServices,\r
233 UsbIoPpi,\r
234 (UINT8) (Index + 1),\r
235 (UINT32 *) &PortStatus\r
236 );\r
237\r
238 if (EFI_ERROR (Status)) {\r
239 continue;\r
240 }\r
241\r
242 if (IsPortConnectChange (PortStatus.PortChangeStatus)) {\r
243 PeiHubClearPortFeature (\r
244 PeiServices,\r
245 UsbIoPpi,\r
246 (UINT8) (Index + 1),\r
247 EfiUsbPortConnectChange\r
248 );\r
249\r
250 MicroSecondDelay (100 * 1000);\r
251\r
252 if (IsPortConnect (PortStatus.PortStatus)) {\r
253\r
254 PeiHubGetPortStatus (\r
255 PeiServices,\r
256 UsbIoPpi,\r
257 (UINT8) (Index + 1),\r
258 (UINT32 *) &PortStatus\r
259 );\r
260\r
261 //\r
262 // Begin to deal with the new device\r
263 //\r
264 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;\r
265 Status = PeiServicesAllocatePages (\r
266 EfiBootServicesCode,\r
267 MemPages,\r
268 &AllocateAddress\r
269 );\r
270 if (EFI_ERROR (Status)) {\r
271 return EFI_OUT_OF_RESOURCES;\r
272 }\r
273\r
274 NewPeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);\r
275 ZeroMem (NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));\r
276\r
277 NewPeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;\r
278 NewPeiUsbDevice->DeviceAddress = 0;\r
279 NewPeiUsbDevice->MaxPacketSize0 = 8;\r
280 NewPeiUsbDevice->DataToggle = 0;\r
281 CopyMem (\r
282 &(NewPeiUsbDevice->UsbIoPpi),\r
283 &mUsbIoPpi,\r
284 sizeof (PEI_USB_IO_PPI)\r
285 );\r
286 CopyMem (\r
287 &(NewPeiUsbDevice->UsbIoPpiList),\r
288 &mUsbIoPpiList,\r
289 sizeof (EFI_PEI_PPI_DESCRIPTOR)\r
290 );\r
291 NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;\r
292 NewPeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;\r
293 NewPeiUsbDevice->UsbHcPpi = PeiUsbDevice->UsbHcPpi;\r
294 NewPeiUsbDevice->Usb2HcPpi = PeiUsbDevice->Usb2HcPpi;\r
295 NewPeiUsbDevice->IsHub = 0x0;\r
296 NewPeiUsbDevice->DownStreamPortNo = 0x0;\r
297\r
298 PeiResetHubPort (PeiServices, UsbIoPpi, (UINT8)(Index + 1));\r
299\r
300 PeiHubGetPortStatus (\r
301 PeiServices,\r
302 UsbIoPpi,\r
303 (UINT8) (Index + 1),\r
304 (UINT32 *) &PortStatus\r
305 );\r
306\r
307 NewPeiUsbDevice->DeviceSpeed = (UINT8)IsPortLowSpeedDeviceAttached (PortStatus.PortStatus);\r
308\r
309 if(NewPeiUsbDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {\r
2256f1f7 310 if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_HIGH) {\r
311 NewPeiUsbDevice->Translator.TranslatorPortNumber = (UINT8)Index;\r
312 NewPeiUsbDevice->Translator.TranslatorHubAddress = *CurrentAddress;\r
313 } else {\r
314 CopyMem(&(NewPeiUsbDevice->Translator), &(PeiUsbDevice->Translator), sizeof(EFI_USB2_HC_TRANSACTION_TRANSLATOR));\r
4b1bf81c 315 }\r
2256f1f7 316 }\r
4b1bf81c 317\r
318 //\r
319 // Configure that Usb Device\r
320 //\r
321 Status = PeiConfigureUsbDevice (\r
322 PeiServices,\r
323 NewPeiUsbDevice,\r
324 (UINT8) (Index + 1),\r
325 CurrentAddress\r
326 );\r
327\r
328 if (EFI_ERROR (Status)) {\r
329 continue;\r
330 }\r
331\r
332 Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);\r
333\r
334 if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {\r
335 NewPeiUsbDevice->IsHub = 0x1;\r
336\r
337 Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);\r
338 if (EFI_ERROR (Status)) {\r
339 return Status;\r
340 }\r
341\r
342 PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);\r
343 }\r
344 }\r
345\r
346 }\r
347 }\r
348\r
349\r
350 return EFI_SUCCESS;\r
351}\r
352\r
353/**\r
354 The enumeration routine to detect device change.\r
355 \r
356 @param PeiServices Describes the list of possible PEI Services.\r
357 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.\r
358 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.\r
359\r
360 @retval EFI_SUCCESS The usb is enumerated successfully.\r
361 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
362 @retval Others Other failure occurs.\r
363\r
364**/\r
365EFI_STATUS\r
366PeiUsbEnumeration (\r
367 IN EFI_PEI_SERVICES **PeiServices,\r
368 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,\r
369 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi\r
370 )\r
371{\r
372 UINT8 NumOfRootPort;\r
373 EFI_STATUS Status;\r
374 UINT8 Index;\r
375 EFI_USB_PORT_STATUS PortStatus;\r
376 PEI_USB_DEVICE *PeiUsbDevice;\r
377 UINTN MemPages;\r
378 EFI_PHYSICAL_ADDRESS AllocateAddress;\r
379 UINT8 CurrentAddress;\r
380\r
381\r
382 CurrentAddress = 0;\r
2256f1f7 383 if (Usb2HcPpi != NULL){\r
4b1bf81c 384 Usb2HcPpi->GetRootHubPortNumber (\r
385 PeiServices,\r
386 Usb2HcPpi,\r
387 (UINT8 *) &NumOfRootPort\r
388 ); \r
2256f1f7 389 } else {\r
4b1bf81c 390 UsbHcPpi->GetRootHubPortNumber (\r
391 PeiServices,\r
392 UsbHcPpi,\r
393 (UINT8 *) &NumOfRootPort\r
394 );\r
395 }\r
396\r
397 for (Index = 0; Index < NumOfRootPort; Index++) {\r
398 //\r
399 // First get root port status to detect changes happen\r
400 //\r
401 if (Usb2HcPpi != NULL) {\r
402 Usb2HcPpi->GetRootHubPortStatus (\r
403 PeiServices,\r
404 Usb2HcPpi,\r
405 (UINT8) Index,\r
406 &PortStatus\r
407 ); \r
408 } else {\r
409 UsbHcPpi->GetRootHubPortStatus (\r
410 PeiServices,\r
411 UsbHcPpi,\r
412 (UINT8) Index,\r
413 &PortStatus\r
414 );\r
415 }\r
416 DEBUG ((EFI_D_INFO, "USB Status --- ConnectChange[%04x] Status[%04x]\n", PortStatus.PortChangeStatus, PortStatus.PortStatus));\r
417 if (IsPortConnectChange (PortStatus.PortChangeStatus)) {\r
418 //\r
419 // Changes happen, first clear this change status\r
420 //\r
421 if (Usb2HcPpi != NULL) {\r
422 Usb2HcPpi->ClearRootHubPortFeature (\r
423 PeiServices,\r
424 Usb2HcPpi,\r
425 (UINT8) Index,\r
426 EfiUsbPortConnectChange\r
427 ); \r
428 } else {\r
429 UsbHcPpi->ClearRootHubPortFeature (\r
430 PeiServices,\r
431 UsbHcPpi,\r
432 (UINT8) Index,\r
433 EfiUsbPortConnectChange\r
434 );\r
435 }\r
436 MicroSecondDelay (100 * 1000);\r
437\r
438 if (IsPortConnect (PortStatus.PortStatus)) {\r
439 if (Usb2HcPpi != NULL) {\r
440 Usb2HcPpi->GetRootHubPortStatus (\r
441 PeiServices,\r
442 Usb2HcPpi,\r
443 (UINT8) Index,\r
444 &PortStatus\r
445 );\r
446 } else {\r
447 UsbHcPpi->GetRootHubPortStatus (\r
448 PeiServices,\r
449 UsbHcPpi,\r
450 (UINT8) Index,\r
451 &PortStatus\r
452 );\r
453 }\r
454\r
455 //\r
456 // Connect change happen\r
457 //\r
458 MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;\r
459 Status = PeiServicesAllocatePages (\r
460 EfiBootServicesCode,\r
461 MemPages,\r
462 &AllocateAddress\r
463 );\r
464 if (EFI_ERROR (Status)) {\r
465 return EFI_OUT_OF_RESOURCES;\r
466 }\r
467\r
468 PeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);\r
469 ZeroMem (PeiUsbDevice, sizeof (PEI_USB_DEVICE));\r
470\r
471 PeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;\r
472 PeiUsbDevice->DeviceAddress = 0;\r
473 PeiUsbDevice->MaxPacketSize0 = 8;\r
474 PeiUsbDevice->DataToggle = 0;\r
475 CopyMem (\r
476 &(PeiUsbDevice->UsbIoPpi),\r
477 &mUsbIoPpi,\r
478 sizeof (PEI_USB_IO_PPI)\r
479 );\r
480 CopyMem (\r
481 &(PeiUsbDevice->UsbIoPpiList),\r
482 &mUsbIoPpiList,\r
483 sizeof (EFI_PEI_PPI_DESCRIPTOR)\r
484 );\r
485 PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;\r
486 PeiUsbDevice->AllocateAddress = (UINTN) AllocateAddress;\r
487 PeiUsbDevice->UsbHcPpi = UsbHcPpi;\r
488 PeiUsbDevice->Usb2HcPpi = Usb2HcPpi;\r
489 PeiUsbDevice->IsHub = 0x0;\r
490 PeiUsbDevice->DownStreamPortNo = 0x0;\r
491\r
492 ResetRootPort (\r
493 PeiServices,\r
494 PeiUsbDevice->UsbHcPpi,\r
495 PeiUsbDevice->Usb2HcPpi,\r
496 Index,\r
497 0\r
498 );\r
499\r
500 if (Usb2HcPpi != NULL) {\r
501 Usb2HcPpi->GetRootHubPortStatus (\r
502 PeiServices,\r
503 Usb2HcPpi,\r
504 (UINT8) Index,\r
505 &PortStatus\r
506 );\r
507 } else {\r
508 UsbHcPpi->GetRootHubPortStatus (\r
509 PeiServices,\r
510 UsbHcPpi,\r
511 (UINT8) Index,\r
512 &PortStatus\r
513 );\r
514 }\r
515\r
516 PeiUsbDevice->DeviceSpeed = (UINT8)IsPortLowSpeedDeviceAttached (PortStatus.PortStatus);\r
517 DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));\r
518\r
519 //\r
520 // Configure that Usb Device\r
521 //\r
522 Status = PeiConfigureUsbDevice (\r
523 PeiServices,\r
524 PeiUsbDevice,\r
525 Index,\r
526 &CurrentAddress\r
527 );\r
528\r
529 if (EFI_ERROR (Status)) {\r
530 continue;\r
531 }\r
532 DEBUG ((EFI_D_INFO, "PeiConfigureUsbDevice Success\n"));\r
533\r
534 Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);\r
535\r
536 if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {\r
537 PeiUsbDevice->IsHub = 0x1;\r
538\r
539 Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);\r
540 if (EFI_ERROR (Status)) {\r
541 return Status;\r
542 }\r
543\r
544 PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);\r
545 }\r
546 } else {\r
547 //\r
548 // Disconnect change happen, currently we don't support\r
549 //\r
550 }\r
551 }\r
552 }\r
553\r
554 return EFI_SUCCESS;\r
555}\r
556\r
557/**\r
558 Configure new detected usb device.\r
559 \r
560 @param PeiServices Describes the list of possible PEI Services.\r
561 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
562 @param Port The port to be configured.\r
563 @param DeviceAddress The device address to be configured.\r
564\r
565 @retval EFI_SUCCESS The new detected usb device is configured successfully.\r
566 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
567 @retval Others Other failure occurs.\r
568\r
569**/\r
570EFI_STATUS\r
571PeiConfigureUsbDevice (\r
572 IN EFI_PEI_SERVICES **PeiServices,\r
573 IN PEI_USB_DEVICE *PeiUsbDevice,\r
574 IN UINT8 Port,\r
575 IN OUT UINT8 *DeviceAddress\r
576 )\r
577{\r
578 EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;\r
579 EFI_STATUS Status;\r
580 PEI_USB_IO_PPI *UsbIoPpi;\r
581 UINT8 Retry;\r
582\r
583 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;\r
584 Status = EFI_SUCCESS;\r
585 ZeroMem (&DeviceDescriptor, sizeof (EFI_USB_DEVICE_DESCRIPTOR));\r
586 //\r
587 // Get USB device descriptor\r
588 //\r
589\r
590 for (Retry = 0; Retry < 3; Retry ++) {\r
591\r
592 PeiUsbDevice->MaxPacketSize0 = 8;\r
593\r
594 Status = PeiUsbGetDescriptor (\r
595 PeiServices,\r
596 UsbIoPpi,\r
597 (USB_DT_DEVICE << 8),\r
598 0,\r
599 8,\r
600 &DeviceDescriptor\r
601 );\r
602\r
603 if (!EFI_ERROR (Status)) {\r
604 DEBUG ((EFI_D_INFO, "PeiUsbGet Device Descriptor the %d time Sucess\n", Retry));\r
605 break;\r
606 }\r
607 }\r
608\r
609 if (Retry == 3) {\r
610 DEBUG ((EFI_D_ERROR, "PeiUsbGet Device Descriptor fail\n", Retry));\r
611 return Status;\r
612 }\r
613\r
614 PeiUsbDevice->MaxPacketSize0 = DeviceDescriptor.MaxPacketSize0;\r
615\r
616 (*DeviceAddress) ++;\r
617\r
618 Status = PeiUsbSetDeviceAddress (\r
619 PeiServices,\r
620 UsbIoPpi,\r
621 *DeviceAddress\r
622 );\r
623\r
624 if (EFI_ERROR (Status)) {\r
625 DEBUG ((EFI_D_ERROR, "PeiUsbSetDeviceAddress Failed\n"));\r
626 return Status;\r
627 }\r
628\r
629 PeiUsbDevice->DeviceAddress = *DeviceAddress;\r
630\r
631 //\r
632 // Get whole USB device descriptor\r
633 //\r
634 Status = PeiUsbGetDescriptor (\r
635 PeiServices,\r
636 UsbIoPpi,\r
637 (USB_DT_DEVICE << 8),\r
638 0,\r
639 (UINT16) sizeof (EFI_USB_DEVICE_DESCRIPTOR),\r
640 &DeviceDescriptor\r
641 );\r
642\r
643 if (EFI_ERROR (Status)) {\r
644 DEBUG ((EFI_D_ERROR, "PeiUsbGetDescriptor First Failed\n"));\r
645 return Status;\r
646 }\r
647 //\r
648 // Get its default configuration and its first interface\r
649 //\r
650 Status = PeiUsbGetAllConfiguration (\r
651 PeiServices,\r
652 PeiUsbDevice\r
653 );\r
654\r
655 if (EFI_ERROR (Status)) {\r
656 return Status;\r
657 }\r
658\r
659 Status = PeiUsbSetConfiguration (\r
660 PeiServices,\r
661 UsbIoPpi\r
662 );\r
663\r
664 if (EFI_ERROR (Status)) {\r
665 return Status;\r
666 }\r
667\r
668 return EFI_SUCCESS;\r
669}\r
670\r
671/**\r
672 Get all configurations from a detected usb device.\r
673 \r
674 @param PeiServices Describes the list of possible PEI Services.\r
675 @param PeiUsbDevice The pointer of PEI_USB_DEVICE instance.\r
676\r
677 @retval EFI_SUCCESS The new detected usb device is configured successfully.\r
678 @retval EFI_OUT_OF_RESOURCES Can't allocate memory resource.\r
679 @retval Others Other failure occurs.\r
680\r
681**/\r
682EFI_STATUS\r
683PeiUsbGetAllConfiguration (\r
684 IN EFI_PEI_SERVICES **PeiServices,\r
685 IN PEI_USB_DEVICE *PeiUsbDevice\r
686 )\r
687{\r
688 EFI_STATUS Status;\r
689 EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc;\r
690 PEI_USB_IO_PPI *UsbIoPpi;\r
691 UINT16 ConfigDescLength;\r
692 UINT8 *Ptr;\r
693 UINTN SkipBytes;\r
694 UINTN LengthLeft;\r
695 UINTN Index;\r
696 UINTN NumOfEndpoint;\r
697\r
698 UsbIoPpi = &PeiUsbDevice->UsbIoPpi;\r
699\r
700 //\r
701 // First get its 4-byte configuration descriptor\r
702 //\r
703 Status = PeiUsbGetDescriptor (\r
704 PeiServices,\r
705 UsbIoPpi,\r
706 (USB_DT_CONFIG << 8), // Value\r
707 0, // Index\r
708 4, // Length\r
709 PeiUsbDevice->ConfigurationData\r
710 );\r
711\r
712 if (EFI_ERROR (Status)) {\r
713 DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor First Failed\n"));\r
714 return Status;\r
715 }\r
716\r
717 ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) PeiUsbDevice->ConfigurationData;\r
718 ConfigDescLength = ConfigDesc->TotalLength;\r
719\r
720 //\r
721 // Then we get the total descriptors for this configuration\r
722 //\r
723 Status = PeiUsbGetDescriptor (\r
724 PeiServices,\r
725 UsbIoPpi,\r
726 (USB_DT_CONFIG << 8),\r
727 0,\r
728 ConfigDescLength,\r
729 PeiUsbDevice->ConfigurationData\r
730 );\r
731\r
732 if (EFI_ERROR (Status)) {\r
733 DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor all Failed\n"));\r
734 return Status;\r
735 }\r
736 //\r
737 // Parse this configuration descriptor\r
738 // First get the current config descriptor;\r
739 //\r
740 Status = GetExpectedDescriptor (\r
741 PeiUsbDevice->ConfigurationData,\r
742 ConfigDescLength,\r
743 USB_DT_CONFIG,\r
744 (UINT8) sizeof (EFI_USB_CONFIG_DESCRIPTOR),\r
745 &SkipBytes\r
746 );\r
747\r
748 if (EFI_ERROR (Status)) {\r
749 return Status;\r
750 }\r
751\r
752 Ptr = PeiUsbDevice->ConfigurationData + SkipBytes;\r
753 PeiUsbDevice->ConfigDesc = (EFI_USB_CONFIG_DESCRIPTOR *) Ptr;\r
754\r
755 Ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR);\r
756 LengthLeft = ConfigDescLength - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR);\r
757\r
758 //\r
759 // Get the first interface descriptor\r
760 //\r
761 Status = GetExpectedDescriptor (\r
762 Ptr,\r
763 LengthLeft,\r
764 USB_DT_INTERFACE,\r
765 (UINT8) sizeof (EFI_USB_INTERFACE_DESCRIPTOR),\r
766 &SkipBytes\r
767 );\r
768\r
769 if (EFI_ERROR (Status)) {\r
770 return Status;\r
771 }\r
772\r
773 Ptr += SkipBytes;\r
774 PeiUsbDevice->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;\r
775\r
776 Ptr += sizeof (EFI_USB_INTERFACE_DESCRIPTOR);\r
777 LengthLeft -= SkipBytes;\r
778 LengthLeft -= sizeof (EFI_USB_INTERFACE_DESCRIPTOR);\r
779\r
780 //\r
781 // Parse all the endpoint descriptor within this interface\r
782 //\r
783 NumOfEndpoint = PeiUsbDevice->InterfaceDesc->NumEndpoints;\r
784 ASSERT (NumOfEndpoint <= MAX_ENDPOINT);\r
785\r
786 for (Index = 0; Index < NumOfEndpoint; Index++) {\r
787 //\r
788 // Get the endpoint descriptor\r
789 //\r
790 Status = GetExpectedDescriptor (\r
791 Ptr,\r
792 LengthLeft,\r
793 USB_DT_ENDPOINT,\r
794 (UINT8) sizeof (EFI_USB_ENDPOINT_DESCRIPTOR),\r
795 &SkipBytes\r
796 );\r
797\r
798 if (EFI_ERROR (Status)) {\r
799 return Status;\r
800 }\r
801\r
802 Ptr += SkipBytes;\r
803 PeiUsbDevice->EndpointDesc[Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;\r
804\r
805 Ptr += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);\r
806 LengthLeft -= SkipBytes;\r
807 LengthLeft -= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);\r
808 }\r
809\r
810 return EFI_SUCCESS;\r
811}\r
812\r
813/**\r
814 Get the start position of next wanted descriptor.\r
815 \r
816 @param Buffer Buffer containing data to parse.\r
817 @param Length Buffer length.\r
818 @param DescType Descriptor type.\r
819 @param DescLength Descriptor length.\r
820 @param ParsedBytes Bytes has been parsed.\r
821\r
822 @retval EFI_SUCCESS Get wanted descriptor successfully.\r
823 @retval EFI_DEVICE_ERROR Error occurred.\r
824\r
825**/\r
826EFI_STATUS\r
827GetExpectedDescriptor (\r
828 IN UINT8 *Buffer,\r
829 IN UINTN Length,\r
830 IN UINT8 DescType,\r
831 IN UINT8 DescLength,\r
832 OUT UINTN *ParsedBytes\r
833 )\r
834{\r
835 UINT16 DescriptorHeader;\r
836 UINT8 Len;\r
837 UINT8 *Ptr;\r
838 UINTN Parsed;\r
839\r
840 Parsed = 0;\r
841 Ptr = Buffer;\r
842\r
843 while (TRUE) {\r
844 //\r
845 // Buffer length should not less than Desc length\r
846 //\r
847 if (Length < DescLength) {\r
848 return EFI_DEVICE_ERROR;\r
849 }\r
850\r
851 DescriptorHeader = (UINT16) (*Ptr + ((*(Ptr + 1)) << 8));\r
852\r
853 Len = Buffer[0];\r
854\r
855 //\r
856 // Check to see if it is a start of expected descriptor\r
857 //\r
858 if (DescriptorHeader == ((DescType << 8) | DescLength)) {\r
859 break;\r
860 }\r
861\r
862 if ((UINT8) (DescriptorHeader >> 8) == DescType) {\r
863 if (Len > DescLength) {\r
864 return EFI_DEVICE_ERROR;\r
865 }\r
866 }\r
867 //\r
868 // Descriptor length should be at least 2\r
869 // and should not exceed the buffer length\r
870 //\r
871 if (Len < 2) {\r
872 return EFI_DEVICE_ERROR;\r
873 }\r
874\r
875 if (Len > Length) {\r
876 return EFI_DEVICE_ERROR;\r
877 }\r
878 //\r
879 // Skip this mismatch descriptor\r
880 //\r
881 Length -= Len;\r
882 Ptr += Len;\r
883 Parsed += Len;\r
884 }\r
885\r
886 *ParsedBytes = Parsed;\r
887\r
888 return EFI_SUCCESS;\r
889}\r
890\r
891/**\r
892 Send reset signal over the given root hub port.\r
893 \r
894 @param PeiServices Describes the list of possible PEI Services.\r
895 @param UsbHcPpi The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.\r
896 @param Usb2HcPpi The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.\r
897 @param PortNum The port to be reset.\r
898 @param RetryIndex The retry times.\r
899\r
900**/\r
901VOID\r
902ResetRootPort (\r
903 IN EFI_PEI_SERVICES **PeiServices,\r
904 IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,\r
905 IN PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi,\r
906 IN UINT8 PortNum,\r
907 IN UINT8 RetryIndex\r
908 )\r
909{\r
910 EFI_STATUS Status;\r
911\r
912\r
913 if (Usb2HcPpi != NULL) {\r
914 MicroSecondDelay (200 * 1000);\r
915 \r
916 //\r
917 // reset root port\r
918 //\r
919 Status = Usb2HcPpi->SetRootHubPortFeature (\r
920 PeiServices,\r
921 Usb2HcPpi,\r
922 PortNum,\r
923 EfiUsbPortReset\r
924 );\r
925 \r
926 if (EFI_ERROR (Status)) {\r
927 DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));\r
928 return;\r
929 }\r
930 \r
931 MicroSecondDelay (200 * 1000);\r
932 \r
933 //\r
934 // clear reset root port\r
935 //\r
936 Status = Usb2HcPpi->ClearRootHubPortFeature (\r
937 PeiServices,\r
938 Usb2HcPpi,\r
939 PortNum,\r
940 EfiUsbPortReset\r
941 );\r
942 \r
943 if (EFI_ERROR (Status)) {\r
944 DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));\r
945 return;\r
946 }\r
947 \r
948 MicroSecondDelay (1 * 1000);\r
949 \r
950 Usb2HcPpi->ClearRootHubPortFeature (\r
951 PeiServices,\r
952 Usb2HcPpi,\r
953 PortNum,\r
954 EfiUsbPortConnectChange\r
955 );\r
956 \r
957 //\r
958 // Set port enable\r
959 //\r
960 Usb2HcPpi->SetRootHubPortFeature(\r
961 PeiServices,\r
962 Usb2HcPpi,\r
963 PortNum,\r
964 EfiUsbPortEnable\r
965 );\r
966 \r
967 Usb2HcPpi->ClearRootHubPortFeature (\r
968 PeiServices,\r
969 Usb2HcPpi,\r
970 PortNum,\r
971 EfiUsbPortEnableChange\r
972 );\r
973 \r
974 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);\r
975 } else {\r
976 MicroSecondDelay (200 * 1000);\r
977 \r
978 //\r
979 // reset root port\r
980 //\r
981 Status = UsbHcPpi->SetRootHubPortFeature (\r
982 PeiServices,\r
983 UsbHcPpi,\r
984 PortNum,\r
985 EfiUsbPortReset\r
986 );\r
987 \r
988 if (EFI_ERROR (Status)) {\r
989 DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));\r
990 return;\r
991 }\r
992 \r
993 MicroSecondDelay (200 * 1000);\r
994 \r
995 //\r
996 // clear reset root port\r
997 //\r
998 Status = UsbHcPpi->ClearRootHubPortFeature (\r
999 PeiServices,\r
1000 UsbHcPpi,\r
1001 PortNum,\r
1002 EfiUsbPortReset\r
1003 );\r
1004 \r
1005 if (EFI_ERROR (Status)) {\r
1006 DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));\r
1007 return;\r
1008 }\r
1009 \r
1010 MicroSecondDelay (1 * 1000);\r
1011 \r
1012 UsbHcPpi->ClearRootHubPortFeature (\r
1013 PeiServices,\r
1014 UsbHcPpi,\r
1015 PortNum,\r
1016 EfiUsbPortConnectChange\r
1017 );\r
1018 \r
1019 //\r
1020 // Set port enable\r
1021 //\r
1022 UsbHcPpi->SetRootHubPortFeature(\r
1023 PeiServices,\r
1024 UsbHcPpi,\r
1025 PortNum,\r
1026 EfiUsbPortEnable\r
1027 );\r
1028 \r
1029 UsbHcPpi->ClearRootHubPortFeature (\r
1030 PeiServices,\r
1031 UsbHcPpi,\r
1032 PortNum,\r
1033 EfiUsbPortEnableChange\r
1034 );\r
1035 \r
1036 MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);\r
1037 }\r
1038 return;\r
1039}\r
1040\r
1041\r