1 /** @file
2 PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid
3 which is used to enable recovery function from USB Drivers.
4 
5 Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
6 
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions
9 of the BSD License which accompanies this distribution.  The
10 full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12 
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 
16 **/
17 
18 #include "EhcPeim.h"
19 
20 //
21 // Two arrays used to translate the EHCI port state (change)
22 // to the UEFI protocol's port state (change).
23 //
24 USB_PORT_STATE_MAP  mUsbPortStateMap[] = {
25   {PORTSC_CONN,     USB_PORT_STAT_CONNECTION},
26   {PORTSC_ENABLED,  USB_PORT_STAT_ENABLE},
27   {PORTSC_SUSPEND,  USB_PORT_STAT_SUSPEND},
28   {PORTSC_OVERCUR,  USB_PORT_STAT_OVERCURRENT},
29   {PORTSC_RESET,    USB_PORT_STAT_RESET},
30   {PORTSC_POWER,    USB_PORT_STAT_POWER},
31   {PORTSC_OWNER,    USB_PORT_STAT_OWNER}
32 };
33 
34 USB_PORT_STATE_MAP  mUsbPortChangeMap[] = {
35   {PORTSC_CONN_CHANGE,    USB_PORT_STAT_C_CONNECTION},
36   {PORTSC_ENABLE_CHANGE,  USB_PORT_STAT_C_ENABLE},
37   {PORTSC_OVERCUR_CHANGE, USB_PORT_STAT_C_OVERCURRENT}
38 };
39 
40 /**
41   Read Ehc Operation register.
42 
43   @param  Ehc       The EHCI device.
44   @param  Offset    The operation register offset.
45 
46   @retval the register content read.
47 
48 **/
49 UINT32
EhcReadOpReg(IN PEI_USB2_HC_DEV * Ehc,IN UINT32 Offset)50 EhcReadOpReg (
51   IN  PEI_USB2_HC_DEV     *Ehc,
52   IN  UINT32              Offset
53   )
54 {
55   UINT32                  Data;
56 
57   ASSERT (Ehc->CapLen != 0);
58 
59   Data = MmioRead32 (Ehc->UsbHostControllerBaseAddress + Ehc->CapLen + Offset);
60 
61   return Data;
62 }
63 
64 /**
65   Write the data to the EHCI operation register.
66 
67   @param  Ehc       The EHCI device.
68   @param  Offset    EHCI operation register offset.
69   @param  Data      The data to write.
70 
71 **/
72 VOID
EhcWriteOpReg(IN PEI_USB2_HC_DEV * Ehc,IN UINT32 Offset,IN UINT32 Data)73 EhcWriteOpReg (
74   IN PEI_USB2_HC_DEV      *Ehc,
75   IN UINT32               Offset,
76   IN UINT32               Data
77   )
78 {
79 
80   ASSERT (Ehc->CapLen != 0);
81 
82   MmioWrite32(Ehc->UsbHostControllerBaseAddress + Ehc->CapLen + Offset, Data);
83 
84 }
85 
86 /**
87   Set one bit of the operational register while keeping other bits.
88 
89   @param  Ehc       The EHCI device.
90   @param  Offset    The offset of the operational register.
91   @param  Bit       The bit mask of the register to set.
92 
93 **/
94 VOID
EhcSetOpRegBit(IN PEI_USB2_HC_DEV * Ehc,IN UINT32 Offset,IN UINT32 Bit)95 EhcSetOpRegBit (
96   IN PEI_USB2_HC_DEV      *Ehc,
97   IN UINT32               Offset,
98   IN UINT32               Bit
99   )
100 {
101   UINT32                  Data;
102 
103   Data  = EhcReadOpReg (Ehc, Offset);
104   Data |= Bit;
105   EhcWriteOpReg (Ehc, Offset, Data);
106 }
107 
108 /**
109   Clear one bit of the operational register while keeping other bits.
110 
111   @param  Ehc       The EHCI device.
112   @param  Offset    The offset of the operational register.
113   @param  Bit       The bit mask of the register to clear.
114 
115 **/
116 VOID
EhcClearOpRegBit(IN PEI_USB2_HC_DEV * Ehc,IN UINT32 Offset,IN UINT32 Bit)117 EhcClearOpRegBit (
118   IN PEI_USB2_HC_DEV      *Ehc,
119   IN UINT32               Offset,
120   IN UINT32               Bit
121   )
122 {
123   UINT32                  Data;
124 
125   Data  = EhcReadOpReg (Ehc, Offset);
126   Data &= ~Bit;
127   EhcWriteOpReg (Ehc, Offset, Data);
128 }
129 
130 /**
131   Wait the operation register's bit as specified by Bit
132   to become set (or clear).
133 
134   @param  Ehc           The EHCI device.
135   @param  Offset        The offset of the operational register.
136   @param  Bit           The bit mask of the register to wait for.
137   @param  WaitToSet     Wait the bit to set or clear.
138   @param  Timeout       The time to wait before abort (in millisecond).
139 
140   @retval EFI_SUCCESS   The bit successfully changed by host controller.
141   @retval EFI_TIMEOUT   The time out occurred.
142 
143 **/
144 EFI_STATUS
EhcWaitOpRegBit(IN PEI_USB2_HC_DEV * Ehc,IN UINT32 Offset,IN UINT32 Bit,IN BOOLEAN WaitToSet,IN UINT32 Timeout)145 EhcWaitOpRegBit (
146   IN PEI_USB2_HC_DEV      *Ehc,
147   IN UINT32               Offset,
148   IN UINT32               Bit,
149   IN BOOLEAN              WaitToSet,
150   IN UINT32               Timeout
151   )
152 {
153   UINT32                  Index;
154 
155   for (Index = 0; Index < Timeout / EHC_SYNC_POLL_INTERVAL + 1; Index++) {
156     if (EHC_REG_BIT_IS_SET (Ehc, Offset, Bit) == WaitToSet) {
157       return EFI_SUCCESS;
158     }
159 
160     MicroSecondDelay (EHC_SYNC_POLL_INTERVAL);
161   }
162 
163   return EFI_TIMEOUT;
164 }
165 
166 /**
167   Read EHCI capability register.
168 
169   @param  Ehc       The EHCI device.
170   @param  Offset    Capability register address.
171 
172   @retval the register content read.
173 
174 **/
175 UINT32
EhcReadCapRegister(IN PEI_USB2_HC_DEV * Ehc,IN UINT32 Offset)176 EhcReadCapRegister (
177   IN  PEI_USB2_HC_DEV     *Ehc,
178   IN  UINT32              Offset
179   )
180 {
181   UINT32                  Data;
182 
183   Data = MmioRead32(Ehc->UsbHostControllerBaseAddress + Offset);
184 
185   return Data;
186 }
187 
188 /**
189   Set door bell and wait it to be ACKed by host controller.
190   This function is used to synchronize with the hardware.
191 
192   @param  Ehc       The EHCI device.
193   @param  Timeout   The time to wait before abort (in millisecond, ms).
194 
195   @retval EFI_TIMEOUT       Time out happened while waiting door bell to set.
196   @retval EFI_SUCCESS       Synchronized with the hardware.
197 
198 **/
199 EFI_STATUS
EhcSetAndWaitDoorBell(IN PEI_USB2_HC_DEV * Ehc,IN UINT32 Timeout)200 EhcSetAndWaitDoorBell (
201   IN  PEI_USB2_HC_DEV     *Ehc,
202   IN  UINT32              Timeout
203   )
204 {
205   EFI_STATUS              Status;
206   UINT32                  Data;
207 
208   EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_IAAD);
209 
210   Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_IAA, TRUE, Timeout);
211 
212   //
213   // ACK the IAA bit in USBSTS register. Make sure other
214   // interrupt bits are not ACKed. These bits are WC (Write Clean).
215   //
216   Data  = EhcReadOpReg (Ehc, EHC_USBSTS_OFFSET);
217   Data &= ~USBSTS_INTACK_MASK;
218   Data |= USBSTS_IAA;
219 
220   EhcWriteOpReg (Ehc, EHC_USBSTS_OFFSET, Data);
221 
222   return Status;
223 }
224 
225 /**
226   Clear all the interrutp status bits, these bits
227   are Write-Clean.
228 
229   @param  Ehc       The EHCI device.
230 
231 **/
232 VOID
EhcAckAllInterrupt(IN PEI_USB2_HC_DEV * Ehc)233 EhcAckAllInterrupt (
234   IN  PEI_USB2_HC_DEV         *Ehc
235   )
236 {
237   EhcWriteOpReg (Ehc, EHC_USBSTS_OFFSET, USBSTS_INTACK_MASK);
238 }
239 
240 /**
241   Enable the periodic schedule then wait EHC to
242   actually enable it.
243 
244   @param  Ehc       The EHCI device.
245   @param  Timeout   The time to wait before abort (in millisecond, ms).
246 
247   @retval EFI_TIMEOUT       Time out happened while enabling periodic schedule.
248   @retval EFI_SUCCESS       The periodical schedule is enabled.
249 
250 **/
251 EFI_STATUS
EhcEnablePeriodSchd(IN PEI_USB2_HC_DEV * Ehc,IN UINT32 Timeout)252 EhcEnablePeriodSchd (
253   IN PEI_USB2_HC_DEV      *Ehc,
254   IN UINT32               Timeout
255   )
256 {
257   EFI_STATUS              Status;
258 
259   EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_PERIOD);
260 
261   Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_PERIOD_ENABLED, TRUE, Timeout);
262   return Status;
263 }
264 
265 /**
266   Enable asynchrounous schedule.
267 
268   @param  Ehc       The EHCI device.
269   @param  Timeout   Time to wait before abort.
270 
271   @retval EFI_SUCCESS       The EHCI asynchronous schedule is enabled.
272   @retval Others            Failed to enable the asynchronous scheudle.
273 
274 **/
275 EFI_STATUS
EhcEnableAsyncSchd(IN PEI_USB2_HC_DEV * Ehc,IN UINT32 Timeout)276 EhcEnableAsyncSchd (
277   IN PEI_USB2_HC_DEV      *Ehc,
278   IN UINT32               Timeout
279   )
280 {
281   EFI_STATUS              Status;
282 
283   EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_ASYNC);
284 
285   Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_ASYNC_ENABLED, TRUE, Timeout);
286   return Status;
287 }
288 
289 /**
290   Check whether Ehc is halted.
291 
292   @param  Ehc       The EHCI device.
293 
294   @retval TRUE      The controller is halted.
295   @retval FALSE     The controller isn't halted.
296 
297 **/
298 BOOLEAN
EhcIsHalt(IN PEI_USB2_HC_DEV * Ehc)299 EhcIsHalt (
300   IN PEI_USB2_HC_DEV      *Ehc
301   )
302 {
303   return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT);
304 }
305 
306 /**
307   Check whether system error occurred.
308 
309   @param  Ehc       The EHCI device.
310 
311   @retval TRUE      System error happened.
312   @retval FALSE     No system error.
313 
314 **/
315 BOOLEAN
EhcIsSysError(IN PEI_USB2_HC_DEV * Ehc)316 EhcIsSysError (
317   IN PEI_USB2_HC_DEV      *Ehc
318   )
319 {
320   return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR);
321 }
322 
323 /**
324   Reset the host controller.
325 
326   @param  Ehc             The EHCI device.
327   @param  Timeout         Time to wait before abort (in millisecond, ms).
328 
329   @retval EFI_TIMEOUT     The transfer failed due to time out.
330   @retval Others          Failed to reset the host.
331 
332 **/
333 EFI_STATUS
EhcResetHC(IN PEI_USB2_HC_DEV * Ehc,IN UINT32 Timeout)334 EhcResetHC (
335   IN PEI_USB2_HC_DEV      *Ehc,
336   IN UINT32               Timeout
337   )
338 {
339   EFI_STATUS              Status;
340 
341   //
342   // Host can only be reset when it is halt. If not so, halt it
343   //
344   if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
345     Status = EhcHaltHC (Ehc, Timeout);
346 
347     if (EFI_ERROR (Status)) {
348       return Status;
349     }
350   }
351 
352   EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET);
353   Status = EhcWaitOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET, FALSE, Timeout);
354   return Status;
355 }
356 
357 /**
358   Halt the host controller.
359 
360   @param  Ehc             The EHCI device.
361   @param  Timeout         Time to wait before abort.
362 
363   @retval EFI_TIMEOUT     Failed to halt the controller before Timeout.
364   @retval EFI_SUCCESS     The EHCI is halt.
365 
366 **/
367 EFI_STATUS
EhcHaltHC(IN PEI_USB2_HC_DEV * Ehc,IN UINT32 Timeout)368 EhcHaltHC (
369   IN PEI_USB2_HC_DEV     *Ehc,
370   IN UINT32              Timeout
371   )
372 {
373   EFI_STATUS              Status;
374 
375   EhcClearOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
376   Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, TRUE, Timeout);
377   return Status;
378 }
379 
380 /**
381   Set the EHCI to run.
382 
383   @param  Ehc             The EHCI device.
384   @param  Timeout         Time to wait before abort.
385 
386   @retval EFI_SUCCESS     The EHCI is running.
387   @retval Others          Failed to set the EHCI to run.
388 
389 **/
390 EFI_STATUS
EhcRunHC(IN PEI_USB2_HC_DEV * Ehc,IN UINT32 Timeout)391 EhcRunHC (
392   IN PEI_USB2_HC_DEV      *Ehc,
393   IN UINT32               Timeout
394   )
395 {
396   EFI_STATUS              Status;
397 
398   EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
399   Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, FALSE, Timeout);
400   return Status;
401 }
402 
403 /**
404   Power On All EHCI Ports.
405 
406   @param  Ehc             The EHCI device.
407 
408 **/
409 VOID
EhcPowerOnAllPorts(IN PEI_USB2_HC_DEV * Ehc)410 EhcPowerOnAllPorts (
411   IN PEI_USB2_HC_DEV          *Ehc
412   )
413 {
414   UINT8     PortNumber;
415   UINT8     Index;
416   UINT32    RegVal;
417 
418   PortNumber = (UINT8)(Ehc->HcStructParams & HCSP_NPORTS);
419   for (Index = 0; Index < PortNumber; Index++) {
420     //
421     // Do not clear port status bits on initialization.  Otherwise devices will
422     // not enumerate properly at startup.
423     //
424     RegVal  = EhcReadOpReg(Ehc, EHC_PORT_STAT_OFFSET + 4 * Index);
425     RegVal &= ~PORTSC_CHANGE_MASK;
426     RegVal |= PORTSC_POWER;
427     EhcWriteOpReg (Ehc, EHC_PORT_STAT_OFFSET + 4 * Index, RegVal);
428   }
429 }
430 
431 /**
432   Initialize the HC hardware.
433   EHCI spec lists the five things to do to initialize the hardware.
434   1. Program CTRLDSSEGMENT.
435   2. Set USBINTR to enable interrupts.
436   3. Set periodic list base.
437   4. Set USBCMD, interrupt threshold, frame list size etc.
438   5. Write 1 to CONFIGFLAG to route all ports to EHCI.
439 
440   @param  Ehc             The EHCI device.
441 
442   @retval EFI_SUCCESS     The EHCI has come out of halt state.
443   @retval EFI_TIMEOUT     Time out happened.
444 
445 **/
446 EFI_STATUS
EhcInitHC(IN PEI_USB2_HC_DEV * Ehc)447 EhcInitHC (
448   IN PEI_USB2_HC_DEV      *Ehc
449   )
450 {
451   EFI_STATUS              Status;
452   EFI_PHYSICAL_ADDRESS        TempPtr;
453   UINTN               PageNumber;
454 
455   ASSERT (EhcIsHalt (Ehc));
456 
457   //
458   // Allocate the periodic frame and associated memeory
459   // management facilities if not already done.
460   //
461   if (Ehc->PeriodFrame != NULL) {
462     EhcFreeSched (Ehc);
463   }
464   PageNumber =  sizeof(PEI_URB)/PAGESIZE +1;
465   Status = PeiServicesAllocatePages (
466              EfiBootServicesCode,
467              PageNumber,
468              &TempPtr
469              );
470   Ehc->Urb = (PEI_URB *) ((UINTN) TempPtr);
471   if (Ehc->Urb  == NULL) {
472     return Status;
473   }
474 
475   EhcPowerOnAllPorts (Ehc);
476   MicroSecondDelay (EHC_ROOT_PORT_RECOVERY_STALL);
477 
478   Status = EhcInitSched (Ehc);
479 
480   if (EFI_ERROR (Status)) {
481     return Status;
482   }
483   //
484   // 1. Program the CTRLDSSEGMENT register with the high 32 bit addr
485   //
486   EhcWriteOpReg (Ehc, EHC_CTRLDSSEG_OFFSET, Ehc->High32bitAddr);
487 
488   //
489   // 2. Clear USBINTR to disable all the interrupt. UEFI works by polling
490   //
491   EhcWriteOpReg (Ehc, EHC_USBINTR_OFFSET, 0);
492 
493   //
494   // 3. Program periodic frame list, already done in EhcInitSched
495   // 4. Start the Host Controller
496   //
497   EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
498 
499   //
500   // 5. Set all ports routing to EHC
501   //
502   EhcSetOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);
503 
504   //
505   // Wait roothub port power stable
506   //
507   MicroSecondDelay (EHC_ROOT_PORT_RECOVERY_STALL);
508 
509   Status = EhcEnablePeriodSchd (Ehc, EHC_GENERIC_TIMEOUT);
510 
511   if (EFI_ERROR (Status)) {
512     return Status;
513   }
514 
515   Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIMEOUT);
516 
517   if (EFI_ERROR (Status)) {
518     return Status;
519   }
520 
521   return EFI_SUCCESS;
522 }
523 
524 /**
525   Submits bulk transfer to a bulk endpoint of a USB device.
526 
527   @param  PeiServices           The pointer of EFI_PEI_SERVICES.
528   @param  This                  The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
529   @param  DeviceAddress         Target device address.
530   @param  EndPointAddress       Endpoint number and its direction in bit 7.
531   @param  DeviceSpeed           Device speed, Low speed device doesn't support
532                                 bulk transfer.
533   @param  MaximumPacketLength   Maximum packet size the endpoint is capable of
534                                 sending or receiving.
535   @param  Data                  Array of pointers to the buffers of data to transmit
536                                 from or receive into.
537   @param  DataLength            The lenght of the data buffer.
538   @param  DataToggle            On input, the initial data toggle for the transfer;
539                                 On output, it is updated to to next data toggle to use of
540                                 the subsequent bulk transfer.
541   @param  TimeOut               Indicates the maximum time, in millisecond, which the
542                                 transfer is allowed to complete.
543                                 If Timeout is 0, then the caller must wait for the function
544                                 to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
545   @param  Translator            A pointr to the transaction translator data.
546   @param  TransferResult        A pointer to the detailed result information of the
547                                 bulk transfer.
548 
549   @retval EFI_SUCCESS           The transfer was completed successfully.
550   @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
551   @retval EFI_INVALID_PARAMETER Parameters are invalid.
552   @retval EFI_TIMEOUT           The transfer failed due to timeout.
553   @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.
554 
555 **/
556 EFI_STATUS
557 EFIAPI
EhcBulkTransfer(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB2_HOST_CONTROLLER_PPI * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN UINT8 DeviceSpeed,IN UINTN MaximumPacketLength,IN OUT VOID * Data[EFI_USB_MAX_BULK_BUFFER_NUM],IN OUT UINTN * DataLength,IN OUT UINT8 * DataToggle,IN UINTN TimeOut,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,OUT UINT32 * TransferResult)558 EhcBulkTransfer (
559   IN EFI_PEI_SERVICES                     **PeiServices,
560   IN PEI_USB2_HOST_CONTROLLER_PPI         *This,
561   IN  UINT8                               DeviceAddress,
562   IN  UINT8                               EndPointAddress,
563   IN  UINT8                               DeviceSpeed,
564   IN  UINTN                               MaximumPacketLength,
565   IN  OUT VOID                            *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
566   IN  OUT UINTN                           *DataLength,
567   IN  OUT UINT8                           *DataToggle,
568   IN  UINTN                               TimeOut,
569   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
570   OUT UINT32                              *TransferResult
571   )
572 {
573   PEI_USB2_HC_DEV         *Ehc;
574   PEI_URB                 *Urb;
575   EFI_STATUS              Status;
576 
577   //
578   // Validate the parameters
579   //
580   if ((DataLength == NULL) || (*DataLength == 0) ||
581       (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {
582     return EFI_INVALID_PARAMETER;
583   }
584 
585   if ((*DataToggle != 0) && (*DataToggle != 1)) {
586     return EFI_INVALID_PARAMETER;
587   }
588 
589   if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
590       ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
591       ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512))) {
592     return EFI_INVALID_PARAMETER;
593   }
594 
595   Ehc =PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS(This);
596   *TransferResult = EFI_USB_ERR_SYSTEM;
597   Status          = EFI_DEVICE_ERROR;
598 
599   if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
600     EhcAckAllInterrupt (Ehc);
601     goto ON_EXIT;
602   }
603 
604   EhcAckAllInterrupt (Ehc);
605 
606   //
607   // Create a new URB, insert it into the asynchronous
608   // schedule list, then poll the execution status.
609   //
610   Urb = EhcCreateUrb (
611           Ehc,
612           DeviceAddress,
613           EndPointAddress,
614           DeviceSpeed,
615           *DataToggle,
616           MaximumPacketLength,
617           Translator,
618           EHC_BULK_TRANSFER,
619           NULL,
620           Data[0],
621           *DataLength,
622           NULL,
623           NULL,
624           1
625           );
626 
627   if (Urb == NULL) {
628     Status = EFI_OUT_OF_RESOURCES;
629     goto ON_EXIT;
630   }
631 
632   EhcLinkQhToAsync (Ehc, Urb->Qh);
633   Status = EhcExecTransfer (Ehc, Urb, TimeOut);
634   EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
635 
636   *TransferResult = Urb->Result;
637   *DataLength     = Urb->Completed;
638   *DataToggle     = Urb->DataToggle;
639 
640   if (*TransferResult == EFI_USB_NOERROR) {
641     Status = EFI_SUCCESS;
642   }
643 
644   EhcAckAllInterrupt (Ehc);
645   EhcFreeUrb (Ehc, Urb);
646 
647 ON_EXIT:
648   return Status;
649 }
650 
651 /**
652   Retrieves the number of root hub ports.
653 
654   @param[in]  PeiServices   The pointer to the PEI Services Table.
655   @param[in]  This          The pointer to this instance of the
656                             PEI_USB2_HOST_CONTROLLER_PPI.
657   @param[out] PortNumber    The pointer to the number of the root hub ports.
658 
659   @retval EFI_SUCCESS           The port number was retrieved successfully.
660   @retval EFI_INVALID_PARAMETER PortNumber is NULL.
661 
662 **/
663 EFI_STATUS
664 EFIAPI
EhcGetRootHubPortNumber(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB2_HOST_CONTROLLER_PPI * This,OUT UINT8 * PortNumber)665 EhcGetRootHubPortNumber (
666   IN EFI_PEI_SERVICES                       **PeiServices,
667   IN PEI_USB2_HOST_CONTROLLER_PPI           *This,
668   OUT UINT8                                 *PortNumber
669   )
670 {
671 
672   PEI_USB2_HC_DEV             *EhcDev;
673   EhcDev = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
674 
675   if (PortNumber == NULL) {
676     return EFI_INVALID_PARAMETER;
677   }
678 
679   *PortNumber = (UINT8)(EhcDev->HcStructParams & HCSP_NPORTS);
680   return EFI_SUCCESS;
681 
682 }
683 
684 /**
685   Clears a feature for the specified root hub port.
686 
687   @param  PeiServices           The pointer of EFI_PEI_SERVICES.
688   @param  This                  The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
689   @param  PortNumber            Specifies the root hub port whose feature
690                                 is requested to be cleared.
691   @param  PortFeature           Indicates the feature selector associated with the
692                                 feature clear request.
693 
694   @retval EFI_SUCCESS            The feature specified by PortFeature was cleared
695                                  for the USB root hub port specified by PortNumber.
696   @retval EFI_INVALID_PARAMETER  PortNumber is invalid or PortFeature is invalid.
697 
698 **/
699 EFI_STATUS
700 EFIAPI
EhcClearRootHubPortFeature(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB2_HOST_CONTROLLER_PPI * This,IN UINT8 PortNumber,IN EFI_USB_PORT_FEATURE PortFeature)701 EhcClearRootHubPortFeature (
702   IN EFI_PEI_SERVICES                       **PeiServices,
703   IN PEI_USB2_HOST_CONTROLLER_PPI           *This,
704   IN  UINT8                 PortNumber,
705   IN  EFI_USB_PORT_FEATURE  PortFeature
706   )
707 {
708   PEI_USB2_HC_DEV         *Ehc;
709   UINT32                  Offset;
710   UINT32                  State;
711   UINT32                  TotalPort;
712   EFI_STATUS              Status;
713 
714   Ehc       = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
715   Status    = EFI_SUCCESS;
716 
717   TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
718 
719   if (PortNumber >= TotalPort) {
720     Status = EFI_INVALID_PARAMETER;
721     goto ON_EXIT;
722   }
723 
724   Offset  = EHC_PORT_STAT_OFFSET + (4 * PortNumber);
725   State   = EhcReadOpReg (Ehc, Offset);
726   State &= ~PORTSC_CHANGE_MASK;
727 
728   switch (PortFeature) {
729   case EfiUsbPortEnable:
730     //
731     // Clear PORT_ENABLE feature means disable port.
732     //
733     State &= ~PORTSC_ENABLED;
734     EhcWriteOpReg (Ehc, Offset, State);
735     break;
736 
737   case EfiUsbPortSuspend:
738     //
739     // A write of zero to this bit is ignored by the host
740     // controller. The host controller will unconditionally
741     // set this bit to a zero when:
742     //   1. software sets the Forct Port Resume bit to a zero from a one.
743     //   2. software sets the Port Reset bit to a one frome a zero.
744     //
745     State &= ~PORSTSC_RESUME;
746     EhcWriteOpReg (Ehc, Offset, State);
747     break;
748 
749   case EfiUsbPortReset:
750     //
751     // Clear PORT_RESET means clear the reset signal.
752     //
753     State &= ~PORTSC_RESET;
754     EhcWriteOpReg (Ehc, Offset, State);
755     break;
756 
757   case EfiUsbPortOwner:
758     //
759     // Clear port owner means this port owned by EHC
760     //
761     State &= ~PORTSC_OWNER;
762     EhcWriteOpReg (Ehc, Offset, State);
763     break;
764 
765   case EfiUsbPortConnectChange:
766     //
767     // Clear connect status change
768     //
769     State |= PORTSC_CONN_CHANGE;
770     EhcWriteOpReg (Ehc, Offset, State);
771     break;
772 
773   case EfiUsbPortEnableChange:
774     //
775     // Clear enable status change
776     //
777     State |= PORTSC_ENABLE_CHANGE;
778     EhcWriteOpReg (Ehc, Offset, State);
779     break;
780 
781   case EfiUsbPortOverCurrentChange:
782     //
783     // Clear PortOverCurrent change
784     //
785     State |= PORTSC_OVERCUR_CHANGE;
786     EhcWriteOpReg (Ehc, Offset, State);
787     break;
788 
789   case EfiUsbPortPower:
790   case EfiUsbPortSuspendChange:
791   case EfiUsbPortResetChange:
792     //
793     // Not supported or not related operation
794     //
795     break;
796 
797   default:
798     Status = EFI_INVALID_PARAMETER;
799     break;
800   }
801 
802 ON_EXIT:
803   return Status;
804 }
805 
806 /**
807   Sets a feature for the specified root hub port.
808 
809   @param  PeiServices           The pointer of EFI_PEI_SERVICES
810   @param  This                  The pointer of PEI_USB2_HOST_CONTROLLER_PPI
811   @param  PortNumber            Root hub port to set.
812   @param  PortFeature           Feature to set.
813 
814   @retval EFI_SUCCESS            The feature specified by PortFeature was set.
815   @retval EFI_INVALID_PARAMETER  PortNumber is invalid or PortFeature is invalid.
816   @retval EFI_TIMEOUT            The time out occurred.
817 
818 **/
819 EFI_STATUS
820 EFIAPI
EhcSetRootHubPortFeature(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB2_HOST_CONTROLLER_PPI * This,IN UINT8 PortNumber,IN EFI_USB_PORT_FEATURE PortFeature)821 EhcSetRootHubPortFeature (
822   IN EFI_PEI_SERVICES                       **PeiServices,
823   IN PEI_USB2_HOST_CONTROLLER_PPI           *This,
824   IN UINT8                                  PortNumber,
825   IN EFI_USB_PORT_FEATURE                   PortFeature
826   )
827 {
828   PEI_USB2_HC_DEV         *Ehc;
829   UINT32                  Offset;
830   UINT32                  State;
831   UINT32                  TotalPort;
832   EFI_STATUS              Status;
833 
834   Ehc       = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
835   Status    = EFI_SUCCESS;
836 
837   TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
838 
839   if (PortNumber >= TotalPort) {
840     Status = EFI_INVALID_PARAMETER;
841     goto ON_EXIT;
842   }
843 
844   Offset  = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
845   State   = EhcReadOpReg (Ehc, Offset);
846 
847   //
848   // Mask off the port status change bits, these bits are
849   // write clean bit
850   //
851   State &= ~PORTSC_CHANGE_MASK;
852 
853   switch (PortFeature) {
854   case EfiUsbPortEnable:
855     //
856     // Sofeware can't set this bit, Port can only be enable by
857     // EHCI as a part of the reset and enable
858     //
859     State |= PORTSC_ENABLED;
860     EhcWriteOpReg (Ehc, Offset, State);
861     break;
862 
863   case EfiUsbPortSuspend:
864     State |= PORTSC_SUSPEND;
865     EhcWriteOpReg (Ehc, Offset, State);
866     break;
867 
868   case EfiUsbPortReset:
869     //
870     // Make sure Host Controller not halt before reset it
871     //
872     if (EhcIsHalt (Ehc)) {
873       Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
874 
875       if (EFI_ERROR (Status)) {
876         break;
877       }
878     }
879 
880     //
881     // Set one to PortReset bit must also set zero to PortEnable bit
882     //
883     State |= PORTSC_RESET;
884     State &= ~PORTSC_ENABLED;
885     EhcWriteOpReg (Ehc, Offset, State);
886     break;
887 
888   case EfiUsbPortPower:
889     //
890     // Not supported, ignore the operation
891     //
892     Status = EFI_SUCCESS;
893     break;
894 
895   case EfiUsbPortOwner:
896     State |= PORTSC_OWNER;
897     EhcWriteOpReg (Ehc, Offset, State);
898     break;
899 
900   default:
901     Status = EFI_INVALID_PARAMETER;
902   }
903 
904 ON_EXIT:
905   return Status;
906 }
907 
908 /**
909   Retrieves the current status of a USB root hub port.
910 
911   @param  PeiServices            The pointer of EFI_PEI_SERVICES.
912   @param  This                   The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
913   @param  PortNumber             The root hub port to retrieve the state from.
914   @param  PortStatus             Variable to receive the port state.
915 
916   @retval EFI_SUCCESS            The status of the USB root hub port specified.
917                                  by PortNumber was returned in PortStatus.
918   @retval EFI_INVALID_PARAMETER  PortNumber is invalid.
919 
920 **/
921 EFI_STATUS
922 EFIAPI
EhcGetRootHubPortStatus(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB2_HOST_CONTROLLER_PPI * This,IN UINT8 PortNumber,OUT EFI_USB_PORT_STATUS * PortStatus)923 EhcGetRootHubPortStatus (
924   IN EFI_PEI_SERVICES                       **PeiServices,
925   IN PEI_USB2_HOST_CONTROLLER_PPI           *This,
926   IN  UINT8                                 PortNumber,
927   OUT EFI_USB_PORT_STATUS                   *PortStatus
928   )
929 {
930   PEI_USB2_HC_DEV         *Ehc;
931   UINT32                  Offset;
932   UINT32                  State;
933   UINT32                  TotalPort;
934   UINTN                   Index;
935   UINTN                   MapSize;
936   EFI_STATUS              Status;
937 
938   if (PortStatus == NULL) {
939     return EFI_INVALID_PARAMETER;
940   }
941 
942   Ehc       =  PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS(This);
943   Status    = EFI_SUCCESS;
944 
945   TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
946 
947   if (PortNumber >= TotalPort) {
948     Status = EFI_INVALID_PARAMETER;
949     goto ON_EXIT;
950   }
951 
952   Offset                        = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
953   PortStatus->PortStatus        = 0;
954   PortStatus->PortChangeStatus  = 0;
955 
956   State                         = EhcReadOpReg (Ehc, Offset);
957 
958   //
959   // Identify device speed. If in K state, it is low speed.
960   // If the port is enabled after reset, the device is of
961   // high speed. The USB bus driver should retrieve the actual
962   // port speed after reset.
963   //
964   if (EHC_BIT_IS_SET (State, PORTSC_LINESTATE_K)) {
965     PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
966 
967   } else if (EHC_BIT_IS_SET (State, PORTSC_ENABLED)) {
968     PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
969   }
970 
971   //
972   // Convert the EHCI port/port change state to UEFI status
973   //
974   MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
975 
976   for (Index = 0; Index < MapSize; Index++) {
977     if (EHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
978       PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);
979     }
980   }
981 
982   MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
983 
984   for (Index = 0; Index < MapSize; Index++) {
985     if (EHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
986       PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
987     }
988   }
989 
990 ON_EXIT:
991   return Status;
992 }
993 
994 /**
995   Submits control transfer to a target USB device.
996 
997   @param  PeiServices            The pointer of EFI_PEI_SERVICES.
998   @param  This                   The pointer of PEI_USB2_HOST_CONTROLLER_PPI.
999   @param  DeviceAddress          The target device address.
1000   @param  DeviceSpeed            Target device speed.
1001   @param  MaximumPacketLength    Maximum packet size the default control transfer
1002                                  endpoint is capable of sending or receiving.
1003   @param  Request                USB device request to send.
1004   @param  TransferDirection      Specifies the data direction for the data stage.
1005   @param  Data                   Data buffer to be transmitted or received from USB device.
1006   @param  DataLength             The size (in bytes) of the data buffer.
1007   @param  TimeOut                Indicates the maximum timeout, in millisecond.
1008                                  If Timeout is 0, then the caller must wait for the function
1009                                  to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
1010   @param  Translator             Transaction translator to be used by this device.
1011   @param  TransferResult         Return the result of this control transfer.
1012 
1013   @retval EFI_SUCCESS            Transfer was completed successfully.
1014   @retval EFI_OUT_OF_RESOURCES   The transfer failed due to lack of resources.
1015   @retval EFI_INVALID_PARAMETER  Some parameters are invalid.
1016   @retval EFI_TIMEOUT            Transfer failed due to timeout.
1017   @retval EFI_DEVICE_ERROR       Transfer failed due to host controller or device error.
1018 
1019 **/
1020 EFI_STATUS
1021 EFIAPI
EhcControlTransfer(IN EFI_PEI_SERVICES ** PeiServices,IN PEI_USB2_HOST_CONTROLLER_PPI * This,IN UINT8 DeviceAddress,IN UINT8 DeviceSpeed,IN UINTN MaximumPacketLength,IN EFI_USB_DEVICE_REQUEST * Request,IN EFI_USB_DATA_DIRECTION TransferDirection,IN OUT VOID * Data,IN OUT UINTN * DataLength,IN UINTN TimeOut,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,OUT UINT32 * TransferResult)1022 EhcControlTransfer (
1023   IN  EFI_PEI_SERVICES                    **PeiServices,
1024   IN  PEI_USB2_HOST_CONTROLLER_PPI        *This,
1025   IN  UINT8                               DeviceAddress,
1026   IN  UINT8                               DeviceSpeed,
1027   IN  UINTN                               MaximumPacketLength,
1028   IN  EFI_USB_DEVICE_REQUEST              *Request,
1029   IN  EFI_USB_DATA_DIRECTION              TransferDirection,
1030   IN  OUT VOID                            *Data,
1031   IN  OUT UINTN                           *DataLength,
1032   IN  UINTN                               TimeOut,
1033   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
1034   OUT UINT32                              *TransferResult
1035   )
1036 {
1037   PEI_USB2_HC_DEV         *Ehc;
1038   PEI_URB                 *Urb;
1039   UINT8                   Endpoint;
1040   EFI_STATUS              Status;
1041 
1042   //
1043   // Validate parameters
1044   //
1045   if ((Request == NULL) || (TransferResult == NULL)) {
1046     return EFI_INVALID_PARAMETER;
1047   }
1048 
1049   if ((TransferDirection != EfiUsbDataIn) &&
1050       (TransferDirection != EfiUsbDataOut) &&
1051       (TransferDirection != EfiUsbNoData)) {
1052     return EFI_INVALID_PARAMETER;
1053   }
1054 
1055   if ((TransferDirection == EfiUsbNoData) &&
1056       ((Data != NULL) || (*DataLength != 0))) {
1057     return EFI_INVALID_PARAMETER;
1058   }
1059 
1060   if ((TransferDirection != EfiUsbNoData) &&
1061      ((Data == NULL) || (*DataLength == 0))) {
1062     return EFI_INVALID_PARAMETER;
1063   }
1064 
1065   if ((MaximumPacketLength != 8)  && (MaximumPacketLength != 16) &&
1066       (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {
1067     return EFI_INVALID_PARAMETER;
1068   }
1069 
1070 
1071   if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
1072       ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
1073       ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512))) {
1074     return EFI_INVALID_PARAMETER;
1075   }
1076 
1077   Ehc             = PEI_RECOVERY_USB_EHC_DEV_FROM_EHCI_THIS (This);
1078 
1079   Status          = EFI_DEVICE_ERROR;
1080   *TransferResult = EFI_USB_ERR_SYSTEM;
1081 
1082   if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
1083     EhcAckAllInterrupt (Ehc);
1084     goto ON_EXIT;
1085   }
1086 
1087   EhcAckAllInterrupt (Ehc);
1088 
1089   //
1090   // Create a new URB, insert it into the asynchronous
1091   // schedule list, then poll the execution status.
1092   //
1093   //
1094   // Encode the direction in address, although default control
1095   // endpoint is bidirectional. EhcCreateUrb expects this
1096   // combination of Ep addr and its direction.
1097   //
1098   Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
1099   Urb = EhcCreateUrb (
1100           Ehc,
1101           DeviceAddress,
1102           Endpoint,
1103           DeviceSpeed,
1104           0,
1105           MaximumPacketLength,
1106           Translator,
1107           EHC_CTRL_TRANSFER,
1108           Request,
1109           Data,
1110           *DataLength,
1111           NULL,
1112           NULL,
1113           1
1114           );
1115 
1116   if (Urb == NULL) {
1117     Status = EFI_OUT_OF_RESOURCES;
1118     goto ON_EXIT;
1119   }
1120 
1121   EhcLinkQhToAsync (Ehc, Urb->Qh);
1122   Status = EhcExecTransfer (Ehc, Urb, TimeOut);
1123   EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
1124 
1125   //
1126   // Get the status from URB. The result is updated in EhcCheckUrbResult
1127   // which is called by EhcExecTransfer
1128   //
1129   *TransferResult = Urb->Result;
1130   *DataLength     = Urb->Completed;
1131 
1132   if (*TransferResult == EFI_USB_NOERROR) {
1133     Status = EFI_SUCCESS;
1134   }
1135 
1136   EhcAckAllInterrupt (Ehc);
1137   EhcFreeUrb (Ehc, Urb);
1138 
1139 ON_EXIT:
1140   return Status;
1141 }
1142 
1143 /**
1144   @param  FileHandle  Handle of the file being invoked.
1145   @param  PeiServices Describes the list of possible PEI Services.
1146 
1147   @retval EFI_SUCCESS            PPI successfully installed.
1148 
1149 **/
1150 EFI_STATUS
1151 EFIAPI
EhcPeimEntry(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)1152 EhcPeimEntry (
1153   IN EFI_PEI_FILE_HANDLE     FileHandle,
1154   IN CONST EFI_PEI_SERVICES  **PeiServices
1155   )
1156 {
1157   PEI_USB_CONTROLLER_PPI      *ChipSetUsbControllerPpi;
1158   EFI_STATUS                  Status;
1159   UINT8                       Index;
1160   UINTN                       ControllerType;
1161   UINTN                       BaseAddress;
1162   UINTN                       MemPages;
1163   PEI_USB2_HC_DEV             *EhcDev;
1164   EFI_PHYSICAL_ADDRESS        TempPtr;
1165 
1166   //
1167   // Shadow this PEIM to run from memory
1168   //
1169   if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
1170     return EFI_SUCCESS;
1171   }
1172 
1173   Status = PeiServicesLocatePpi (
1174              &gPeiUsbControllerPpiGuid,
1175              0,
1176              NULL,
1177              (VOID **) &ChipSetUsbControllerPpi
1178              );
1179   if (EFI_ERROR (Status)) {
1180     return EFI_UNSUPPORTED;
1181   }
1182 
1183   Index = 0;
1184   while (TRUE) {
1185     Status = ChipSetUsbControllerPpi->GetUsbController (
1186                                         (EFI_PEI_SERVICES **) PeiServices,
1187                                         ChipSetUsbControllerPpi,
1188                                         Index,
1189                                         &ControllerType,
1190                                         &BaseAddress
1191                                         );
1192     //
1193     // When status is error, meant no controller is found
1194     //
1195     if (EFI_ERROR (Status)) {
1196       break;
1197     }
1198 
1199     //
1200     // This PEIM is for UHC type controller.
1201     //
1202     if (ControllerType != PEI_EHCI_CONTROLLER) {
1203       Index++;
1204       continue;
1205     }
1206 
1207     MemPages = sizeof (PEI_USB2_HC_DEV) / PAGESIZE + 1;
1208     Status = PeiServicesAllocatePages (
1209                EfiBootServicesCode,
1210                MemPages,
1211                &TempPtr
1212                );
1213     if (EFI_ERROR (Status)) {
1214       return EFI_OUT_OF_RESOURCES;
1215     }
1216 
1217     ZeroMem((VOID *)(UINTN)TempPtr, MemPages*PAGESIZE);
1218     EhcDev = (PEI_USB2_HC_DEV *) ((UINTN) TempPtr);
1219 
1220     EhcDev->Signature = USB2_HC_DEV_SIGNATURE;
1221 
1222     EhcDev->UsbHostControllerBaseAddress = (UINT32) BaseAddress;
1223 
1224 
1225     EhcDev->HcStructParams = EhcReadCapRegister (EhcDev, EHC_HCSPARAMS_OFFSET);
1226     EhcDev->HcCapParams    = EhcReadCapRegister (EhcDev, EHC_HCCPARAMS_OFFSET);
1227     EhcDev->CapLen         = EhcReadCapRegister (EhcDev, EHC_CAPLENGTH_OFFSET) & 0x0FF;
1228     //
1229     // Initialize Uhc's hardware
1230     //
1231     Status = InitializeUsbHC (EhcDev);
1232     if (EFI_ERROR (Status)) {
1233       return Status;
1234     }
1235 
1236     EhcDev->Usb2HostControllerPpi.ControlTransfer          = EhcControlTransfer;
1237     EhcDev->Usb2HostControllerPpi.BulkTransfer             = EhcBulkTransfer;
1238     EhcDev->Usb2HostControllerPpi.GetRootHubPortNumber     = EhcGetRootHubPortNumber;
1239     EhcDev->Usb2HostControllerPpi.GetRootHubPortStatus     = EhcGetRootHubPortStatus;
1240     EhcDev->Usb2HostControllerPpi.SetRootHubPortFeature    = EhcSetRootHubPortFeature;
1241     EhcDev->Usb2HostControllerPpi.ClearRootHubPortFeature  = EhcClearRootHubPortFeature;
1242 
1243     EhcDev->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
1244     EhcDev->PpiDescriptor.Guid = &gPeiUsb2HostControllerPpiGuid;
1245     EhcDev->PpiDescriptor.Ppi = &EhcDev->Usb2HostControllerPpi;
1246 
1247     Status = PeiServicesInstallPpi (&EhcDev->PpiDescriptor);
1248     if (EFI_ERROR (Status)) {
1249       Index++;
1250       continue;
1251     }
1252 
1253     Index++;
1254   }
1255 
1256   return EFI_SUCCESS;
1257 }
1258 
1259 /**
1260   @param  EhcDev                 EHCI Device.
1261 
1262   @retval EFI_SUCCESS            EHCI successfully initialized.
1263   @retval EFI_ABORTED            EHCI was failed to be initialized.
1264 
1265 **/
1266 EFI_STATUS
InitializeUsbHC(IN PEI_USB2_HC_DEV * EhcDev)1267 InitializeUsbHC (
1268   IN PEI_USB2_HC_DEV      *EhcDev
1269   )
1270 {
1271   EFI_STATUS  Status;
1272 
1273 
1274   EhcResetHC (EhcDev, EHC_RESET_TIMEOUT);
1275 
1276   Status = EhcInitHC (EhcDev);
1277 
1278   if (EFI_ERROR (Status)) {
1279     return EFI_ABORTED;
1280   }
1281 
1282   return EFI_SUCCESS;
1283 }
1284