diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/usb/usbbus.c | |
download | zprj-master.tar.xz |
Diffstat (limited to 'Core/EM/usb/usbbus.c')
-rw-r--r-- | Core/EM/usb/usbbus.c | 3118 |
1 files changed, 3118 insertions, 0 deletions
diff --git a/Core/EM/usb/usbbus.c b/Core/EM/usb/usbbus.c new file mode 100644 index 0000000..12002bd --- /dev/null +++ b/Core/EM/usb/usbbus.c @@ -0,0 +1,3118 @@ +//**************************************************************************** +//**************************************************************************** +//** ** +//** (C)Copyright 1985-2015, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** +//** ** +//** Phone (770)-246-8600 ** +//** ** +//**************************************************************************** +//**************************************************************************** + +//**************************************************************************** +// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/usbbus.c 101 11/04/15 9:52p Wilsonlee $ +// +// $Revision: 101 $ +// +// $Date: 11/04/15 9:52p $ +// +//**************************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/usbbus.c $ +// +// 101 11/04/15 9:52p Wilsonlee +// TAG] EIP241067 +// [Category] Improvement +// [Description] Add the device descriptor to the DEV_INFO structure. +// [Files] usb.c, usbdef.h, xhci.c, usbbus.c, AmiUsbController.h +// +// 100 5/28/15 5:01a Wilsonlee +// [TAG] EIP218997 +// [Category] Improvement +// [Description] Break the GetQueue loop if UninstallDevice is failed. +// [Files] usbbus.c, efiusbkb.c, efiusbmass.c, efiusbms.c, +// efiusbpoint.c, efiusbhid.c +// +// 99 5/26/15 10:49p Wilsonlee +// [TAG] EIP219177 +// [Category] Improvement +// [Description] Fixed static code analysis issues in Usb module. +// [Files] UsbInt13.c, ehci.c, usbbus.c +// +// 98 4/29/15 11:29p Wilsonlee +// [TAG] EIP215031 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Transcend USB 3.0 HDD is disappeared in the setup menu by +// cold boot. +// [RootCause] We only can get SerialNumber string descriptor before +// setting configuration for this device, otherwise it is failed at +// getting this descriptor and inquiry command is also failed. +// [Solution] Retry inquiry command. +// [Files] usb.c, usbmass.c, efiusbmass.c, usbbus.c, usbdef.h +// +// 97 3/20/15 7:19a Wilsonlee +// [TAG] EIP209904 +// [Category] Improvement +// [Description] Remove "ASSERT(HubNode != NULL);" because it will be to +// see a DEV_INFO from not-yet-installed hub in the some cases. +// [Files] usbbus.c +// +// 96 11/23/14 9:11p Wilsonlee +// [TAG] EIP188119 +// [Category] Improvement +// [Description] Disconnect devices and uninstall usb device related +// protocols if we call stop api for the host controllers. +// [Files] usbkbd.c, usbbus.c, uhcd.h, uhcd.c +// +// 95 10/23/14 10:07p Wilsonlee +// [TAG] EIP183572 +// [Category] Improvement +// [Description] Change tpl of UsbHcOnTimer to EFI_TPL_CALLBACK +// [Files] efiusbmass.c, usbbus.c +// +// 94 9/30/14 2:07a Wilsonlee +// [TAG] EIP183572 +// [Category] Improvement +// [Description] Change tpl of UsbHcOnTimer to EFI_TPL_CALLBACK +// [Files] efiusbmass.c, usbbus.c +// +// 93 9/29/14 11:37p Wilsonlee +// [TAG] EIP181169 +// [Category] Improvement +// [Description] Support XHCI 1.1/USB 3.1. +// [Files] xhci.c, xhci.h, usb.c, usbbus.c, usbdef.h, UsbHc.h +// +// 92 9/04/14 7:27a Wilsonlee +// [TAG] EIP179794 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Unplug RTKUSB LAN on BSU cause system hang up. +// [RootCause] We return the wrong status for UsbIoTransfers if the +// device is not present. +// [Solution] Return EFI_DEVICE_ERROR if the device is not present. +// [Files] usbbus.c +// +// 91 8/20/14 10:03p Wilsonlee +// [TAG] EIP180089 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] After updated to AMI_USB_07, we get EHCI TIMEOUT for +// specific mouse. +// [RootCause] This device may not respond getting string descriptors +// which describing manufacturer, product and the device's serial number. +// [Solution] Set the timeout value to 100 ms, the original is 20 secs. +// [Files] usbbus.c, usbdef.h +// +// 90 7/30/14 5:16a Wilsonlee +// [TAG] EIP176293 +// [Category] Improvement +// [Description] The changes are for DisplayLink USB Network driver. +// [Files] usbbus.c, usb.c +// +// 89 7/06/14 11:02p Wilsonlee +// [TAG] EIP176289 +// [Category] Improvement +// [Description] The device path for multiple LUN devices is created +// using MSG_DEVICE_LOGICAL_UNIT_DP node. +// [Files] usbbus.c +// +// 88 6/26/14 1:18a Wilsonlee +// [TAG] EIP173387 +// [Category] Improvement +// [Description] Remove TODO comments. +// [Files] usbsetup.c, xhci.c, usbmass.c, usbCCID.c, usb.c, uhci.c, +// syskbc.c, usbport.c, usbbus.c, uhcd.c, UsbBotPeim.c, PeiXhci.c, +// PeiEhci.c +// +// 87 4/30/14 5:27a Wilsonlee +// [TAG] EIP164842 +// [Category] Improvement +// [Description] Check if the devices have put into to our queue before +// we put them. +// [Files] UsbInt13.c, amiusb.c, ehci.c, ohci.c, usb.c, usbdef.h, +// usbmass.c, xhci.c, amiusbhc.c, efiusbmass.c, uhcd.c, usbbus.c, usbsb.c +// +// 86 4/29/14 8:37p Wilsonlee +// [TAG] EIP165318 +// [Category] Improvement +// [Description] Retry the DisconnectController() from a timer event +// until it succeeds if it fails. +// [Files] usbbus.c +// +// 85 4/03/14 4:40a Wilsonlee +// [TAG] EIP158119 +// [Category] Improvement +// [Description] Change parent port number of USB device paths to +// 0-based. +// [Files] usbbus.c +// +// 84 12/20/13 3:42a Wilsonlee +// [TAG] EIP147402 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] System hang at 0xA2 if plugging Seagate USB device. +// [RootCause] This device doesn't respond get descriptor command after +// we install mass storage driver. +// [Solution] We store the string descriptor when we load the langid +// table. +// [Files] usbbus.c, usbbus.h +// +// 83 11/04/13 2:58a Wilsonlee +// [TAG] EIP135009 +// [Category] Improvement +// [Description] Retry 3 times when devices stall the get descriptor +// command. +// [Files] usbbus.c +// +// 82 9/04/13 5:47a Wilsonlee +// [TAG] EIP134478 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] The devices which behind the hub don't install successfully +// in shell. +// [RootCause] Find the wrong root hub port. +// [Solution] Check DEV_INFO_VALID_STRUC and DEV_INFO_DEV_PRESENT flag +// to find the root hub port. +// [Files] usb.c, xhci.c, usbbus.c +// +// 81 8/16/13 4:19a Ryanchou +// +// 80 7/30/13 2:31a Roberthsu +// [TAG] EIP126741 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Cannot boot to uefi usb device with Sophos software. +// [RootCause] When boot into tool. Ownership to os event occur.Usb +// will disconnect device.And record this disconnect event. Then ownership +// to bios,bios will connect all device.Run legacy to efi function. Bios +// run disconnect event first.Then reconnect device.Because usb key behind +// hub. So usb key disconnect also. +// [Solution] Check device when device reconnect.If device and port +// number the same.Use the same device info. +// [Files] usb.c,usbmass.c,efiusbmass.c,uhcd.c,usbbus.c +// +// 79 4/14/13 11:01p Wilsonlee +// [TAG] EIP120345 +// [Category] Improvement +// [Description] EFI_USB_IO_PROTOCOL.UsbGetStringDescriptor() returns +// EFI_SUCCESS if String is NULL. +// [Files] usbbus.c +// +// 78 1/23/13 4:38a Wilsonlee +// [TAG] EIP109538 +// [Category] Improvement +// [Description] Fix the code check error result. +// [Files] usbkbd.c, usbCCID.c, usbbus.c, efiusbccid.c +// +// 77 1/22/13 2:39a Wilsonlee +// [TAG] EIP110305 +// [Category] Improvement +// [Description] Set the device address after we send the first +// get-device-descriptor command. +// [Files] usbmass.c, usb.c, usbdef.h, usbbus.c, efiusbmass.c, uhcd.c, +// usbport.c +// +// 76 1/11/13 4:19a Ryanchou +// [TAG] EIP102491 +// [Category] Improvement +// [Description] Synchronized with Aptio V USB module +// [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h, +// usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c. +// usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c, +// efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c +// +// 75 1/07/13 12:57a Wilsonlee +// [TAG] EIP111305 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] It is failed at reloading the usb keyboard driver. +// [RootCause] The DEV_INFO_VALID_STRUC and DEV_INFO_DEV_PRESENT flag +// were cleared when the usb driver is disconnecting. +// [Solution] We should not clear the DEV_INFO_VALID_STRUC and +// DEV_INFO_DEV_PRESENT flag at USBKBDDisconnectDevice. +// [Files] usbkbd.c, usbbus.c +// +// 74 11/10/12 6:41a Ryanchou +// [TAG] EIP99431 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] Cannot use the UsbIo's UsbAsyncInterruptTransfer for +// keyboard input +// [RootCause] Stopping EFI USB keyboard driver does not stop the +// endpoint polling, then application calls UsbAsyncInterruptTransfer, +// error will be returned. +// [Solution] Stops endpoint polling and release resource when +// disconnecting the device driver. And improve the +// UsbSyncInterruptTransfer. +// [Files] amiusb.c, amiusb.h, ehci.c, ohci.c, uhci.c, usb.c, +// usbCCID.c, usbdef.h, usbhub.c, usbkbd.c, usbmass.c, usbms.c, +// usbpoint.c, amiusbhc.c, efiusbhid.c, usbbus.c, usbbus.h +// +// 73 11/09/12 12:25a Wilsonlee +// [TAG] EIP104910 +// [Category] Improvement +// [Description] Raise the tpl to TPL_CALLBACK when we connect or +// disconnect controller for the usb device. +// [Files] usbbus.c +// +// 72 9/12/12 3:49a Wilsonlee +// [TAG] EIP100371 +// [Category] Improvement +// [Description] Set the tpl to TPL_APPLICATION when we connect or +// disconnect controller for the usb device. +// [Files] usbbus.c +// +// 71 9/04/12 6:15a Ryanchou +// [TAG] EIP99123 +// [Category] Improvement +// [Description] Roll back EIP79221 changes that has device +// compatibility issue. +// [Files] usbbus.c, usbbus.h +// +// 70 8/29/12 10:03p Wilsonlee +// [TAG] EIP97609 +// [Category] Improvement +// [Description] Handle the set interface request in the +// UsbIoControlTransfer. +// [Files] usbbus.c +// +// 69 6/01/12 5:44a Ryanchou +// [TAG] EIP90535 +// [Category] Improvement +// [Description] Increase the buffer size in the function +// GetUsbDescriptor. +// [Files] usbbus.c +// +// 68 5/04/12 6:43a Ryanchou +// [TAG] EIP82875 +// [Category] Improvement +// [Description] Support start/stop individual USB host to avoid +// reconnect issues. +// [Files] usbport.c, usbsb.c, amiusb.c, amiusb.h, ehci.c, ohci.c, +// uhci.c, uhci.h, usb.c, usbdef.h, xhci.c, amiusbhc.c, uhcd.c, uhcd.h, +// usbbus.c, usbmisc.c +// +// 67 5/04/12 5:33a Wilsonlee +// [TAG] EIP89307 +// [Category] Improvement +// [Description] Modify incorrect #pragma pack directive. +// [Files] amidef.h, amiusb.c, ehci.h, ohci.c, ohci.h, uhci.h, usb.c, +// usbdef.h, xhci.h, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, +// UsbIo.h +// +// 66 4/05/12 7:34a Wilsonlee +// [TAG] EIP84215 +// [Category] Improvement +// [Description] Update the DataSync in LUN0 DevInfo if it is a +// multi-lun device. +// [Files] usbbus.c +// +// 65 2/16/12 8:54p Wilsonlee +// [TAG] EIP81612 +// [Category] Spec Update +// [Severity] Minor +// [Description] Add EFI_USB_SPEED_SUPER in EFI_USB2_HC_PROTOCOL +// according to UEFI 2.3.1 spec +// [Files] usb.c, usbbus.c, amiusbhc.c +// +// 64 1/31/12 12:34a Roberthsu +// [TAG] EIP79221 +// [Category] Improvement +// [Description] Add get serial number and product string descriptor. +// [Files] usbbus.c,usbbus.h +// +// 63 1/13/12 4:26a Ryanchou +// [TAG] EIP47348 +// [Category] New Feature +// [Description] Support for USB Port Reset function. +// [Files] amiusb.c, amiusb.h, amiusbhc.c, uhci.c, usb.c, usbbus.c, +// usbbus.h, usbmass.c +// +// 62 1/06/12 1:02a Rajeshms +// [TAG] EIP62737 +// [Category] Improvement +// [Description] Added USB Device number into USB mass device name +// string based on SDL Token. +// [Files] Usb.sdl, usbport.c, usbmass.c, UsbInt13.h, UsbInt13.c, +// usbbus.c, Bfiusb.equ +// +// 61 12/14/11 2:09a Ryanchou +// [TAG] EIP76397 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] ASSERT occurred when executing "reconnect -r" under shell +// [RootCause] The EIP63188 changes locate all USB controllers at one +// time, the "reconnect -r" will connect ConIn and ConOut first, so USB +// driver only locate a controller. +// [Solution] Rollback the EIP63188 changes to avoid this issue. +// [Files] amiusbhc.c, efiusbhid.c, efiusbkb.c, uhcd.c, uhcd.h, +// usbbus.c usbhid.c +// +// 60 8/05/11 7:31a Ryanchou +// [TAG] EIP66231 +// [Category] Improvement +// [Description] Remove token POINT_SUPPORT.Add token USB_DEV_POINT.Add +// check core version in point driver.Add check device descriptor to send +// get lang id command.Modify check button usage page. +// [Files] efiusbhid.c, efiusbpoint.c, usbbus.c, usbhid.c, usbpoint.c, +// usbsrc.sdl +// +// 59 7/13/11 4:10a Ryanchou +// [TAG] EIP59332 +// [Category] Improvement +// [Description] Modified the Stop function for UHCD and USBBUS to +// properly stop devices and uninstall the protocols. +// [Files] uhcd.c, uhcd.h, uhci.c, usbbus.c, UsbInt13.c, usbmisc.c +// +// 58 6/23/11 6:49a Ryanchou +// [TAG] EIP61644 +// [Category] Improvement +// [Description] Uninstall USB bus driver only DEV_INFO_DEV_BUS is set. +// [Files] usbbus.c +// +// 57 6/22/11 9:38a Ryanchou +// [TAG] EIP60640 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Logitec USB keyboard has no function in DOS. +// [RootCause] The USB keybaord may stall get configuration descriptor +// request or set address request. +// [Solution] Retry five times when the device stalls these request. +// [Files] usb.c, usbbus.c +// +// 56 6/21/11 11:57p Ryanchou +// [TAG] EIP60745 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] USB driver doesn't pass SCT 2.3 ComponentName2 protocol +// test +// [RootCause] USB driver fails to pass SCT 2.3 ComponentName2 protocol +// test - function GetControllerName conformance test, because there is no +// checking if passed handle is valid or not, or even NULL +// [Solution] Check the handle is valid in GetControllerName function. +// [Files] uhcd.c, usbbus.c +// +// 55 5/03/11 10:45a Ryanchou +// [TAG] EIP59272 +// [Category] Improvement +// [Description] According Uefi 2.1 Aptio porting document, changes made +// to install the component name protocol. +// [Files] componentname.c, componentname.h, efiusbkb.c, efiusbmass.c, +// efiusbms.c, uhcd.c, uhcd.h, usbbus.c +// +// 54 3/30/11 8:25a Ryanchou +// [TAG] EIP54126 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Sometimes system hangs at checkpoint 0xB4. +// [RootCause] The bLength field of configuration descriptor is zero. +// [Solution] Check wether bLength field is zero before paring next +// descriptor. +// [Files] usb.c, usbbus.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c +// +// 53 3/16/11 5:34p Anandakrishnanl +// [TAG] EIP56121 +// [Category] Defect +// [Description] GetSupportedLanguages() returns invalid return status +// [Files] usbbus.c +// +// 52 3/04/11 1:29p Olegi +// +// 51 3/04/11 1:25p Olegi +// [TAG] EIP55172 +// [Category] Spec Update +// [Severity] Important +// [Description] Install EFI_COMPONENT_NAME_PROTOCOL if BIOS is in UEFI +// 2.0 mode and EFI_COMPONENT_NAME2_PROTOCOL if BIOS is in UEFI 2.1 mode. +// [Files] uhcd.c +// usbbus.c +// efiusbkb.c +// efiusbmass.c +// efiusbms.c +// componentname.c +// componentname.h +// +// 50 1/06/11 11:28a Olegi +// [TAG] EIP51191 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] USB mass storage device name is different for UEFI and +// Legacy device +// [RootCause] The change in InstallDevice done for 47749; it uninstalls +// UsbIo for a current device if ConnectController is unsuccessful. +// ConnectController could be unsecsessful for a number of legitemate +// reasons, one of them is the driver for this device is not present in +// the project (which is the case for a USB hub). +// [Solution] Removed UsbIo uninstallation in case of ConnectController +// failure. +// [Files] USBBUS.C +// +// 49 11/08/10 10:03a Olegi +// [TAG] EIP47749 +// [Category] Improvement +// [Description] Intermittently with Certain USB devices at PC B4h +// [Files] usbbus.c +// +// 48 10/19/10 4:22p Krishnakumarg +// +// [TAG] EIP45589 +// [Category] DEFECT +// [Severity] MAJOR +// [Symptom] USB3.0 controller did not show boot option when only one +// USB device connected. +// [RootCause] USB Bus polling time was high(one second). +// [Solution] Reduce the usb bus polling time(100ms) +// [Files] usbbus.c +// +// 47 8/18/10 4:21p Olegi +// Klockwork related fixes; EIP37978 +// +// 46 6/17/10 10:35a Olegi +// EIP39326: Runtime data moved to runtime memory region. +// +// 45 3/15/10 12:14p Olegi +// UsbBusStart: Raise the tpl level more then EFI_TPL_CALLBACK to make it +// can be called in other callback function.EIP35956 +// +// 44 2/27/10 12:00p Olegi +// +// 43 2/08/10 10:06a Olegi +// EIP33381: Implement multiple bulk endpoint in UsbIoProtocol. +// +// 42 10/30/09 5:48p Olegi +// +// 41 9/24/09 1:32p Olegi +// EIP27593: Fix in UsbIoGetStringDescriptor. +// +// 40 8/18/09 11:53a Olegi +// +// 39 12/16/08 10:51a Olegi +// Correction in the return values: 0 changed to NULL. EIP#17767. +// +// 38 10/22/08 4:25p Olegi +// QueueData1 declaration and initialization is moved to UHCD.C +// +// 37 9/05/08 4:17p Olegi +// gQueueCnnctDisc is made a part of global data structure. +// +// 36 9/02/08 10:35a Olegi +// Bugfix in UsbIoBulkTransfer. +// +// 35 6/27/08 5:57p Olegi +// - Coding standard related modifications +// - LoadName function modified to return USB mass storage device name +// from the INQUIRY command +// +// 34 6/19/08 5:01p Olegi +// +// 33 5/16/08 12:02p Olegi +// Compliance with AMI coding standard. +// +// 21 10/26/06 3:58p Olegi +// EFI_USB2_HC_PROTOCOL implementatin. +// +// 17 5/31/06 6:56p Mirk +// Core 4.5 compliant - DP Length manipulation changes. +// +// 15 3/20/06 3:37p Olegi +// Version 8.5 - x64 compatible. +// +// 12 11/03/05 6:32p Andriyn +// LUN support +// +// 9 6/15/05 1:59p Andriyn +// Comments were changed +//**************************************************************************** +//<AMI_FHDR_START> +// +// Name: UsbBus.c +// +// Description: USB Bus driver implementation +// +//<AMI_FHDR_END> +//**************************************************************************** + +//#include "Efi.h" +#include "amidef.h" +#include "usbdef.h" +#include "uhcd.h" + +#include "usbdef.h" +#include "usbbus.h" +#include "componentname.h" + +//#pragma warning(disable: 4244) + +extern EFI_GUID gEfiUsb2HcProtocolGuid; + +EFI_DRIVER_BINDING_PROTOCOL gUSBBusDriverBinding = { + UsbBusSupported, + UsbBusStart, + UsbBusStop, + USB_DRIVER_VERSION, + NULL, + NULL +}; + +extern USB_GLOBAL_DATA* gUsbData; + +TREENODE_T UsbRootRoot = {0,}; +TREENODE_T* gUsbRootRoot = &UsbRootRoot; +EFI_EVENT gEvUsbEnumTimer=0; +int gCounterUsbEnumTimer=0; +int gBustreeLock = 0; + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbIo2Dev +// +// Description: This function returns a pointer to USB device from UsbIo. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +USBDEV_T* UsbIo2Dev(EFI_USB_IO_PROTOCOL* UsbIo) +{ + return (USBDEV_T*)((char*)UsbIo - (UINTN)&((USBDEV_T*)0)->io ); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: HcByIndex +// +// Description: Predicate for searching host controller node in the tree +// by bHcNumber +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +int HcByIndex(VOID* n, VOID* d) +{ + USBBUS_HC_T* HcNode = (USBBUS_HC_T*)n; + + return n && (HcNode->type == NodeHC) + && (HcNode->hc_data->bHCNumber == *(UINT8*)d ); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: HcByHandle +// +// Description: Predicate for searching host controller node in the tree +// by EFI controller handle +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +int HcByHandle(VOID* n, VOID* d) +{ + USBBUS_HC_T* HcNode = (USBBUS_HC_T*)n; + return (HcNode->type == NodeHC) && (HcNode->hc_data->Controller == *(EFI_HANDLE*)d ); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: DevByIndex +// +// Description: Predicate for searching device node in the tree +// by index of the DEV_INFO structure in the aDevInfoTable +// array of USB data +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +int DevByIndex(VOID* n, VOID* d) +{ + USBDEV_T* Dev = (USBDEV_T*)n; + return (Dev->type == NodeDevice) && (Dev->dev_info == + gUsbData->aDevInfoTable + *(UINT8*)d ); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: DevGrpByAddr +// +// Description: Predicate for searching device node in the tree +// by USB address of the device +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +int DevGrpByAddr(VOID* n, VOID* d) +{ + USBDEV_T* Dev = (USBDEV_T*)n; + return (Dev->type == NodeDevice || Dev->type == NodeGroup) && + (Dev->dev_info->bDeviceAddress == *(UINT8*)d ); +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: DevGrpByPortIf +// +// Description: Predicate for searching device node in the tree +// by parent hub port of the device, interface and LUN +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +int DevGrpByPortIf(VOID* n, VOID* d) +{ + USBDEV_T* Dev = (USBDEV_T*)n; + return (Dev->type == NodeDevice || Dev->type == NodeGroup) && + (Dev->dev_info->bHubPortNumber == ((DEV_INFO*)d)->bHubPortNumber ) && + (Dev->dev_info->bInterfaceNum == ((DEV_INFO*)d)->bInterfaceNum ) && + (Dev->dev_info->bLUN == ((DEV_INFO*)d)->bLUN ); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: DevByInfo +// +// Description: Predicate for searching device node in the tree +// by comparing pointers to the DEV_INFO structure +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +int DevByInfo(VOID* n, VOID* d ) +{ + USBDEV_T* Dev = (USBDEV_T*)n; + return (Dev->type == NodeDevice) && (Dev->dev_info == (DEV_INFO*)d ); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: DevByAdrIf +// +// Description: Predicate for searching device node in the tree +// by USB address and interface number of the device +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +int DevByAdrIf(VOID* n, VOID* d) +{ + USBDEV_T* Dev = (USBDEV_T*)n; + + return ((Dev->type == NodeDevice) && + (Dev->dev_info->bDeviceAddress == ((DEV_INFO*)d)->bDeviceAddress ) && + (Dev->dev_info->bInterfaceNum == ((DEV_INFO*)d)->bInterfaceNum )&& + (Dev->dev_info->bLUN == ((DEV_INFO*)d)->bLUN)); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbDevGetGroup +// +// Description: Retrieve DEVGROUP_T that is parent of +// the specified USB device in the USB Bus tree +// +// Input: Device for which the parent is requested +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +DEVGROUP_T* UsbDevGetGroup(USBDEV_T* Dev) +{ + return (DEVGROUP_T*)Dev->node.parent->data; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: DpAddUsbSegment +// +// Description: Builds a new path appending a USB segment +// +// Output: Pointer to a callee allocated memory buffer +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_DEVICE_PATH_PROTOCOL* +DpAddUsbSegment( + EFI_DEVICE_PATH_PROTOCOL* Dp, + UINT8 bHubPortNumber, + UINT8 bInterfaceNum +) +{ + USB_DEVICE_PATH DpNewSegment = {0,}; + DpNewSegment.Header.Type = MESSAGING_DEVICE_PATH; + DpNewSegment.Header.SubType = MSG_USB_DP; + SET_NODE_LENGTH(&DpNewSegment.Header, sizeof(DpNewSegment)); + + DpNewSegment.InterfaceNumber = bInterfaceNum; + DpNewSegment.ParentPortNumber = bHubPortNumber; + return EfiAppendDevicePathNode(Dp,(EFI_DEVICE_PATH_PROTOCOL*)&DpNewSegment); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: DpAddLun +// +// Description: Builds a new path appending a LUN node +// +// +// Output: Pointer to a callee allocated memory buffer +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_DEVICE_PATH_PROTOCOL* +DpAddLun( + EFI_DEVICE_PATH_PROTOCOL* Dp, + UINT8 Lun +) +{ + LOGICAL_UNIT_DEVICE_PATH DpNewSegment = {0,}; + + DpNewSegment.Header.Type = MESSAGING_DEVICE_PATH; + DpNewSegment.Header.SubType = MSG_USB_LOGICAL_UNIT_CLASS_DP; + SET_NODE_LENGTH(&DpNewSegment.Header, sizeof(DpNewSegment)); + DpNewSegment.Lun = Lun; + return EfiAppendDevicePathNode(Dp,(EFI_DEVICE_PATH_PROTOCOL*)&DpNewSegment); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: ReadUsbDescriptor +// +// Description: This function executes a get descriptor command to the +// given USB device and endpoint +// +// Input: dev a pointer to USBDEV_T corresponding to the device +// fpBuffer Buffer to be used for the transfer +// wLength Size of the requested descriptor +// bDescType Requested descriptor type +// bDescIndex Descriptor index +// wLangIndex LangIndex +// +// Output: Pointer to memory buffer containing the descriptor +// NULL on error +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8* +ReadUsbDescriptor( USBDEV_T* Dev, + UINT8* Buffer, + UINT16 Length, + UINT8 DescType, + UINT8 DescIndex, + UINT16 LangIndex ) +{ + HC_STRUC* HcStruc = Dev->hc_info; + DEV_INFO* DevInfo = Dev->dev_info; + UINT8 GetDescIteration; + UINT16 Reg; + UINT16 Status; + + for (GetDescIteration = 0; GetDescIteration < 3; GetDescIteration++) { + Reg = (UINT16)((DescType << 8) + DescIndex); + Status = UsbSmiControlTransfer( + HcStruc, + DevInfo, + (UINT16)USB_RQ_GET_DESCRIPTOR, + (UINT16)LangIndex, + Reg, + Buffer, + Length); + if (Status) { + return Buffer; + } + if (gUsbData->dLastCommandStatusExtended & USB_TRNSFR_TIMEOUT) { + break; + } + pBS->Stall(10 * 1000); + } + + return NULL; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetUsbDescriptor +// +// Description: Allocates memory necessary to hold complete descriptor +// and returns the descriptor there +// +// Input: dev a pointer to USBDEV_T corresponding to the device +// type Requested descriptor type +// index Descriptor index +// langindex LangIndex +// +// Output: Pointer to memory buffer containing the descriptor +// NULL on error +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +USB_DESCRIPTOR_T* +GetUsbDescriptor( + USBDEV_T* Dev, + UINT8 Type, + UINT8 Index, + UINT16 LangIndex) +{ + UINT8 Buffer[0xFF] = {0}; + USB_DESCRIPTOR_T *Desc; + UINT8* DescBuffer; + + DescBuffer= ReadUsbDescriptor(Dev, Buffer, sizeof(Buffer), Type, Index, LangIndex); + + if ((DescBuffer == NULL) || + (((USB_DESCRIPTOR_T*)Buffer)->DescriptorType != Type) || + (((USB_DESCRIPTOR_T*)Buffer)->Length == 0)) { + return NULL; + } + gBS->AllocatePool(EfiBootServicesData, ((USB_DESCRIPTOR_T*)Buffer)->Length, &Desc); + + EfiCopyMem(Desc, Buffer, ((USB_DESCRIPTOR_T*)Buffer)->Length); + + return Desc; + +/* + EfiZeroMem(Desc, ((USB_DESCRIPTOR_T*)Buffer)->Length); + DescBuffer = ReadUsbDescriptor(Dev, (UINT8*)Desc, + ((USB_DESCRIPTOR_T*)Buffer)->Length, Type, Index, LangIndex); + //ASSERT(Desc->DescriptorType == Type); //(EIP60640-) + if (DescBuffer == NULL){ + gBS->FreePool(Desc); + return NULL; + } + // + //Decriptor Type cannot be 0, this case means that Get Descriptor cmd timed out + // + if (Desc->DescriptorType == 0) { + gBS->FreePool(Desc); + return NULL; + } else { + return Desc; + } +*/ +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: FreeConfigDesc +// +// Description: Delocates memory that was used by the descriptor +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID FreeConfigDesc( VOID* Desc ) +{ + if (Desc != 0) gBS->FreePool(Desc); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: NextDescriptor +// +// Description: Returns pointer to the next descriptor for the pack of +// USB descriptors located in continues memory segment +// - result of reading CONFIG_DESCRIPTOR +// Notes: +// Uses TotalLength of the CONFIG_DESCRIPTOR and Length +// field of each USB descriptor found inside the pack +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +int +NextDescriptor( + EFI_USB_CONFIG_DESCRIPTOR* Desc, + UINTN* Offset +) +{ + if( Desc == NULL || *Offset >= Desc->TotalLength ) return FALSE; + if( ((EFI_USB_CONFIG_DESCRIPTOR*)((char*)Desc+*Offset))->Length == 0) return FALSE; + *Offset += ((EFI_USB_CONFIG_DESCRIPTOR*)((char*)Desc+*Offset))->Length; + if( *Offset >= Desc->TotalLength ) return FALSE; + + return TRUE; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbDevConfigDesc +// +// Description: Returns a pointer to the memory containing CONFIG_DESCRIPTOR +// reported by the USB device +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_USB_CONFIG_DESCRIPTOR* +DevGroupConfigDesc( DEVGROUP_T* Grp ){ + return Grp->f_DevDesc && (Grp->active_config != -1)? + Grp->configs[Grp->active_config]:NULL; +} + +EFI_USB_CONFIG_DESCRIPTOR* +UsbDevConfigDesc( USBDEV_T* Dev ){ + return DevGroupConfigDesc( UsbDevGetGroup(Dev)); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbDevLoadAllDescritors +// +// Description: Reads DEVICE and CONFIG descriptors for each +// configuration available in the device. Marks +// the index of the buffer containing CONFIG descriptor +// for active configurations currently selected in +// USB device +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +UsbDevLoadAllDescritors( + DEVGROUP_T* Dev +) +{ + UINT8 i; + EFI_STATUS Status; + + //ASSERT( Dev->f_DevDesc == 0 ); + Dev->configs = NULL; + // + // Device descriptor + // + gBS->CopyMem((UINT8*)&Dev->dev_desc, (UINT8*)&Dev->dev_info->DevDesc, sizeof(Dev->dev_desc)); + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USB Bus: dev descr: "); + USB_DEBUG(DEBUG_LEVEL_USBBUS, "cls:%x;subcls:%x;proto:%x;vndr:%x;id:%x\n", + Dev->dev_desc.DeviceClass, + Dev->dev_desc.DeviceSubClass, + Dev->dev_desc.DeviceProtocol, + Dev->dev_desc.IdVendor, + Dev->dev_desc.IdProduct); + USB_DEBUG(DEBUG_LEVEL_USBBUS, "\t\tstr1:%x,str2:%x,str3:%x\n", + Dev->dev_desc.StrManufacturer, + Dev->dev_desc.StrProduct, + Dev->dev_desc.StrSerialNumber ); + + Dev->f_DevDesc = TRUE; + + // + // Config descriptor + // + Dev->config_count = Dev->dev_desc.NumConfigurations; +// dev->configs = (EFI_USB_CONFIG_DESCRIPTOR**)MallocZ(dev->config_count*sizeof(EFI_USB_CONFIG_DESCRIPTOR*)); + Status = gBS->AllocatePool (EfiBootServicesData, + Dev->config_count*sizeof(EFI_USB_CONFIG_DESCRIPTOR*), (VOID *)&Dev->configs); + ASSERT_EFI_ERROR(Status); + EfiZeroMem(Dev->configs, Dev->config_count*sizeof(EFI_USB_CONFIG_DESCRIPTOR*)); + + Dev->active_config = -1; + for(i=0; i<Dev->config_count; ++i){ + //read each configuration + //first failed read will terminate loop + + //Optimization: allloc&read MAX size first + // and read second time only if total length is greater + //Read 1 : get total length + EFI_USB_CONFIG_DESCRIPTOR tmp = {0,0,}; + UINT8* p = ReadUsbDescriptor((USBDEV_T*)Dev,(UINT8*)&tmp, + sizeof(tmp),DESC_TYPE_CONFIG,i, 0 ); + //ASSERT(tmp.DescriptorType == DESC_TYPE_CONFIG); + //ASSERT(tmp.TotalLength >= sizeof(tmp)); + // + //Addressing timeouts caused by device errors - empty DESC structure will be returned + // + if( (p == NULL) || (tmp.DescriptorType == 0) ) { + break; + } + + //Read 2: Actual content +// dev->configs[i] = MallocZ(tmp.TotalLength); + Status = gBS->AllocatePool (EfiBootServicesData, tmp.TotalLength, &Dev->configs[i]); + ASSERT_EFI_ERROR(Status); + EfiZeroMem(Dev->configs[i], tmp.TotalLength); + + p = ReadUsbDescriptor((USBDEV_T*)Dev, (UINT8*)Dev->configs[i], + tmp.TotalLength, DESC_TYPE_CONFIG, i, 0); + //ASSERT(Dev->configs[i]->DescriptorType == DESC_TYPE_CONFIG); //(EIP60640-) + // + //Addressing timeouts caused by device errors - empty DESC structure will be returned + // + if( (p == NULL) || (Dev->configs[i]->DescriptorType == 0) ){ + gBS->FreePool(Dev->configs[i]); + Dev->configs[i] = 0; + break; + } + //config Desc is here + + //Active Config + if( Dev->configs[i]->ConfigurationValue == Dev->dev_info->bConfigNum ){ + Dev->active_config = i; + } + } +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbDevLoadEndpoints +// +// Description: Locates information about each endpoint inside the +// descriptors pack loaded with CONFIG descriptor +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +UsbDevLoadEndpoints( + USBDEV_T* Dev +) +{ + EFI_USB_INTERFACE_DESCRIPTOR *TmpDesc; + EFI_USB_ENDPOINT_DESCRIPTOR *EpDesc; + EFI_USB_CONFIG_DESCRIPTOR *CfgDesc; + int j; + UINTN Offset; + DEVGROUP_T *Grp = UsbDevGetGroup(Dev); + + Dev->first_endpoint = Grp->endpoint_count; + Dev->end_endpoint = Grp->endpoint_count; + + CfgDesc = UsbDevConfigDesc(Dev); + USB_DEBUG(DEBUG_LEVEL_USBBUS, + "\tScanning config desc: "); + USB_DEBUG(DEBUG_LEVEL_USBBUS, + "%x(type:%x;len:%x;val:%x;total:%x)\n", + CfgDesc,CfgDesc->DescriptorType,CfgDesc->Length, + CfgDesc->ConfigurationValue,CfgDesc->TotalLength ); + + // + // Search interface descriptor + // + for(Offset = 0; NextDescriptor(CfgDesc,&Offset);) + { + TmpDesc = (EFI_USB_INTERFACE_DESCRIPTOR *)((char*)CfgDesc+Offset); + USB_DEBUG(DEBUG_LEVEL_USBBUS, + "\t\tdesc: %x(type:%x;len:%x;if:%x;aif:%x)\n", + TmpDesc,TmpDesc->DescriptorType,TmpDesc->Length, + TmpDesc->InterfaceNumber, TmpDesc->AlternateSetting ); + if( TmpDesc->DescriptorType == DESC_TYPE_INTERFACE && + TmpDesc->InterfaceNumber== Dev->dev_info->bInterfaceNum && + TmpDesc->AlternateSetting == Dev->dev_info->bAltSettingNum) + { + //found + USB_DEBUG(DEBUG_LEVEL_USBBUS, + "\t...IF found.\n" ); + + Dev->descIF= TmpDesc; + + ASSERT(TmpDesc->NumEndpoints < COUNTOF(Grp->endpoints)); + for(j=0;j<TmpDesc->NumEndpoints && NextDescriptor(CfgDesc,&Offset);){ + EpDesc = (EFI_USB_ENDPOINT_DESCRIPTOR*)((char*)CfgDesc+Offset); + if( EpDesc->DescriptorType == DESC_TYPE_ENDPOINT ){ + USB_DEBUG(DEBUG_LEVEL_USBBUS, + "\t\tend-point desc: %x", EpDesc); + USB_DEBUG(DEBUG_LEVEL_USBBUS, + "(index:%x;type:%x;len:%x;addr:%x;pcksz:%x;attr:%x,t:%x)\n", + Grp->endpoint_count, + EpDesc->DescriptorType,EpDesc->Length, + EpDesc->EndpointAddress, EpDesc->MaxPacketSize, + EpDesc->Attributes, EpDesc->Interval); + Grp->endpoints[Grp->endpoint_count].address = EpDesc->EndpointAddress; + Grp->endpoints[Grp->endpoint_count++].desc = EpDesc; + Grp->a2endpoint[COMPRESS_EP_ADR(EpDesc->EndpointAddress)] = EpDesc; + j++; + } + if( EpDesc->DescriptorType == DESC_TYPE_INTERFACE ){ + //Oops, We stepped into another interface + break; + } + } + Dev->end_endpoint = Grp->endpoint_count; + USB_DEBUG(DEBUG_LEVEL_USBBUS, + "\t\tinterface end-points: "); + USB_DEBUG(DEBUG_LEVEL_USBBUS, + "first:%x; end:%x, grp.endpoint_count:%x\n", + Dev->first_endpoint, Dev->end_endpoint, Grp->endpoint_count); + return; + } + } + USB_DEBUG(DEBUG_LEVEL_USBBUS, + "\t...IF not found.\n" ); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetMaxPacket +// +// Description: Retrieves information about a max packet size +// for the specified endpoint of the device +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT16 +GetMaxPacket( + UINT8 Endpoint, + USBDEV_T* Dev +) +{ + DEVGROUP_T *Grp = UsbDevGetGroup(Dev); + EFI_USB_ENDPOINT_DESCRIPTOR* Desc = Grp->a2endpoint[COMPRESS_EP_ADR(Endpoint)]; + if (Desc == 0) return 0; + return Desc->MaxPacketSize; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: GetEndpointDesc +// +// Description: Retrieves information about a max packet size +// for the specified endpoint of the device +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_USB_ENDPOINT_DESCRIPTOR* +GetEndpointDesc( + UINT8 Endpoint, + USBDEV_T* Dev +) +{ + DEVGROUP_T *Grp = UsbDevGetGroup(Dev); + EFI_USB_ENDPOINT_DESCRIPTOR* Desc; + + if (((Endpoint & 0x7F)==0) || ((Endpoint & 0x7F) > 0xF)) + return NULL; + Desc = Grp->a2endpoint[COMPRESS_EP_ADR(Endpoint)]; + + return Desc; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbIoControlTransfer +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbIoControlTransfer( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT32 Timeout, + IN OUT VOID *Data, + IN UINTN DataLength, + OUT UINT32 *UsbStatus +) +{ + USBDEV_T* Dev = UsbIo2Dev(UsbIo); + EFI_STATUS Status; + + ASSERT( Dev->dev_info ); + ASSERT( Dev->hc ); + + if( Request == NULL || UsbStatus == NULL ) return EFI_INVALID_PARAMETER; + if (Direction > EfiUsbNoData) return EFI_INVALID_PARAMETER; + + if (!(Dev->dev_info->Flag & DEV_INFO_DEV_PRESENT)) { + return EFI_DEVICE_ERROR; + } + + Status = Dev->hc->ControlTransfer( + Dev->hc, Dev->dev_info->bDeviceAddress, GetSpeed(Dev), + (UINTN)Dev->dev_info->wEndp0MaxPacket, //(EIP81612) + Request, Direction, Data, &DataLength, Timeout, NULL, UsbStatus); + if (EFI_ERROR(Status)) { + return Status; + } + if ((Request->Request == (USB_RQ_SET_INTERFACE >> 8)) && + (Request->RequestType == (USB_RQ_SET_INTERFACE & 0x0F) ) && + (Request->Index == Dev->dev_info->bInterfaceNum)) { + Dev->dev_info->bAltSettingNum = (UINT8)Request->Value; + UsbDevLoadEndpoints(Dev); + } + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbIoBulkTransfer +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbIoBulkTransfer( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Endpoint, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN Timeout, + OUT UINT32 *UsbStatus +) +{ + USBDEV_T* Dev = UsbIo2Dev(UsbIo); + UINT16 MaxPacket; + UINT8 ToggleBit = (Endpoint & 0xF) - 1; + //(EIP84215)> + UINT16 *wDataSync; + UINT8 Toggle; + EFI_STATUS Status; + EFI_USB_ENDPOINT_DESCRIPTOR* EpDesc = GetEndpointDesc(Endpoint, Dev); + DEV_INFO *DevInfoToDataSync; + //<(EIP84215) + if (((Endpoint & 0x7F)==0) || ((Endpoint & 0x7F) > 0xF)) + return EFI_INVALID_PARAMETER; + +// if ( Dev->dev_info->bBulkInEndpoint && +// ((Endpoint & 0x80) && ((Endpoint & 0x7F) != Dev->dev_info->bBulkInEndpoint)) ) { +// return EFI_INVALID_PARAMETER; +// } + +// if ( Dev->dev_info->bBulkOutEndpoint && +// (!(Endpoint & 0x80) && (Endpoint != Dev->dev_info->bBulkOutEndpoint)) ) { +// return EFI_INVALID_PARAMETER; +// } + + if ( Data == NULL || DataLength == NULL || UsbStatus == NULL ) { + return EFI_INVALID_PARAMETER; + } + + if( EpDesc == NULL ) { + return EFI_INVALID_PARAMETER; + } + MaxPacket = EpDesc->MaxPacketSize; + ASSERT( Dev->dev_info ); + ASSERT( Dev->hc ); + + if( UsbStatus == NULL || MaxPacket == 0) { + return EFI_INVALID_PARAMETER; + } + + if ( (EpDesc->Attributes & EP_DESC_FLAG_TYPE_BITS) != EP_DESC_FLAG_TYPE_BULK ) { + return EFI_INVALID_PARAMETER; + } + + if (!(Dev->dev_info->Flag & DEV_INFO_DEV_PRESENT)) { + return EFI_DEVICE_ERROR; + } + //(EIP84215+)> + if (Dev->dev_info->fpLUN0DevInfoPtr) { + DevInfoToDataSync = Dev->dev_info->fpLUN0DevInfoPtr; + }else { + DevInfoToDataSync = Dev->dev_info; + } + + if (Endpoint & 0x80) { + wDataSync = &DevInfoToDataSync->wDataInSync; + }else { + wDataSync = &DevInfoToDataSync->wDataOutSync; + } + //<(EIP84215+) + GETBIT( *wDataSync, Toggle, ToggleBit ); + + Status = Dev->hc->BulkTransfer( + Dev->hc, Dev->dev_info->bDeviceAddress, Endpoint, GetSpeed(Dev), + MaxPacket, 1, &Data, DataLength, &Toggle, Timeout, NULL, UsbStatus); + + SETBIT( *wDataSync, Toggle, ToggleBit ); + + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbIoIsochronousTransfer +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbIoAsyncInterruptTransfer( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Endpoint, + IN BOOLEAN IsNewTransfer, + IN UINTN PollingInterval, + IN UINTN DataLength, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK InterruptCallback, + IN VOID *Context +) +{ + USBDEV_T* Dev = UsbIo2Dev(UsbIo); + UINT8 Toggle; + UINT8 ToggleBit = (Endpoint & 0xF) - 1; + //(EIP84215)> + UINT16 *wDataSync; + EFI_STATUS Status; + EFI_USB_ENDPOINT_DESCRIPTOR* EpDesc = GetEndpointDesc(Endpoint, Dev); + DEV_INFO *DevInfoToDataSync; + //<(EIP84215) + ASSERT( Dev->dev_info ); + ASSERT( Dev->hc ); + + // Check whether Endpoint is valid + if(EpDesc == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((EpDesc->Attributes & EP_DESC_FLAG_TYPE_BITS) != EP_DESC_FLAG_TYPE_INT ) { + return EFI_INVALID_PARAMETER; + } + + if (IsNewTransfer && (PollingInterval < 1 || PollingInterval > 255)) { + return EFI_INVALID_PARAMETER; + } + + if (IsNewTransfer) { + if (!(Dev->dev_info->Flag & DEV_INFO_DEV_PRESENT)) { + return EFI_DEVICE_ERROR; + } + } + //(EIP84215+)> + if (Dev->dev_info->fpLUN0DevInfoPtr) { + DevInfoToDataSync = Dev->dev_info->fpLUN0DevInfoPtr; + }else { + DevInfoToDataSync = Dev->dev_info; + } + + if (Endpoint & 0x80) { + wDataSync = &DevInfoToDataSync->wDataInSync; + }else { + wDataSync = &DevInfoToDataSync->wDataOutSync; + } + //<(EIP84215+) + GETBIT( *wDataSync, Toggle, ToggleBit ); + + Status = Dev->hc->AsyncInterruptTransfer( + Dev->hc, Dev->dev_info->bDeviceAddress, Endpoint, + GetSpeed(Dev), EpDesc->MaxPacketSize, IsNewTransfer, + &Toggle, PollingInterval, DataLength, NULL, + InterruptCallback, Context ); + + SETBIT( *wDataSync, Toggle, ToggleBit ); + + if (!EFI_ERROR(Status)) { + Dev->async_endpoint = IsNewTransfer ? Endpoint : 0; + } + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbIoSyncInterruptTransfer +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbIoSyncInterruptTransfer( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Endpoint, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN Timeout, + OUT UINT32 *UsbStatus +) +{ + USBDEV_T* Dev = UsbIo2Dev(UsbIo); + UINT8 Toggle; + UINT8 ToggleBit = (Endpoint & 0xF) - 1; + //(EIP84215)> + UINT16 *wDataSync; + EFI_STATUS Status; + EFI_USB_ENDPOINT_DESCRIPTOR* EpDesc = GetEndpointDesc(Endpoint, Dev); + DEV_INFO *DevInfoToDataSync; + //<(EIP84215) + ASSERT( Dev->dev_info ); + ASSERT( Dev->hc ); + + // Check whether Endpoint is valid + if( EpDesc == NULL ) { + return EFI_INVALID_PARAMETER; + } + + if ( (EpDesc->Attributes & EP_DESC_FLAG_TYPE_BITS) != EP_DESC_FLAG_TYPE_INT ) { + return EFI_INVALID_PARAMETER; + } + + if ( Data == NULL || DataLength == NULL || UsbStatus == NULL ) { + return EFI_INVALID_PARAMETER; + } + + if (!(Dev->dev_info->Flag & DEV_INFO_DEV_PRESENT)) { + return EFI_DEVICE_ERROR; + } + //(EIP84215+)> + if (Dev->dev_info->fpLUN0DevInfoPtr) { + DevInfoToDataSync = Dev->dev_info->fpLUN0DevInfoPtr; + }else { + DevInfoToDataSync = Dev->dev_info; + } + + if (Endpoint & 0x80) { + wDataSync = &DevInfoToDataSync->wDataInSync; + }else { + wDataSync = &DevInfoToDataSync->wDataOutSync; + } + //<(EIP84215+) + GETBIT( *wDataSync, Toggle, ToggleBit ); + Status = Dev->hc->SyncInterruptTransfer( + Dev->hc, Dev->dev_info->bDeviceAddress, Endpoint, + GetSpeed(Dev), EpDesc->MaxPacketSize, + Data, DataLength, &Toggle, Timeout, NULL, UsbStatus); + SETBIT( *wDataSync, Toggle, ToggleBit ); + + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbIoIsochronousTransfer +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbIoIsochronousTransfer( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Endpoint, + IN OUT VOID *Data, + IN UINTN DataLength, + OUT UINT32 *Status +) +{ + USBDEV_T* Dev = UsbIo2Dev(UsbIo); + UINT16 MaxPacket;// = GetMaxPacket(Endpoint,dev); + EFI_USB_ENDPOINT_DESCRIPTOR* EpDesc = GetEndpointDesc(Endpoint, Dev); + + if (EpDesc == NULL) { + return EFI_INVALID_PARAMETER; + } + + MaxPacket = EpDesc->MaxPacketSize; + ASSERT( Dev->dev_info ); + ASSERT( Dev->hc ); + + if (Status == NULL || MaxPacket == 0) { + return EFI_INVALID_PARAMETER; + } + + if ((EpDesc->Attributes & EP_DESC_FLAG_TYPE_BITS) != EP_DESC_FLAG_TYPE_ISOC) { + return EFI_INVALID_PARAMETER; + } + + if (!(Dev->dev_info->Flag & DEV_INFO_DEV_PRESENT)) { + return EFI_DEVICE_ERROR; + } + + return Dev->hc->IsochronousTransfer( + Dev->hc, Dev->dev_info->bDeviceAddress, Endpoint, GetSpeed(Dev), + MaxPacket, 1, &Data, DataLength, NULL, Status); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbIoAsyncIsochronousTransfer +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbIoAsyncIsochronousTransfer( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Endpoint, + IN OUT VOID *Data, + IN UINTN DataLength, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallback, + IN VOID *Context +) +{ + USBDEV_T* Dev = UsbIo2Dev(UsbIo); + UINT16 MaxPacket;// = GetMaxPacket(Endpoint, Dev); + EFI_USB_ENDPOINT_DESCRIPTOR* EpDesc = GetEndpointDesc(Endpoint, Dev); + + if (EpDesc == NULL) { + return EFI_INVALID_PARAMETER; + } + MaxPacket = EpDesc->MaxPacketSize; + ASSERT( Dev->dev_info ); + ASSERT( Dev->hc ); + if ((EpDesc->Attributes & EP_DESC_FLAG_TYPE_BITS) != EP_DESC_FLAG_TYPE_ISOC) { + return EFI_INVALID_PARAMETER; + } + + if (!(Dev->dev_info->Flag & DEV_INFO_DEV_PRESENT)) { + return EFI_DEVICE_ERROR; + } + + return Dev->hc->AsyncIsochronousTransfer( + Dev->hc, Dev->dev_info->bDeviceAddress, Endpoint, GetSpeed(Dev), + MaxPacket, 1, &Data, DataLength, NULL, IsochronousCallback, Context ); +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbIoPortReset +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbIoPortReset( + IN EFI_USB_IO_PROTOCOL *UsbIo +) +{ + USBDEV_T* Dev = UsbIo2Dev(UsbIo); + DEVGROUP_T* Grp = UsbDevGetGroup(Dev); + UINT8 Status; + UINT8 i; + + if (Dev->dev_info->bDeviceType == BIOS_DEV_TYPE_HUB) + return EFI_INVALID_PARAMETER; + + Status = UsbResetAndReconfigDev(Dev->hc_info, Dev->dev_info); + if (Status != USB_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + if( UsbSmiGetDescriptor(Dev->hc_info, Dev->dev_info, (UINT8*)&Grp->dev_desc, + sizeof(Grp->dev_desc), DESC_TYPE_DEVICE, 0) == 0 ){ + return EFI_DEVICE_ERROR; + } + + for(i = 0; i < Grp->dev_desc.NumConfigurations; i++) { + if (ReadUsbDescriptor(Dev, (UINT8*)Grp->configs[i], + Grp->configs[i]->TotalLength, DESC_TYPE_CONFIG, i, 0) == 0) { + return EFI_DEVICE_ERROR; + } + } + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbIoGetDeviceDescriptor +// +// Description: Retrieves the USB Device Descriptor. +// +// Input: +// UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. Type +// EFI_USB_IO_PROTOCOL is defined in Section 14.2.5. +// Desc A pointer to the caller allocated USB Device Descriptor. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbIoGetDeviceDescriptor( + IN EFI_USB_IO_PROTOCOL *UsbIo, + OUT EFI_USB_DEVICE_DESCRIPTOR *Desc +) +{ + USBDEV_T* Dev = UsbIo2Dev(UsbIo); + DEVGROUP_T* Grp = UsbDevGetGroup(Dev); + ASSERT( Dev->dev_info ); + ASSERT( Dev->hc ); + if( Desc == NULL ) return EFI_INVALID_PARAMETER; + + if( Grp->f_DevDesc ){ + *Desc = Grp->dev_desc; + return EFI_SUCCESS; + } else + return EFI_NOT_FOUND; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbIoGetConfigDescriptor +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbIoGetConfigDescriptor( + IN EFI_USB_IO_PROTOCOL *UsbIo, + OUT EFI_USB_CONFIG_DESCRIPTOR *Desc +) +{ + USBDEV_T* Dev = UsbIo2Dev(UsbIo); + DEVGROUP_T* Grp = UsbDevGetGroup(Dev); + ASSERT( Dev->dev_info ); + ASSERT( Dev->hc ); + if( Desc == NULL ) return EFI_INVALID_PARAMETER; + + if( Grp->configs && Grp->active_config != -1 && + Grp->configs[Grp->active_config] ){ + *Desc = *Grp->configs[Grp->active_config]; + return EFI_SUCCESS; + } else + return EFI_NOT_FOUND; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbIoGetInterfaceDescriptor +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbIoGetInterfaceDescriptor( + IN EFI_USB_IO_PROTOCOL *UsbIo, + OUT EFI_USB_INTERFACE_DESCRIPTOR *Desc +) +{ + USBDEV_T* Dev = UsbIo2Dev(UsbIo); + + ASSERT( Dev->dev_info ); + ASSERT( Dev->hc ); + if (Desc == NULL) return EFI_INVALID_PARAMETER; + + if (Dev->descIF == NULL) return EFI_NOT_FOUND; + + *Desc = *Dev->descIF; + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbIoGetEndpointDescriptor +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbIoGetEndpointDescriptor( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 EndpointIndex, + OUT EFI_USB_ENDPOINT_DESCRIPTOR *Desc +) +{ + USBDEV_T* Dev = UsbIo2Dev(UsbIo); + DEVGROUP_T *Grp; + EFI_USB_ENDPOINT_DESCRIPTOR* DescCopy; + + if( Desc == NULL || EndpointIndex >= 0x10) return EFI_INVALID_PARAMETER; + + ASSERT( Dev->dev_info ); + ASSERT( Dev->hc ); + + USB_DEBUG( 3, "Get Endpoint desc: devaddr: 0x%x; Endpoint: 0x%x\n", + Dev->dev_info->bDeviceAddress, EndpointIndex ); + USB_DEBUG( 3, "\tfirst Endpoint: 0x%x; last Endpoint: 0x%x\n", + Dev->first_endpoint, Dev->end_endpoint-1 ); + + if( Dev->first_endpoint + EndpointIndex >= Dev->end_endpoint ) + return EFI_NOT_FOUND; + + ASSERT( Dev->first_endpoint + EndpointIndex < 0x20 ); + + Grp = UsbDevGetGroup(Dev); + DescCopy = Grp->endpoints[Dev->first_endpoint + EndpointIndex].desc; + + ASSERT( DescCopy ); + + if (DescCopy==NULL) return EFI_NOT_FOUND; + + USB_DEBUG( 3, "\tendp addr: 0x%x; attr: 0x%x; MaxPacket: 0x%x\n", + DescCopy->EndpointAddress, + DescCopy->Attributes, DescCopy->MaxPacketSize ); + + *Desc = *DescCopy; + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbIoGetStringDescriptor +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS +UsbIoGetStringDescriptor( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 LangId, + IN UINT8 StringId, + OUT CHAR16 **String +) +{ + USBDEV_T* Dev = UsbIo2Dev(UsbIo); + EFI_USB_STRING_DESCRIPTOR* StrDesc = NULL; + UINT16 Index; + UINT16 *LangIdTable; + DEVGROUP_T* Grp; + EFI_STATUS Status = EFI_NOT_FOUND; + + ASSERT(Dev->dev_info); + ASSERT(Dev->hc); + + Grp = UsbDevGetGroup(Dev); + + if (StringId == 0 || Grp->lang_table == NULL) { + //reserved ids: stringid==0 => langid table descripto; + return Status; + } + // search langid_table + LangIdTable = Grp->lang_table->langID; + for (Index = 0; Index < Grp->lang_table->len ; Index++) { + if (LangId == LangIdTable[Index]) { + break; + } + } + + if (Index == Grp->lang_table->len) { + return Status; + } + + if (LangId == USB_US_LAND_ID) { + if (StringId == Grp->dev_desc.StrSerialNumber) { + StrDesc = Grp->SerialNumberStrDesc; + } else if (StringId == Grp->dev_desc.StrProduct) { + StrDesc = Grp->ProductStrDesc; + } else if (StringId == Grp->dev_desc.StrManufacturer) { + StrDesc = Grp->ManufacturerStrDesc; + } + } + // + // Get string descriptor: variable size + // + if (StrDesc == NULL) { + StrDesc = (EFI_USB_STRING_DESCRIPTOR*)GetUsbDescriptor(Dev, DESC_TYPE_STRING, + StringId, LangId); + } + + if (StrDesc == NULL) { + return Status; + } + + if (StrDesc->Length > 2 && StrDesc->DescriptorType == DESC_TYPE_STRING) { + // + // Allocate memory for string & copy + // + if (String != NULL) { + gBS->AllocatePool(EfiBootServicesData, StrDesc->Length, String); + EfiZeroMem(*String, StrDesc->Length); + EfiCopyMem(*String, StrDesc->String, StrDesc->Length -2); + } + Status = EFI_SUCCESS; + } + if ((StrDesc != Grp->SerialNumberStrDesc) && (StrDesc != Grp->ProductStrDesc) && + (StrDesc != Grp->ManufacturerStrDesc)) { + gBS->FreePool(StrDesc); + } + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbIoGetSupportedLanguages +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbIoGetSupportedLanguages( + IN EFI_USB_IO_PROTOCOL *UsbIo, + OUT UINT16 **LangIdTable, + OUT UINT16 *TableSize ) +{ + USBDEV_T* Dev = UsbIo2Dev(UsbIo); + DEVGROUP_T* Grp; + + ASSERT( Dev->dev_info ); + ASSERT( Dev->hc ); + Grp = UsbDevGetGroup(Dev); + if (LangIdTable == NULL || TableSize == NULL) { + return EFI_SUCCESS; + } + if (Grp->lang_table == NULL) { + *LangIdTable = 0; + *TableSize = 0; + } else { + *LangIdTable = Grp->lang_table->langID; + *TableSize = Grp->lang_table->len*2; + } + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: LoadName +// +// Description: loads STRING descriptor that corresponds to +// the name of the USB device +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +CHAR16* +LoadName( + USBDEV_T* Dev +) +{ + EFI_USB_INTERFACE_DESCRIPTOR DescIf = {0,}; + EFI_USB_DEVICE_DESCRIPTOR DescDev = {0,}; + DEVGROUP_T* Grp = UsbDevGetGroup(Dev); + CHAR16* StrIf = 0; + CHAR16* StrProduct = 0; +// CHAR16* StrManufact=0; + CHAR16 Lang; + CHAR16 *MassStorageName; + UINT8 *p; + UINT8 i; + + for (i = 0; i < 64; i++) { + if (Dev->dev_info->DevNameString[i] != 0) { + break; + } + } + + if (i != 64) { + gBS->AllocatePool (EfiBootServicesData, 128, &MassStorageName); + EfiZeroMem(MassStorageName, 128); + for (p = (UINT8*)&Dev->dev_info->DevNameString, i=0; i<64; i++) { + if (p[i] == 0) break; + MassStorageName[i] = (CHAR16)p[i]; + } + return MassStorageName; + } + + if( Grp->lang_table == 0 || Grp->lang_table->len == 0 ) return 0; + + Lang = Grp->lang_table->langID[0]; + + UsbIoGetInterfaceDescriptor(&Dev->io,&DescIf); + if( DescIf.Interface && !EFI_ERROR( + UsbIoGetStringDescriptor(&Dev->io, Lang, + DescIf.Interface, &StrIf ))) + return StrIf; + + UsbIoGetDeviceDescriptor(&Dev->io, &DescDev); + if( DescDev.StrProduct && !EFI_ERROR( + UsbIoGetStringDescriptor(&Dev->io, Lang, + DescDev.StrProduct, &StrProduct ))) + return StrProduct; + + return NULL; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: InstallDevice +// +// Description: Adds a device to the tree; creates an EFI handle for the +// usb device; installs USB_IO and DEVICEPATH protocols +// on a new device handle; connects a new device to +// EFI device drivers +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +TREENODE_T* +UsbDevHubNode( + TREENODE_T *HcNode, + DEV_INFO *DevInfo +) +{ +// int i; + TREENODE_T *HubNode=0; + TREENODE_T *HubGrpNode; + + HubGrpNode = TreeSearchDeep(HcNode->child, DevGrpByAddr, &DevInfo->bHubDeviceNumber ); + if (HubGrpNode != NULL){ + HubNode = HubGrpNode->child; + ASSERT(HubNode); + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: parent Hub found: %x\n", HubNode ); + return HubNode; + } +/* + for( i=0;i<COUNTOF(gUsbData->aDevInfoTable) && (HubNode==0);i++){ + if((gUsbData->aDevInfoTable[i].Flag & (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT)) + != (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT)) + continue; + if( gUsbData->aDevInfoTable[i].bHCNumber == DevInfo->bHCNumber && + gUsbData->aDevInfoTable[i].bDeviceAddress == DevInfo->bHubDeviceNumber ) + { + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: UsbDevHubNode: valid hub info [%d]: %x\n",i, gUsbData->aDevInfoTable +i ); + InstallDevice( gUsbData->aDevInfoTable +i ); + HubNode = TreeSearchDeep(HcNode->child, DevByInfo, gUsbData->aDevInfoTable +i ); + ASSERT(HubNode); + } + } +*/ + return HubNode; +} + +VOID InstallDevice(DEV_INFO* DevInfo) +{ + TREENODE_T* HcNode; + TREENODE_T* HubNode; + TREENODE_T* ParentNode; + USBDEV_T* Dev; + DEVGROUP_T* Grp; + EFI_STATUS Status; + EFI_TPL OldTpl; + UINT16 Index; + UINT16 *LangId; + UINT16 OrgTimeOutValue; + + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: InstallDevice "); + USB_DEBUG(DEBUG_LEVEL_USBBUS, "(hc:%x,hub:%x,port:%x,addr:%x,if:%x,aif:%x,lun:%x)\n", + DevInfo->bHCNumber, DevInfo->bHubDeviceNumber, DevInfo->bHubPortNumber, DevInfo->bDeviceAddress, + DevInfo->bInterfaceNum, DevInfo->bAltSettingNum, DevInfo->bLUN ); + + // Find HC node in tree + HcNode = TreeSearchSibling(gUsbRootRoot->child, HcByIndex, &DevInfo->bHCNumber ); + + // Do not assert here: it's fine to see a DEV_INFO from not-yet-installed HC + if( HcNode == NULL ) return; + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: HC node found: %x\n", HcNode ); + + // Find a hub node in tree + if( DevInfo->bHubDeviceNumber & BIT7){ // hub is a root HC + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: Connecting to root Hub\n", DevInfo->bHCNumber ); + ASSERT( (DevInfo->bHubDeviceNumber & ~BIT7 )== DevInfo->bHCNumber ); + HubNode = HcNode; + } else { // hub is usb hub device + HubNode = UsbDevHubNode(HcNode, DevInfo); + // Do not assert here: it may be to see a DEV_INFO from not-yet-installed hub. + //ASSERT(HubNode != NULL); + if (HubNode == NULL) return; + } + + ParentNode = NULL; + ParentNode = TreeSearchSibling(HubNode->child, + DevGrpByAddr, &DevInfo->bDeviceAddress ); + + if( ParentNode == NULL ){ + // Create group + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: group created\n" ); + Status = gBS->AllocatePool (EfiBootServicesData, sizeof(DEVGROUP_T), &Grp); + ASSERT_EFI_ERROR(Status); + EfiZeroMem(Grp, sizeof(DEVGROUP_T)); + + Grp->dev_info = DevInfo; + Grp->hc = ((USBBUS_HC_T*)HcNode->data)->hc; + Grp->hc_info = ((USBBUS_HC_T*)HcNode->data)->hc_data; + Grp->f_DevDesc = FALSE; + Grp->configs = NULL; + Grp->config_count = 0; + Grp->ManufacturerStrDesc = NULL; + Grp->ProductStrDesc = NULL; + Grp->SerialNumberStrDesc = NULL; + Grp->type = NodeGroup; + Grp->active_config = 0; + UsbDevLoadAllDescritors(Grp); + // + // Check at least for Device Descriptor present before proceeding + // + if(Grp->f_DevDesc == FALSE) { + // + //When no Device Descriptor present quit installing the device + // + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: dev install aborted - no device descriptor\n"); + return; + } + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: descriptors loaded\n" ); + + //(EIP66231+)> + if ((Grp->dev_desc.StrManufacturer != 0) || (Grp->dev_desc.StrProduct != 0) || + (Grp->dev_desc.StrSerialNumber != 0)) { + // Load langid table + Grp->lang_table = (lang_table_t*)GetUsbDescriptor((USBDEV_T*)Grp, DESC_TYPE_STRING, 0, 0); + if (Grp->lang_table && Grp->lang_table->len != 0) { + Grp->lang_table->len = (Grp->lang_table->len -2) / sizeof(UINT16); + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: LangID table loaded\n" ); + + LangId = Grp->lang_table->langID; + + for (Index = 0; Index < Grp->lang_table->len; Index++) { + if (LangId[Index] == USB_US_LAND_ID) { + break; + } + } + + if (Index != Grp->lang_table->len) { + // Some devices may not respond getting string descriptors + // whcih describing manufacturer, product set the timeout value to 100 ms. + OrgTimeOutValue = gUsbData->wTimeOutValue; + gUsbData->wTimeOutValue = USB_GET_STRING_DESC_TIMEOUT_MS; + if (Grp->dev_desc.StrManufacturer != 0) { + Grp->ManufacturerStrDesc = + (EFI_USB_STRING_DESCRIPTOR*)GetUsbDescriptor( + (USBDEV_T*)Grp, DESC_TYPE_STRING, + Grp->dev_desc.StrManufacturer, USB_US_LAND_ID); + } + if (Grp->dev_desc.StrProduct != 0) { + Grp->ProductStrDesc = + (EFI_USB_STRING_DESCRIPTOR*)GetUsbDescriptor( + (USBDEV_T*)Grp, DESC_TYPE_STRING, + Grp->dev_desc.StrProduct, USB_US_LAND_ID); + } + if (Grp->dev_desc.StrSerialNumber != 0) { + // Set timeout value to 3000 ms for the serial number string descriptor. + gUsbData->wTimeOutValue = USB_GET_SERIAL_NUMBER_DESC_TIMEOUT_MS; + Grp->SerialNumberStrDesc = + (EFI_USB_STRING_DESCRIPTOR*)GetUsbDescriptor( + (USBDEV_T*)Grp, DESC_TYPE_STRING, + Grp->dev_desc.StrSerialNumber, USB_US_LAND_ID); + } + gUsbData->wTimeOutValue = OrgTimeOutValue; + } + } + } + //<(EIP66231+) + TreeAddChild(HubNode,(ParentNode = TreeCreate(&Grp->node, Grp))); + } else { + // Old group was found in tree + TREENODE_T *tmp = TreeSearchSibling(ParentNode->child, DevByAdrIf, DevInfo ); + if(tmp){ + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: IF is already in tree: %x\n", tmp ); + return; + } + + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: multi-function; group node found: %x\n", ParentNode ); + Grp = (DEVGROUP_T*)ParentNode->data; + } + + // Create new device node as a child of HubNode + gBS->AllocatePool (EfiBootServicesData, sizeof(USBDEV_T), &Dev); + ASSERT(Dev); + if (Dev == NULL) return; + EfiZeroMem(Dev, sizeof(USBDEV_T)); + + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: device node created: %x\n", + &Dev->node ); + Dev->type = NodeDevice; + TreeAddChild(ParentNode, TreeCreate(&Dev->node, Dev)); + Dev->dev_info = DevInfo; + Dev->hc = ((USBBUS_HC_T*)HcNode->data)->hc; + Dev->hc_info = ((USBBUS_HC_T*)HcNode->data)->hc_data; + Dev->f_connected = FALSE; + + UsbDevLoadEndpoints(Dev); + + // Speed 00/10/01 - High/Full/Low + //(EIP81612)> + switch (Dev->dev_info->bEndpointSpeed) { + case USB_DEV_SPEED_SUPER_PLUS: + Dev->speed = EFI_USB_SPEED_SUPER_PLUS; + break; + case USB_DEV_SPEED_SUPER: + Dev->speed = EFI_USB_SPEED_SUPER; + break; + case USB_DEV_SPEED_FULL: + Dev->speed = EFI_USB_SPEED_FULL; + break; + case USB_DEV_SPEED_LOW: + Dev->speed = EFI_USB_SPEED_LOW; + break; + case USB_DEV_SPEED_HIGH: + Dev->speed = EFI_USB_SPEED_HIGH; + } + //<(EIP81612) + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: endpoints loaded\n" ); + + // Create Device Path + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: preparing DP...\n" ); + + ASSERT(((USBDEV_T*)HubNode->data)->dp); + Dev->dp = DpAddUsbSegment(((USBDEV_T*)HubNode->data)->dp, + DevInfo->bHubPortNumber - 1, DevInfo->bInterfaceNum); + if (DevInfo->bLUN) { + Dev->dp = DpAddLun(Dev->dp, DevInfo->bLUN); + } + ASSERT(Dev->dp); + + // Install USB_IO protocol + Dev->io.UsbControlTransfer = UsbIoControlTransfer; + Dev->io.UsbBulkTransfer = UsbIoBulkTransfer; + Dev->io.UsbAsyncInterruptTransfer = UsbIoAsyncInterruptTransfer; + Dev->io.UsbSyncInterruptTransfer = UsbIoSyncInterruptTransfer; + Dev->io.UsbIsochronousTransfer = UsbIoIsochronousTransfer; + Dev->io.UsbAsyncIsochronousTransfer = UsbIoAsyncIsochronousTransfer; + + Dev->io.UsbGetDeviceDescriptor = UsbIoGetDeviceDescriptor; + Dev->io.UsbGetConfigDescriptor = UsbIoGetConfigDescriptor; + Dev->io.UsbGetInterfaceDescriptor = UsbIoGetInterfaceDescriptor; + Dev->io.UsbGetEndpointDescriptor = UsbIoGetEndpointDescriptor; + Dev->io.UsbGetStringDescriptor = UsbIoGetStringDescriptor; + Dev->io.UsbGetSupportedLanguages = UsbIoGetSupportedLanguages; + + Dev->io.UsbPortReset = UsbIoPortReset; + +// DEBUG_DELAY(); + //Install DP_ protocol + Status = gBS->InstallMultipleProtocolInterfaces ( + &Dev->handle, + &gEfiUsbIoProtocolGuid, &Dev->io, + &gEfiDevicePathProtocolGuid, Dev->dp, + NULL); + ASSERT_EFI_ERROR(Status); + + *(UINTN*)Dev->dev_info->Handle = (UINTN)Dev->handle; + Dev->dev_info->Flag |= DEV_INFO_DEV_BUS; + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: USB_IO %x installed on Dev %x\n", &Dev->io, Dev ); + + { + VOID* tmp; + VERIFY_EFI_ERROR( + gBS->OpenProtocol ( + Dev->hc_info->Controller, + &gEfiUsb2HcProtocolGuid, + &tmp, + gUSBBusDriverBinding.DriverBindingHandle, + Dev->handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER )); + } + + PROGRESS_CODE(DXE_USB_HOTPLUG); + + OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL); + pBS->RestoreTPL(TPL_CALLBACK); + + // Connect controller to start device drvirs + Status = gBS->ConnectController(Dev->handle,NULL,NULL,TRUE); + + pBS->RaiseTPL(TPL_HIGH_LEVEL); + pBS->RestoreTPL(OldTpl); + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: instdev: connect controller: %r\n", Status ); + + if( !EFI_ERROR(Status)){ + Dev->f_connected = TRUE; + } + return; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UninstallDevice +// +// Description: Disconnects device; uninstalls USB_IO and DEVICEPATH protocols +// delocates all memory used USB Bus driver to support the device +// removes device node from the tree; if device has children, all +// UninstallDevice procedure is repeated for each child. +// +// In case if disconnect or protocol uninstall fails, it reports +// error stauts returned from Boot service procedure. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS UninstallDevice(USBDEV_T* Dev) +{ + EFI_STATUS Status; + EFI_TPL OldTpl; + + // + // Uninstall connected devices if it's a hub + // + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: UninstallDevice: node %x; ", &Dev->node); + USB_DEBUG(DEBUG_LEVEL_USBBUS, "info:%x [adr:%d;if:%d] uninstalling children...\n", + Dev->dev_info,Dev->dev_info->bDeviceAddress, Dev->dev_info->bInterfaceNum); + if( TreeSearchSibling( Dev->node.child, eUninstallDevice, &Status )) + return Status; + + OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL); + pBS->RestoreTPL(TPL_CALLBACK); + + Status = gBS->DisconnectController(Dev->handle, NULL, NULL); + + pBS->RaiseTPL(TPL_HIGH_LEVEL); + pBS->RestoreTPL(OldTpl); + + if (EFI_ERROR(Status)) { + QueuePut(&gUsbData->QueueCnnctDisc, Dev->dev_info); + Dev->dev_info->Flag |= DEV_INFO_IN_QUEUE; + return Status; + } + + if (Dev->async_endpoint != 0) { + Status = Dev->io.UsbAsyncInterruptTransfer(&Dev->io, Dev->async_endpoint, FALSE, + 0, 0, NULL, NULL); + Dev->async_endpoint = 0; + } + + Status = gBS->CloseProtocol ( + Dev->hc_info->Controller, + &gEfiUsb2HcProtocolGuid, + gUSBBusDriverBinding.DriverBindingHandle, + Dev->handle + ); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + + // + // Try to uninstall protocols + // + // they can be denied to uninstall, which result in + // keeping this device and all bus alive + // + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: uninstdev: [%d:%d] uninstalling protocols...", + Dev->dev_info->bDeviceAddress, Dev->dev_info->bInterfaceNum); + Status = gBS->UninstallMultipleProtocolInterfaces ( + Dev->handle, + &gEfiUsbIoProtocolGuid, &Dev->io, + &gEfiDevicePathProtocolGuid, Dev->dp, + NULL); + USB_DEBUG(DEBUG_LEVEL_USBBUS, "%r\n", Status ); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) return Status; + + Dev->dev_info->Flag &= ~DEV_INFO_DEV_BUS; + if (!(Dev->dev_info->Flag & (DEV_INFO_MASS_DEV_REGD | DEV_INFO_DEV_PRESENT))) { + Dev->dev_info->Flag &= ~DEV_INFO_VALID_STRUC; + } + + // + // Unistall succeeded, free usbdev + // + TreeRemove(&Dev->node); + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: uninstdev: [%d:%d] done.\n", + Dev->dev_info->bDeviceAddress, Dev->dev_info->bInterfaceNum); + + if(Dev->name) + gBS->FreePool(Dev->name); + gBS->FreePool(Dev); + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: eUninstallDevice +// +// Description: Enumeration call-back function that is usded +// uninstall all enumerated device nodes +// Stops enumeration as soon as error was recieved +// Input: +// Node - tree node of the USB device or group +// Contex - pointer to the EFI_STATUS variable that +// recieves status information if error +// was recieved +// Output: TRUE on error found; this will stop enumeration +// FALSE on succesfull uninstall operation +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> +int +eUninstallDevice( + VOID* Node, + VOID* Context +) +{ + EFI_STATUS *Status = (EFI_STATUS*)Context; + DEVGROUP_T* Grp = (DEVGROUP_T*)Node; + ASSERT(Status); + + if (Grp->type == NodeGroup) { + // + // Uninstall all CONNECTED devices within group + // + TreeSearchSibling( Grp->node.child, eUninstallDevice, Status ); + if (EFI_ERROR(*Status)) { + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: devgroup uninstall failed: devaddr:0x%x\n", + Grp->dev_info->bDeviceAddress ); + return TRUE; //stop enumeration + } + // Free devgroup + TreeRemove(&Grp->node); + if (Grp->configs) { + int i; + for (i = 0; i < Grp->config_count; ++i) { + if (Grp->configs[i]) { + gBS->FreePool(Grp->configs[i]); + } + } + gBS->FreePool(Grp->configs); + } + if (Grp->ManufacturerStrDesc) { + gBS->FreePool(Grp->ManufacturerStrDesc); + } + if (Grp->ProductStrDesc) { + gBS->FreePool(Grp->ProductStrDesc); + } + if (Grp->SerialNumberStrDesc) { + gBS->FreePool(Grp->SerialNumberStrDesc); + } + gBS->FreePool(Grp); + } else if (Grp->type == NodeDevice ) { + // + //Uninstall Device + // + *Status = UninstallDevice((USBDEV_T*)Node); + if (EFI_ERROR(*Status)) { + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: usbdev uninstall failed: if:%d\n", + ((USBDEV_T*)Node)->dev_info->bInterfaceNum ); + return TRUE; //stop enumeration + } + } + return FALSE;// continue enumeration +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: RemoveHubEcho +// +// Description: Finds the USB hub node that sits on the same +// path (seq. of (hub ports,if) ) but have different +// USB address or DEV_INFO node. This could be the result +// of lost disconnect event or previous error to uninstall +// USB_IO +// Input: +// pDevInfo - DEV_INFO structure that is checked for +// echoes in the bus +// Output: EFI_SUCCESS - echo wasn't found or was succesfully removed +// otherwise return status resulted from attemp to remove the node +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +RemoveHubEcho( + TREENODE_T *HcNode, + UINT8 Addr +) +{ + while(!( Addr & BIT7 )){ + // + // Find hub DEV_INFO + // + int i; + TREENODE_T *HubNode; + TREENODE_T* DevNode; + DEV_INFO* DevInfo=NULL; + + for ( i= 1; i < MAX_DEVICES; i++) { + if( ((gUsbData->aDevInfoTable[i].Flag & + (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT | DEV_INFO_DEV_DUMMY)) + != (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT)) && + gUsbData->aDevInfoTable[i].bDeviceAddress == Addr ) + { + DevInfo = gUsbData->aDevInfoTable+i; + break; + } + } + if ( DevInfo == NULL ) + return EFI_NOT_FOUND; + + // + // Search for parent hub + // + if( DevInfo->bHubDeviceNumber & BIT7 ){ + //Root hub + HubNode = HcNode; + } else { + //USB hub device + TREENODE_T* HubGrpNode = TreeSearchDeep(HcNode->child, + DevGrpByAddr, &DevInfo->bHubDeviceNumber ); + if( HubGrpNode != NULL ){ + USBDEV_T* Dev; + + HubNode = HubGrpNode->child; + ASSERT(HubNode); + DevNode = TreeSearchSibling(HubNode->child, + DevGrpByPortIf, DevInfo); + if(DevNode==NULL) return EFI_SUCCESS; + Dev = (USBDEV_T*)DevNode->data; + if( Dev && (DevInfo->bDeviceAddress != + Dev->dev_info->bDeviceAddress || + DevInfo != Dev->dev_info )) + { + // + // The disconnect event must have been droped + // disconnect old info now + // + + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: echo found [%x]:\n" ); + USB_DEBUG(DEBUG_LEVEL_USBBUS, + "\t(hc:0x%x,hub:0x%x,port:%d,addr:0x%x,if:%d)\n", + Dev->dev_info->bHCNumber, + Dev->dev_info->bHubDeviceNumber, + Dev->dev_info->bHubPortNumber, + Dev->dev_info->bDeviceAddress, + Dev->dev_info->bInterfaceNum); + return RemoveDevInfo(Dev->dev_info); + } + return EFI_SUCCESS; + } else { + // + // Either hub wasn't added to bus yet; or there is echo for the + // brunch. The the later case succesfull removal of the burnch + // removes an echo for this device info + // + Addr = DevInfo->bHubDeviceNumber; + + } + } + } + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: RemoveDevInfoEcho +// +// Description: Finds the USB device node that sits on the same +// path (seq. of (hub ports,if) ) but have different +// USB address or DEV_INFO node. This could be the result +// of lost disconnect event or previous error to uninstall +// USB_IO +// Input: +// DevInfo - DEV_INFO structure that is checked for +// echoes in the bus +// Output: EFI_SUCCESS - echo wasn't found or was succesfully removed +// otherwise return status resulted from attemp to remove the node +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +RemoveDevInfoEcho( + DEV_INFO *DevInfo +) +{ + USBDEV_T *Dev; + TREENODE_T *DevNode; + TREENODE_T *HcNode, *HubNode; + + HcNode = TreeSearchSibling(gUsbRootRoot->child,HcByIndex, + &DevInfo->bHCNumber); + if(HcNode==NULL) return EFI_SUCCESS; + + if( DevInfo->bHubDeviceNumber & BIT7 ){ + //Root hub + HubNode = HcNode; + } else { + //USB hub device + TREENODE_T* HubGrpNode = TreeSearchDeep(HcNode->child, + DevGrpByAddr, &DevInfo->bHubDeviceNumber ); + if( HubGrpNode != NULL ){ + HubNode = HubGrpNode->child; + ASSERT(HubNode); + } else { + // + // Either hub wasn't added to bus yet; or there is echo for the + // brunch. The the later case succesfull removal of the burnch + // removes an echo for this device info + // + //return RemoveHubEcho(HcNode, DevInfo->bHubDeviceNumber); + return EFI_SUCCESS; + } + } + DevNode = TreeSearchSibling(HubNode->child, DevGrpByPortIf, DevInfo); + if(DevNode==NULL) return EFI_SUCCESS; + Dev = (USBDEV_T*)DevNode->data; + if (Dev != NULL) { + // + // The disconnect event must have been droped + // disconnect old info now + // + + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: echo found [%x]:\n" ); + USB_DEBUG(DEBUG_LEVEL_USBBUS, + "\t(hc:0x%x,hub:0x%x,port:%d,addr:0x%x,if:%d)\n", + Dev->dev_info->bHCNumber, + Dev->dev_info->bHubDeviceNumber, + Dev->dev_info->bHubPortNumber, + Dev->dev_info->bDeviceAddress, + Dev->dev_info->bInterfaceNum); + return RemoveDevInfo(Dev->dev_info); + } + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: RemoveDevInfo +// +// Description: Removes device node from the USB bus tree. Device node +// corresponds to the DEV_INFO. Device gets removed in response to +// the pending removal event sheduled from SMM when disconnect +// was detected on USB +// Input: +// DevInfo - DEV_INFO structure that was disconnect +// +// Output: EFI_SUCCESS - echo wasn't found or was succesfully removed +// otherwise return status resulted from attemp to remove the node +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS RemoveDevInfo(DEV_INFO* DevInfo) +{ + TREENODE_T *DevNode; + TREENODE_T *HcNode; + EFI_STATUS Status; + + HcNode = TreeSearchSibling(gUsbRootRoot->child, HcByIndex, + &DevInfo->bHCNumber); + if(HcNode==NULL) return EFI_NOT_FOUND; + + //Check for echoes + + DevNode = TreeSearchDeep(HcNode->child,DevGrpByAddr, + &DevInfo->bDeviceAddress); + if (DevNode==NULL){ + USB_DEBUG(DEBUG_LEVEL_USBBUS, "\tdevice is not found in the tree...\n" ); + return EFI_NOT_FOUND; + } + USB_DEBUG(DEBUG_LEVEL_USBBUS, "\tdevice found in the tree...\n" ); + + Status = EFI_SUCCESS; + eUninstallDevice(DevNode->data, &Status); + USB_DEBUG(DEBUG_LEVEL_USBBUS, "\tDisconnect complete: %r.\n", Status ); + + return Status; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbHcOnTimer +// +// Description: Timer call-back routine that is +// is used to monitor changes on USB Bus +// It monitors the state of queueCnnct and queueDiscnct queues +// which get populated by UsbSmiNotify call-back routine +// +// When this routine finds a new device connected to usb it +// will install a device node for that device by calling +// InstallDevice +// +// When this routine finds a disconneced device it uninstalls the +// device node by calling UninstallDevice +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +UsbHcOnTimer( + EFI_EVENT Event, + VOID *Context +) +{ + DEV_INFO* EventCnnct = 0; + static int i = 0; + int Lock; + EFI_STATUS Status; + + UsbSmiPeriodicEvent(); + + if (Event) { + gBS->SetTimer(Event, TimerCancel, ONESECOND / 10); + } + + ATOMIC({Lock = gBustreeLock; gBustreeLock = 1;}); + + if (Lock) { + USB_DEBUG(DEBUG_LEVEL_USBBUS, "UsbHcOnTimer:: is locked; return\n"); + return; + } + + do { + ATOMIC({EventCnnct = QueueGet(&gUsbData->QueueCnnctDisc);}); + + if (EventCnnct == NULL) { + break; + } + EventCnnct->Flag &= ~DEV_INFO_IN_QUEUE; + // + // There is no need to raise tpl here: this is callback of Event with + // TPL_CALLBACK, so this code doesn't reenter; the Install and Uninstall + // are also called from driver stop and start. Stop and start protect + // the code at TPL_CALLBACK level + // + if( (EventCnnct->Flag & (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT | + DEV_INFO_DEV_DUMMY)) == (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT) ){ + USB_DEBUG(DEBUG_LEVEL_USBBUS, "UsbHcOnTimer:: event connect [%d]: %x\n", i++, EventCnnct); + + RemoveDevInfoEcho(EventCnnct); + InstallDevice(EventCnnct); + } else if ((EventCnnct->Flag & (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT | + DEV_INFO_DEV_DUMMY)) == DEV_INFO_VALID_STRUC) { + USB_DEBUG(DEBUG_LEVEL_USBBUS, + "UsbHcOnTimer:: event disconnect [%d]: %x\n", i++, EventCnnct); + USB_DEBUG(DEBUG_LEVEL_USBBUS, + "\t(hc:0x%x,hub:0x%x,port:%d,addr:0x%x,if:%d)\n", + EventCnnct->bHCNumber, EventCnnct->bHubDeviceNumber, + EventCnnct->bHubPortNumber, EventCnnct->bDeviceAddress, + EventCnnct->bInterfaceNum); + //RemoveDevInfoEcho(EventCnnct); + Status = RemoveDevInfo(EventCnnct); + if (EFI_ERROR(Status)) { + break; + } + } + } while ( EventCnnct != NULL ); + + gBustreeLock = 0; + + if (Event) { + gBS->SetTimer(Event, TimerPeriodic, ONESECOND / 10); + } +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: PopulateTree +// +// Description: Enumerate all DEV_INFO structures in the aDevInfoTable array +// and install all currently connected device +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +PopulateTree( + HC_STRUC *HcStruc +) +{ + UINT16 i; + + PROGRESS_CODE(DXE_USB_DETECT); + + UsbHcOnTimer(NULL, NULL); + + for (i = 1; i < COUNTOF(gUsbData->aDevInfoTable); i++) { + if ((gUsbData->aDevInfoTable[i].Flag & (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT | + DEV_INFO_DEV_DUMMY | DEV_INFO_DEV_BUS)) == (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT)) { + if (HcStruc != gUsbData->HcTable[gUsbData->aDevInfoTable[i].bHCNumber - 1]) { + continue; + } + // + // Valid and present device behind specified HC, so insert it in the tree + // + USB_DEBUG(DEBUG_LEVEL_3, "USBBUS: PopulateTree: found valid dev info[%d]: %x\n",i, gUsbData->aDevInfoTable +i ); + + //RemoveDevInfoEcho(&gUsbData->aDevInfoTable[i]); + //InstallDevice( gUsbData->aDevInfoTable + i ); + if (!(gUsbData->aDevInfoTable[i].Flag & DEV_INFO_IN_QUEUE)) { + QueuePut(&gUsbData->QueueCnnctDisc, &gUsbData->aDevInfoTable[i]); + gUsbData->aDevInfoTable[i].Flag |= DEV_INFO_IN_QUEUE; + } + } + } +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbBusGetControllerName +// +// Description: This function is a part of binding protocol, it returns +// the string with the controller name. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +CHAR16* +UsbBusGetControllerName( + EFI_HANDLE Controller, + EFI_HANDLE Child +) +{ + //(EIP60745+)> + EFI_STATUS Status; + + Status = gBS->OpenProtocol ( Controller, + &gEfiUsb2HcProtocolGuid, + NULL, + gUSBBusDriverBinding.DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); + + if (Status != EFI_SUCCESS && Status != EFI_ALREADY_STARTED) { + return NULL; + } + //<(EIP60745+) + if(Child) { + //Get name for USB device + EFI_USB_IO_PROTOCOL *UsbIo; + USBDEV_T *Dev ; + if( EFI_ERROR(gBS->HandleProtocol(Child,& gEfiUsbIoProtocolGuid, &UsbIo))) + { + return NULL; + } + Dev = UsbIo2Dev(UsbIo); + if( Dev->name == 0) + Dev->name = LoadName(Dev); + return Dev->name; + } else { + //Get name for USB HC + return L"USB Host Controller (USBBUS)"; + } +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbBusInit +// +// Description: Install driver binding and controller name protocols +// for the USB bus driver. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbBusInit( + EFI_HANDLE ImageHandle, + EFI_HANDLE ServiceHandle +) +{ + //(EIP59272)> + static NAME_SERVICE_T usbbus_names; + gUSBBusDriverBinding.DriverBindingHandle = ServiceHandle; + gUSBBusDriverBinding.ImageHandle = ImageHandle; + + return gBS->InstallMultipleProtocolInterfaces( + &gUSBBusDriverBinding.DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, &gUSBBusDriverBinding, + &gEfiComponentName2ProtocolGuid, InitNamesProtocol(&usbbus_names, + L"USB bus", UsbBusGetControllerName), + NULL); + //<(EIP59272) +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbBusSupported +// +// Description: This is a binding protocol function that returns EFI_SUCCESS +// for USB controller and EFI_UNSUPPORTED for any other kind of +// controller. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbBusSupported( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + EFI_DEVICE_PATH_PROTOCOL *DevicePath +) +{ + EFI_STATUS Status; + VOID* Ptr = 0; + + Status = gBS->OpenProtocol ( Controller, &gEfiUsb2HcProtocolGuid, + &Ptr, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); + + if (Status != EFI_SUCCESS && Status != EFI_ALREADY_STARTED) { + return EFI_UNSUPPORTED; + } else if (Status == EFI_ALREADY_STARTED) { + return Status; + } + + gBS->CloseProtocol ( Controller, &gEfiUsb2HcProtocolGuid, + This->DriverBindingHandle, Controller); + + Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, + NULL, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); + + if (Status != EFI_SUCCESS && Status != EFI_ALREADY_STARTED) { + return EFI_UNSUPPORTED; + } + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbBusStop +// +// Description: This function is part of binding protocol installed on USB +// controller. It stops the controller and removes all the +// children. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbBusStop ( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + UINTN NumberOfChildren, + EFI_HANDLE *Children ) +{ + EFI_STATUS Status = EFI_SUCCESS; + TREENODE_T *HcNode; + USBBUS_HC_T *HcDev; + + //EFI_TPL SaveTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); + //ASSERT(SaveTpl <= EFI_TPL_NOTIFY ); + + HcNode = TreeSearchSibling(gUsbRootRoot->child, HcByHandle, &Controller ); + ASSERT(HcNode); + if( HcNode == NULL ) { + //gBS->RestoreTPL(SaveTpl); + return EFI_DEVICE_ERROR; + } + HcDev = (USBBUS_HC_T*)HcNode->data; + + VERIFY_EFI_ERROR( + gBS->SetTimer( gEvUsbEnumTimer, TimerCancel, ONESECOND/10)); + + UsbHcOnTimer(NULL, NULL); + + if (TreeSearchSibling(HcNode->child, eUninstallDevice, &Status) != NULL) + { + USB_DEBUG(DEBUG_LEVEL_USBBUS, + "USBBUS: Stop HC: [%d] failed to uninstall children\n", + ((USBBUS_HC_T*)HcNode->data)->hc_data->bHCNumber); + //gBS->RestoreTPL(SaveTpl); + VERIFY_EFI_ERROR( + gBS->SetTimer ( gEvUsbEnumTimer, TimerPeriodic, ONESECOND/10)); + return Status; + } + + if (NumberOfChildren == 0) { + TreeRemove(HcNode); + + // + // Close Protocols opened by driver + // + gBS->CloseProtocol ( + Controller, &gEfiUsb2HcProtocolGuid, + This->DriverBindingHandle, Controller); + + gBS->FreePool(HcDev); + + if(--gCounterUsbEnumTimer==0){ + VERIFY_EFI_ERROR( + gBS->SetTimer ( gEvUsbEnumTimer, TimerCancel, ONESECOND/10)); + VERIFY_EFI_ERROR( + gBS->CloseEvent (gEvUsbEnumTimer)); + gEvUsbEnumTimer=0; + } + } + + if (gCounterUsbEnumTimer != 0) { + VERIFY_EFI_ERROR( + gBS->SetTimer ( gEvUsbEnumTimer, TimerPeriodic, ONESECOND/10)); + } + //gBS->RestoreTPL(SaveTpl); + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbBusStart +// +// Description: This function is part of binding protocol installed on USB +// controller. It starts the USB bus for a given controller. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbBusStart( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + EFI_DEVICE_PATH_PROTOCOL *DevicePathProtocol +) +{ + USBBUS_HC_T* HcDev = 0; + EFI_STATUS Status = EFI_UNSUPPORTED; + + VERIFY_EFI_ERROR ( + gBS->AllocatePool ( + EfiBootServicesData, + sizeof(USBBUS_HC_T), + &HcDev )); + HcDev->type = NodeHC; + HcDev->hc_data = FindHcStruc(Controller); + +// ASSERT(HcDev->hc_data); + if (HcDev->hc_data == NULL) { + gBS->FreePool(HcDev); + return EFI_DEVICE_ERROR; + } + + // + // Open Protocols + // + Status = gBS->OpenProtocol ( Controller, + &gEfiUsb2HcProtocolGuid, &HcDev->hc, + This->DriverBindingHandle, Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER ); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) { + return Status; + } + + Status = gBS->OpenProtocol ( Controller, + &gEfiDevicePathProtocolGuid, + &HcDev->dp, This->DriverBindingHandle, + Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Install Polling timer + // + { + //EFI_TPL SaveTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); + //ASSERT( SaveTpl <= EFI_TPL_NOTIFY); + if(gEvUsbEnumTimer != 0) { + VERIFY_EFI_ERROR( + gBS->SetTimer ( gEvUsbEnumTimer, TimerCancel, ONESECOND/10)); + } + // + // Critical section + +// HookSmiNotify(1); + + USB_DEBUG(DEBUG_LEVEL_USBBUS,"**** \tnew hc_struc: %x(type:%x,number:%x)\n", + HcDev->hc_data, HcDev->hc_data->bHCType, HcDev->hc_data->bHCNumber); + + // + // Create HC branch in the USB root + // + TreeAddChild(gUsbRootRoot, TreeCreate(&HcDev->node,HcDev)); + + gCounterUsbEnumTimer++; + PopulateTree(HcDev->hc_data); + + UsbHcOnTimer(NULL, NULL); + + // Setting up global: gUsbDeviceToDisconnect, gUsbDeviceToConnect + if (gEvUsbEnumTimer == 0) { + USB_DEBUG(DEBUG_LEVEL_USBBUS, "USBBUS: Start: setup timer callback %x\n", &UsbHcOnTimer ); + VERIFY_EFI_ERROR( + gBS->CreateEvent ( EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, UsbHcOnTimer,0,&gEvUsbEnumTimer)); + } + VERIFY_EFI_ERROR( + gBS->SetTimer ( gEvUsbEnumTimer, TimerPeriodic, ONESECOND/10)); + //gBS->RestoreTPL(SaveTpl); + } + + return EFI_SUCCESS; +} + +#if defined(DEBUG_SWITCH) && (DEBUG_SWITCH == 1) +VOID DEBUG_DELAY() +{ + int i; + PrintDebugMsg(3,"\nDELAY: "); + for(i=0;i<10;i++){ + PrintDebugMsg(3,"%d..",i); + pBS->Stall(200*1000); + } + PrintDebugMsg(3,"\n"); +} +#endif + +//**************************************************************************** +//**************************************************************************** +//** ** +//** (C)Copyright 1985-2015, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** +//** ** +//** Phone (770)-246-8600 ** +//** ** +//**************************************************************************** +//**************************************************************************** |