\r
Usb Bus Driver Binding and Bus IO Protocol.\r
\r
-Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "UsbBus.h"\r
\r
-//\r
-// USB_BUS_PROTOCOL is only used to locate USB_BUS\r
-//\r
-EFI_GUID mUsbBusProtocolGuid = EFI_USB_BUS_PROTOCOL_GUID;\r
-\r
EFI_USB_IO_PROTOCOL mUsbIoProtocol = {\r
UsbIoControlTransfer,\r
UsbIoBulkTransfer,\r
NULL\r
};\r
\r
-\r
/**\r
USB_IO function to execute a control transfer. This\r
function will execute the USB transfer. If transfer\r
USB_ENDPOINT_DESC *EpDesc;\r
EFI_TPL OldTpl;\r
EFI_STATUS Status;\r
+ UINTN RequestedDataLength;\r
\r
if (UsbStatus == NULL) {\r
return EFI_INVALID_PARAMETER;\r
UsbIf = USB_INTERFACE_FROM_USBIO (This);\r
Dev = UsbIf->Device;\r
\r
+ RequestedDataLength = DataLength;\r
Status = UsbHcControlTransfer (\r
Dev->Bus,\r
Dev->Address,\r
&Dev->Translator,\r
UsbStatus\r
);\r
+ //\r
+ // If the request completed sucessfully and the Direction of the request is\r
+ // EfiUsbDataIn or EfiUsbDataOut, then make sure the actual number of bytes\r
+ // transfered is the same as the number of bytes requested. If a different\r
+ // number of bytes were transfered, then return EFI_DEVICE_ERROR.\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+ if (Direction != EfiUsbNoData && DataLength != RequestedDataLength) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto ON_EXIT;\r
+ }\r
+ }\r
\r
if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {\r
//\r
// Clear TT buffer when CTRL/BULK split transaction failes\r
// Clear the TRANSLATOR TT buffer, not parent's buffer\r
//\r
- ASSERT (Dev->Translator.TranslatorHubAddress < USB_MAX_DEVICES);\r
+ ASSERT (Dev->Translator.TranslatorHubAddress < Dev->Bus->MaxDevices);\r
if (Dev->Translator.TranslatorHubAddress != 0) {\r
UsbHubCtrlClearTTBuffer (\r
Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],\r
// Clear TT buffer when CTRL/BULK split transaction failes.\r
// Clear the TRANSLATOR TT buffer, not parent's buffer\r
//\r
- ASSERT (Dev->Translator.TranslatorHubAddress < USB_MAX_DEVICES);\r
+ ASSERT (Dev->Translator.TranslatorHubAddress < Dev->Bus->MaxDevices);\r
if (Dev->Translator.TranslatorHubAddress != 0) {\r
UsbHubCtrlClearTTBuffer (\r
Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],\r
USB_INTERFACE *UsbIf;\r
USB_INTERFACE *HubIf;\r
USB_DEVICE *Dev;\r
- UINT8 Address;\r
EFI_TPL OldTpl;\r
EFI_STATUS Status;\r
+ UINT8 DevAddress;\r
\r
OldTpl = gBS->RaiseTPL (USB_BUS_TPL);\r
\r
goto ON_EXIT;\r
}\r
\r
+ HubIf->HubApi->ClearPortChange (HubIf, Dev->ParentPort);\r
+\r
//\r
- // Reset the device to its current address. The device now has a\r
- // address of ZERO, so need to set Dev->Address to zero first for\r
- // host to communicate with the device\r
+ // Reset the device to its current address. The device now has an address\r
+ // of ZERO after port reset, so need to set Dev->Address to the device again for\r
+ // host to communicate with it.\r
//\r
- Address = Dev->Address;\r
- Dev->Address = 0;\r
- Status = UsbSetAddress (Dev, Address);\r
+ DevAddress = Dev->Address;\r
+ Dev->Address = 0;\r
+ Status = UsbSetAddress (Dev, DevAddress);\r
+ Dev->Address = DevAddress;\r
\r
gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);\r
- \r
+\r
if (EFI_ERROR (Status)) {\r
+ //\r
+ // It may fail due to device disconnection or other reasons.\r
+ //\r
DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set address for device %d - %r\n",\r
- Address, Status));\r
+ Dev->Address, Status));\r
\r
goto ON_EXIT;\r
}\r
\r
- Dev->Address = Address;\r
+ DEBUG (( EFI_D_INFO, "UsbIoPortReset: device is now ADDRESSED at %d\n", Dev->Address));\r
\r
- DEBUG (( EFI_D_INFO, "UsbIoPortReset: device is now ADDRESSED at %d\n", Address));\r
- \r
//\r
// Reset the current active configure, after this device\r
// is in CONFIGURED state.\r
\r
if (EFI_ERROR (Status)) {\r
DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set configure for device %d - %r\n",\r
- Address, Status));\r
+ Dev->Address, Status));\r
}\r
}\r
\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- UsbBus->Signature = USB_BUS_SIGNATURE;\r
- UsbBus->HostHandle = Controller;\r
+ UsbBus->Signature = USB_BUS_SIGNATURE;\r
+ UsbBus->HostHandle = Controller;\r
+ UsbBus->MaxDevices = USB_MAX_DEVICES;\r
\r
Status = gBS->OpenProtocol (\r
Controller,\r
goto CLOSE_HC;\r
}\r
\r
- UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);\r
- UsbHcSetState (UsbBus, EfiUsbHcStateOperational);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // The EFI_USB2_HC_PROTOCOL is produced for XHCI support.\r
+ // Then its max supported devices are 256. Otherwise it's 128.\r
+ //\r
+ ASSERT (UsbBus->Usb2Hc != NULL);\r
+ if (UsbBus->Usb2Hc->MajorRevision == 0x3) {\r
+ UsbBus->MaxDevices = 256;\r
+ }\r
+ }\r
\r
//\r
// Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.\r
//\r
Status = gBS->InstallProtocolInterface (\r
&Controller,\r
- &mUsbBusProtocolGuid,\r
+ &gEfiCallerIdGuid,\r
EFI_NATIVE_INTERFACE,\r
&UsbBus->BusId\r
);\r
RootHub->Bus = UsbBus;\r
RootHub->NumOfInterface = 1;\r
RootHub->Interfaces[0] = RootIf;\r
+ RootHub->Tier = 0;\r
RootIf->Signature = USB_INTERFACE_SIGNATURE;\r
RootIf->Device = RootHub;\r
RootIf->DevicePath = UsbBus->DevicePath;\r
\r
+ //\r
+ // Report Status Code here since we will enumerate the USB devices\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_IO_BUS_USB | EFI_IOB_PC_DETECT),\r
+ UsbBus->DevicePath\r
+ );\r
+\r
Status = mUsbRootHubApi.Init (RootIf);\r
\r
if (EFI_ERROR (Status)) {\r
}\r
\r
UNINSTALL_USBBUS:\r
- gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId);\r
+ gBS->UninstallProtocolInterface (Controller, &gEfiCallerIdGuid, &UsbBus->BusId);\r
\r
CLOSE_HC:\r
if (UsbBus->Usb2Hc != NULL) {\r
//\r
if (RemainingDevicePath != NULL) {\r
//\r
- // Check if RemainingDevicePath is the End of Device Path Node, \r
+ // Check if RemainingDevicePath is the End of Device Path Node,\r
// if yes, go on checking other conditions\r
//\r
if (!IsDevicePathEnd (RemainingDevicePath)) {\r
// check its validation\r
//\r
DevicePathNode.DevPath = RemainingDevicePath;\r
- \r
+\r
if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) ||\r
(DevicePathNode.DevPath->SubType != MSG_USB_DP &&\r
DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP\r
&& DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP\r
)) {\r
- \r
+\r
return EFI_UNSUPPORTED;\r
}\r
}\r
if (Status == EFI_ALREADY_STARTED) {\r
return EFI_SUCCESS;\r
}\r
- \r
+\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
Controller\r
);\r
}\r
- \r
+\r
//\r
// Open the EFI Device Path protocol needed to perform the supported test\r
//\r
{\r
EFI_USB_BUS_PROTOCOL *UsbBusId;\r
EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &ParentDevicePath,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Report Status Code here since we will initialize the host controller\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_IO_BUS_USB | EFI_IOB_PC_INIT),\r
+ ParentDevicePath\r
+ );\r
\r
//\r
// Locate the USB bus protocol, if it is found, USB bus\r
//\r
Status = gBS->OpenProtocol (\r
Controller,\r
- &mUsbBusProtocolGuid,\r
+ &gEfiCallerIdGuid,\r
(VOID **) &UsbBusId,\r
This->DriverBindingHandle,\r
Controller,\r
//\r
// If first start, build the bus execute environment and install bus protocol\r
//\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_IO_BUS_USB | EFI_P_PC_ENABLE));\r
Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
//\r
Status = gBS->OpenProtocol (\r
Controller,\r
- &mUsbBusProtocolGuid,\r
+ &gEfiCallerIdGuid,\r
(VOID **) &UsbBusId,\r
This->DriverBindingHandle,\r
Controller,\r
//\r
// If RemainingDevicePath is the End of Device Path Node,\r
// skip enumerate any device and return EFI_SUCESSS\r
- // \r
+ //\r
return EFI_SUCCESS;\r
}\r
}\r
EFI_TPL OldTpl;\r
UINTN Index;\r
EFI_STATUS Status;\r
+ EFI_STATUS ReturnStatus;\r
\r
Status = EFI_SUCCESS;\r
\r
//\r
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
\r
+ ReturnStatus = EFI_SUCCESS;\r
for (Index = 0; Index < NumberOfChildren; Index++) {\r
Status = gBS->OpenProtocol (\r
ChildHandleBuffer[Index],\r
UsbIf = USB_INTERFACE_FROM_USBIO (UsbIo);\r
UsbDev = UsbIf->Device;\r
\r
- UsbRemoveDevice (UsbDev);\r
+ ReturnStatus = UsbRemoveDevice (UsbDev);\r
}\r
\r
gBS->RestoreTPL (OldTpl);\r
- return EFI_SUCCESS;\r
+ return ReturnStatus;\r
}\r
\r
DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %p\n", Controller));\r
//\r
Status = gBS->OpenProtocol (\r
Controller,\r
- &mUsbBusProtocolGuid,\r
+ &gEfiCallerIdGuid,\r
(VOID **) &BusId,\r
This->DriverBindingHandle,\r
Controller,\r
// BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict\r
//\r
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
- UsbHcSetState (Bus, EfiUsbHcStateHalt);\r
\r
RootHub = Bus->Devices[0];\r
RootIf = RootHub->Interfaces[0];\r
\r
- mUsbRootHubApi.Release (RootIf);\r
-\r
- for (Index = 1; Index < USB_MAX_DEVICES; Index++) {\r
+ ASSERT (Bus->MaxDevices <= 256);\r
+ ReturnStatus = EFI_SUCCESS;\r
+ for (Index = 1; Index < Bus->MaxDevices; Index++) {\r
if (Bus->Devices[Index] != NULL) {\r
- UsbRemoveDevice (Bus->Devices[Index]);\r
+ Status = UsbRemoveDevice (Bus->Devices[Index]);\r
+ if (EFI_ERROR (Status)) {\r
+ ReturnStatus = Status;\r
+ }\r
}\r
}\r
\r
gBS->RestoreTPL (OldTpl);\r
\r
- gBS->FreePool (RootIf);\r
- gBS->FreePool (RootHub);\r
- Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);\r
- ASSERT (!EFI_ERROR (Status));\r
+ if (!EFI_ERROR (ReturnStatus)) {\r
+ mUsbRootHubApi.Release (RootIf);\r
+ gBS->FreePool (RootIf);\r
+ gBS->FreePool (RootHub);\r
\r
- //\r
- // Uninstall the bus identifier and close USB_HC/USB2_HC protocols\r
- //\r
- gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &Bus->BusId);\r
+ Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);\r
+ ASSERT (!EFI_ERROR (Status));\r
\r
- if (Bus->Usb2Hc != NULL) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsb2HcProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- }\r
+ //\r
+ // Uninstall the bus identifier and close USB_HC/USB2_HC protocols\r
+ //\r
+ gBS->UninstallProtocolInterface (Controller, &gEfiCallerIdGuid, &Bus->BusId);\r
\r
- if (Bus->UsbHc != NULL) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbHcProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- }\r
+ if (Bus->Usb2Hc != NULL) {\r
+ Status = gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiUsb2HcProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ }\r
\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
+ if (Bus->UsbHc != NULL) {\r
+ Status = gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiUsbHcProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+ }\r
\r
- gBS->FreePool (Bus);\r
+ if (!EFI_ERROR (Status)) {\r
+ gBS->CloseProtocol (\r
+ Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
\r
+ gBS->FreePool (Bus);\r
+ }\r
+ }\r
return Status;\r
}\r