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