//**************************************************************************** //**************************************************************************** //** ** //** (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 //**************************************************************************** // // // Name: UsbBus.c // // Description: USB Bus driver implementation // // //**************************************************************************** //#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; // //--------------------------------------------------------------------------- // // Name: UsbIo2Dev // // Description: This function returns a pointer to USB device from UsbIo. // //--------------------------------------------------------------------------- // USBDEV_T* UsbIo2Dev(EFI_USB_IO_PROTOCOL* UsbIo) { return (USBDEV_T*)((char*)UsbIo - (UINTN)&((USBDEV_T*)0)->io ); } // //--------------------------------------------------------------------------- // // Name: HcByIndex // // Description: Predicate for searching host controller node in the tree // by bHcNumber // //--------------------------------------------------------------------------- // 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 ); } // //--------------------------------------------------------------------------- // // Name: HcByHandle // // Description: Predicate for searching host controller node in the tree // by EFI controller handle // //--------------------------------------------------------------------------- // 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 ); } // //--------------------------------------------------------------------------- // // 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 // //--------------------------------------------------------------------------- // int DevByIndex(VOID* n, VOID* d) { USBDEV_T* Dev = (USBDEV_T*)n; return (Dev->type == NodeDevice) && (Dev->dev_info == gUsbData->aDevInfoTable + *(UINT8*)d ); } // //--------------------------------------------------------------------------- // // Name: DevGrpByAddr // // Description: Predicate for searching device node in the tree // by USB address of the device // //--------------------------------------------------------------------------- // 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 ); } // //--------------------------------------------------------------------------- // // Name: DevGrpByPortIf // // Description: Predicate for searching device node in the tree // by parent hub port of the device, interface and LUN // //--------------------------------------------------------------------------- // 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 ); } // //--------------------------------------------------------------------------- // // Name: DevByInfo // // Description: Predicate for searching device node in the tree // by comparing pointers to the DEV_INFO structure // //--------------------------------------------------------------------------- // int DevByInfo(VOID* n, VOID* d ) { USBDEV_T* Dev = (USBDEV_T*)n; return (Dev->type == NodeDevice) && (Dev->dev_info == (DEV_INFO*)d ); } // //--------------------------------------------------------------------------- // // Name: DevByAdrIf // // Description: Predicate for searching device node in the tree // by USB address and interface number of the device // //--------------------------------------------------------------------------- // 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)); } // //--------------------------------------------------------------------------- // // 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 // //--------------------------------------------------------------------------- // DEVGROUP_T* UsbDevGetGroup(USBDEV_T* Dev) { return (DEVGROUP_T*)Dev->node.parent->data; } // //--------------------------------------------------------------------------- // // Name: DpAddUsbSegment // // Description: Builds a new path appending a USB segment // // Output: Pointer to a callee allocated memory buffer // //--------------------------------------------------------------------------- // 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); } // //--------------------------------------------------------------------------- // // Name: DpAddLun // // Description: Builds a new path appending a LUN node // // // Output: Pointer to a callee allocated memory buffer // //--------------------------------------------------------------------------- // 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); } // //--------------------------------------------------------------------------- // // 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 // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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 // //--------------------------------------------------------------------------- // 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; } */ } // //--------------------------------------------------------------------------- // // Name: FreeConfigDesc // // Description: Delocates memory that was used by the descriptor // //--------------------------------------------------------------------------- // VOID FreeConfigDesc( VOID* Desc ) { if (Desc != 0) gBS->FreePool(Desc); } // //--------------------------------------------------------------------------- // // 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 // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Name: UsbDevConfigDesc // // Description: Returns a pointer to the memory containing CONFIG_DESCRIPTOR // reported by the USB device // //--------------------------------------------------------------------------- // 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)); } // //--------------------------------------------------------------------------- // // 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 // //--------------------------------------------------------------------------- // 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; iconfig_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; } } } // //--------------------------------------------------------------------------- // // Name: UsbDevLoadEndpoints // // Description: Locates information about each endpoint inside the // descriptors pack loaded with CONFIG descriptor // //--------------------------------------------------------------------------- // 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;jNumEndpoints && 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" ); } // //--------------------------------------------------------------------------- // // Name: GetMaxPacket // // Description: Retrieves information about a max packet size // for the specified endpoint of the device // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Name: GetEndpointDesc // // Description: Retrieves information about a max packet size // for the specified endpoint of the device // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Name: UsbIoControlTransfer // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Name: UsbIoBulkTransfer // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Name: UsbIoIsochronousTransfer // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Name: UsbIoSyncInterruptTransfer // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Name: UsbIoIsochronousTransfer // //--------------------------------------------------------------------------- // 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); } // //--------------------------------------------------------------------------- // // Name: UsbIoAsyncIsochronousTransfer // //--------------------------------------------------------------------------- // 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 ); } // //--------------------------------------------------------------------------- // // Name: UsbIoPortReset // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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. // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Name: UsbIoGetConfigDescriptor // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Name: UsbIoGetInterfaceDescriptor // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Name: UsbIoGetEndpointDescriptor // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Name: UsbIoGetStringDescriptor // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Name: UsbIoGetSupportedLanguages // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Name: LoadName // // Description: loads STRING descriptor that corresponds to // the name of the USB device // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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 // //--------------------------------------------------------------------------- // 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;iaDevInfoTable) && (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; } // //--------------------------------------------------------------------------- // // 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. // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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 // //--------------------------------------------------------------------------- // 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 } // //--------------------------------------------------------------------------- // // 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 // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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 // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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 // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // 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 // //--------------------------------------------------------------------------- // 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); } } // //--------------------------------------------------------------------------- // // Name: PopulateTree // // Description: Enumerate all DEV_INFO structures in the aDevInfoTable array // and install all currently connected device //--------------------------------------------------------------------------- // 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; } } } } // //--------------------------------------------------------------------------- // // Name: UsbBusGetControllerName // // Description: This function is a part of binding protocol, it returns // the string with the controller name. // //--------------------------------------------------------------------------- // 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)"; } } // //--------------------------------------------------------------------------- // // Name: UsbBusInit // // Description: Install driver binding and controller name protocols // for the USB bus driver. // //--------------------------------------------------------------------------- // 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) } // //--------------------------------------------------------------------------- // // 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. // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Name: UsbBusStop // // Description: This function is part of binding protocol installed on USB // controller. It stops the controller and removes all the // children. // //--------------------------------------------------------------------------- // 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; } // //--------------------------------------------------------------------------- // // Name: UsbBusStart // // Description: This function is part of binding protocol installed on USB // controller. It starts the USB bus for a given controller. // //--------------------------------------------------------------------------- // 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 ** //** ** //**************************************************************************** //****************************************************************************