alder_lake_bios/Insyde/InsydeModulePkg/Bus/Usb/UsbBusPei/UsbIo.c

666 lines
20 KiB
C

/** @file
Usb Io PPI
;******************************************************************************
;* Copyright (c) 2012 - 2019, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "UsbBus.h"
#include "UsbHelper.h"
/**
Pei Usb Control Transfer
@param PeiServices EFI_PEI_SERVICES
@param This PEI_USB3_IO_PPI
@param Request Request packet
@param Direction IN/OUT/NODATA
@param Timeout Time out value in millisecond
@param Data Data buffer
@param DataLength Data length
@retval EFI_SUCCESS Success
**/
EFI_STATUS
EFIAPI
PeiUsbControlTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN EFI_USB_DEVICE_REQUEST *Request,
IN EFI_USB_DATA_DIRECTION Direction,
IN UINT32 Timeout,
IN OUT VOID *Data, OPTIONAL
IN UINTN DataLength OPTIONAL
)
{
PEI_USB_DEVICE *PeiUsbDev;
PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
return PeiUsbDev->Usb3IoPpi.UsbControlTransfer (
PeiServices,
&PeiUsbDev->Usb3IoPpi,
Request,
Direction,
Timeout,
Data,
DataLength
);
}
/**
Pei Usb Bulk Transfer
@param PeiServices EFI_PEI_SERVICES
@param This PEI_USB3_IO_PPI
@param DeviceEndpoint Device Endpoint
@param Data Data buffer
@param DataLength Data length
@param Timeout Time out value in millisecond
@retval EFI_SUCCESS Success
**/
EFI_STATUS
EFIAPI
PeiUsbBulkTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN UINT8 DeviceEndpoint,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN UINTN Timeout
)
{
PEI_USB_DEVICE *PeiUsbDev;
PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
return PeiUsbDev->Usb3IoPpi.UsbBulkTransfer (
PeiServices,
&PeiUsbDev->Usb3IoPpi,
DeviceEndpoint,
Data,
DataLength,
Timeout
);
}
/**
Retrieves the interface Descriptor for that controller.
@param PeiServices EFI_PEI_SERVICES
@param This Indicates the calling context.
@param InterfaceDescriptor A pointer to the caller allocated USB interface
Descriptor.
@retval EFI_SUCCESS
@retval EFI_INVALID_PARAMETER
@retval EFI_NOT_FOUND
**/
EFI_STATUS
EFIAPI
PeiUsbGetInterfaceDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
OUT EFI_USB_INTERFACE_DESCRIPTOR **InterfaceDescriptor
)
{
PEI_USB_DEVICE *PeiUsbDev;
PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
return PeiUsbDev->Usb3IoPpi.UsbGetInterfaceDescriptor (
PeiServices,
&PeiUsbDev->Usb3IoPpi,
InterfaceDescriptor
);
}
/**
Retrieves the endpoint Descriptor for a given endpoint.
@param PeiServices EFI_PEI_SERVICES
@param This Indicates the calling context.
@param EndpointIndex Indicates which endpoint descriptor to retrieve.
The valid range is 0..15.
@param EndpointDescriptor A pointer to the caller allocated USB Endpoint
Descriptor of a USB controller.
@retval EFI_SUCCESS The endpoint descriptor was retrieved successfully.
@retval EFI_INVALID_PARAMETER EndpointIndex is not valid.
EndpointDescriptor is NULL.
@retval EFI_NOT_FOUND The endpoint descriptor cannot be found.
The device may not be correctly configured.
**/
EFI_STATUS
EFIAPI
PeiUsbGetEndpointDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This,
IN UINT8 EndpointIndex,
OUT EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptor
)
{
PEI_USB_DEVICE *PeiUsbDev;
PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
return PeiUsbDev->Usb3IoPpi.UsbGetEndpointDescriptor (
PeiServices,
&PeiUsbDev->Usb3IoPpi,
EndpointIndex,
EndpointDescriptor
);
}
/**
Pei Usb PortReset
@param PeiServices EFI_PEI_SERVICES
@param This PEI_USB3_IO_PPI
@retval EFI_SUCCESS Success
**/
EFI_STATUS
EFIAPI
PeiUsbPortReset (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB_IO_PPI *This
)
{
PEI_USB_DEVICE *PeiUsbDev;
PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
return PeiUsbDev->Usb3IoPpi.UsbPortReset (
PeiServices,
&PeiUsbDev->Usb3IoPpi
);
}
/**
Pei Usb Control Transfer
@param PeiServices EFI_PEI_SERVICES
@param This PEI_USB3_IO_PPI
@param Request Request packet
@param Direction IN/OUT/NODATA
@param Timeout Time out value in millisecond
@param Data Data buffer
@param DataLength Data length
@retval EFI_SUCCESS Success
**/
EFI_STATUS
EFIAPI
PeiUsb3ControlTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB3_IO_PPI *This,
IN EFI_USB_DEVICE_REQUEST *Request,
IN EFI_USB_DATA_DIRECTION Direction,
IN UINT32 Timeout,
IN OUT VOID *Data, OPTIONAL
IN UINTN DataLength OPTIONAL
)
{
EFI_STATUS Status;
PEI_USB_DEVICE *PeiUsbDev;
PEI_USB3_HOST_CONTROLLER_PPI *UsbHcPpi;
UINT32 TransferResult;
PeiUsbDev = PEI_USB3_DEVICE_FROM_THIS (This);
UsbHcPpi = PeiUsbDev->UsbHcPpi;
Status = UsbHcPpi->ControlTransfer (
PeiServices,
UsbHcPpi,
PeiUsbDev->DeviceAddress,
PeiUsbDev->DeviceSpeed,
(PeiUsbDev->MaxPacketSize0 == 9) ? 0x200 : PeiUsbDev->MaxPacketSize0,
Request,
Direction,
Data,
&DataLength,
Timeout,
&PeiUsbDev->Translator,
&TransferResult
);
return Status;
}
/**
Pei Usb Bulk Transfer
@param PeiServices EFI_PEI_SERVICES
@param This PEI_USB3_IO_PPI
@param DeviceEndpoint Device Endpoint
@param Data Data buffer
@param DataLength Data length
@param Timeout Time out value in millisecond
@retval EFI_SUCCESS Success
**/
EFI_STATUS
EFIAPI
PeiUsb3BulkTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB3_IO_PPI *This,
IN UINT8 DeviceEndpoint,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN UINTN Timeout
)
{
EFI_STATUS Status;
PEI_USB_DEVICE *PeiUsbDev;
PEI_USB3_HOST_CONTROLLER_PPI *UsbHcPpi;
UINT32 TransferResult;
UINTN MaxPacketLength;
UINT8 DataToggle;
UINT8 OldToggle;
EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
UINT8 EndpointIndex;
PeiUsbDev = PEI_USB3_DEVICE_FROM_THIS (This);
UsbHcPpi = PeiUsbDev->UsbHcPpi;
EndpointDescriptor = NULL;
EndpointIndex = 0;
while (EndpointIndex < MAX_ENDPOINT) {
Status = PeiUsb3GetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);
if (EFI_ERROR (Status)) {
return EFI_INVALID_PARAMETER;
}
if (EndpointDescriptor->EndpointAddress == DeviceEndpoint) {
break;
}
EndpointIndex++;
}
if (EndpointIndex == MAX_ENDPOINT) {
return EFI_INVALID_PARAMETER;
}
MaxPacketLength = PeiUsbDev->EndpointDesc[EndpointIndex]->MaxPacketSize;
if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
DataToggle = 1;
} else {
DataToggle = 0;
}
OldToggle = DataToggle;
Status = UsbHcPpi->BulkTransfer (
PeiServices,
UsbHcPpi,
PeiUsbDev->DeviceAddress,
DeviceEndpoint,
PeiUsbDev->DeviceSpeed,
MaxPacketLength,
&Data,
DataLength,
&DataToggle,
Timeout,
&PeiUsbDev->Translator,
&TransferResult
);
if (OldToggle != DataToggle) {
PeiUsbDev->DataToggle = (UINT8) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
}
return Status;
}
/**
Pei Usb Sync Interrupt Transfer
@param PeiServices EFI_PEI_SERVICES
@param This PEI_USB3_IO_PPI
@param DeviceEndpoint Device Endpoint
@param Data Data buffer
@param DataLength Data length
@param Timeout Time out value in millisecond
@retval EFI_SUCCESS Success
**/
EFI_STATUS
EFIAPI
PeiUsb3SyncInterruptTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB3_IO_PPI *This,
IN UINT8 DeviceEndpoint,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN UINTN Timeout
)
{
EFI_STATUS Status;
PEI_USB_DEVICE *PeiUsbDev;
PEI_USB3_HOST_CONTROLLER_PPI *UsbHcPpi;
UINT32 TransferResult;
UINTN MaxPacketLength;
UINT8 DataToggle, OldToggle;
EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
UINT8 EndpointIndex;
PeiUsbDev = PEI_USB3_DEVICE_FROM_THIS (This);
UsbHcPpi = PeiUsbDev->UsbHcPpi;
EndpointDescriptor = NULL;
EndpointIndex = 0;
while (EndpointIndex < MAX_ENDPOINT) {
Status = PeiUsb3GetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);
if ( EFI_ERROR(Status)) {
return EFI_INVALID_PARAMETER;
}
if (EndpointDescriptor->EndpointAddress == DeviceEndpoint) {
break;
}
EndpointIndex++;
}
if (EndpointIndex == MAX_ENDPOINT) {
return EFI_INVALID_PARAMETER;
}
MaxPacketLength = PeiUsbDev->EndpointDesc[EndpointIndex]->MaxPacketSize;
if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
DataToggle = 1;
} else {
DataToggle = 0;
}
OldToggle = DataToggle;
Status = UsbHcPpi->InterruptTransfer (
PeiServices,
UsbHcPpi,
PeiUsbDev->DeviceAddress,
DeviceEndpoint,
PeiUsbDev->DeviceSpeed,
MaxPacketLength,
Data,
DataLength,
&DataToggle,
Timeout,
&PeiUsbDev->Translator,
NULL,
NULL,
0,
&TransferResult
);
if (OldToggle != DataToggle) {
PeiUsbDev->DataToggle = (UINT8)(PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
}
return Status;
}
/**
Pei Usb Async Interrupt Transfer
@param PeiServices EFI_PEI_SERVICES
@param This PEI_USB3_IO_PPI
@param DeviceEndpoint Device Endpoint
@param Data Data buffer
@param DataLength Data length
@param InterruptCallBack The Callback function. This function is called if
the asynchronous interrupt transfer is completed.
@param Context Passed to InterruptCallback
@retval EFI_SUCCESS Success
@retval EFI_INVALID_PARAMETER
**/
EFI_STATUS
EFIAPI
PeiUsb3AsyncInterruptTransfer (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB3_IO_PPI *This,
IN UINT8 DeviceEndpoint,
IN OUT VOID *Data,
IN OUT UINTN *DataLength,
IN EFI_ASYNC_USB_TRANSFER_CALLBACK InterruptCallBack ,
IN VOID *Context,
IN UINTN PollingInterval
)
{
EFI_STATUS Status;
PEI_USB_DEVICE *PeiUsbDev;
PEI_USB3_HOST_CONTROLLER_PPI *UsbHcPpi;
UINTN MaxPacketLength;
UINT8 DataToggle;
EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
UINT8 EndpointIndex;
UINT32 TransferResult;
PeiUsbDev = PEI_USB3_DEVICE_FROM_THIS (This);
UsbHcPpi = PeiUsbDev->UsbHcPpi;
EndpointDescriptor = NULL;
EndpointIndex = 0;
while (EndpointIndex < MAX_ENDPOINT) {
Status = PeiUsb3GetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);
if ( EFI_ERROR(Status)) {
return EFI_INVALID_PARAMETER;
}
if (EndpointDescriptor->EndpointAddress == DeviceEndpoint) {
break;
}
EndpointIndex++;
}
if (EndpointIndex == MAX_ENDPOINT) {
return EFI_INVALID_PARAMETER;
}
MaxPacketLength = PeiUsbDev->EndpointDesc[EndpointIndex]->MaxPacketSize;
DataToggle = (UINT8)PeiUsbDev->DataToggle;
Status = UsbHcPpi->InterruptTransfer (
PeiServices,
UsbHcPpi,
PeiUsbDev->DeviceAddress,
DeviceEndpoint,
PeiUsbDev->DeviceSpeed,
MaxPacketLength,
NULL,
DataLength,
&DataToggle,
0,
&PeiUsbDev->Translator,
InterruptCallBack,
Context,
PollingInterval,
&TransferResult
);
return Status;
}
/**
Retrieves the interface Descriptor for that controller.
@param PeiServices EFI_PEI_SERVICES
@param This Indicates the calling context.
@param InterfaceDescriptor A pointer to the caller allocated USB interface
Descriptor.
@retval EFI_SUCCESS
@retval EFI_INVALID_PARAMETER
@retval EFI_NOT_FOUND
**/
EFI_STATUS
EFIAPI
PeiUsb3GetInterfaceDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB3_IO_PPI *This,
OUT EFI_USB_INTERFACE_DESCRIPTOR **InterfaceDescriptor
)
{
PEI_USB_DEVICE *PeiUsbDev;
PeiUsbDev = PEI_USB3_DEVICE_FROM_THIS (This);
*InterfaceDescriptor = PeiUsbDev->InterfaceDesc;
return EFI_SUCCESS;
}
/**
Retrieves the endpoint Descriptor for a given endpoint.
@param PeiServices EFI_PEI_SERVICES
@param This Indicates the calling context.
@param EndpointIndex Indicates which endpoint descriptor to retrieve.
The valid range is 0..15.
@param EndpointDescriptor A pointer to the caller allocated USB Endpoint
Descriptor of a USB controller.
@retval EFI_SUCCESS The endpoint descriptor was retrieved successfully.
@retval EFI_INVALID_PARAMETER EndpointIndex is not valid.
EndpointDescriptor is NULL.
@retval EFI_NOT_FOUND The endpoint descriptor cannot be found.
The device may not be correctly configured.
**/
EFI_STATUS
EFIAPI
PeiUsb3GetEndpointDescriptor (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB3_IO_PPI *This,
IN UINT8 EndpointIndex,
OUT EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptor
)
{
PEI_USB_DEVICE *PeiUsbDev;
PeiUsbDev = PEI_USB3_DEVICE_FROM_THIS (This);
if (EndpointIndex >= PeiUsbDev->InterfaceDesc->NumEndpoints) {
return EFI_NOT_FOUND;
}
*EndpointDescriptor = PeiUsbDev->EndpointDesc[EndpointIndex];
return EFI_SUCCESS;
}
/**
Pei Usb PortReset
@param PeiServices EFI_PEI_SERVICES
@param This PEI_USB3_IO_PPI
@retval EFI_SUCCESS Success
**/
EFI_STATUS
EFIAPI
PeiUsb3PortReset (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB3_IO_PPI *This
)
{
PEI_USB_DEVICE *PeiUsbDev;
EFI_STATUS Status;
UINT8 Address;
PeiUsbDev = PEI_USB3_DEVICE_FROM_THIS (This);
ResetRootPort (
PeiUsbDev,
PeiUsbDev->DeviceAddress
);
//
// Set address
//
Address = PeiUsbDev->DeviceAddress;
PeiUsbDev->DeviceAddress = 0;
Status = PeiUsbSetDeviceAddress (
PeiServices,
This,
Address
);
if (EFI_ERROR (Status)) {
return Status;
}
PeiUsbDev->DeviceAddress = Address;
//
// Set default configuration
//
Status = PeiUsbSetConfiguration (
PeiServices,
This
);
return Status;
}
/**
Clear Endpoint Halt
@param PeiServices EFI_PEI_SERVICES
@param This PEI_USB3_IO_PPI
@param EndpointAddress Endpoint Address
@retval EFI_SUCCESS Success
**/
EFI_STATUS
EFIAPI
PeiUsb3ClearEndpointHalt (
IN EFI_PEI_SERVICES **PeiServices,
IN PEI_USB3_IO_PPI *This,
IN UINT8 EndpointAddress
)
{
EFI_STATUS Status;
PEI_USB_DEVICE *PeiUsbDev;
EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
UINT8 EndpointIndex;
EndpointDescriptor = NULL;
EndpointIndex = 0;
PeiUsbDev = PEI_USB3_DEVICE_FROM_THIS (This);
while (EndpointIndex < MAX_ENDPOINT) {
Status = PeiUsb3GetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);
if (EFI_ERROR (Status)) {
return EFI_INVALID_PARAMETER;
}
if (EndpointDescriptor->EndpointAddress == EndpointAddress) {
break;
}
EndpointIndex++;
}
if (EndpointIndex == MAX_ENDPOINT) {
return EFI_INVALID_PARAMETER;
}
Status = PeiUsbClearDeviceFeature (
PeiServices,
This,
USB_TARGET_ENDPOINT,
USB_FEATURE_ENDPOINT_HALT,
EndpointAddress
);
//
// set data toggle to zero.
//
if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
PeiUsbDev->DataToggle = (UINT8) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
}
return Status;
}