2
The Ehci controller driver.
4
EhciDxe driver is responsible for managing the behavior of EHCI controller.
5
It implements the interfaces of monitoring the status of all ports and transferring
6
Control, Bulk, Interrupt and Isochronous requests to Usb2.0 device.
8
Note that EhciDxe driver is enhanced to guarantee that the EHCI controller get attached
9
to the EHCI controller before the UHCI driver attaches to the companion UHCI controller.
10
This way avoids the control transfer on a shared port between EHCI and companion host
11
controller when UHCI gets attached earlier than EHCI and a USB 2.0 device inserts.
13
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
14
This program and the accompanying materials
15
are licensed and made available under the terms and conditions of the BSD License
16
which accompanies this distribution. The full text of the license may be found at
17
http://opensource.org/licenses/bsd-license.php
19
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
20
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
28
// Two arrays used to translate the EHCI port state (change)
29
// to the UEFI protocol's port state (change).
31
USB_PORT_STATE_MAP mUsbPortStateMap[] = {
32
{PORTSC_CONN, USB_PORT_STAT_CONNECTION},
33
{PORTSC_ENABLED, USB_PORT_STAT_ENABLE},
34
{PORTSC_SUSPEND, USB_PORT_STAT_SUSPEND},
35
{PORTSC_OVERCUR, USB_PORT_STAT_OVERCURRENT},
36
{PORTSC_RESET, USB_PORT_STAT_RESET},
37
{PORTSC_POWER, USB_PORT_STAT_POWER},
38
{PORTSC_OWNER, USB_PORT_STAT_OWNER}
41
USB_PORT_STATE_MAP mUsbPortChangeMap[] = {
42
{PORTSC_CONN_CHANGE, USB_PORT_STAT_C_CONNECTION},
43
{PORTSC_ENABLE_CHANGE, USB_PORT_STAT_C_ENABLE},
44
{PORTSC_OVERCUR_CHANGE, USB_PORT_STAT_C_OVERCURRENT}
47
EFI_DRIVER_BINDING_PROTOCOL
48
gEhciDriverBinding = {
49
EhcDriverBindingSupported,
50
EhcDriverBindingStart,
58
Retrieves the capability of root hub ports.
60
@param This This EFI_USB_HC_PROTOCOL instance.
61
@param MaxSpeed Max speed supported by the controller.
62
@param PortNumber Number of the root hub ports.
63
@param Is64BitCapable Whether the controller supports 64-bit memory
66
@retval EFI_SUCCESS Host controller capability were retrieved successfully.
67
@retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.
73
IN EFI_USB2_HC_PROTOCOL *This,
75
OUT UINT8 *PortNumber,
76
OUT UINT8 *Is64BitCapable
82
if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {
83
return EFI_INVALID_PARAMETER;
86
OldTpl = gBS->RaiseTPL (EHC_TPL);
87
Ehc = EHC_FROM_THIS (This);
89
*MaxSpeed = EFI_USB_SPEED_HIGH;
90
*PortNumber = (UINT8) (Ehc->HcStructParams & HCSP_NPORTS);
91
*Is64BitCapable = (UINT8) (Ehc->HcCapParams & HCCP_64BIT);
93
DEBUG ((EFI_D_INFO, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));
95
gBS->RestoreTPL (OldTpl);
101
Provides software reset for the USB host controller.
103
@param This This EFI_USB2_HC_PROTOCOL instance.
104
@param Attributes A bit mask of the reset operation to perform.
106
@retval EFI_SUCCESS The reset operation succeeded.
107
@retval EFI_INVALID_PARAMETER Attributes is not valid.
108
@retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
109
not currently supported by the host controller.
110
@retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
116
IN EFI_USB2_HC_PROTOCOL *This,
123
UINT32 DbgCtrlStatus;
125
Ehc = EHC_FROM_THIS (This);
127
if (Ehc->DevicePath != NULL) {
129
// Report Status Code to indicate reset happens
131
REPORT_STATUS_CODE_WITH_DEVICE_PATH (
133
(EFI_IO_BUS_USB | EFI_IOB_PC_RESET),
138
OldTpl = gBS->RaiseTPL (EHC_TPL);
140
switch (Attributes) {
141
case EFI_USB_HC_RESET_GLOBAL:
143
// Flow through, same behavior as Host Controller Reset
145
case EFI_USB_HC_RESET_HOST_CONTROLLER:
147
// Host Controller must be Halt when Reset it
149
if (Ehc->DebugPortNum != 0) {
150
DbgCtrlStatus = EhcReadDbgRegister(Ehc, 0);
151
if ((DbgCtrlStatus & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) == (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) {
152
Status = EFI_SUCCESS;
157
if (!EhcIsHalt (Ehc)) {
158
Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
160
if (EFI_ERROR (Status)) {
161
Status = EFI_DEVICE_ERROR;
167
// Clean up the asynchronous transfers, currently only
168
// interrupt supports asynchronous operation.
170
EhciDelAllAsyncIntTransfers (Ehc);
171
EhcAckAllInterrupt (Ehc);
174
Status = EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
176
if (EFI_ERROR (Status)) {
180
Status = EhcInitHC (Ehc);
183
case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:
184
case EFI_USB_HC_RESET_HOST_WITH_DEBUG:
185
Status = EFI_UNSUPPORTED;
189
Status = EFI_INVALID_PARAMETER;
193
DEBUG ((EFI_D_INFO, "EhcReset: exit status %r\n", Status));
194
gBS->RestoreTPL (OldTpl);
200
Retrieve the current state of the USB host controller.
202
@param This This EFI_USB2_HC_PROTOCOL instance.
203
@param State Variable to return the current host controller
206
@retval EFI_SUCCESS Host controller state was returned in State.
207
@retval EFI_INVALID_PARAMETER State is NULL.
208
@retval EFI_DEVICE_ERROR An error was encountered while attempting to
209
retrieve the host controller's current state.
215
IN EFI_USB2_HC_PROTOCOL *This,
216
OUT EFI_USB_HC_STATE *State
223
return EFI_INVALID_PARAMETER;
226
OldTpl = gBS->RaiseTPL (EHC_TPL);
227
Ehc = EHC_FROM_THIS (This);
229
if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
230
*State = EfiUsbHcStateHalt;
232
*State = EfiUsbHcStateOperational;
235
gBS->RestoreTPL (OldTpl);
237
DEBUG ((EFI_D_INFO, "EhcGetState: current state %d\n", *State));
243
Sets the USB host controller to a specific state.
245
@param This This EFI_USB2_HC_PROTOCOL instance.
246
@param State The state of the host controller that will be set.
248
@retval EFI_SUCCESS The USB host controller was successfully placed
249
in the state specified by State.
250
@retval EFI_INVALID_PARAMETER State is invalid.
251
@retval EFI_DEVICE_ERROR Failed to set the state due to device error.
257
IN EFI_USB2_HC_PROTOCOL *This,
258
IN EFI_USB_HC_STATE State
264
EFI_USB_HC_STATE CurState;
266
Status = EhcGetState (This, &CurState);
268
if (EFI_ERROR (Status)) {
269
return EFI_DEVICE_ERROR;
272
if (CurState == State) {
276
OldTpl = gBS->RaiseTPL (EHC_TPL);
277
Ehc = EHC_FROM_THIS (This);
280
case EfiUsbHcStateHalt:
281
Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
284
case EfiUsbHcStateOperational:
285
if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR)) {
286
Status = EFI_DEVICE_ERROR;
291
// Software must not write a one to this field unless the host controller
292
// is in the Halted state. Doing so will yield undefined results.
293
// refers to Spec[EHCI1.0-2.3.1]
295
if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
296
Status = EFI_DEVICE_ERROR;
300
Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
303
case EfiUsbHcStateSuspend:
304
Status = EFI_UNSUPPORTED;
308
Status = EFI_INVALID_PARAMETER;
311
DEBUG ((EFI_D_INFO, "EhcSetState: exit status %r\n", Status));
312
gBS->RestoreTPL (OldTpl);
318
Retrieves the current status of a USB root hub port.
320
@param This This EFI_USB2_HC_PROTOCOL instance.
321
@param PortNumber The root hub port to retrieve the state from.
322
This value is zero-based.
323
@param PortStatus Variable to receive the port state.
325
@retval EFI_SUCCESS The status of the USB root hub port specified.
326
by PortNumber was returned in PortStatus.
327
@retval EFI_INVALID_PARAMETER PortNumber is invalid.
328
@retval EFI_DEVICE_ERROR Can't read register.
333
EhcGetRootHubPortStatus (
334
IN EFI_USB2_HC_PROTOCOL *This,
336
OUT EFI_USB_PORT_STATUS *PortStatus
347
UINT32 DbgCtrlStatus;
349
if (PortStatus == NULL) {
350
return EFI_INVALID_PARAMETER;
353
OldTpl = gBS->RaiseTPL (EHC_TPL);
355
Ehc = EHC_FROM_THIS (This);
356
Status = EFI_SUCCESS;
358
TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
360
if (PortNumber >= TotalPort) {
361
Status = EFI_INVALID_PARAMETER;
365
Offset = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
366
PortStatus->PortStatus = 0;
367
PortStatus->PortChangeStatus = 0;
369
if ((Ehc->DebugPortNum != 0) && (PortNumber == (Ehc->DebugPortNum - 1))) {
370
DbgCtrlStatus = EhcReadDbgRegister(Ehc, 0);
371
if ((DbgCtrlStatus & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) == (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) {
376
State = EhcReadOpReg (Ehc, Offset);
379
// Identify device speed. If in K state, it is low speed.
380
// If the port is enabled after reset, the device is of
381
// high speed. The USB bus driver should retrieve the actual
382
// port speed after reset.
384
if (EHC_BIT_IS_SET (State, PORTSC_LINESTATE_K)) {
385
PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
387
} else if (EHC_BIT_IS_SET (State, PORTSC_ENABLED)) {
388
PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;
392
// Convert the EHCI port/port change state to UEFI status
394
MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);
396
for (Index = 0; Index < MapSize; Index++) {
397
if (EHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {
398
PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);
402
MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);
404
for (Index = 0; Index < MapSize; Index++) {
405
if (EHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {
406
PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);
411
gBS->RestoreTPL (OldTpl);
417
Sets a feature for the specified root hub port.
419
@param This This EFI_USB2_HC_PROTOCOL instance.
420
@param PortNumber Root hub port to set.
421
@param PortFeature Feature to set.
423
@retval EFI_SUCCESS The feature specified by PortFeature was set.
424
@retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
425
@retval EFI_DEVICE_ERROR Can't read register.
430
EhcSetRootHubPortFeature (
431
IN EFI_USB2_HC_PROTOCOL *This,
433
IN EFI_USB_PORT_FEATURE PortFeature
443
OldTpl = gBS->RaiseTPL (EHC_TPL);
444
Ehc = EHC_FROM_THIS (This);
445
Status = EFI_SUCCESS;
447
TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
449
if (PortNumber >= TotalPort) {
450
Status = EFI_INVALID_PARAMETER;
454
Offset = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));
455
State = EhcReadOpReg (Ehc, Offset);
458
// Mask off the port status change bits, these bits are
461
State &= ~PORTSC_CHANGE_MASK;
463
switch (PortFeature) {
464
case EfiUsbPortEnable:
466
// Sofeware can't set this bit, Port can only be enable by
467
// EHCI as a part of the reset and enable
469
State |= PORTSC_ENABLED;
470
EhcWriteOpReg (Ehc, Offset, State);
473
case EfiUsbPortSuspend:
474
State |= PORTSC_SUSPEND;
475
EhcWriteOpReg (Ehc, Offset, State);
478
case EfiUsbPortReset:
480
// Make sure Host Controller not halt before reset it
482
if (EhcIsHalt (Ehc)) {
483
Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);
485
if (EFI_ERROR (Status)) {
486
DEBUG ((EFI_D_INFO, "EhcSetRootHubPortFeature :failed to start HC - %r\n", Status));
492
// Set one to PortReset bit must also set zero to PortEnable bit
494
State |= PORTSC_RESET;
495
State &= ~PORTSC_ENABLED;
496
EhcWriteOpReg (Ehc, Offset, State);
499
case EfiUsbPortPower:
501
// Set port power bit when PPC is 1
503
if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) {
504
State |= PORTSC_POWER;
505
EhcWriteOpReg (Ehc, Offset, State);
509
case EfiUsbPortOwner:
510
State |= PORTSC_OWNER;
511
EhcWriteOpReg (Ehc, Offset, State);
515
Status = EFI_INVALID_PARAMETER;
519
DEBUG ((EFI_D_INFO, "EhcSetRootHubPortFeature: exit status %r\n", Status));
521
gBS->RestoreTPL (OldTpl);
527
Clears a feature for the specified root hub port.
529
@param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
530
@param PortNumber Specifies the root hub port whose feature is
531
requested to be cleared.
532
@param PortFeature Indicates the feature selector associated with the
533
feature clear request.
535
@retval EFI_SUCCESS The feature specified by PortFeature was cleared
536
for the USB root hub port specified by PortNumber.
537
@retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
538
@retval EFI_DEVICE_ERROR Can't read register.
543
EhcClearRootHubPortFeature (
544
IN EFI_USB2_HC_PROTOCOL *This,
546
IN EFI_USB_PORT_FEATURE PortFeature
556
OldTpl = gBS->RaiseTPL (EHC_TPL);
557
Ehc = EHC_FROM_THIS (This);
558
Status = EFI_SUCCESS;
560
TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);
562
if (PortNumber >= TotalPort) {
563
Status = EFI_INVALID_PARAMETER;
567
Offset = EHC_PORT_STAT_OFFSET + (4 * PortNumber);
568
State = EhcReadOpReg (Ehc, Offset);
569
State &= ~PORTSC_CHANGE_MASK;
571
switch (PortFeature) {
572
case EfiUsbPortEnable:
574
// Clear PORT_ENABLE feature means disable port.
576
State &= ~PORTSC_ENABLED;
577
EhcWriteOpReg (Ehc, Offset, State);
580
case EfiUsbPortSuspend:
582
// A write of zero to this bit is ignored by the host
583
// controller. The host controller will unconditionally
584
// set this bit to a zero when:
585
// 1. software sets the Forct Port Resume bit to a zero from a one.
586
// 2. software sets the Port Reset bit to a one frome a zero.
588
State &= ~PORSTSC_RESUME;
589
EhcWriteOpReg (Ehc, Offset, State);
592
case EfiUsbPortReset:
594
// Clear PORT_RESET means clear the reset signal.
596
State &= ~PORTSC_RESET;
597
EhcWriteOpReg (Ehc, Offset, State);
600
case EfiUsbPortOwner:
602
// Clear port owner means this port owned by EHC
604
State &= ~PORTSC_OWNER;
605
EhcWriteOpReg (Ehc, Offset, State);
608
case EfiUsbPortConnectChange:
610
// Clear connect status change
612
State |= PORTSC_CONN_CHANGE;
613
EhcWriteOpReg (Ehc, Offset, State);
616
case EfiUsbPortEnableChange:
618
// Clear enable status change
620
State |= PORTSC_ENABLE_CHANGE;
621
EhcWriteOpReg (Ehc, Offset, State);
624
case EfiUsbPortOverCurrentChange:
626
// Clear PortOverCurrent change
628
State |= PORTSC_OVERCUR_CHANGE;
629
EhcWriteOpReg (Ehc, Offset, State);
632
case EfiUsbPortPower:
634
// Clear port power bit when PPC is 1
636
if ((Ehc->HcCapParams & HCSP_PPC) == HCSP_PPC) {
637
State &= ~PORTSC_POWER;
638
EhcWriteOpReg (Ehc, Offset, State);
641
case EfiUsbPortSuspendChange:
642
case EfiUsbPortResetChange:
644
// Not supported or not related operation
649
Status = EFI_INVALID_PARAMETER;
654
DEBUG ((EFI_D_INFO, "EhcClearRootHubPortFeature: exit status %r\n", Status));
655
gBS->RestoreTPL (OldTpl);
661
Submits control transfer to a target USB device.
663
@param This This EFI_USB2_HC_PROTOCOL instance.
664
@param DeviceAddress The target device address.
665
@param DeviceSpeed Target device speed.
666
@param MaximumPacketLength Maximum packet size the default control transfer
667
endpoint is capable of sending or receiving.
668
@param Request USB device request to send.
669
@param TransferDirection Specifies the data direction for the data stage
670
@param Data Data buffer to be transmitted or received from USB
672
@param DataLength The size (in bytes) of the data buffer.
673
@param TimeOut Indicates the maximum timeout, in millisecond.
674
@param Translator Transaction translator to be used by this device.
675
@param TransferResult Return the result of this control transfer.
677
@retval EFI_SUCCESS Transfer was completed successfully.
678
@retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
679
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
680
@retval EFI_TIMEOUT Transfer failed due to timeout.
681
@retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
687
IN EFI_USB2_HC_PROTOCOL *This,
688
IN UINT8 DeviceAddress,
689
IN UINT8 DeviceSpeed,
690
IN UINTN MaximumPacketLength,
691
IN EFI_USB_DEVICE_REQUEST *Request,
692
IN EFI_USB_DATA_DIRECTION TransferDirection,
694
IN OUT UINTN *DataLength,
696
IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
697
OUT UINT32 *TransferResult
707
// Validate parameters
709
if ((Request == NULL) || (TransferResult == NULL)) {
710
return EFI_INVALID_PARAMETER;
713
if ((TransferDirection != EfiUsbDataIn) &&
714
(TransferDirection != EfiUsbDataOut) &&
715
(TransferDirection != EfiUsbNoData)) {
716
return EFI_INVALID_PARAMETER;
719
if ((TransferDirection == EfiUsbNoData) &&
720
((Data != NULL) || (*DataLength != 0))) {
721
return EFI_INVALID_PARAMETER;
724
if ((TransferDirection != EfiUsbNoData) &&
725
((Data == NULL) || (*DataLength == 0))) {
726
return EFI_INVALID_PARAMETER;
729
if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&
730
(MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {
731
return EFI_INVALID_PARAMETER;
734
if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {
735
return EFI_INVALID_PARAMETER;
738
OldTpl = gBS->RaiseTPL (EHC_TPL);
739
Ehc = EHC_FROM_THIS (This);
741
Status = EFI_DEVICE_ERROR;
742
*TransferResult = EFI_USB_ERR_SYSTEM;
744
if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
745
DEBUG ((EFI_D_ERROR, "EhcControlTransfer: HC halted at entrance\n"));
747
EhcAckAllInterrupt (Ehc);
751
EhcAckAllInterrupt (Ehc);
754
// Create a new URB, insert it into the asynchronous
755
// schedule list, then poll the execution status.
758
// Encode the direction in address, although default control
759
// endpoint is bidirectional. EhcCreateUrb expects this
760
// combination of Ep addr and its direction.
762
Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
781
DEBUG ((EFI_D_ERROR, "EhcControlTransfer: failed to create URB"));
783
Status = EFI_OUT_OF_RESOURCES;
787
EhcLinkQhToAsync (Ehc, Urb->Qh);
788
Status = EhcExecTransfer (Ehc, Urb, TimeOut);
789
EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
792
// Get the status from URB. The result is updated in EhcCheckUrbResult
793
// which is called by EhcExecTransfer
795
*TransferResult = Urb->Result;
796
*DataLength = Urb->Completed;
798
if (*TransferResult == EFI_USB_NOERROR) {
799
Status = EFI_SUCCESS;
802
EhcAckAllInterrupt (Ehc);
803
EhcFreeUrb (Ehc, Urb);
806
Ehc->PciIo->Flush (Ehc->PciIo);
807
gBS->RestoreTPL (OldTpl);
809
if (EFI_ERROR (Status)) {
810
DEBUG ((EFI_D_ERROR, "EhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
818
Submits bulk transfer to a bulk endpoint of a USB device.
820
@param This This EFI_USB2_HC_PROTOCOL instance.
821
@param DeviceAddress Target device address.
822
@param EndPointAddress Endpoint number and its direction in bit 7.
823
@param DeviceSpeed Device speed, Low speed device doesn't support bulk
825
@param MaximumPacketLength Maximum packet size the endpoint is capable of
826
sending or receiving.
827
@param DataBuffersNumber Number of data buffers prepared for the transfer.
828
@param Data Array of pointers to the buffers of data to transmit
829
from or receive into.
830
@param DataLength The lenght of the data buffer.
831
@param DataToggle On input, the initial data toggle for the transfer;
832
On output, it is updated to to next data toggle to
833
use of the subsequent bulk transfer.
834
@param TimeOut Indicates the maximum time, in millisecond, which
835
the transfer is allowed to complete.
836
@param Translator A pointr to the transaction translator data.
837
@param TransferResult A pointer to the detailed result information of the
840
@retval EFI_SUCCESS The transfer was completed successfully.
841
@retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
842
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
843
@retval EFI_TIMEOUT The transfer failed due to timeout.
844
@retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
850
IN EFI_USB2_HC_PROTOCOL *This,
851
IN UINT8 DeviceAddress,
852
IN UINT8 EndPointAddress,
853
IN UINT8 DeviceSpeed,
854
IN UINTN MaximumPacketLength,
855
IN UINT8 DataBuffersNumber,
856
IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
857
IN OUT UINTN *DataLength,
858
IN OUT UINT8 *DataToggle,
860
IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
861
OUT UINT32 *TransferResult
870
// Validate the parameters
872
if ((DataLength == NULL) || (*DataLength == 0) ||
873
(Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {
874
return EFI_INVALID_PARAMETER;
877
if ((*DataToggle != 0) && (*DataToggle != 1)) {
878
return EFI_INVALID_PARAMETER;
881
if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||
882
((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
883
((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512))) {
884
return EFI_INVALID_PARAMETER;
887
OldTpl = gBS->RaiseTPL (EHC_TPL);
888
Ehc = EHC_FROM_THIS (This);
890
*TransferResult = EFI_USB_ERR_SYSTEM;
891
Status = EFI_DEVICE_ERROR;
893
if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
894
DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: HC is halted\n"));
896
EhcAckAllInterrupt (Ehc);
900
EhcAckAllInterrupt (Ehc);
903
// Create a new URB, insert it into the asynchronous
904
// schedule list, then poll the execution status.
924
DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: failed to create URB\n"));
926
Status = EFI_OUT_OF_RESOURCES;
930
EhcLinkQhToAsync (Ehc, Urb->Qh);
931
Status = EhcExecTransfer (Ehc, Urb, TimeOut);
932
EhcUnlinkQhFromAsync (Ehc, Urb->Qh);
934
*TransferResult = Urb->Result;
935
*DataLength = Urb->Completed;
936
*DataToggle = Urb->DataToggle;
938
if (*TransferResult == EFI_USB_NOERROR) {
939
Status = EFI_SUCCESS;
942
EhcAckAllInterrupt (Ehc);
943
EhcFreeUrb (Ehc, Urb);
946
Ehc->PciIo->Flush (Ehc->PciIo);
947
gBS->RestoreTPL (OldTpl);
949
if (EFI_ERROR (Status)) {
950
DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
958
Submits an asynchronous interrupt transfer to an
959
interrupt endpoint of a USB device.
961
@param This This EFI_USB2_HC_PROTOCOL instance.
962
@param DeviceAddress Target device address.
963
@param EndPointAddress Endpoint number and its direction encoded in bit 7
964
@param DeviceSpeed Indicates device speed.
965
@param MaximumPacketLength Maximum packet size the target endpoint is capable
966
@param IsNewTransfer If TRUE, to submit an new asynchronous interrupt
967
transfer If FALSE, to remove the specified
968
asynchronous interrupt.
969
@param DataToggle On input, the initial data toggle to use; on output,
970
it is updated to indicate the next data toggle.
971
@param PollingInterval The he interval, in milliseconds, that the transfer
973
@param DataLength The length of data to receive at the rate specified
975
@param Translator Transaction translator to use.
976
@param CallBackFunction Function to call at the rate specified by
978
@param Context Context to CallBackFunction.
980
@retval EFI_SUCCESS The request has been successfully submitted or canceled.
981
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
982
@retval EFI_OUT_OF_RESOURCES The request failed due to a lack of resources.
983
@retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
988
EhcAsyncInterruptTransfer (
989
IN EFI_USB2_HC_PROTOCOL * This,
990
IN UINT8 DeviceAddress,
991
IN UINT8 EndPointAddress,
992
IN UINT8 DeviceSpeed,
993
IN UINTN MaximumPacketLength,
994
IN BOOLEAN IsNewTransfer,
995
IN OUT UINT8 *DataToggle,
996
IN UINTN PollingInterval,
998
IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,
999
IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
1000
IN VOID *Context OPTIONAL
1010
// Validate parameters
1012
if (!EHCI_IS_DATAIN (EndPointAddress)) {
1013
return EFI_INVALID_PARAMETER;
1016
if (IsNewTransfer) {
1017
if (DataLength == 0) {
1018
return EFI_INVALID_PARAMETER;
1021
if ((*DataToggle != 1) && (*DataToggle != 0)) {
1022
return EFI_INVALID_PARAMETER;
1025
if ((PollingInterval > 255) || (PollingInterval < 1)) {
1026
return EFI_INVALID_PARAMETER;
1030
OldTpl = gBS->RaiseTPL (EHC_TPL);
1031
Ehc = EHC_FROM_THIS (This);
1034
// Delete Async interrupt transfer request. DataToggle will return
1035
// the next data toggle to use.
1037
if (!IsNewTransfer) {
1038
Status = EhciDelAsyncIntTransfer (Ehc, DeviceAddress, EndPointAddress, DataToggle);
1040
DEBUG ((EFI_D_INFO, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status));
1044
Status = EFI_SUCCESS;
1046
if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
1047
DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: HC is halt\n"));
1048
EhcAckAllInterrupt (Ehc);
1050
Status = EFI_DEVICE_ERROR;
1054
EhcAckAllInterrupt (Ehc);
1056
Data = AllocatePool (DataLength);
1059
DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: failed to allocate buffer\n"));
1061
Status = EFI_OUT_OF_RESOURCES;
1065
Urb = EhcCreateUrb (
1071
MaximumPacketLength,
1073
EHC_INT_TRANSFER_ASYNC,
1083
DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: failed to create URB\n"));
1085
gBS->FreePool (Data);
1086
Status = EFI_OUT_OF_RESOURCES;
1091
// New asynchronous transfer must inserted to the head.
1092
// Check the comments in EhcMoniteAsyncRequests
1094
EhcLinkQhToPeriod (Ehc, Urb->Qh);
1095
InsertHeadList (&Ehc->AsyncIntTransfers, &Urb->UrbList);
1098
Ehc->PciIo->Flush (Ehc->PciIo);
1099
gBS->RestoreTPL (OldTpl);
1106
Submits synchronous interrupt transfer to an interrupt endpoint
1109
@param This This EFI_USB2_HC_PROTOCOL instance.
1110
@param DeviceAddress Target device address.
1111
@param EndPointAddress Endpoint number and its direction encoded in bit 7
1112
@param DeviceSpeed Indicates device speed.
1113
@param MaximumPacketLength Maximum packet size the target endpoint is capable
1114
of sending or receiving.
1115
@param Data Buffer of data that will be transmitted to USB
1116
device or received from USB device.
1117
@param DataLength On input, the size, in bytes, of the data buffer; On
1118
output, the number of bytes transferred.
1119
@param DataToggle On input, the initial data toggle to use; on output,
1120
it is updated to indicate the next data toggle.
1121
@param TimeOut Maximum time, in second, to complete.
1122
@param Translator Transaction translator to use.
1123
@param TransferResult Variable to receive the transfer result.
1125
@return EFI_SUCCESS The transfer was completed successfully.
1126
@return EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
1127
@return EFI_INVALID_PARAMETER Some parameters are invalid.
1128
@return EFI_TIMEOUT The transfer failed due to timeout.
1129
@return EFI_DEVICE_ERROR The failed due to host controller or device error
1134
EhcSyncInterruptTransfer (
1135
IN EFI_USB2_HC_PROTOCOL *This,
1136
IN UINT8 DeviceAddress,
1137
IN UINT8 EndPointAddress,
1138
IN UINT8 DeviceSpeed,
1139
IN UINTN MaximumPacketLength,
1141
IN OUT UINTN *DataLength,
1142
IN OUT UINT8 *DataToggle,
1144
IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
1145
OUT UINT32 *TransferResult
1154
// Validates parameters
1156
if ((DataLength == NULL) || (*DataLength == 0) ||
1157
(Data == NULL) || (TransferResult == NULL)) {
1158
return EFI_INVALID_PARAMETER;
1161
if (!EHCI_IS_DATAIN (EndPointAddress)) {
1162
return EFI_INVALID_PARAMETER;
1165
if ((*DataToggle != 1) && (*DataToggle != 0)) {
1166
return EFI_INVALID_PARAMETER;
1169
if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) ||
1170
((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||
1171
((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072))) {
1172
return EFI_INVALID_PARAMETER;
1175
OldTpl = gBS->RaiseTPL (EHC_TPL);
1176
Ehc = EHC_FROM_THIS (This);
1178
*TransferResult = EFI_USB_ERR_SYSTEM;
1179
Status = EFI_DEVICE_ERROR;
1181
if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {
1182
DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));
1184
EhcAckAllInterrupt (Ehc);
1188
EhcAckAllInterrupt (Ehc);
1190
Urb = EhcCreateUrb (
1196
MaximumPacketLength,
1198
EHC_INT_TRANSFER_SYNC,
1208
DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: failed to create URB\n"));
1210
Status = EFI_OUT_OF_RESOURCES;
1214
EhcLinkQhToPeriod (Ehc, Urb->Qh);
1215
Status = EhcExecTransfer (Ehc, Urb, TimeOut);
1216
EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);
1218
*TransferResult = Urb->Result;
1219
*DataLength = Urb->Completed;
1220
*DataToggle = Urb->DataToggle;
1222
if (*TransferResult == EFI_USB_NOERROR) {
1223
Status = EFI_SUCCESS;
1227
Ehc->PciIo->Flush (Ehc->PciIo);
1228
gBS->RestoreTPL (OldTpl);
1230
if (EFI_ERROR (Status)) {
1231
DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));
1239
Submits isochronous transfer to a target USB device.
1241
@param This This EFI_USB2_HC_PROTOCOL instance.
1242
@param DeviceAddress Target device address.
1243
@param EndPointAddress End point address with its direction.
1244
@param DeviceSpeed Device speed, Low speed device doesn't support this
1246
@param MaximumPacketLength Maximum packet size that the endpoint is capable of
1247
sending or receiving.
1248
@param DataBuffersNumber Number of data buffers prepared for the transfer.
1249
@param Data Array of pointers to the buffers of data that will
1250
be transmitted to USB device or received from USB
1252
@param DataLength The size, in bytes, of the data buffer.
1253
@param Translator Transaction translator to use.
1254
@param TransferResult Variable to receive the transfer result.
1256
@return EFI_UNSUPPORTED Isochronous transfer is unsupported.
1261
EhcIsochronousTransfer (
1262
IN EFI_USB2_HC_PROTOCOL *This,
1263
IN UINT8 DeviceAddress,
1264
IN UINT8 EndPointAddress,
1265
IN UINT8 DeviceSpeed,
1266
IN UINTN MaximumPacketLength,
1267
IN UINT8 DataBuffersNumber,
1268
IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
1269
IN UINTN DataLength,
1270
IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
1271
OUT UINT32 *TransferResult
1274
return EFI_UNSUPPORTED;
1279
Submits Async isochronous transfer to a target USB device.
1281
@param This This EFI_USB2_HC_PROTOCOL instance.
1282
@param DeviceAddress Target device address.
1283
@param EndPointAddress End point address with its direction.
1284
@param DeviceSpeed Device speed, Low speed device doesn't support this
1286
@param MaximumPacketLength Maximum packet size that the endpoint is capable of
1287
sending or receiving.
1288
@param DataBuffersNumber Number of data buffers prepared for the transfer.
1289
@param Data Array of pointers to the buffers of data that will
1290
be transmitted to USB device or received from USB
1292
@param DataLength The size, in bytes, of the data buffer.
1293
@param Translator Transaction translator to use.
1294
@param IsochronousCallBack Function to be called when the transfer complete.
1295
@param Context Context passed to the call back function as
1298
@return EFI_UNSUPPORTED Isochronous transfer isn't supported.
1303
EhcAsyncIsochronousTransfer (
1304
IN EFI_USB2_HC_PROTOCOL *This,
1305
IN UINT8 DeviceAddress,
1306
IN UINT8 EndPointAddress,
1307
IN UINT8 DeviceSpeed,
1308
IN UINTN MaximumPacketLength,
1309
IN UINT8 DataBuffersNumber,
1310
IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
1311
IN UINTN DataLength,
1312
IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
1313
IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
1317
return EFI_UNSUPPORTED;
1321
Entry point for EFI drivers.
1323
@param ImageHandle EFI_HANDLE.
1324
@param SystemTable EFI_SYSTEM_TABLE.
1326
@return EFI_SUCCESS Success.
1327
EFI_DEVICE_ERROR Fail.
1332
EhcDriverEntryPoint (
1333
IN EFI_HANDLE ImageHandle,
1334
IN EFI_SYSTEM_TABLE *SystemTable
1337
return EfiLibInstallDriverBindingComponentName2 (
1340
&gEhciDriverBinding,
1342
&gEhciComponentName,
1343
&gEhciComponentName2
1349
Test to see if this driver supports ControllerHandle. Any
1350
ControllerHandle that has Usb2HcProtocol installed will
1353
@param This Protocol instance pointer.
1354
@param Controller Handle of device to test.
1355
@param RemainingDevicePath Not used.
1357
@return EFI_SUCCESS This driver supports this device.
1358
@return EFI_UNSUPPORTED This driver does not support this device.
1363
EhcDriverBindingSupported (
1364
IN EFI_DRIVER_BINDING_PROTOCOL *This,
1365
IN EFI_HANDLE Controller,
1366
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1370
EFI_PCI_IO_PROTOCOL *PciIo;
1371
USB_CLASSC UsbClassCReg;
1374
// Test whether there is PCI IO Protocol attached on the controller handle.
1376
Status = gBS->OpenProtocol (
1378
&gEfiPciIoProtocolGuid,
1380
This->DriverBindingHandle,
1382
EFI_OPEN_PROTOCOL_BY_DRIVER
1385
if (EFI_ERROR (Status)) {
1386
return EFI_UNSUPPORTED;
1389
Status = PciIo->Pci.Read (
1392
PCI_CLASSCODE_OFFSET,
1393
sizeof (USB_CLASSC) / sizeof (UINT8),
1397
if (EFI_ERROR (Status)) {
1398
Status = EFI_UNSUPPORTED;
1403
// Test whether the controller belongs to Ehci type
1405
if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) || (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB)
1406
|| ((UsbClassCReg.ProgInterface != PCI_IF_EHCI) && (UsbClassCReg.ProgInterface !=PCI_IF_UHCI))) {
1408
Status = EFI_UNSUPPORTED;
1412
gBS->CloseProtocol (
1414
&gEfiPciIoProtocolGuid,
1415
This->DriverBindingHandle,
1423
Get the usb debug port related information.
1425
@param Ehc The EHCI device.
1427
@retval RETURN_SUCCESS Get debug port number, bar and offset successfully.
1428
@retval Others The usb host controller does not supported usb debug port capability.
1432
EhcGetUsbDebugPortInfo (
1436
EFI_PCI_IO_PROTOCOL *PciIo;
1438
UINT8 CapabilityPtr;
1443
ASSERT (Ehc->PciIo != NULL);
1447
// Detect if the EHCI host controller support Capaility Pointer.
1449
Status = PciIo->Pci.Read (
1452
PCI_PRIMARY_STATUS_OFFSET,
1457
if (EFI_ERROR (Status)) {
1461
if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) {
1463
// The Pci Device Doesn't Support Capability Pointer.
1465
return EFI_UNSUPPORTED;
1469
// Get Pointer To Capability List
1471
Status = PciIo->Pci.Read (
1474
PCI_CAPBILITY_POINTER_OFFSET,
1479
if (EFI_ERROR (Status)) {
1484
// Find Capability ID 0xA, Which Is For Debug Port
1486
while (CapabilityPtr != 0) {
1487
Status = PciIo->Pci.Read (
1495
if (EFI_ERROR (Status)) {
1499
if (CapabilityId == EHC_DEBUG_PORT_CAP_ID) {
1503
Status = PciIo->Pci.Read (
1511
if (EFI_ERROR (Status)) {
1517
// No Debug Port Capability Found
1519
if (CapabilityPtr == 0) {
1520
return EFI_UNSUPPORTED;
1524
// Get The Base Address Of Debug Port Register In Debug Port Capability Register
1526
Status = PciIo->Pci.Read (
1534
if (EFI_ERROR (Status)) {
1538
Ehc->DebugPortOffset = DebugPort & 0x1FFF;
1539
Ehc->DebugPortBarNum = (UINT8)((DebugPort >> 13) - 1);
1540
Ehc->DebugPortNum = (UINT8)((Ehc->HcStructParams & 0x00F00000) >> 20);
1547
Create and initialize a USB2_HC_DEV.
1549
@param PciIo The PciIo on this device.
1550
@param DevicePath The device path of host controller.
1551
@param OriginalPciAttributes Original PCI attributes.
1553
@return The allocated and initialized USB2_HC_DEV structure if created,
1559
IN EFI_PCI_IO_PROTOCOL *PciIo,
1560
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1561
IN UINT64 OriginalPciAttributes
1567
Ehc = AllocateZeroPool (sizeof (USB2_HC_DEV));
1574
// Init EFI_USB2_HC_PROTOCOL interface and private data structure
1576
Ehc->Signature = USB2_HC_DEV_SIGNATURE;
1578
Ehc->Usb2Hc.GetCapability = EhcGetCapability;
1579
Ehc->Usb2Hc.Reset = EhcReset;
1580
Ehc->Usb2Hc.GetState = EhcGetState;
1581
Ehc->Usb2Hc.SetState = EhcSetState;
1582
Ehc->Usb2Hc.ControlTransfer = EhcControlTransfer;
1583
Ehc->Usb2Hc.BulkTransfer = EhcBulkTransfer;
1584
Ehc->Usb2Hc.AsyncInterruptTransfer = EhcAsyncInterruptTransfer;
1585
Ehc->Usb2Hc.SyncInterruptTransfer = EhcSyncInterruptTransfer;
1586
Ehc->Usb2Hc.IsochronousTransfer = EhcIsochronousTransfer;
1587
Ehc->Usb2Hc.AsyncIsochronousTransfer = EhcAsyncIsochronousTransfer;
1588
Ehc->Usb2Hc.GetRootHubPortStatus = EhcGetRootHubPortStatus;
1589
Ehc->Usb2Hc.SetRootHubPortFeature = EhcSetRootHubPortFeature;
1590
Ehc->Usb2Hc.ClearRootHubPortFeature = EhcClearRootHubPortFeature;
1591
Ehc->Usb2Hc.MajorRevision = 0x2;
1592
Ehc->Usb2Hc.MinorRevision = 0x0;
1595
Ehc->DevicePath = DevicePath;
1596
Ehc->OriginalPciAttributes = OriginalPciAttributes;
1598
InitializeListHead (&Ehc->AsyncIntTransfers);
1600
Ehc->HcStructParams = EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET);
1601
Ehc->HcCapParams = EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET);
1602
Ehc->CapLen = EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET) & 0x0FF;
1604
DEBUG ((EFI_D_INFO, "EhcCreateUsb2Hc: capability length %d\n", Ehc->CapLen));
1607
// EHCI Controllers with a CapLen of 0 are ignored.
1609
if (Ehc->CapLen == 0) {
1610
gBS->FreePool (Ehc);
1614
EhcGetUsbDebugPortInfo (Ehc);
1617
// Create AsyncRequest Polling Timer
1619
Status = gBS->CreateEvent (
1620
EVT_TIMER | EVT_NOTIFY_SIGNAL,
1622
EhcMonitorAsyncRequests,
1627
if (EFI_ERROR (Status)) {
1628
gBS->FreePool (Ehc);
1636
One notified function to stop the Host Controller when gBS->ExitBootServices() called.
1638
@param Event Pointer to this event
1639
@param Context Event hanlder private data
1644
EhcExitBootService (
1652
Ehc = (USB2_HC_DEV *) Context;
1655
// Reset the Host Controller
1657
EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
1662
Starting the Usb EHCI Driver.
1664
@param This Protocol instance pointer.
1665
@param Controller Handle of device to test.
1666
@param RemainingDevicePath Not used.
1668
@return EFI_SUCCESS supports this device.
1669
@return EFI_UNSUPPORTED do not support this device.
1670
@return EFI_DEVICE_ERROR cannot be started due to device Error.
1671
@return EFI_OUT_OF_RESOURCES cannot allocate resources.
1676
EhcDriverBindingStart (
1677
IN EFI_DRIVER_BINDING_PROTOCOL *This,
1678
IN EFI_HANDLE Controller,
1679
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1684
EFI_PCI_IO_PROTOCOL *PciIo;
1685
EFI_PCI_IO_PROTOCOL *Instance;
1687
UINT64 OriginalPciAttributes;
1688
BOOLEAN PciAttributesSaved;
1689
USB_CLASSC UsbClassCReg;
1690
EFI_HANDLE *HandleBuffer;
1691
UINTN NumberOfHandles;
1693
UINTN UhciSegmentNumber;
1694
UINTN UhciBusNumber;
1695
UINTN UhciDeviceNumber;
1696
UINTN UhciFunctionNumber;
1697
UINTN EhciSegmentNumber;
1698
UINTN EhciBusNumber;
1699
UINTN EhciDeviceNumber;
1700
UINTN EhciFunctionNumber;
1702
EFI_DEVICE_PATH_PROTOCOL *HcDevicePath;
1705
// Open the PciIo Protocol, then enable the USB host controller
1707
Status = gBS->OpenProtocol (
1709
&gEfiPciIoProtocolGuid,
1711
This->DriverBindingHandle,
1713
EFI_OPEN_PROTOCOL_BY_DRIVER
1716
if (EFI_ERROR (Status)) {
1721
// Open Device Path Protocol for on USB host controller
1723
HcDevicePath = NULL;
1724
Status = gBS->OpenProtocol (
1726
&gEfiDevicePathProtocolGuid,
1727
(VOID **) &HcDevicePath,
1728
This->DriverBindingHandle,
1730
EFI_OPEN_PROTOCOL_GET_PROTOCOL
1733
PciAttributesSaved = FALSE;
1735
// Save original PCI attributes
1737
Status = PciIo->Attributes (
1739
EfiPciIoAttributeOperationGet,
1741
&OriginalPciAttributes
1744
if (EFI_ERROR (Status)) {
1747
PciAttributesSaved = TRUE;
1749
Status = PciIo->Attributes (
1751
EfiPciIoAttributeOperationSupported,
1755
if (!EFI_ERROR (Status)) {
1756
Supports &= EFI_PCI_DEVICE_ENABLE;
1757
Status = PciIo->Attributes (
1759
EfiPciIoAttributeOperationEnable,
1765
if (EFI_ERROR (Status)) {
1766
DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to enable controller\n"));
1771
// Get the Pci device class code.
1773
Status = PciIo->Pci.Read (
1776
PCI_CLASSCODE_OFFSET,
1777
sizeof (USB_CLASSC) / sizeof (UINT8),
1781
if (EFI_ERROR (Status)) {
1782
Status = EFI_UNSUPPORTED;
1786
// determine if the device is UHCI host controller or not. If yes, then find out the
1787
// companion usb ehci host controller and force EHCI driver get attached to it before
1788
// UHCI driver attaches to UHCI host controller.
1790
if ((UsbClassCReg.ProgInterface == PCI_IF_UHCI) &&
1791
(UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
1792
(UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
1793
Status = PciIo->GetLocation (
1800
if (EFI_ERROR (Status)) {
1804
Status = gBS->LocateHandleBuffer (
1806
&gEfiPciIoProtocolGuid,
1811
if (EFI_ERROR (Status)) {
1815
for (Index = 0; Index < NumberOfHandles; Index++) {
1817
// Get the device path on this handle
1819
Status = gBS->HandleProtocol (
1820
HandleBuffer[Index],
1821
&gEfiPciIoProtocolGuid,
1824
ASSERT_EFI_ERROR (Status);
1826
Status = Instance->Pci.Read (
1829
PCI_CLASSCODE_OFFSET,
1830
sizeof (USB_CLASSC) / sizeof (UINT8),
1834
if (EFI_ERROR (Status)) {
1835
Status = EFI_UNSUPPORTED;
1839
if ((UsbClassCReg.ProgInterface == PCI_IF_EHCI) &&
1840
(UsbClassCReg.BaseCode == PCI_CLASS_SERIAL) &&
1841
(UsbClassCReg.SubClassCode == PCI_CLASS_SERIAL_USB)) {
1842
Status = Instance->GetLocation (
1849
if (EFI_ERROR (Status)) {
1853
// Currently, the judgment on the companion usb host controller is through the
1854
// same bus number, which may vary on different platform.
1856
if (EhciBusNumber == UhciBusNumber) {
1857
gBS->CloseProtocol (
1859
&gEfiPciIoProtocolGuid,
1860
This->DriverBindingHandle,
1863
EhcDriverBindingStart(This, HandleBuffer[Index], NULL);
1867
Status = EFI_NOT_FOUND;
1872
// Create then install USB2_HC_PROTOCOL
1874
Ehc = EhcCreateUsb2Hc (PciIo, HcDevicePath, OriginalPciAttributes);
1877
DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to create USB2_HC\n"));
1879
Status = EFI_OUT_OF_RESOURCES;
1883
Status = gBS->InstallProtocolInterface (
1885
&gEfiUsb2HcProtocolGuid,
1886
EFI_NATIVE_INTERFACE,
1890
if (EFI_ERROR (Status)) {
1891
DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));
1896
// Robustnesss improvement such as for Duet platform
1897
// Default is not required.
1899
if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
1900
EhcClearLegacySupport (Ehc);
1903
if (Ehc->DebugPortNum != 0) {
1904
State = EhcReadDbgRegister(Ehc, 0);
1905
if ((State & (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) != (USB_DEBUG_PORT_IN_USE | USB_DEBUG_PORT_OWNER)) {
1906
EhcResetHC (Ehc, EHC_RESET_TIMEOUT);
1910
Status = EhcInitHC (Ehc);
1912
if (EFI_ERROR (Status)) {
1913
DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to init host controller\n"));
1914
goto UNINSTALL_USBHC;
1918
// Start the asynchronous interrupt monitor
1920
Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_INTERVAL);
1922
if (EFI_ERROR (Status)) {
1923
DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));
1925
EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
1926
goto UNINSTALL_USBHC;
1930
// Create event to stop the HC when exit boot service.
1932
Status = gBS->CreateEventEx (
1937
&gEfiEventExitBootServicesGuid,
1938
&Ehc->ExitBootServiceEvent
1940
if (EFI_ERROR (Status)) {
1941
goto UNINSTALL_USBHC;
1945
// Install the component name protocol, don't fail the start
1946
// because of something for display.
1950
gEhciComponentName.SupportedLanguages,
1951
&Ehc->ControllerNameTable,
1952
L"Enhanced Host Controller (USB 2.0)",
1957
gEhciComponentName2.SupportedLanguages,
1958
&Ehc->ControllerNameTable,
1959
L"Enhanced Host Controller (USB 2.0)",
1964
DEBUG ((EFI_D_INFO, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller));
1968
gBS->UninstallProtocolInterface (
1970
&gEfiUsb2HcProtocolGuid,
1976
gBS->CloseEvent (Ehc->PollTimer);
1977
gBS->FreePool (Ehc);
1980
if (PciAttributesSaved) {
1982
// Restore original PCI attributes
1986
EfiPciIoAttributeOperationSet,
1987
OriginalPciAttributes,
1992
gBS->CloseProtocol (
1994
&gEfiPciIoProtocolGuid,
1995
This->DriverBindingHandle,
2004
Stop this driver on ControllerHandle. Support stoping any child handles
2005
created by this driver.
2007
@param This Protocol instance pointer.
2008
@param Controller Handle of device to stop driver on.
2009
@param NumberOfChildren Number of Children in the ChildHandleBuffer.
2010
@param ChildHandleBuffer List of handles for the children we need to stop.
2012
@return EFI_SUCCESS Success.
2013
@return EFI_DEVICE_ERROR Fail.
2018
EhcDriverBindingStop (
2019
IN EFI_DRIVER_BINDING_PROTOCOL *This,
2020
IN EFI_HANDLE Controller,
2021
IN UINTN NumberOfChildren,
2022
IN EFI_HANDLE *ChildHandleBuffer
2026
EFI_USB2_HC_PROTOCOL *Usb2Hc;
2027
EFI_PCI_IO_PROTOCOL *PciIo;
2031
// Test whether the Controller handler passed in is a valid
2032
// Usb controller handle that should be supported, if not,
2033
// return the error status directly
2035
Status = gBS->OpenProtocol (
2037
&gEfiUsb2HcProtocolGuid,
2039
This->DriverBindingHandle,
2041
EFI_OPEN_PROTOCOL_GET_PROTOCOL
2044
if (EFI_ERROR (Status)) {
2048
Ehc = EHC_FROM_THIS (Usb2Hc);
2052
// Stop AsyncRequest Polling timer then stop the EHCI driver
2053
// and uninstall the EHCI protocl.
2055
gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL);
2056
EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);
2058
Status = gBS->UninstallProtocolInterface (
2060
&gEfiUsb2HcProtocolGuid,
2064
if (EFI_ERROR (Status)) {
2068
if (Ehc->PollTimer != NULL) {
2069
gBS->CloseEvent (Ehc->PollTimer);
2072
if (Ehc->ExitBootServiceEvent != NULL) {
2073
gBS->CloseEvent (Ehc->ExitBootServiceEvent);
2078
if (Ehc->ControllerNameTable != NULL) {
2079
FreeUnicodeStringTable (Ehc->ControllerNameTable);
2083
// Disable routing of all ports to EHCI controller, so all ports are
2084
// routed back to the UHCI controller.
2086
EhcClearOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);
2089
// Restore original PCI attributes
2093
EfiPciIoAttributeOperationSet,
2094
Ehc->OriginalPciAttributes,
2098
gBS->CloseProtocol (
2100
&gEfiPciIoProtocolGuid,
2101
This->DriverBindingHandle,