summaryrefslogtreecommitdiff
path: root/Core/EM/usb/rt/usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/usb/rt/usb.c')
-rw-r--r--Core/EM/usb/rt/usb.c5300
1 files changed, 5300 insertions, 0 deletions
diff --git a/Core/EM/usb/rt/usb.c b/Core/EM/usb/rt/usb.c
new file mode 100644
index 0000000..b1baa4a
--- /dev/null
+++ b/Core/EM/usb/rt/usb.c
@@ -0,0 +1,5300 @@
+#pragma warning(disable: 4001)
+#pragma warning(disable: 4127)
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************
+
+//****************************************************************************
+// $Header: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usb.c 183 10/21/16 1:48a Wilsonlee $
+//
+// $Revision: 183 $
+//
+// $Date: 10/21/16 1:48a $
+//****************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usb.c $
+//
+// 183 10/21/16 1:48a Wilsonlee
+// Fixed Cppcheck error.
+//
+// 182 10/16/16 10:12p Wilsonlee
+// [TAG] EIP288158
+// [Category] Improvement
+// [Description] Check if gUsbData is integrity.
+// [Files] amiusb.cif, usbsb.c, AmiUsbLib.cif, AmiUsbLib.sdl,
+// AmiUsbSmmGlobalDataValidationLib.c,
+// AmiUsbSmmGlobalDataValidationLib.cif,
+// AmiUsbSmmGlobalDataValidationLib.mak, Crc32.c, amiusb.c, amiusb.h,
+// ehci.c, elib.c, ohci.c, syskbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h,
+// usbhid.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c, usbrt.mak, xhci.c,
+// amiusbhc.c, efiusbccid.c, efiusbmass.c, uhcd.c, usbmisc.c,
+// AmiUsbController.h, AmiUsbLibInclude.cif,
+// AmiUsbSmmGlobalDataValidationLib.h
+//
+// 181 7/28/16 4:56a Wilsonlee
+// [TAG] EIP264662
+// [Category] Improvement
+// [Description] Don't install usb hw smi after reconnecting usb
+// controllers.
+// [Files] uhcd.c, usb.c, ohci.c, amiusb.c, amiusbhc.c
+//
+// 180 3/02/16 9:41p Wilsonlee
+// [TAG] EIP254309
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] GK-FORCE K83 USB KB function abnormal.
+// [RootCause] This device has an interrupt out endpoint and doesn't
+// support "Set Report" request.
+// [Solution] Use the interrupt out endpoint instead of sending "Set
+// Report" request.
+// [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c,
+// usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusb.h, efiusbms,c, amiusbhc.c
+//
+// 179 11/04/15 9:51p 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
+//
+// 178 9/01/15 10:17p Wilsonlee
+// [TAG] EIP235482
+// [Category] Improvement
+// [Description] Select this alternate setting for multiple TTs hubs.
+// [Files] usbhub.c, usb.c, amiusb.h, usbdef.h
+//
+// 177 7/24/15 3:30a Wilsonlee
+// [TAG] EIP229294
+// [Category] Improvement
+// [Description] If the device descriptor returns with a value in its
+// length field that is greater 18, it is valid and we should ignore the
+// extra bytes.
+// [Files] usb.c
+//
+// 176 5/28/15 4:29a Wilsonlee
+// [TAG] EIP219785
+// [Category] Improvement
+// [Description] Suspend usb devices which are connected to Hubs.
+// [Files] usb.c, usbdef.h
+//
+// 175 4/29/15 11:26p 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
+//
+// 174 4/27/15 2:25a Wilsonlee
+// [TAG] EIP211855
+// [Category] Improvement
+// [Description] Set the default interface if the device has alternate
+// setting for the interface.
+// [Files] usb.c, usbdef.h
+//
+// 173 4/07/15 4:03a Wilsonlee
+// [TAG] EIP211598
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Keyboard/Mouse sometimes cannot work when connected to USB
+// 3.0 HUB.
+// [RootCause] It's failed at setting device address.
+// [Solution] Wait 10 ms for stable before we set device address.
+// [Files] usb.c
+//
+// 172 3/08/15 10:49p Wilsonlee
+// [TAG] EIP207774
+// [Category] Improvement
+// [Description] Set USB_FLAG_DRIVER_STARTED flag when HC is running and
+// clear it if we don't start any HC.
+// [Files] uhci.c, usb.c, ehci.c, ohci.c, xhci.c, amiusb.h
+//
+// 171 2/16/15 2:44a Wilsonlee
+// [TAG] EIP205373
+// [Category] Improvement
+// [Description] Cppcheck errors in Usb module.
+// [Files] usb.c, usbport.c, uhcd.c, usbCCID.c
+//
+// 170 1/22/15 10:19p Wilsonlee
+// [TAG] EIP201434
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Number of connected devices isn't correct if we plug out
+// keyboards or mice behind hub in xhci.
+// [RootCause] The PortConnectChange bit is cleared when we check port
+// status for interrupt endpoint transaction error.
+// [Solution] Don't clear change bits if we check port status for
+// interrupt endpoint transaction error.
+// [Files] xhci.c, usbhub.c, usbdef.h, usb.c, uhci.c, ohci.c, ehci.c,
+// amiusbhc.c
+//
+// 169 12/15/14 2:16a Wilsonlee
+// [TAG] EIP194720
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] System shutdown delay when connect with cardreader.
+// [RootCause] When we reenumerate devices, we still reserve the
+// original device info, then we will use the wrong info to send command
+// and the device may not respond.
+// [Solution] Remove the present flag of devices before we reenumerate.
+// [Files] usb.c
+//
+// 168 11/23/14 10:09p Wilsonlee
+// [TAG] EIP189293
+// [Category] Improvement
+// [Description] Implement XHCI key repeat function.
+// [Files] usb.c, xhci.c , xhci.h, amiusb.c
+//
+// 167 9/29/14 11:35p 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
+//
+// 166 9/02/14 3:53a Wilsonlee
+// [TAG] EIP182567
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] POST B4h sometimes stays about 30 sec if using special
+// KB/Ms.
+// [RootCause] t's timeout in getting config or report descriptor
+// commands.
+// [Solution] Set the timeout to 500 ms.
+// [Files] usb.c, usbhid.c, usbdef.h
+//
+// 165 7/30/14 5:17a Wilsonlee
+// [TAG] EIP176293
+// [Category] Improvement
+// [Description] The changes are for DisplayLink USB Network driver.
+// [Files] usbbus.c, usb.c
+//
+// 164 7/28/14 7:39a Wilsonlee
+// [TAG] EIP176070
+// [Category] Improvement
+// [Description] Add 100 microseconds before we send get configuration
+// descriptor command if the device is full speed.
+// [Files] usb.c
+//
+// 163 6/26/14 1:16a 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
+//
+// 162 6/20/14 2:11a Wilsonlee
+// [TAG] EIP174589
+// [Category] Improvement
+// [Description] Fix build error if USB_HID_KEYREPEAT_USE_SETIDLE is 1.
+// [Files] usb.c
+//
+// 161 5/12/14 4:29a Wilsonlee
+// [TAG] EIP168515
+// [Category] New Feature
+// [Description] Add the token "USB_CONTROLLERS_INITIAL_DELAY_LIST" if
+// usb controllers need to delay for stabilization.
+// [Files] usb.sdl, usb.c
+//
+// 160 4/30/14 5:25a 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
+//
+// 159 4/29/14 8:30p Wilsonlee
+// [TAG] EIP164772
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] System would auto wake up if USB hot-plug in S5 state via
+// USB hub.
+// [RootCause] The usb hubs have connnect / disconnect wakeup function
+// if we send remote wakeup command
+// [Solution] Don't send remote wakeup command to the usb hubs.
+// [Files] usb.c
+//
+// 158 2/26/14 1:55a Wilsonlee
+// [TAG] EIP149854
+// [Category] Improvement
+// [Description] Add data length parameter to polling callback function.
+// [Files] usbkbd.c, uhci.c, usb.c, usbhub.c, usbCCID.c, usbms.c,
+// usbhid.c, usbpoint.c, usbkbd.h, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 157 11/26/13 1:23a Wilsonlee
+// [TAG] EIP143251
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] The usb mouse lost if it behinds TI TUSB8040A1 hub under
+// BIOS.
+// [RootCause] The device may connect later, then we clear connect
+// change without setting the device is connected.
+// [Solution] Don't get port status again before we clear the changes.
+// [Files] usb.c, usbhub.c
+//
+// 156 11/04/13 3:26a Wilsonlee
+// [TAG] EIP139714
+// [Category] Improvement
+// [Description] Improve the UsbIoPortReset function to support the xhci
+// controller.
+// [Files] usb.c
+//
+// 155 9/04/13 5:46a 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
+//
+// 154 8/16/13 4:17a Ryanchou
+//
+// 153 8/02/13 6:16a Ryanchou
+//
+// 152 7/29/13 5:19a 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
+//
+// 151 7/22/13 10:31p Wilsonlee
+// [TAG] EIP125357
+// [Category] Improvement
+// [Description] Check if the port releases to a select host controller.
+// [Files] uhci.c, usb.c, usbhub.c, ehci.c, ohci.c, xhci.c, usbdef.h
+//
+// 150 7/17/13 4:14a Roberthsu
+// [TAG] EIP126319
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] TEAC floppy can not detect when cold boot.
+// [RootCause] Device need more delay after get config descriptor.
+// [Solution] Add delay to 1ms.
+// [Files] usb.c
+//
+// 149 6/26/13 3:36a Roberthsu
+// [TAG] EIP125792
+// [Category] Bug Fix
+// [Severity:] Normal
+// [Symptom:] Keep function not work
+// [Root Cause] When check port change. We can not get baseclass.
+// [Solution] Add Vaild base class flag.
+// [Files] UsbPort.c,Usb.c
+//
+// 148 5/01/13 9:54p Wilsonlee
+// [TAG] EIP121643
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Cannot detect the usb floppy.
+// [RootCause] This device doesn't return data when we sned
+// get-config-descriptor command.
+// [Solution] We retry to send get-config-descriptor command if there is
+// no data.
+// [Files] usb.c, ehci.c
+//
+// 147 4/19/13 12:44a Wilsonlee
+// Fix build error if token USB_S5_WAKEUP_SUPPORT is enabled.
+//
+// 146 4/18/13 11:22a Ryanchou
+// Fix build error if token x64_BUILD is 0.
+//
+// 145 3/19/13 3:58a Ryanchou
+// [TAG] EIP118177
+// [Category] Improvement
+// [Description] Dynamically allocate HCStrucTable at runtime.
+// [Files] usb.sdl, usbport.c, usbsb.c, amiusb.c, ehci.c, ohci.c,
+// syskbc.c, sysnokbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h, usbhid.c,
+// usbhub.c, usbmass.c, usbrt.mak, usb.sd, amiusbhc.c, efiusbccid.c,
+// efiusbhid.c, efiusbmass.c, efiusbms.c, uhcd.c, uhcd.h, uhcd.mak,
+// usbmisc.c, usbsrc.sdl
+//
+// 144 3/15/13 5:57a Ryanchou
+//
+// 143 3/15/13 4:59a Ryanchou
+// [TAG] EIP117211
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB Memory Allocation Failure for Sizes Above 4k
+// [RootCause] The variable count will be reset when across a page
+// boundary.
+// [Solution] Only reset the variable Count if the allocated blocks less
+// than a page.
+// [Files] usb.c
+//
+// 142 3/07/13 9:25p Wilsonlee
+// [TAG] EIP116044
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] TEAC FDD is not recognized after hot plugging under DOS.
+// [RootCause] Setting the device configuration is failed.
+// [Solution] This device configure successfully by that we set the
+// device address after sending the first get-device-descriptor command.
+// [Files] usb.c
+//
+// 141 3/07/13 8:52a Ryanchou
+// [TAG] EIP113218
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB keyboard cannot work after ownership change back to
+// BIOS
+// [RootCause] The key repeat SMI does not generated because the HC is
+// stopped.
+// [Solution] Use the other HC to generate key repeat SMI
+// [Files] usb.c, usbhid.c, usbkbd.c
+//
+// 140 1/23/13 8:33p Wilsonlee
+// [TAG] EIP108891
+// [Category] Improvement
+// [Description] For usb wakp up function, we need to add some delay to
+// wait the usb devces connect.
+// [Files] usb.c
+//
+// 139 1/22/13 2:38a 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
+//
+// 138 1/11/13 4:15a 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
+//
+// 137 12/05/12 4:23a Roberthsu
+// [TAG] EIP96616
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] When Legacy to EFI, USB KB can't be used.
+// [RootCause] Usb device driver content incorrect driver entry.Legacy
+// insert a devicet,when legacy to efi,device does not install efi driver.
+// [Solution] When legacy to efi, scan device info table and put it
+// to smiqueue.
+// [Files] usb.sdl,uhcd.c,usb.c
+//
+// 136 11/29/12 7:47a Ryanchou
+// [TAG] EIP107586
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Unplug USB keyboard does not uninstall EFI USB keyboard
+// driver properly
+// [RootCause] The EIP99431 changes clear DEV_INFO.bSubDeviceType in
+// runtime keyboard driver, that cause EFI keyboard driver does not know
+// what type of the device is.
+// [Solution] Do not clear DEV_INFO.bSubDeviceType in runtime keyboard
+// driver.
+// [Files] usb.c, usbhid.c, efiusbhid.c
+//
+// 135 11/22/12 9:20p Wilsonlee
+// [TAG] EIP106887
+// [Category] New Feature
+// [Description] Support usb S5 wake up function for UHCI.
+// [Files] usb.c, uhci.c, uhci.h
+//
+// 134 11/13/12 7:11a Wilsonlee
+// [TAG] EIP82553
+// [Category] New Feature
+// [Description] Support usb S5 wake up function for XHCI.
+// [Files] usb.c, ehci.c, ohci.c, xhci.c, xhci.h
+//
+// 133 11/10/12 6:39a 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
+//
+// 132 10/25/12 4:14a Wilsonlee
+// [TAG] EIP82354
+// [Category] New Feature
+// [Description] Support usb S5 wake up function for OHCI.
+// [Files] usb.c, ehci.c, ohci.c
+//
+// 131 9/28/12 2:38a Wilsonlee
+// [TAG] EIP93154
+// [Category] Improvement
+// [Description] Change the unit of the FixedDelay from 15 us to 1 us.
+// [Files] amiusb.h, xhci.c, ehci.c, ohci.c, uhci.c, usb.c, usbCCID.c,
+// usbmass.c, usbhub.c, elib.c
+//
+// 130 9/03/12 4:55a Roberthsu
+// [TAG] EIP98145
+// [Category] Improvement
+// [Description] Add skip function message.
+// [Files] usb.c,usbsrc.sdl
+//
+// 129 8/29/12 9:32a Ryanchou
+// [TAG] EIP88307
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Key repeat cannot be stopped if the keyboard is connected
+// to xHCI.
+// [RootCause] Periodic timer SMI stop generating when USB SMI and
+// periodic timer SMI is generated frequently.
+// [Solution] Reduces the key repeat rate to avoid this issue.
+// [Files] ehci.c, usb.c, usb.sdl
+//
+// 128 8/29/12 8:18a Ryanchou
+// [TAG] EIP77262
+// [Category] New Feature
+// [Description] Remove SMM dependency of USB.
+// [Files] usb.sdl, usbport.c, amiusb.c, amiusb.dxs, amiusb.h, ehci.c,
+// elib.c, ohci.c, uhci.c, usb.c, usbdef.h, usbrt.mak, xhci.c, amiusbhc.c,
+// efiusbccid.c, efiusbhid.c, efiusbkb.c, efiusbmass.c, uhcd.c, uhcd.dxs,
+// uhcd.h, usbmisc.c, AmiUsbController.h
+//
+// 127 8/22/12 4:59a Wilsonlee
+// [TAG] EIP98230
+// [Category] Improvement
+// [Description] Set the default of the MaxPacket for endpoint 0 by the
+// device speed.
+// [Files] usb.c
+//
+// 126 6/13/12 2:39a Roberthsu
+// [TAG] EIP90124
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Insert barcode when pxe option rom running.Barcode will not
+// work under dos.
+// [RootCause] Because pxe option under legacy mode.Back to efi mode
+// barcode after reinit will fail under dos.
+// [Solution] In function USB_ReConfigDevice check device initial done.
+// [Files] usb.c
+//
+// 125 5/22/12 10:04a Ryanchou
+// [TAG] EIP90154
+// [Category] Improvement
+// [Description] Remove the USBSB_EnableSmmPeriodicSmi and
+// USBSB_DisableSmmPeriodicSmi hooks.
+// [Files] amidef.h, amiusb.c, usb.c, usbsb.c
+//
+// 124 5/22/12 4:48a Wilsonlee
+// [TAG] EIP89641
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB Keyboard driver overwrites INT0 vector (address 0:0)
+// [RootCause] The Queue Head cross the page boundary.
+// [Solution] Added page alignment restriction into memory allocation
+// routine.
+// [Files] usb.c
+//
+// 123 5/04/12 6:40a 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
+//
+// 122 5/04/12 5:27a 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
+//
+// 121 4/24/12 3:36a Wilsonlee
+// [TAG] EIP81761
+// [Category] Improvement
+// [Description] Determine the limit of devices after checking whether
+// this device is reconnected.
+// [Files] usb.c
+//
+// 120 2/16/12 8:53p 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
+//
+// 119 1/13/12 4:24a 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
+//
+// 118 1/04/12 6:23a Ryanchou
+//
+// 117 1/04/12 6:22a Ryanchou
+// [TAG] EIP78861
+// [Category] Improvement
+// [Description] Some device will be disconnected after port
+// reset, and reconnected for a while, added 100 ms delay in this case.
+// [Files] usb.c
+//
+// 116 12/26/11 2:24a Roberthsu
+// [TAG] EIP74609
+// [Category] Improvement
+// [Description] Add check oemskiplist at check port change.
+// [Files] usbport.c,usb.c,AmiUsbController.h
+//
+// 115 12/08/11 1:46a Ryanchou
+// [TAG] EIP75441
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] System hangs at 0xB4 after restart from Win7
+// [RootCause] The device does not use standard BOT protocol under
+// Windows.
+// [Solution] Add the device into bad device table.
+// [Files] usb.c usbport.c
+//
+// 114 11/28/11 8:36p Wilsonlee
+// [TAG] EIP73803
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] The mouse can't work under setup after hot-plug.
+// [RootCause] The device may fail at the get device descriptor or set
+// device configuration.
+// [Solution] Add 10 msec delay before getting device descriptor if the
+// device is low or full speed and add 2 msec delay after setting the
+// device's address.
+// [Files] usb.c
+//
+// 113 11/08/11 8:21a Wilsonlee
+// [TAG] EIP74876
+// [Category] New Feature
+// [Description] Add USB API for shutdown single USB controller.
+// [Files] amiusb.c, amiusb.h, usb.c, usbdef.h, uhcd.c, uhcd.h,
+// AmiUsbController.h
+//
+// 112 11/05/11 7:36a Wilsonlee
+// [TAG] EIP64781
+// [Category] New Feature
+// [Description] Added SDL token
+// SKIP_CARD_READER_CONNECT_BEEP_IF_NO_MEDIA that skip the connect beep if
+// no media present in USB card reader.
+// [Files] usbport.c, usbmass.c, usb.c, usbdef.h, uhcd.c, usbsrc.sdl
+//
+// 111 10/25/11 8:23a Wilsonlee
+// [TAG] EIP71750
+// [Category] New Feature
+// [Description] Support extraUSB device driver hook by elink.
+//
+// 110 10/25/11 3:51a Ryanchou
+// [TAG] EIP70933
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] System hangs at checkpoint 0x98 when webcam plugged
+// [RootCause] The webcam return invalid data in configuration
+// descriptor.
+// [Solution] Get the configuration descriptor twice, the first time is
+// to receive the returned configure descriptor to get the total length
+// and the second time is to feed the length to the function again.
+// [Files] usb.c, usbdef.h
+//
+// 109 8/08/11 6:59a Ryanchou
+// [TAG] EIP54018
+// [Category] New Feature
+// [Description] Added USB S5 wake up support.
+// [Files] amiusb.c, ehci.c, ohci.c, uhci.c, usb.c, usb.sdl, usbdef.h,
+// usbsb.c xhci.c
+//
+// 108 8/08/11 5:17a Ryanchou
+// [TAG] EIP60561
+// [Category] New Feature
+// [Description] Add USB timing policy protocol for timing override.
+// [Files] ehci.c, guids.c, ohci.c, uhcd.c, uhci.c usb.c, usbdef.h,
+// usbhub.c, usbmass.c, UsbPolicy.h, usbport.c usbsrc.sdl
+//
+// 107 8/05/11 6:18a Ryanchou
+// [TAG] EIP60706
+// [Category] Improvement
+// [Description] Move gUsbBadDeviceTable into SMRAM.
+// [Files] usbport.c, amiusb.c, usb.c, uhcd.c, AmiUsbController.h
+//
+// 106 7/22/11 5:37a Ryanchou
+// [TAG] EIP65385
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB mouse can not be detected.
+// [RootCause] The device is connected in disconnect progress, port
+// reset is not issued.
+// [Solution] Remove the code that check device connection in disconnect
+// progress.
+// [Files] usb.c
+//
+// 105 7/19/11 5:17a Ryanchou
+// [TAG] EIP64498
+// [Category] New Feature
+// [Description] Implement EHCI key repeat function.
+// [Files] ehci.c, ehci.h, usb.c, usbdef.h
+//
+// 104 7/15/11 6:11a Ryanchou
+// [TAG] EIP38434
+// [Category] New Feature
+// [Description] Added USB HID report protocol support.
+// [Files] amiusb.c, AmiUsbController.h, amiusbhc.c, efiusbkb.c,
+// efiusbkb.h, ehci.c, ohci.c, uhcd.c uhcd.cif, uhci.c, usb.c, usbdef.h,
+// usbkbd.c, usbkbd.h, usbms.c, usbrt.cif, usbsb.c, usbsetup.c,
+// usbsrc.sdl, xhci.c
+//
+// 103 7/13/11 2:47a Ryanchou
+// [TAG] EIP60460
+// [Category] Improvement
+// [Description] Adds a flag when device disconnected during data
+// transfer, BIOS will not issue a transfer to the devicce if this flag is
+// set. This change is for Fresco USB 3.0 controller.
+// [Files] usb.c, usbdef.h, xhci.c, xhci.h
+//
+// 102 7/12/11 8:09a Ryanchou
+// [TAG] EIP56918
+// [Category] New Feature
+// [Description] Added CCID device support.
+// [Files] amiusb.c, amiusb.h, amiusbrtCCID.h, ehci.c, ohci.c, uhci.c,
+// usb.c, UsbCCID.c, usbdef.h, usbrt.cif, usbsetup.c, efiusbccid.c,
+// framework.cif, uhcd.c, uhcd.cif, uhcd.h, usbsrc.sdl, AmiusbCCID.h,
+// AmiUsbController.h, AmiUSBProtocols.cif
+//
+// 101 6/22/11 9:36a 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
+//
+// 100 6/22/11 1:44a Ryanchou
+// [TAG] EIP59738
+// [Category] Improvement
+// [Description] Support Block size other than 512 bytes USB HDD in UEFI
+// mode.
+// [Files] efiusbmass.c, uhci.c, usb.c, usbdef.h, usbmass.c
+//
+// 99 6/21/11 9:33a Ryanchou
+// [TAG] EIP59601
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] USB devices can't be detected if webcam is connected.
+// [RootCause] The configuration descriptor length is greater than
+// buffer length, the causes the last descriptor is invalid.
+// [Solution] If the next descriptor cross the buffer boundary, skip the
+// descriptor.
+// [Files] usb.c
+//
+// 98 4/06/11 5:27a Tonylo
+// [TAG] EIP52339
+// [Category] New Feature
+// [Description] USB changes of USB host safe disabling solution.
+//
+// 97 4/06/11 1:33a Ryanchou
+// [TAG] EIP54782
+// [Category] Improvement
+// [Description] Change polling data size of HID devices to max packet
+// size of interrupt endpoint.
+// [Files] ehci.c, ohci.c, uhci.c, usb.c, usbdef.h, xhci.c
+//
+// 96 4/06/11 12:49a Ryanchou
+// [TAG] EIP51653
+// [Category] New Feature
+// [Description] Added an interface that skips specific port
+// enumeration.
+// [Files] AmiUsbController.h, uhcd.c, uhcd.h, usb.c, usbdef.h,
+// usbport.c
+//
+// 95 3/30/11 8:13a 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
+//
+// 94 3/29/11 10:52p Ryanchou
+// [TAG] EIP55401
+// [Category] Improvement
+// [Description] Improve the USB 3.0 device compatibility.
+// [Files] ehci.c, ehci.h, ohci.c, uhci.c, usb.c, usbdef.h, usbhub.c,
+// xhci.c
+//
+// 93 3/29/11 10:08a Ryanchou
+// [TAG] EIP53518
+// [Category] Improvement
+// [Description] Added chipset xHCI chip support.
+// [Files] amiusb.c, amiusb.h, ehci.c, ohci.c, uhcd.c, uhci.c, usb.c,
+// usb.sdl, usbdef.h, usbport, usbsb.c, xhci.c
+//
+// 92 1/17/11 3:51a Ryanchou
+// [TAG] EIP50361
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] Hot plug USB 3.0 flash drive in setup will cause system
+// hang.
+// [RootCause] The memory may be destroyed if the Address Device command
+// fails.
+// [Solution] Check the memory has been allocated when free the memory.
+// [Files] usb.c xhci.c xhci.h
+//
+// 91 11/11/10 11:36p Ryanchou
+// [TAG] EIP45578
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] USB 3.0 device can't be detected.
+// [RootCause] Address Device Command fails.
+// [Solution] Reset the device and attempt the Address Device Command
+// again.
+// [Files] ehci.c, ohci.c, uhci.c, usb.c, usbdef.h, usbhub.c, xhci.c
+//
+// 90 10/28/10 12:34a Ryanchou
+// EIP46865: Comment out unnecessary ASSERT macro.
+//
+// 89 10/28/10 12:24a Ryanchou
+// EIP45643: Fixed system hangs when hot plug USB mass storage quickly on
+// USB 3.0 port.
+//
+// 88 10/21/10 10:12a Ryanchou
+// EIP45121: Added xHCI Supported Protocol Capability and fix the problem
+// that USB 3.0 device can't be detected.
+//
+// 87 10/20/10 10:24a Ryanchou
+// EIP44702: Added USB 3.0 hub support.
+//
+// 86 10/20/10 12:55a Ryanchou
+// EIP45828: If the flag DEV_INFO_MASS_DEV_REGD is set, check if the
+// controller type is difference between old DevInfo and new one.
+//
+// 85 9/16/10 9:22a Ryanchou
+// EIP44149: Disable slot if the Address Device command was unsuccessful.
+//
+// 84 9/07/10 4:12a Tonylo
+// Remove user tags for coding standard.
+//
+// 83 8/18/10 4:23p Olegi
+// Klockwork related fixes; EIP37978
+//
+// 82 8/13/10 4:10p Olegi
+// Bugfix in CheckDeviceLimit function. EIP41442
+//
+// 81 7/15/10 4:39a Tonylo
+// EIP15489 - Add USB HandOff function for shurdown/init USB legacy
+// through USB API function.
+//
+// 80 7/13/10 5:09a Ryanchou
+// EIP39838: Fixed configure USB hub fail.
+//
+// 79 7/02/10 1:59a Ryanchou
+// Update DevMiscInfo field when hot plug USB mass storage.
+//
+// 78 6/22/10 9:29a Ryanchou
+// EIP39374: Fixed USB mass storage hot plug issue.
+//
+// 77 6/11/10 1:43a Ryanchou
+// EIP36720: Fixed USB keyboard hot plug in setup issue.
+//
+// 76 5/11/10 11:02a Olegi
+// Bugfix in USB_InitDeviceDataDummy; EIP37974
+//
+// 75 3/19/10 10:05a Olegi
+//
+// 74 3/11/10 9:42a Olegi
+//
+// 73 3/10/10 6:36p Olegi
+//
+// 72 3/10/10 6:35p Olegi
+//
+// 71 3/06/10 1:11p Olegi
+//
+// 70 2/27/10 11:58a Olegi
+// Change in the arguments of pfnHCDInitDeviceData function.
+//
+// 69 2/26/10 4:23p Olegi
+//
+// 68 2/23/10 1:20p Olegi
+// Work around Klockwork issues. EIP34370
+//
+// 67 2/08/10 9:38a Olegi
+// EIP34448: Bugfix in prepareForLegacyOS.
+//
+// 66 1/13/10 3:20p Olegi
+// Correction in CheckDeviceLimit routine, EIP32804.
+//
+// 65 12/31/09 9:53a Olegi
+//
+// 64 12/10/09 10:12a Olegi
+// Added UsbControlTimeout setup selection. EIP30079.
+//
+// 63 11/12/09 6:09p Olegi
+//
+// 62 11/09/09 5:40p Olegi
+//
+// 61 10/30/09 5:47p Olegi
+//
+// 60 10/13/09 8:55a Olegi
+// EIP28323: Change in USBGetProperDeviceInfoStructure:
+// - Undo the checking for DEV_INFO_DEV_BUS so that in device structure
+// re-used.
+//
+// 59 10/09/09 5:57p Olegi
+//
+// 58 10/08/09 10:18a Olegi
+// EIP28031: USB_SmiQueuePut must not be called after OS booted as it
+// modifies the BS memory.
+//
+// 57 10/07/09 9:48a Olegi
+// USB Hub error handling improvement. EIP#25601.
+//
+// 56 10/02/09 10:49a Olegi
+// Code cleanup.
+//
+// 55 9/15/09 12:21p Olegi
+// Added KEY_REPEAT_LOGIC functionality. EIP#25841
+//
+// 54 8/26/09 11:41a Olegi
+// Changes that prevent collision of keyboard activity and mass storage
+// access. EIP#22808
+//
+// 53 8/18/09 2:36p Rameshr
+// Symptom: When the system is inside the Option rom, connect uSb keyboard
+// and it doesn't work.
+// Rootcause: In post only EFI driver configure the USB keyboard. So Once
+// comes out from option rom Usbkeyboard works.
+// Solution: When you are inside the option rom configure the newly
+// connected USB keyboard and notify EFI driver.
+//
+// 52 8/06/09 4:15p Olegi
+// Changes related to EIP#23335: connect status change is not maintained
+// properly when device is disconnected while connection is in progress.
+//
+// 51 6/11/09 5:29p Olegi
+// Increased the default timeout value to 20 sec. Thermlake external HDD
+// is not responding to the first READ_10 command for 14 seconds.
+//
+// 50 6/04/09 3:42p Olegi
+// USB_ConfigureDevice: for the existing devices copy the information
+// about the parent controller/hub/port# into the new device structure.
+//
+// 49 6/01/09 2:48p Olegi
+// EIP#22046: while detecting the new device we get the configuration
+// descriptor, assuming it is followed by the interface descriptor; if it
+// is not an interface descriptor, we used to think it is not the first
+// one, so we never send set address and configuration request.
+//
+// 47 5/08/09 8:56a Olegi
+// Increased the timeout value from 5 sec to 10 sec. Several types of
+// external USB HDDs require this change to be properly enumerated.
+//
+// 46 1/29/09 2:32p Olegi
+// Added the check for device limit before device is configured.
+//
+// 44 9/05/08 4:21p Olegi
+// fpCallbackNotify4 is replaced with the local function.
+//
+// 42 5/16/08 12:01p Olegi
+// Compliance with AMI coding standard.
+//
+// 39 10/30/07 12:07p Olegi
+// Set configuration one more time: it was found that for some devices
+// SET_CONFIGURATION must be the executed right before issuing device
+// specific commands. Example is USB Netac Key (VID 0x0644 DID 0x0000).
+//
+// 38 10/15/07 5:20p Olegi
+// Modified USB_on_identifyDev() routine.
+//
+// 37 9/26/07 9:15a Olegi
+// Added USB_FORCE_64BIT_ALIGNMENT flag.
+//
+// 36 9/06/07 5:59p Olegi
+// Added support for 64-byte pool allocation byte alignment.
+//
+// 35 7/09/07 2:11p Olegi
+// Changed the maximum data size of the BulkTransfer from 1kB to 64kB.
+//
+// 32 5/05/07 1:54p Olegi
+// Persistent DOS drives.
+//
+// 31 4/17/07 8:43a Michaela
+// Bugfix in USB_DetectNewDevice function.
+//
+// 30 4/17/07 8:24a Olegi
+// Device detection algorythm update, in sync with Core8.
+//
+// 24 12/22/06 4:05p Olegi
+// Timeout implementation.
+//
+// 17 4/14/06 6:39p Olegi
+// Conversion to be able to use x64 compiler.
+//
+// 16 3/20/06 3:37p Olegi
+// Version 8.5 - x64 compatible.
+//
+// 14 3/06/06 6:24p Olegi
+// Lun devices support modifications: supported using the index in
+// DEV_INFO table, not through dedicated massLun table.
+//
+// 13 3/01/06 3:50p Olegi
+// USB_FLAG_RUNNING_UNDER_OS flag added.
+//
+// 11 1/11/06 11:51a Olegi
+// Multi-functional devices handling changed.
+//
+// 10 12/19/05 10:17a Olegi
+// USB_StopHostControllers modified to control the sequence of stopping
+// (EHCI first, others follow).
+//
+// 9 11/03/05 6:31p Andriyn
+// LUN Support changes
+//
+// 7 6/20/05 8:55a Olegi
+// .NET compiler with highest warning level and warning-as-error
+// modification.
+//
+// 6 6/16/05 12:19p Andriyn
+// Fix usb device lost after boot to legacy OS: don't disable port even if
+// device is not
+// supported by USBRT: there could be another device at the same address
+//
+// 5 6/15/05 1:59p Andriyn
+// Comments were changed
+//
+// 4 6/01/05 5:34p Olegi
+// Bugfix in USB_DetectNewDevice.
+//
+// 3 5/17/05 7:51p Andriyn
+// USB BUS pre-release
+//
+// 2 5/10/05 4:11p Andriyn
+// USBBUS implementation
+//
+// 1 3/15/05 9:23a Olegi
+// Initial VSS check-in.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: Usb.c
+//
+// Description: AMI USB main wrapper
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <Token.h>
+#include "amidef.h"
+#include "usbdef.h"
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+#include <AmiBufferValidationLib.h>
+#include <AmiUsbSmmGlobalDataValidationLib.h>
+#endif
+
+#include <PCI.h> //(EIP54018+)
+
+BOOLEAN gKeyRepeatStatus = FALSE;
+extern BOOLEAN gCheckUsbApiParameter;
+
+BOOLEAN OEMSkipList(UINT8,UINT8,UINT16,UINT8,UINT8); //(EIP74609+)
+
+#if USB_DEV_HUB
+UINT8 USBHub_EnablePort(HC_STRUC*, UINT8, UINT8);
+UINT8 USBHub_DisablePort(HC_STRUC*, UINT8, UINT8);
+UINT8 USBHub_ResetPort(HC_STRUC*, UINT8, UINT8);
+//VOID USBHubFillDriverEntries (DEV_DRIVER*); //(EIP71750-)
+UINT8 USBHub_GetPortStatus (HC_STRUC*, UINT8, UINT8, BOOLEAN);
+#endif
+
+VOID SpeakerBeep (UINT8, UINT16, HC_STRUC*);
+VOID FixedDelay(UINTN);
+//VOID BusFillDriverEntries(DEV_DRIVER*); //(EIP71750-)
+ //(EIP38434+)>
+//#if USB_DEV_KBD
+//VOID USBKBDFillDriverEntries (DEV_DRIVER*);
+//#endif
+//#if USB_DEV_MOUSE
+//VOID USBMSFillDriverEntries (DEV_DRIVER*);
+//#endif
+ //(EIP71750-)>
+//VOID USBHIDFillDriverEntries (DEV_DRIVER*);
+ //<(EIP38434+)
+//#if USB_DEV_MASS
+//VOID USBMassFillDriverEntries (DEV_DRIVER*);
+//#endif
+//#if USB_DEV_CCID
+//VOID USBCCIDFillDriverEntries (DEV_DRIVER*);
+//#endif
+ //<(EIP71750-)
+VOID MemFill (UINT8*, UINT32, UINT8);
+VOID MemCopy (UINT8*, UINT8*, UINT32);
+
+VOID USBAPI_CheckDevicePresence (URP_STRUC*);
+
+extern USB_BADDEV_STRUC gUsbBadDeviceTable[]; //(EIP60706)
+
+DEV_INFO* USB_GetDeviceInfoStruc(UINT8, DEV_INFO*, UINT8, HC_STRUC*); //(EIP98145)
+VOID* USB_MemAlloc(UINT16);
+UINT8 USB_MemFree (VOID*, UINT16);
+UINT8* USB_GetDescriptor (HC_STRUC*, DEV_INFO*, UINT8*, UINT16, UINT8 , UINT8);
+UINT8 USB_SetAddress(HC_STRUC*,DEV_INFO*, UINT8);
+DEV_INFO* USBIdentifyAndConfigureDevice (HC_STRUC* , DEV_INFO* , UINT8* , UINT16 ,UINT16 );
+UINT8 USB_DisconnectDevice (HC_STRUC*, UINT8, UINT8 );
+VOID USB_InitFrameList (HC_STRUC*, UINT32);
+DEV_DRIVER* UsbFindDeviceDriverEntry(DEV_DRIVER*);
+
+UINT8 USB_MemInit (VOID);
+UINT8 USBInitHostController(UINT16 *, UINT8);
+UINT8 USB_EnumerateRootHubPorts(UINT8);
+UINT8 USBLogError(UINT16);
+BOOLEAN CheckDeviceLimit(UINT8);
+VOID USB_SmiQueuePutMsg(QUEUE_T*, VOID*, int);
+
+ //(EIP54018+)>
+UINT32 ReadPCIConfig(UINT16, UINT8);
+#if USB_S5_WAKEUP_SUPPORT
+VOID DwordWritePCIConfig(UINT16, UINT8, UINT32);
+VOID WordWritePCIConfig(UINT16, UINT8, UINT16);
+VOID ByteWritePCIConfig(UINT16, UINT8, UINT8);
+VOID UsbSbEnablePme(VOID);
+#endif
+ //<(EIP54018+)
+
+extern USB_GLOBAL_DATA *gUsbData; // Defined in AMIUHCD
+
+#ifdef USB_CONTROLLERS_INITIAL_DELAY_LIST
+typedef struct {
+ UINT16 Vid;
+ UINT16 Did;
+ UINT16 DelayTime;
+} CONTROLLERS_INITIAL_DELAY_LIST;
+
+CONTROLLERS_INITIAL_DELAY_LIST gControllersInitialDelayList[] = {USB_CONTROLLERS_INITIAL_DELAY_LIST};
+#endif
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_StartHostControllers
+//
+// Description: This function initializes the USB host controllers and
+// enumerate the root hub ports for possible USB devices.
+//
+// Output: fpGlobalDataArea Far pointer to the global data area
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_StartHostControllers(UINT8* fpGlobalDataArea)
+{
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: StopControllerType
+//
+// Description: This function stops all USB host controllers of a given type
+//
+// Output: HC type
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+StopControllerType(
+ UINT8 hc_type
+)
+{
+ UINT8 i;
+ HC_STRUC* fpHCStruc;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "stopping all HC type %x:", hc_type);
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ fpHCStruc = gUsbData->HcTable[i];
+ if (fpHCStruc == NULL) {
+ continue;
+ }
+ if ((fpHCStruc->bHCType == hc_type) &&
+ (fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDStop)(fpHCStruc);
+ USB_DEBUG(DEBUG_LEVEL_3, ".");
+ }
+ }
+ USB_DEBUG(DEBUG_LEVEL_3, "\n");
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: StartControllerType
+//
+// Description: This function start all USB host controllers of a given type
+//
+// Output: HC type
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+StartControllerType(
+ UINT8 hc_type
+)
+{
+ UINT8 i;
+ HC_STRUC* fpHCStruc;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "starting all HC type %x:", hc_type);
+ for (i=0; i<gUsbData->HcTableCount; i++) {
+ fpHCStruc = gUsbData->HcTable[i];
+ if (fpHCStruc == NULL) {
+ continue;
+ }
+ if (!(fpHCStruc->dHCFlag & HC_STATE_USED)) {
+ continue;
+ }
+ if ((fpHCStruc->bHCType == hc_type) ) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDStart)(fpHCStruc);
+ USB_DEBUG(DEBUG_LEVEL_3, ".");
+ }
+ }
+ USB_DEBUG(DEBUG_LEVEL_3, "\n");
+}
+
+ //(EIP74876+)>
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: StopControllerBdf
+//
+// Description: This function stops the USB host controllers of a given Bus Dev Function
+//
+// Input: BusDevFuncNum
+//
+// Output: None
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+StopControllerBdf(
+ UINT16 BusDevFuncNum
+)
+{
+ UINT8 i;
+ HC_STRUC* HcStruc;
+
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ HcStruc = gUsbData->HcTable[i];
+ if (HcStruc == NULL) {
+ continue;
+ }
+ if ((HcStruc->wBusDevFuncNum == BusDevFuncNum) &&
+ (HcStruc->dHCFlag & HC_STATE_RUNNING)) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDStop)(HcStruc);
+ break;
+ }
+ }
+}
+ //<(EIP74876+)
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_StopHostControllers
+//
+// Description: This function stops the USB host controllers and
+// frees the data structures associated with the host controllers
+// In case of USB2.0 first stop USB1.1 controllers, then USB2.0.
+//
+// Output: None
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_StopHostControllers (VOID)
+{
+ // Suppress disconnect beeps as they might be confusing
+ gUsbData->dUSBStateFlag &= (~USB_FLAG_ENABLE_BEEP_MESSAGE);
+
+ StopControllerType(USB_HC_XHCI); //(EIP52339+)
+ StopControllerType(USB_HC_UHCI);
+ StopControllerType(USB_HC_OHCI);
+ StopControllerType(USB_HC_EHCI);
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: UsbHcStart
+//
+// Description: This function initializes the USB host controller and
+// enumerate the root hub ports for possible USB devices.
+//
+// Input: HcStruc HC struc pointer
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbHcStart(HC_STRUC* HcStruc)
+{
+ UINT8 Index = 0;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "Starting HC %X, HCNum %d, type %x\n",
+ HcStruc->wBusDevFuncNum, HcStruc->bHCNumber, HcStruc->bHCType);
+
+ // Execute start routine of the host controller driver
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDStart)(HcStruc);
+
+ // Check if the HC is running
+ if ((HcStruc->dHCFlag & HC_STATE_RUNNING) == 0) {
+ return USB_ERROR;
+ }
+
+ for (Index = 0; Index < gUsbData->HcTableCount; Index++) {
+ if (gUsbData->HcTable[Index] == NULL) {
+ continue;
+ }
+ if (HcStruc == gUsbData->HcTable[Index]) {
+ continue;
+ }
+ if (HcStruc->BaseAddress == gUsbData->HcTable[Index]->BaseAddress) {
+ break;
+ }
+ if (HcStruc->fpFrameList != NULL) {
+ if (HcStruc->fpFrameList == gUsbData->HcTable[Index]->fpFrameList) {
+ break;
+ }
+ }
+ if (HcStruc->usbbus_data != NULL) {
+ if (HcStruc->usbbus_data == gUsbData->HcTable[Index]->usbbus_data) {
+ break;
+ }
+ }
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (HcStruc->wBusDevFuncNum == gUsbData->HcTable[Index]->wBusDevFuncNum) {
+ break;
+ }
+#endif
+ }
+
+ if (Index != gUsbData->HcTableCount) {
+ HcStruc->dHCFlag &= ~HC_STATE_RUNNING;
+ return USB_ERROR;
+ }
+
+ HcStruc->dHCFlag |= HC_STATE_INITIALIZED;
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B)
+ UpdateAmiUsbSmmGlobalDataCrc32(gUsbData);
+#endif
+#endif
+
+#ifdef USB_CONTROLLERS_INITIAL_DELAY_LIST
+ for (Index = 0; Index < COUNTOF(gControllersInitialDelayList); Index++) {
+ if ((gControllersInitialDelayList[Index].Vid == HcStruc->Vid) &&
+ (gControllersInitialDelayList[Index].Did == HcStruc->Did)) {
+ if (gControllersInitialDelayList[Index].DelayTime) {
+ FixedDelay(gControllersInitialDelayList[Index].DelayTime * 1000);
+ }
+ break;
+ }
+ }
+#endif
+
+ USB_DEBUG(DEBUG_LEVEL_3, "Enumerating HC#%d, type 0x%x\n", HcStruc->bHCNumber, HcStruc->bHCType);
+ // Issue enumerate call for this HC
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDEnumeratePorts)(HcStruc);
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: UsbHcStop
+//
+// Description: This function stops the USB host controller.
+//
+// Input: HcStruc HC struc pointer
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbHcStop(HC_STRUC* HcStruc)
+{
+ if ((HcStruc->dHCFlag & HC_STATE_RUNNING) == 0) {
+ return USB_ERROR;
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_3, "Stopping HC %X, HCNum %d, type %x\n",
+ HcStruc->wBusDevFuncNum, HcStruc->bHCNumber, HcStruc->bHCType);
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDStop)(HcStruc);
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: CheckBiosOwnedHc
+//
+// Description: This function checks bios owned hc.
+// Clear USB_FLAG_DRIVER_STARTED if we don't start
+// any host controller.
+//
+// Input: None
+//
+// Output: None
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+CheckBiosOwnedHc(
+ VOID
+)
+{
+ UINT8 Index;
+ HC_STRUC *HcStruc;
+
+ for (Index = 0; Index < gUsbData->HcTableCount; Index++) {
+ HcStruc = gUsbData->HcTable[Index];
+ if (HcStruc == NULL) {
+ continue;
+ }
+ if (HcStruc->dHCFlag & HC_STATE_RUNNING) {
+ return;
+ }
+ }
+
+ gUsbData->dUSBStateFlag &= ~(USB_FLAG_DRIVER_STARTED);
+
+ return;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_EnmumerateRootHubPorts
+//
+// Description: This function enumerates the root hub ports of the all
+// selected type HCs
+//
+//
+// Output: bType - HC type
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_EnumerateRootHubPorts (UINT8 bType)
+{
+ UINT8 Index;
+ HC_STRUC* fpHCStruc;
+
+ USB_DEBUG(DEBUG_LEVEL_4, "Enumerating HC Ports.\n");
+ for (Index = 0; Index < gUsbData->HcTableCount; Index++) {
+ //
+ // Get the HCStruc pointer associated with this controller
+ //
+ fpHCStruc = gUsbData->HcTable[Index];
+ if (fpHCStruc == NULL) {
+ continue;
+ }
+
+ if((fpHCStruc->bHCType) == bType && (fpHCStruc->dHCFlag & HC_STATE_RUNNING)) {
+ USB_DEBUG(DEBUG_LEVEL_3, "Enumerating HC#%d, type 0x%x\n", fpHCStruc->bHCNumber, bType);
+ //
+ // Issue enumerate call for this HC
+ //
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(bType)].pfnHCDEnumeratePorts)(fpHCStruc);
+ }
+ }
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_InitHostControllers
+//
+// Description: This function initializes the specified type of the HC
+// from the provided list of host controller PCI addresses
+//
+// Output: pHCPCIAddrList Pointer to table of HC PCI addresses in the system
+// bHCType Type of HC to be initialized (EHCI, OHCI etc)
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBInitHostController(
+ UINT16 * pHCPCIAddrList,
+ UINT8 bHCType)
+{
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_GetHubPortStatus
+//
+// Description: This function returns the hub port status
+//
+// Input: HcStruc HC struc pointer
+// HubAddr USB device address of the hub or HC number
+// BIT7 = 1/0 Roothub/Hub
+// PortNum Port number
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_GetHubPortStatus (
+ HC_STRUC* HcStruc,
+ UINT8 HubAddr,
+ UINT8 PortNum,
+ BOOLEAN ClearChangeBits
+)
+{
+ //
+ // Check whether the request is for root hub or generic hub
+ //
+ if (HubAddr & BIT7) {
+ // Root hub
+ return (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDGetRootHubStatus)(
+ HcStruc, PortNum, ClearChangeBits);
+ } else {
+ #if USB_DEV_HUB
+ return USBHub_GetPortStatus (HcStruc, HubAddr, PortNum, ClearChangeBits);
+ #else
+ return 0;
+ #endif
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_DisableHubPort
+//
+// Description: This function disables the hub port
+//
+// Output: fpHCStruc HC struc pointer
+// bHubAddr USB device address of the hub or HC number
+// BIT7 = 1/0 Roothub/Hub
+// bPortNum Port number
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_DisableHubPort(
+ HC_STRUC* fpHCStruc,
+ UINT8 bHubAddr,
+ UINT8 bPortNum)
+{
+ //
+ // Check whether the request is for root hub or generic hub
+ //
+ if (bHubAddr & BIT7) {
+ //
+ // Issue the disable root hub call to disable the hub port
+ //
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDDisableRootHub)(
+ fpHCStruc,
+ bPortNum);
+#if USB_DEV_HUB
+ }
+ else {
+ USBHub_DisablePort (fpHCStruc, bHubAddr, bPortNum);
+#endif
+ }
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_EnableHubPort
+//
+// Description: This function enables the hub port
+//
+// Output: fpHCStruc HC struc pointer
+// bHubAddr USB device address of the hub or HC number
+// BIT7 = 1/0 Roothub/Hub
+// bPortNum Port number
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_EnableHubPort (
+ HC_STRUC* fpHCStruc,
+ UINT8 bHubAddr,
+ UINT8 bPortNum)
+{
+ //
+ // Check whether the request is for root hub or generic hub
+ //
+ if (bHubAddr & BIT7) {
+ //
+ // Root hub
+ // Issue the disable root hub call to disable the hub port
+ //
+ return (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDEnableRootHub)(fpHCStruc, bPortNum);
+ } else {
+ #if USB_DEV_HUB
+ return USBHub_EnablePort (fpHCStruc, bHubAddr, bPortNum);
+ #else
+ return USB_ERROR; // Only root hub could be successfully enabled
+ #endif
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_ResetHubPort
+//
+// Description: This function resets the hub port
+//
+// Input: HcStruc HC struc pointer
+// HubAddr USB device address of the hub or HC number
+// BIT7 = 1/0 Roothub/Hub
+// PortNum Port number
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_ResetHubPort (
+ HC_STRUC* HcStruc,
+ UINT8 HubAddr,
+ UINT8 PortNum)
+{
+ //
+ // Check whether the request is for root hub or generic hub
+ //
+ if (HubAddr & BIT7) {
+ //
+ // Root hub
+ // Issue the reset root hub call to reset the hub port
+ //
+ return (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDResetRootHub)(HcStruc, PortNum);
+ } else {
+ #if USB_DEV_HUB
+ return USBHub_ResetPort (HcStruc, HubAddr, PortNum);
+ #else
+ return USB_ERROR; // Only root hub could be successfully reset
+ #endif
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_DetectNewDevice
+//
+// Description: This function checks the port status provided and depending
+// on the status it invokes device connect/disconnect routine
+//
+// Output: fpHCStruc Pointer to HCStruc
+// bHubAddr For root port this is the host controller index
+// in gUsbData->aHCStrucTable combined with BIT7;
+// For devices connected to a hub this is parent
+// hub USB address
+// bHubPort Parent hub port number
+// bPortStatus Port status read
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USB_DetectNewDevice(
+ HC_STRUC* fpHCStruc,
+ UINT8 bHubAddr,
+ UINT8 bHubPort,
+ UINT8 bPortStatus
+)
+{
+ UINT8 bErrorFlag = 0;
+ UINT16 wDescLength;
+ UINT8 bDevConfigured;
+ UINTN ConfigLevel = 0;
+ UINT16 wTotalLength;
+ UINT8 *fpBuffer = NULL;
+ DEV_INFO *fpDevInfo,
+ *fPointer;
+ DEV_DESC *fpDevDesc;
+ CNFG_DESC *fpCnfgDesc;
+ INTRF_DESC *fpIntrfDesc;
+ UINT8 *DevMiscInfo;
+ UINT8 Status;
+ BOOLEAN SkipConnectBeep = FALSE; //(EIP64781+)
+ UINT16 OrgTimeOutValue; //(EIP75441+)
+ UINT8 DeviceAddress;
+
+ //
+ // Get the temporary device info structure pointer (index 0)
+ //
+ fpDevInfo = gUsbData->aDevInfoTable;
+
+ //
+ // Fill the necessary entries in the device info
+ //
+ fpDevInfo->Flag = DEV_INFO_VALID_STRUC;
+ fpDevInfo->bDeviceAddress = 0;
+ //fpDevInfo->wEndp0MaxPacket = 0x40; //(EIP98230-)
+ fpDevInfo->bDeviceType = 0;
+ fpDevInfo->wIncompatFlags = 0;
+ fpDevInfo->DevMiscInfo = NULL;
+
+ //
+ // Fill the hub/host controller information
+ //
+ fpDevInfo->bHubDeviceNumber = bHubAddr;
+ fpDevInfo->bHubPortNumber = bHubPort;
+
+ //
+ // Fill the device speed
+ //
+USB_DEBUG(DEBUG_LEVEL_3, "USB_DetectNewDevice: wPS = %x\n", bPortStatus);
+ fpDevInfo->bEndpointSpeed = (bPortStatus & USB_PORT_STAT_DEV_SPEED_MASK) >>
+ USB_PORT_STAT_DEV_SPEED_MASK_SHIFT;
+
+ //(EIP98145+)>
+#if SHOW_SKIP_PORT_INFORMATION
+{
+ UINT8 i;
+ DEV_INFO *tmpDevInfo;
+ tmpDevInfo = fpDevInfo;
+ USB_DEBUG(3, "==== SHOW_SKIP_PORT_INFORMATION ==== \n");
+ USB_DEBUG(DEBUG_LEVEL_3, "BDF %x \nRoutePath = ",fpHCStruc->wBusDevFuncNum);
+ for(i=0;i<5;i++)
+ {
+ if(tmpDevInfo->bHubDeviceNumber & BIT7)
+ {
+ USB_DEBUG(3, "\nRootPort %x \n",tmpDevInfo->bHubPortNumber);
+ break;
+ }
+ USB_DEBUG(3, "%x ",tmpDevInfo->bHubPortNumber);
+ tmpDevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_ADDR, 0, tmpDevInfo->bHubDeviceNumber, 0);
+ if(tmpDevInfo == NULL) break;
+ }
+ USB_DEBUG(3, "==== SHOW_SKIP_PORT_INFORMATION ==== \n");
+}
+#endif
+ //<(EIP98145+)
+ //(EIP98230+)>
+ switch (fpDevInfo->bEndpointSpeed) {
+ case USB_DEV_SPEED_SUPER_PLUS:
+ case USB_DEV_SPEED_SUPER:
+ fpDevInfo->wEndp0MaxPacket = 0x200;
+ break;
+ case USB_DEV_SPEED_HIGH:
+ fpDevInfo->wEndp0MaxPacket = 0x40;
+ break;
+ case USB_DEV_SPEED_FULL:
+ case USB_DEV_SPEED_LOW:
+ fpDevInfo->wEndp0MaxPacket = 0x08;
+ break;
+ }
+ //<(EIP98230+)
+
+ //
+ // Fill the HC struc index value
+ //
+ fpDevInfo->bHCNumber = fpHCStruc->bHCNumber;
+
+ bErrorFlag = TRUE; // Assume as error
+ bDevConfigured = FALSE; // No device configured
+
+ //
+ // Allocate memory for device requests
+ //
+ ConfigLevel = USB_ERR_DEV_INIT_MEM_ALLOC; // For proper error handling
+ fpBuffer = USB_MemAlloc (GET_MEM_BLK_COUNT(MAX_CONTROL_DATA_SIZE));
+ if (fpBuffer == NULL) {
+ SpeakerBeep(8, 0x2000, fpHCStruc);
+ return (DEV_INFO*)ConfigLevel;
+ }
+ ConfigLevel = USB_ERR_DEV_INIT_GET_DESC_8;
+
+ // Initialize HC specific data before device configuration
+ Status = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDInitDeviceData)(
+ fpHCStruc, fpDevInfo, bPortStatus, &DevMiscInfo);
+ if(Status != USB_SUCCESS) {
+ USB_MemFree(fpBuffer, (UINT8)(MAX_CONTROL_DATA_SIZE / sizeof(MEM_BLK)));
+ SpeakerBeep(8, 0x2000, fpHCStruc);
+ return (DEV_INFO*)ConfigLevel;
+ }
+ fpDevInfo->DevMiscInfo = (VOID*)DevMiscInfo;
+
+//
+// Next send a GetDescriptor command to the device to get its Device
+// Descriptor. Assume a MaxPacket size of 64 bytes (the device will use 8,
+// 16, 32, or 64). Regardless of the packet size used by te device we can
+// always get the real MaxPacket size that the device is using, because
+// this piece of information is at offset 7 in the device descriptor.
+//
+ OrgTimeOutValue = gUsbData->wTimeOutValue; //(EIP75441+)
+ gUsbData->wTimeOutValue = 1000; //(EIP75441+)
+
+ fpDevDesc = (DEV_DESC*)USB_GetDescriptor(
+ fpHCStruc,
+ fpDevInfo,
+ fpBuffer,
+ 8,
+ DESC_TYPE_DEVICE,
+ 0);
+
+ gUsbData->wTimeOutValue = OrgTimeOutValue; //(EIP75441+)
+ if(fpDevDesc == NULL) {
+ goto detection_complete;
+ }
+
+ //
+ // Get and store the endpoint 0 max packet size
+ //
+ ConfigLevel = USB_ERR_DEV_INIT_SET_ADDR;
+ //
+ // Endpoint 0 max packet size check.
+ // CyQ've USB modem(Model:MQ4UFM560) return invalid device descriptor after
+ // warm reset.
+ //
+ //(EIP81612)>
+ if (fpDevDesc->BcdUsb >= 0x0300) {
+ fpDevInfo->wEndp0MaxPacket = (UINT16)1 << fpDevDesc->MaxPacketSize0;
+ } else {
+ fpDevInfo->wEndp0MaxPacket = (fpDevDesc->MaxPacketSize0)?
+ (UINT16)fpDevDesc->MaxPacketSize0 : 0x40;
+ }
+ //<(EIP81612)
+ //(EIP73803)>
+ if((fpDevInfo->bEndpointSpeed == USB_DEV_SPEED_LOW) ||
+ (fpDevInfo->bEndpointSpeed == USB_DEV_SPEED_FULL) ||
+ (fpDevInfo->bEndpointSpeed == USB_DEV_SPEED_HIGH)){
+ FixedDelay(10 * 1000); // 10msec delay
+ }
+ //<(EIP73803)
+
+ //To assign an address to a USB device, the USB device transitions the state
+ //from the Default to the Address state.
+ for (DeviceAddress = 1; DeviceAddress < 64; DeviceAddress++) {
+ if (gUsbData->DeviceAddressMap & Shl64(1, DeviceAddress)) {
+ break;
+ }
+ }
+
+ if (DeviceAddress == 64) {
+ goto detection_complete;
+ }
+ Status = USB_SetAddress(fpHCStruc, fpDevInfo, DeviceAddress);
+ if (Status == USB_ERROR) {
+ goto detection_complete;
+ }
+ gUsbData->DeviceAddressMap &= ~(Shl64(1, DeviceAddress));
+ fpDevInfo->bDeviceAddress = DeviceAddress;
+ FixedDelay(2 * 1000);
+
+ //
+ // Now send a GetDescriptor command to the device to get its device descriptor.
+ //
+ fpDevDesc = (DEV_DESC*)USB_GetDescriptor(
+ fpHCStruc,
+ fpDevInfo,
+ fpBuffer,
+ 18,
+ DESC_TYPE_DEVICE,
+ 0);
+
+ //ASSERT(fpDevDesc != NULL);
+ if (fpDevDesc == NULL) {
+ goto detection_complete;
+ }
+ // If a descriptor returns with a value in its length field that is
+ // less than defined by USB specification, the descriptor is invalid.
+ if (fpDevDesc->DescLength < 18) {
+ goto detection_complete;
+ }
+ if (fpDevDesc->NumConfigs == 0) {
+ fpDevDesc->NumConfigs = 1;
+ }
+
+ MemCopy((UINT8*)fpDevDesc, (UINT8*)&fpDevInfo->DevDesc, sizeof(DEV_DESC));
+
+ ConfigLevel = USB_ERR_DEV_INIT_GET_DESC_200;
+ //
+ // Get the relevant information from the descriptor and store it in
+ // device information struture
+ //
+ fpDevInfo->wVendorId = fpDevDesc->VendorId;
+ fpDevInfo->wDeviceId = fpDevDesc->DeviceId;
+//
+// Look at each of the device's ConfigDescriptors and InterfaceDescriptors
+// until an InterfaceDescriptor is found with BaseClass, SubClass, and
+// Protocol fields indicating boot keyboard, mouse, hub or storage support.
+//
+ fpDevInfo->bConfigNum = 0;
+
+ if (fpDevInfo->bEndpointSpeed == USB_DEV_SPEED_FULL) {
+ FixedDelay(100);
+ }
+
+ do { // For processing multiple configurations
+ //(EIP70933+)>
+ fpCnfgDesc = (CNFG_DESC*)USB_GetDescriptor(
+ fpHCStruc,
+ fpDevInfo,
+ fpBuffer,
+ 0xFF,
+ DESC_TYPE_CONFIG,
+ fpDevInfo->bConfigNum);
+ if(fpCnfgDesc == NULL) {
+ break;
+ }
+ wTotalLength = fpCnfgDesc->wTotalLength;
+ if (wTotalLength > 0xFF) {
+ if(wTotalLength > (MAX_CONTROL_DATA_SIZE - 1)) {
+ wTotalLength = MAX_CONTROL_DATA_SIZE - 1;
+ }
+ fpCnfgDesc = (CNFG_DESC*)USB_GetDescriptor(
+ fpHCStruc,
+ fpDevInfo,
+ fpBuffer,
+ wTotalLength,
+ DESC_TYPE_CONFIG,
+ fpDevInfo->bConfigNum);
+ //<(EIP70933+)
+ if(fpCnfgDesc == NULL) {
+ break;
+ }
+ }
+ if (fpDevInfo->bEndpointSpeed == USB_DEV_SPEED_FULL) {
+ FixedDelay(100);
+ }
+//
+// fpCnfgDesc should now point to a ConfigDescriptor. Verify this and
+// then get some fields out of it. Then point to the next descriptor.
+//
+ if(fpCnfgDesc->bDescType == DESC_TYPE_CONFIG) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDEnableEndpoints)(
+ fpHCStruc, fpDevInfo, (UINT8*)fpCnfgDesc);
+
+ //wTotalLength = fpCnfgDesc->wTotalLength; //(EIP70933-)
+ wDescLength = (UINT8)fpCnfgDesc->bDescLength;
+ fpDevInfo->bConfigNum = fpCnfgDesc->bConfigValue;
+
+ //(EIP70933-)>
+/*
+ if(wTotalLength > (MAX_CONTROL_DATA_SIZE - 1)) {
+ wTotalLength = MAX_CONTROL_DATA_SIZE - 1;
+ }
+*/
+ //<(EIP70933-)
+
+ // Check if the device has alternate setting for the interface.
+ for (;wDescLength < wTotalLength;) {
+ //
+ // fpIntrfDesc should now point to an InterfaceDescriptor. Verify this
+ // and then check its BaseClass, SubClass, and Protocol fields for
+ // usable devices.
+ //
+ fpIntrfDesc = (INTRF_DESC*)((UINT8*)fpCnfgDesc + wDescLength);
+ //(EIP59601+)>
+ if ((fpIntrfDesc->bDescLength == 0) ||
+ ((fpIntrfDesc->bDescLength + wDescLength) > wTotalLength)) {
+ break;
+ }
+ if ((fpIntrfDesc->bDescType == DESC_TYPE_INTERFACE) && (fpIntrfDesc->bAltSettingNum != 0)) {
+ fpDevInfo->Flag |= DEV_INFO_ALT_SETTING_IF;
+ break;
+ }
+ if (fpIntrfDesc->bDescLength) {
+ wDescLength += (UINT16)fpIntrfDesc->bDescLength;
+ } else {
+ break;
+ }
+ }
+
+ wDescLength = (UINT8)fpCnfgDesc->bDescLength;
+
+ for (;wDescLength < wTotalLength;) {
+ //
+ // fpIntrfDesc should now point to an InterfaceDescriptor. Verify this
+ // and then check its BaseClass, SubClass, and Protocol fields for
+ // usable devices.
+ //
+ fpIntrfDesc = (INTRF_DESC*)((UINT8*)fpCnfgDesc + wDescLength);
+ //(EIP59601+)>
+ if ((fpIntrfDesc->bDescLength == 0) ||
+ ((fpIntrfDesc->bDescLength + wDescLength) > wTotalLength)) {
+ break;
+ }
+ //<(EIP59601+)
+ if ((fpIntrfDesc->bDescType == DESC_TYPE_INTERFACE) && (fpIntrfDesc->bAltSettingNum == 0)) {
+ fpDevInfo->bInterfaceNum = fpIntrfDesc->bInterfaceNum;
+ fpDevInfo->bAltSettingNum = 0;
+ //USB_DEBUG(DEBUG_LEVEL_6, "USBIdentifyAndConfigureDevice::fpIntrfDesc %lx\n",fpIntrfDesc);
+ USB_DEBUG(DEBUG_LEVEL_3, "USBIdentifyAndConfigureDevice:: %04x/%04x Intrf %d, AltSetting %d\n",
+ fpDevInfo->wVendorId, fpDevInfo->wDeviceId, fpIntrfDesc->bInterfaceNum, fpIntrfDesc->bAltSettingNum);
+ USB_DEBUG(3, "fpCnfgDesc %x, wDescLength 0x%x, wTotalLength 0x%x\n", fpCnfgDesc, wDescLength, wTotalLength);
+ fPointer = USBIdentifyAndConfigureDevice(
+ fpHCStruc,
+ fpDevInfo,
+ (UINT8*)fpCnfgDesc,
+ wDescLength,
+ wTotalLength);
+ if(fPointer != NULL) {
+ fpDevInfo = fPointer;
+ bDevConfigured = TRUE; // At-least one device is configured
+ //(EIP64781+)>
+ if(gUsbData->dUSBStateFlag & USB_FLAG_SKIP_CARD_READER_CONNECT_BEEP) {
+ if(fpDevInfo->bBaseClass == BASE_CLASS_MASS_STORAGE) {
+ SkipConnectBeep = TRUE;
+ }
+ }
+ //<(EIP64781+)
+ }
+ //(EIP22046+)>
+ //
+ // There is one more config. Set device info structure entry 0 for it
+ //
+ if ((fpCnfgDesc->bNumInterfaces > 1) && bDevConfigured) {
+ gUsbData->aDevInfoTable[0].Flag |= DEV_INFO_MULTI_IF;
+ }
+ //<(EIP22046+)
+ }
+ if (fpIntrfDesc->bDescLength &&
+ !(fpIntrfDesc->bDescType == DESC_TYPE_INTERFACE &&
+ fpIntrfDesc->bBaseClass == BASE_CLASS_HUB)) {
+ wDescLength += (UINT16)fpIntrfDesc->bDescLength;
+ if (wDescLength < wTotalLength) {
+ //(EIP22046-)>
+ //
+ // There is one more config. Set device info structure entry 0 for it
+ //
+ /*
+ if (fpDevInfo->bInterfaceNum > 0) {
+ fpDevInfo->Flag |= DEV_INFO_MULTI_IF;
+ }
+ gUsbData->aDevInfoTable[0].Flag |= DEV_INFO_MULTI_IF;
+ */
+ //<(EIP22046-)
+ fpDevInfo = gUsbData->aDevInfoTable;
+ }
+ } else {
+ break; // fpIntrfDesc->bDescLength == 0
+ }
+ } // while ()
+ } // if
+ //
+ // Check if we have at least one usable device
+ //
+ if (bDevConfigured) {
+ bErrorFlag = FALSE; // Device successfully configured
+ ConfigLevel = (UINTN)gUsbData->aDevInfoTable;
+ goto detection_complete;
+ }
+ else {
+ fpDevInfo->bConfigNum++;
+ }
+ } while (fpDevInfo->bConfigNum < fpDevInfo->DevDesc.NumConfigs); // while
+
+detection_complete:
+ //
+ // At this point, if bErrorFlag is FALSE then we successfully configured
+ // atleast a device.
+ // If bErrorFlag is TRUE then there is error in configuring the device
+ //
+ if (bErrorFlag) {
+ USBLogError((UINT16)ConfigLevel); // Log configuration level
+
+ SpeakerBeep(8, 0x2000, fpHCStruc);
+
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDDeinitDeviceData)
+ (fpHCStruc, fpDevInfo);
+ if(ConfigLevel != USB_ERR_DEV_INIT_GET_DESC_8) {
+ //
+ // Disable the hub port
+ //
+ USB_DisableHubPort(
+ fpHCStruc,
+ fpDevInfo->bHubDeviceNumber,
+ fpDevInfo->bHubPortNumber);
+ ConfigLevel = 0;
+ }
+ if (fpDevInfo->bDeviceAddress) {
+ gUsbData->DeviceAddressMap |= Shl64(1, fpDevInfo->bDeviceAddress);
+ }
+ }
+ else {
+ //(EIP64781+)>
+ if(!SkipConnectBeep) {
+ SpeakerBeep(4, 0x1000, fpHCStruc);
+ }
+ //<(EIP64781+)
+ }
+ USB_MemFree(fpBuffer, (UINT8)(MAX_CONTROL_DATA_SIZE / sizeof(MEM_BLK)));
+
+ return (DEV_INFO*)ConfigLevel;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_StopDevice
+//
+// Description: This function stops the device:
+// - calls its disconnect function if available
+// - stops polling the device's interrupt endpoint
+// - updates device address memory map
+//
+//
+// Output: fpHCStruc Pointer to HCStruc
+// bHCNubAddr Hub address
+// bHCPort Port number
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_StopDevice(
+ HC_STRUC* fpHCStruc,
+ UINT8 bHubAddr,
+ UINT8 bHCPort)
+{
+ UINT8 bCount;
+ DEV_DRIVER* fpDevDriver;
+ DEV_INFO* fpDevice;
+ UINT8 Status;
+
+ Status = USB_ERROR;
+ //
+ // Find the device entry that would match the input.
+ //
+ for (bCount = 1; bCount < MAX_DEVICES; bCount++)
+ {
+ fpDevice = &gUsbData->aDevInfoTable[bCount];
+ if((fpDevice->Flag & (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_DUMMY)) ==
+ DEV_INFO_VALID_STRUC) {
+ if((fpDevice->bHubDeviceNumber == bHubAddr) &&
+ (fpDevice->bHubPortNumber == bHCPort))
+ {
+ //
+ // Device found - issue disconnect call for the device
+ //
+ if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) {
+ if (!(fpDevice->Flag & DEV_INFO_IN_QUEUE)) {
+ USB_SmiQueuePut(fpDevice);
+ fpDevice->Flag |= DEV_INFO_IN_QUEUE;
+ }
+ }
+
+ fpDevDriver = UsbFindDeviceDriverEntry(fpDevice->fpDeviceDriver);
+ //
+ // Check disconnect function is valid, if yes - execute it
+ //
+ if (fpDevDriver && fpDevDriver->pfnDisconnectDevice)
+ {
+ fpDevDriver->pfnDisconnectDevice(fpDevice);
+ fpDevice->fpDeviceDriver = NULL;
+ } else {
+ //
+ // Stop polling the device's interrupt endpoint
+ //
+ if (fpDevice->IntInEndpoint) {
+ Status = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDDeactivatePolling)
+ (fpHCStruc, fpDevice);
+ fpDevice->IntInEndpoint = 0;
+ }
+ }
+
+ // HC device removal call
+ Status = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDDeinitDeviceData)
+ (fpHCStruc, fpDevice);
+
+ // Reset the disconnecting flag
+ fpDevice->Flag &= ~DEV_INFO_DEV_DISCONNECTING;
+
+ //
+ // Update Device Address Map, preserving the address for registered devices
+ //
+ gUsbData->DeviceAddressMap |= Shl64(1, fpDevice->bDeviceAddress);
+ fpDevice->Flag &= ~DEV_INFO_DEV_PRESENT;
+ if (!(fpDevice->Flag & (DEV_INFO_DEV_BUS | DEV_INFO_MASS_DEV_REGD))) {
+ // Reset the device info structure validity ~flag
+ fpDevice->Flag &= ~DEV_INFO_VALID_STRUC;
+ }
+ USB_DEBUG(3, "Release Dev[%d]: %x, flag %x\n", bCount, fpDevice, fpDevice->Flag);
+ }
+ }
+ }
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_DisconnectDevice
+//
+// Description: This function is called when a device disconnect is
+// detected. This routine disables the hub port and stops the
+// device and its children by calling another routine.
+//
+// Output: fpHCStruc Far pointer to HCStruc of the host controller
+// bHubAddr USB device address of the hub whose status
+// has changed
+// bit 7 : 1 - Root hub, 0 for other hubs
+// bit 6-0 : Device address of the hub
+// bPortNum Port number
+//
+// Output: Status: USB_SUCCESS = Success
+// USB_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_DisconnectDevice(
+ HC_STRUC* fpHCStruc,
+ UINT8 bHubAddr,
+ UINT8 bHCPort)
+{
+ //
+ // A device has been disconnected from the USB. First disable the hub port
+ // that the device was plugged into. Then free up the device's entry in the
+ // DeviceTable. If there an error occurs while disabling the port, assume
+ // that the device is still present an leave its DeviceTable entry in place.
+ //
+ USB_DisableHubPort(fpHCStruc, bHubAddr, bHCPort);
+
+ USB_StopDevice(fpHCStruc, bHubAddr, bHCPort);
+
+ return USB_SUCCESS;
+
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: USBCheckPortChange
+//
+// Description: This routine processes the port status change (like connect,
+// disconnect, etc.) for the root hub and external hubs.
+//
+// Output: HcStruc Pointer to Host Controller structure
+// HubAddr Device address of the hub whose status
+// has changed:
+// bit 7 : 1 - Root hub, 0 for other hubs
+// bit 6-0 : Device address of the hub
+// PortNum Hub port number
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBCheckPortChange (
+ HC_STRUC *HcStruc,
+ UINT8 HubAddr,
+ UINT8 PortNum
+)
+{
+ UINT8 PortStatus;
+ DEV_INFO *Dev;
+ UINT8 Count;
+
+ for (Count = 0; Count < 5; Count++) {
+ PortStatus = USB_GetHubPortStatus(HcStruc, HubAddr, PortNum, TRUE);
+
+ //
+ // Check the obtained port status
+ //
+ if (PortStatus == USB_ERROR) {
+ return USB_ERROR;
+ }
+ if (!(PortStatus & USB_PORT_STAT_DEV_OWNER)) {
+ return USB_SUCCESS;
+ }
+ if (OEMSkipList(HubAddr,PortNum,HcStruc->wBusDevFuncNum,0,0)) {
+ USB_DEBUG(3, "Match the skip table ; skipping this device.\n"); //(EIP98145)
+ return USB_SUCCESS;
+ }
+ if (!Count && !(PortStatus & USB_PORT_STAT_DEV_CONNECT_CHANGED)) {
+ return USB_SUCCESS;
+ }
+
+ if (PortStatus & USB_PORT_STAT_DEV_CONNECTED) {
+ if (gUsbData->bHandOverInProgress) {
+ USB_DisableHubPort(HcStruc, HubAddr, PortNum);
+ return USB_SUCCESS;
+ }
+ if ((Count != 0) || !(PortStatus & USB_PORT_STAT_DEV_ENABLED)) {
+ // Reset and enable the port
+ USB_ResetHubPort(HcStruc, HubAddr, PortNum);
+ USB_EnableHubPort(HcStruc, HubAddr, PortNum);
+ PortStatus = USB_GetHubPortStatus(HcStruc, HubAddr, PortNum, TRUE);
+
+ if (PortStatus == USB_ERROR) {
+ return USB_ERROR;
+ }
+ if (!(PortStatus & USB_PORT_STAT_DEV_OWNER)) {
+ return USB_SUCCESS;
+ }
+ if (!(PortStatus & USB_PORT_STAT_DEV_CONNECTED)) {
+ // Some device will be disconnected after
+ // port reset, and reconnected for a while.
+ FixedDelay(100 * 1000);
+ continue;
+ }
+ // Check whether port is enabled
+ if (!(PortStatus & USB_PORT_STAT_DEV_ENABLED)) {
+ FixedDelay(100 * 1000); // 100msec delay
+ continue;
+ }
+ }
+ Dev = USB_DetectNewDevice(HcStruc, HubAddr, PortNum, PortStatus);
+ if ((UINTN)Dev == USB_ERR_DEV_INIT_GET_DESC_8) {
+ FixedDelay(100 * 1000); // 100msec delay
+ continue;
+ }
+ if ((UINTN)Dev == 0) {
+ return USB_ERROR;
+ }
+ if ((UINTN)Dev > USB_ERR_DEV_INIT_GET_DESC_200) {
+ return USB_SUCCESS;
+ }
+ SpeakerBeep(16, 0x4000, HcStruc); // Issue error beep
+ return USB_ERROR;
+ } else { // Disconnect
+ USB_DisconnectDevice(HcStruc, HubAddr, PortNum);
+ SpeakerBeep(8, 0x1000, HcStruc);
+ return USB_SUCCESS;
+ }
+ }
+ if (Count == 5) {
+ USB_DisableHubPort(HcStruc, HubAddr, PortNum);
+ return USB_ERROR;
+ }
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_MemAlloc
+//
+// Description: This routine allocates blocks of memory from the global
+// memory pool
+//
+// Output: bNumBlocks Number of 32 byte blocks needed
+//
+// Output: Start offset to the allocated block (NULL on error)
+//
+// NOTES: This routine allocates continuous 32 byte memory blocks.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID _FAR_ *
+USB_MemAlloc(UINT16 wNumBlk)
+{
+ UINT8 bMemIsFound = FALSE,
+ bBitCount = 0,
+ bStart = 0;
+ UINT16 wCount;
+ UINT16 Count = 0; // Contiguous blocks counter
+
+ UINT16 BlkOffset = 0,
+ wMapDwordPtr;
+ //(EIP89641)>
+ UINT16 PageCount = 0;
+ UINT16 MapDwordCount = 0;
+ UINT32 BlksStsDwordsPerPage = 0;
+
+ UINT32 dMask,
+ dTemp;
+
+ if (wNumBlk == 0) return NULL;
+
+#if USB_FORCE_64BIT_ALIGNMENT
+ if (wNumBlk % 2) wNumBlk++;
+#endif
+ wCount = wNumBlk;
+
+ BlksStsDwordsPerPage = (gUsbData->MemBlkStsBytes >> 2) / gUsbData->MemPages;
+
+ //
+ // Locate wNumBlk contiguous blocks from each memory page
+ //
+ for(PageCount = 0; (PageCount < gUsbData->MemPages) && !bMemIsFound; PageCount++) {
+
+ // Do not reset the counter if the allocated blocks greater than a page.
+ if (wNumBlk <= (0x1000 / sizeof(MEM_BLK))) {
+ Count = 0; // Reset contiguous blocks counter
+ }
+
+ for (MapDwordCount = 0; MapDwordCount < BlksStsDwordsPerPage; MapDwordCount++) {
+ //
+ // Read the next DWORD memory map data
+ //
+ wMapDwordPtr = (PageCount * BlksStsDwordsPerPage) + MapDwordCount;
+ dTemp = gUsbData->aMemBlkSts[wMapDwordPtr];
+
+ for (bBitCount = 0; bBitCount < 32; bBitCount++) {
+ BlkOffset++;
+ if (dTemp & (UINT32)(1 << bBitCount)) {
+ Count++; // Found another free block
+ if(Count == wCount) {
+ BlkOffset = (UINT16)(BlkOffset-Count);
+ bMemIsFound = TRUE;
+ break; // Found the requested number of free blocks
+ }
+ }
+ else
+ {
+ Count = 0; // Reset contiguous blocks counter
+ }
+ }
+ if (bMemIsFound) break;
+ }
+ }
+ //<(EIP89641)
+ if (!bMemIsFound) {
+ ASSERT(FALSE);
+ return NULL;
+ }
+
+//
+// Change the appropriate bits in the memory map to indicate that some memory
+// is being allocated
+//
+// At this point,
+// bBitCount points to the end of the block within DWORD
+// wMapDwordPtr points to the status dword in question
+
+// We have to reset bCount number of bits starting from
+// wMapDwordPtr[bBitCount] to wStsX[BitPosY]
+// where wStsX is the status double word of the starting block,
+// BitPosY is the bit position of the starting block.
+//
+ USB_DEBUG(DEBUG_LEVEL_4, "wMapDwordPtr = %d\n", wMapDwordPtr);
+//
+// Let us have a do loop to do the trick
+//
+ do {
+ //
+ // Find out how many bits we can reset in current (pointed by wMapDwordPtr)
+ // double word
+ //
+ Count = (UINT16)((bBitCount >= (wCount-1)) ? wCount : bBitCount+1);
+ //
+ // Find out the starting bit offset
+ //
+ bStart = (UINT8)(bBitCount + 1 - Count);
+ //
+ // Form the 32bit mask for the AND operation
+ // First prepare the bits left on the left
+ //
+ // Note: FFFFFFFF << 32 treated differently by different compilers; it
+ // results as 0 for 16 bit compiler and FFFFFFFF for 32 bit. That's why
+ // we use caution while preparing the AND mask for the memory map update.
+ //
+ dMask = ((Count + bStart) < 32) ? (0xFFFFFFFF << (Count + bStart)) : 0;
+
+ //
+ // Second, prepare the bits on the right
+ //
+ if (bStart)
+ {
+ dMask = dMask | ~(0xFFFFFFFF << bStart);
+ }
+
+ //
+ // Reset the specified number of bits
+ //
+ gUsbData->aMemBlkSts[wMapDwordPtr] &= dMask;
+
+ //
+ // Update the bCount, StsWordCount & BitCount
+ //
+ bBitCount = 31; // End of previous double word where we have to start
+ wMapDwordPtr--; // Previous double word
+ wCount = wCount - Count;
+ } while ( wCount );
+
+ USB_DEBUG(DEBUG_LEVEL_4, "MemAlloc: %d block(s) at %x %x %x\n",
+ wNumBlk,
+ gUsbData->fpMemBlockStart + BlkOffset * sizeof(MEM_BLK),
+ gUsbData->aMemBlkSts[0],
+ gUsbData->aMemBlkSts[1]);
+
+ return ((VOID _FAR_ *)
+ (gUsbData->fpMemBlockStart + (UINT32)BlkOffset * sizeof(MEM_BLK)));
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_MemFree
+//
+// Description: This routine frees the chunk of memory allocated using
+// the USBMem_Alloc call
+//
+// Output: fpPtr Pointer to the memory block to be freed
+// bNumBlocks Number of 32 byte blocks to be freed
+//
+// Output: Start offset to the allocated block (NULL on error)
+//
+// NOTES: This routine frees continuous memory blocks starting
+// from the fpPtr.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_MemFree (
+ VOID _FAR_ * fpPtr,
+ UINT16 wNumBlk)
+{
+ UINT8 bOffset, bCount;
+ UINT16 wBlkCount, wBlkOffset, wStsWord;
+
+#if USB_FORCE_64BIT_ALIGNMENT
+ if (wNumBlk % 2) wNumBlk++;
+#endif
+ wBlkCount = wNumBlk;
+ wBlkOffset = 0;
+
+ //
+ // Check for pointer validity
+ //
+ if (fpPtr == NULL) return USB_ERROR;
+
+ if ((fpPtr < (VOID *)gUsbData->fpMemBlockStart) ||
+ (fpPtr > (VOID *)(gUsbData->fpMemBlockStart +
+ (MEM_BLK_COUNT+1)*sizeof(MEM_BLK)))) {
+ return USB_ERROR;
+ }
+
+ wBlkOffset = (UINT16)((UINTN)fpPtr - (UINTN)gUsbData->fpMemBlockStart) / sizeof (MEM_BLK);
+
+ if (wBlkOffset >= MEM_BLK_COUNT) {
+ return USB_ERROR;
+ }
+
+ wStsWord = (UINT16)(wBlkOffset >> 5); // Divide by 32
+ bOffset = (UINT8)(wBlkOffset & 0x1F); // Mod 32
+ bCount = 0;
+
+ do {
+ gUsbData->aMemBlkSts[wStsWord] |= ((UINT32)1 << (bCount + bOffset));
+ wBlkCount--;
+ bCount++;
+
+ if ((bCount + bOffset) && (!((bCount + bOffset) & 0x1F))) {
+ wStsWord ++;
+ bCount = bOffset = 0;
+ }
+ } while (wBlkCount);
+
+ USB_DEBUG(DEBUG_LEVEL_4, "MemFree: %d block(s) at %x %x %x\n",
+ wNumBlk, fpPtr,
+ gUsbData->aMemBlkSts[0], gUsbData->aMemBlkSts[1]);
+ //
+ // Pointer is valid. Fill the memory with 0's
+ //
+ MemFill (fpPtr, (UINT32)(wNumBlk * sizeof (MEM_BLK)), 0);
+
+ return USB_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_InstallCallBackFunction
+//
+// Description: This function adds a new callback function to the globall
+// callback function list and returns the index of it.
+//
+// Output: pfnCallBackFunction Callback function address
+//
+// Output: Callback function index
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_InstallCallBackFunction (
+ CALLBACK_FUNC CallBackFunction
+)
+{
+ UINT8 Index;
+ //
+ // Check whether this function is already installed or none found
+ //
+ for (Index = 0; Index < MAX_CALLBACK_FUNCTION; Index++) {
+ //
+ // Check for null entry
+ //
+ if (gUsbData->aCallBackFunctionTable[Index] == 0) {
+ break; // No entry found
+ }
+
+ if (gUsbData->aCallBackFunctionTable[Index] == CallBackFunction) {
+ return (UINT8)(Index+1);
+ }
+ }
+
+ ASSERT(Index != MAX_CALLBACK_FUNCTION);
+ if (Index == MAX_CALLBACK_FUNCTION) {
+ EFI_DEADLOOP(); // Exceeding max # of callback function is illegal
+ } else {
+ //
+ // Store the call back function
+ //
+ gUsbData->aCallBackFunctionTable[Index] = CallBackFunction;
+ }
+
+ return (UINT8)(Index + 1);
+}
+
+DEV_DRIVER*
+UsbFindDeviceDriverEntry(
+ DEV_DRIVER* DevDriver
+)
+{
+ UINTN Index;
+
+ if (DevDriver == NULL) {
+ return DevDriver;
+ }
+
+ for (Index = 0; Index < MAX_DEVICE_TYPES; Index++) {
+ if (DevDriver == &gUsbData->aDevDriverTable[Index]) {
+ return &gUsbData->aDevDriverTable[Index];
+ }
+ if (DevDriver == &gUsbData->aDelayedDrivers[Index]) {
+ return &gUsbData->aDelayedDrivers[Index];
+ }
+ }
+
+ return NULL;
+
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_GetDescriptor
+//
+// Description: This function executes a get descriptor command to the
+// given USB device and endpoint
+//
+// Output: fpHCStruc HCStruc pointer
+// fpDevInfo Device info pointer
+// fpBuffer Buffer to be used for the transfer
+// wLength Size of the requested descriptor
+// bDescType Requested descriptor type
+// bDescIndex Descriptor index
+//
+// Output: Pointer to memory buffer containing the descriptor
+// NULL on error
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8*
+USB_GetDescriptor(
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo,
+ UINT8* fpBuffer,
+ UINT16 wLength,
+ UINT8 bDescType,
+ UINT8 bDescIndex)
+{
+ UINT8 bGetDescIteration;
+ UINT16 wReg,
+ wStatus;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return NULL;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return NULL;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpBuffer, wLength);
+ if (EFI_ERROR(EfiStatus)) {
+ return NULL;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+ //(EIP60640)>
+ for (bGetDescIteration = 0; bGetDescIteration < 5; bGetDescIteration++) {
+ wReg = (UINT16)((bDescType << 8) + bDescIndex);
+ wStatus = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDControlTransfer)(
+ fpHCStruc,
+ fpDevInfo,
+ (UINT16)USB_RQ_GET_DESCRIPTOR,
+ (UINT16)0,
+ wReg,
+ fpBuffer,
+ wLength);
+ if (wStatus) {
+ return fpBuffer;
+ }
+ if (gUsbData->dLastCommandStatusExtended & USB_TRNSFR_TIMEOUT) {
+ break;
+ }
+ FixedDelay(10 * 1000);
+ }
+ //<(EIP60640)
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_SetAddress
+//
+// Description: This function sets the USB device address of device 0 to
+// the given value. After this call the USB device will respond
+// at its new address.
+//
+// Output: fpHCStruc Pointer to HCStruc structure
+// fpDevInfo Pointer to device info structure
+// bNewDevAddr New device address to set
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+// Notes: Skip SET_ADDRESS request for XHCI controllers
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_SetAddress(
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo,
+ UINT8 bNewDevAddr)
+{
+ //(EIP60640)>
+ UINT8 SetAddressIteration;
+
+ for (SetAddressIteration = 0; SetAddressIteration < 5; SetAddressIteration++) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(fpHCStruc->bHCType)].pfnHCDControlTransfer)(
+ fpHCStruc,
+ fpDevInfo,
+ (UINT16)USB_RQ_SET_ADDRESS,
+ 0,
+ (UINT16)bNewDevAddr,
+ 0,
+ 0);
+ if (!(gUsbData->bLastCommandStatus & USB_CONTROL_STALLED )) {
+ USB_DEBUG(DEBUG_LEVEL_5, "USB_SetAddress#%d\n",bNewDevAddr);
+ return USB_SUCCESS;
+ }
+ }
+ return USB_ERROR;
+ //<(EIP60640)
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_SetConfig
+//
+// Description: This function sets the device configuration.
+//
+// Input: HcStruc Pointer to HCStruc structure
+// DevInfo Pointer to device info structure
+// ConfigNum Configuration Value
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_SetConfig(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8 ConfigNum)
+{
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDControlTransfer)(
+ HcStruc,
+ DevInfo,
+ USB_RQ_SET_CONFIGURATION,
+ 0,
+ (UINT16)ConfigNum,
+ 0,
+ 0);
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: UsbSetInterface
+//
+// Description: This function sets the device interface.
+//
+// Input: HcStruc Pointer to HCStruc structure
+// DevInfo Pointer to device info structure
+// InterfaceNum Interface Value
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbSetInterface(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8 InterfaceNum
+)
+{
+ USB_DEBUG(3, "UsbSetInterface %d\n", InterfaceNum);
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDControlTransfer)(
+ HcStruc,
+ DevInfo,
+ USB_RQ_SET_INTERFACE,
+ 0,
+ (UINT16)InterfaceNum,
+ 0,
+ 0);
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USBLogError
+//
+// Description: This routine logs the USB error in the data area. This
+// logged errors will be displayed during the POST.
+//
+// Output: wErrorCode Error code to log
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USBLogError(UINT16 wErrorCode)
+{
+ //
+ // First check for end of the buffer
+ //
+ if(gUsbData->bErrorLogIndex < MAX_USB_ERRORS_NUM)
+ {
+ //
+ // Still have space to log errors
+ //
+ gUsbData->aErrorLogBuffer[gUsbData->bErrorLogIndex] = wErrorCode;
+ gUsbData->bErrorLogIndex++;
+ }
+ return USB_ERROR;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_GetDeviceInfoStruc
+//
+// Description: This function is used to retrieve the device info structure
+// for the particular device address & HCStruc
+//
+// Output: bSearchFlag Flag indicating search type
+// = USB_SRCH_DEV_ADDR to search by device address and
+// HCStruc pointer
+// = USB_SRCH_DEV_TYPE to search by device type
+// = USB_SRCH_HC_STRUC to search by HC struc pointer
+// = USB_SRCH_DEV_NUM to count the number of devices connected:
+// if fpHCStruc is not NULL - count only devices connected to
+// certain controller, otherwise - all devices of requested
+// type.
+// = USB_SERCH_DEV_INDX to search by device location in the DEV_INFO:
+// a) if fpDevInfo <> 0 return index or the fpDevInfo
+// b) if bDevAddr <> 0 return the corresponding fpDevInfo
+// c) if both bDevAddr <> 0 and fpDevInfo <> 0, consider a)
+//
+// fpDevInfoPtr Pointer to the device info structure from where the
+// search begins (if 0 start from first entry)
+// bDev Device address/drive number/device type
+// pHCStruc Pointer to the HCStruc structure
+//
+// Output: Depending on bSearchFlag this function returns:
+// - pointer to DEV_INFO structure
+// - table index
+// - number of devices
+// Function returns NULL if device is not found.
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USB_GetDeviceInfoStruc(
+ UINT8 bSearchFlag,
+ DEV_INFO* fpDev_Info,
+ UINT8 bDev,
+ HC_STRUC* fpHcStruc
+)
+{
+ UINT8 Index;
+ BOOLEAN TerminateSearch = FALSE;
+ UINT32 dDeviceCounter = 0;
+
+ if (bSearchFlag == USB_SRCH_DEV_INDX) {
+ if (fpDev_Info) {
+ for (Index=1; Index < MAX_DEVICES; Index++) {
+ if (&gUsbData->aDevInfoTable[Index] == fpDev_Info) {
+ return (DEV_INFO*)(UINTN)Index;
+ }
+ }
+ return NULL; // Device address not found in the table
+ }
+ if (bDev == USB_HOTPLUG_FDD_ADDRESS) return &gUsbData->FddHotplugDev;
+ if (bDev == USB_HOTPLUG_HDD_ADDRESS) return &gUsbData->HddHotplugDev;
+ if (bDev == USB_HOTPLUG_CDROM_ADDRESS) return &gUsbData->CdromHotplugDev;
+
+ if (bDev) return &gUsbData->aDevInfoTable[bDev];
+ return NULL; // Invalid input - both bDev and fpDevInfo are zeroes.
+ }
+
+ for (Index = 1; Index < MAX_DEVICES; Index ++) {
+ //
+ // if fpDev_Info is not null then position the search at the correct
+ // index that matches the fpDev_Info
+ //
+ if (fpDev_Info) {
+ if (&gUsbData->aDevInfoTable[Index] != fpDev_Info)
+ continue;
+ else {
+ fpDev_Info = 0;
+ continue;
+ }
+ }
+ //
+ // For USB_SRCH_DEVBASECLASS_NUM devices are counted regardless of their
+ // DEV_INFO_VALID_STRUC flag
+ //
+ if (bSearchFlag == USB_SRCH_DEVBASECLASS_NUM)
+ {
+ if(gUsbData->aDevInfoTable[Index].bBaseClass == bDev) {
+ if (fpHcStruc) {
+ //
+ // Check if device belongs to the specified HC
+ //
+ if (gUsbData->aDevInfoTable[Index].bHCNumber != fpHcStruc->bHCNumber)
+ {
+ continue;
+ }
+ }
+ if (gUsbData->aDevInfoTable[Index].Flag & DEV_INFO_DEV_PRESENT)
+ {
+ dDeviceCounter++;
+ }
+ }
+ continue;
+ }
+
+ if ((gUsbData->aDevInfoTable[Index].Flag & DEV_INFO_VALIDPRESENT) ==
+ DEV_INFO_VALIDPRESENT){
+ switch(bSearchFlag) {
+ case USB_SRCH_HC_STRUC:
+ if (fpHcStruc == NULL) return NULL;
+ if (gUsbData->HcTable
+ [gUsbData->aDevInfoTable[Index].bHCNumber-1] == fpHcStruc) {
+ TerminateSearch = TRUE;
+ }
+ break;
+
+ case USB_SRCH_DEV_TYPE:
+ if (gUsbData->aDevInfoTable[Index].bDeviceType == bDev) {
+ TerminateSearch = TRUE;
+ }
+ break;
+ case USB_SRCH_DEV_NUM:
+ if (gUsbData->aDevInfoTable[Index].bDeviceType == bDev) {
+ if (fpHcStruc) {
+ //
+ // Check if device belongs to the specified HC
+ //
+ if (gUsbData->aDevInfoTable[Index].bHCNumber != fpHcStruc->bHCNumber)
+ {
+ break;
+ }
+ }
+ dDeviceCounter++;
+ }
+ break; // Do not change TerminateSearch so loop continues
+ case USB_SRCH_DEV_ADDR:
+ if (gUsbData->aDevInfoTable[Index].bDeviceAddress == bDev) {
+ if ((fpHcStruc == NULL) ||
+ (gUsbData->HcTable
+ [gUsbData->aDevInfoTable[Index].bHCNumber-1] == fpHcStruc)) {
+ TerminateSearch = TRUE;
+ }
+ }
+ break;
+
+ default:
+ return NULL;
+ }
+ }
+ if (TerminateSearch) return ((DEV_INFO*)&gUsbData->aDevInfoTable[Index]);
+ }
+ if ( (bSearchFlag == USB_SRCH_DEV_NUM) || (bSearchFlag == USB_SRCH_DEVBASECLASS_NUM) )
+ return (DEV_INFO*)(UINTN)dDeviceCounter;
+
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// PROCEDURE: UsbAllocDevInfo
+//
+// Description: Finds a non-used DEV_INFO record in aDevInfoTable and marks it
+// reserved. To free the user need to clear DEV_INFO_VALID_STRUC
+// bit in bFlag of DEV_INFO
+//
+// Output: Pointer to new device info. struc. 0 on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+DEV_INFO* UsbAllocDevInfo()
+{
+ UINT8 bIndex;
+ DEV_INFO *fpNewDevInfo;
+
+ for (bIndex = 1; bIndex < MAX_DEVICES; bIndex ++){
+ fpNewDevInfo = gUsbData->aDevInfoTable +bIndex;
+ if ((fpNewDevInfo->Flag &
+ ( DEV_INFO_VALID_STRUC | DEV_INFO_DEV_BUS)) == 0 ){
+ //
+ // Free device info structure. Save it if not.
+ //
+ fpNewDevInfo->Flag |= DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT;
+ return fpNewDevInfo;
+ }
+ }
+ return NULL;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBGetProperDeviceInfoStructure
+//
+// Description: This routine searches for a device info structure that
+// matches the vendor and device id, and LUN of the device
+// found. If such a device info structure not found, then it
+// will return a free device info structure
+//
+// Input: Vendor, Device ID, Current LUN
+//
+// Output: Pointer to new device info. struc. NULL on error
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USBGetProperDeviceInfoStructure(
+ DEV_INFO* Dev,
+ UINT8 Lun)
+{
+ UINT8 bCount;
+ DEV_INFO *fpDevInfo, *fpFreeDevInfo;
+
+ fpFreeDevInfo = NULL;
+
+//
+// Scan through the device info table for a free entry. Also if the device
+// connected is a mass storage device look for a device info structure whose
+// device is disconnected and its vendor & device id matches the one of
+// current device. If such a structure found that means this device may be
+// reconnected - use the same structure
+//
+ for (bCount = 1; bCount < MAX_DEVICES; bCount++)
+ {
+ fpDevInfo = (DEV_INFO*) &gUsbData->aDevInfoTable[bCount];
+
+ if (fpDevInfo->Flag & DEV_INFO_DEV_DUMMY) {
+ continue;
+ }
+
+ // Check whether the structure is valid
+ if (!(fpDevInfo->Flag & DEV_INFO_VALID_STRUC)) {
+ if (fpFreeDevInfo == NULL) {
+ fpFreeDevInfo = fpDevInfo; // Store the value of the free device info
+ }
+ } else {
+ //
+ // Yes, structure is valid. Check for device presence
+ //
+ if (fpDevInfo->Flag & DEV_INFO_DEV_PRESENT) {
+ if ((fpDevInfo->bHubDeviceNumber != Dev->bHubDeviceNumber) ||
+ (fpDevInfo->bHubPortNumber != Dev->bHubPortNumber)) {
+ continue;
+ }
+ }
+ //
+ // Device is not present. Match the vendor, device id and LUN with
+ // current device info
+ //
+ if ((fpDevInfo->wVendorId == Dev->wVendorId) &&
+ (fpDevInfo->wDeviceId == Dev->wDeviceId) &&
+ (fpDevInfo->bInterfaceNum == Dev->bInterfaceNum) &&
+ (fpDevInfo->bEndpointSpeed == Dev->bEndpointSpeed) &&
+ (fpDevInfo->bLUN == Lun)) {
+ return fpDevInfo; // "Abandoned" device entry found
+ }
+ }
+ }
+ return fpFreeDevInfo;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// PROCEDURE: USB_ConfigureDevice
+//
+// Description: This routine completes the USB device configuration for
+// the devices supported by USB BIOS. This routine
+// handles the generic configuration for the devices.
+//
+// Output: pHCStruc HCStruc pointer
+// pDevInfo Device information structure pointer
+// pDesc Pointer to the descriptor structure
+// wStart Offset within interface descriptor
+// supported by the device
+// wEnd End offset of the device descriptor
+//
+// Output: Pointer to new device info. struc. 0 on error
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USB_ConfigureDevice (
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ UINT8* Desc,
+ UINT16 Start,
+ UINT16 End
+)
+{
+ DEV_INFO *NewDevInfo;
+
+ NewDevInfo = USBGetProperDeviceInfoStructure(DevInfo, 0);
+
+ if (NewDevInfo == NULL) {
+ return NULL;
+ }
+ //
+ // Check whether this device is reconnected by checking the valid
+ // structure flag
+ //
+ if (NewDevInfo->Flag & DEV_INFO_VALID_STRUC) {
+ USB_DEBUG(DEBUG_LEVEL_3, "USB_ConfigureDevice: Existing device.\n");
+ //
+ // This device is reconnected. Reuse the old device address so that
+ // INT13h can identify this drive properly
+ //
+ DevInfo->Flag |= NewDevInfo->Flag;
+ NewDevInfo->wDataInSync = 0;
+ NewDevInfo->wDataOutSync = 0;
+ }
+ else {
+ //
+ // Check whether we reached the limit of devices of this type
+ //
+ if (CheckDeviceLimit(DevInfo->bBaseClass) == TRUE) {
+ return NULL;
+ }
+ }
+
+ //
+ // For registered devices skip updating bFlag
+ //
+ if (!(NewDevInfo->Flag & DEV_INFO_MASS_DEV_REGD)) {
+ //
+ // Since DeviceInfo[0] already has many fields filled in, the new entry
+ // should be initialized with a copy of DeviceInfo[0]. But, the new
+ // DeviceInfo should not be marked as "present" until the device
+ // is successfully initialized.
+ //
+ // Copy old DeviceInfo struc to new DeviceInfo struc and zero device[0]
+ //
+ MemCopy ((UINT8*)DevInfo, (UINT8*)NewDevInfo, sizeof (DEV_INFO));
+ NewDevInfo->Flag &= DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT |
+ DEV_INFO_MASS_DEV_REGD | DEV_INFO_DEV_BUS |
+ DEV_INFO_IN_QUEUE | DEV_INFO_ALT_SETTING_IF;
+ } else {
+ // Change the parent HC number and port number in the existing DEV_INFO
+ NewDevInfo->bHCNumber = DevInfo->bHCNumber;
+ NewDevInfo->bHubDeviceNumber = DevInfo->bHubDeviceNumber;
+ NewDevInfo->bHubPortNumber = DevInfo->bHubPortNumber;
+ NewDevInfo->bEndpointSpeed = DevInfo->bEndpointSpeed;
+ NewDevInfo->wEndp0MaxPacket = DevInfo->wEndp0MaxPacket;
+ NewDevInfo->DevMiscInfo = DevInfo->DevMiscInfo;
+ NewDevInfo->bDeviceAddress = DevInfo->bDeviceAddress;
+ }
+
+ //
+ // Do a SetConfiguration command to the device to set it to its
+ // HID/Boot configuration.
+ //
+ NewDevInfo->Flag |= DEV_INFO_VALIDPRESENT;
+ if (!(DevInfo->Flag & DEV_INFO_MULTI_IF)) {
+ USB_SetConfig(HcStruc, NewDevInfo, NewDevInfo->bConfigNum);
+ if (DevInfo->Flag & DEV_INFO_ALT_SETTING_IF) {
+ UsbSetInterface(HcStruc, NewDevInfo, NewDevInfo->bAltSettingNum);
+ }
+ }
+
+ USB_DEBUG(3, "new dev: %x, flag: %x, addr %d\n",
+ NewDevInfo, NewDevInfo->Flag, NewDevInfo->bDeviceAddress);
+
+ return NewDevInfo;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBCheckNonCompliantDevice
+//
+// Description: This function checks for non-compliant USB devices by
+// by comparing the device's vendor and device id with
+// the non-compliant device table list and updates the
+// data structures appropriately to support the device.
+//
+// Input: fpHCStruc - HCStruc pointer
+// fpDevInfo - Device information structure pointer
+// fpDesc - Pointer to the descriptor structure
+// wDescLength - End offset of the device descriptor
+//
+// Output: Updated fpDevInfo->wIncompatFlags field
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+USBCheckNonCompliantDevice(
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo,
+ UINT8* fpDesc,
+ UINT16 wLength,
+ UINT16 wDescLength
+)
+{
+ USB_BADDEV_STRUC *fpBadDevice;
+ INTRF_DESC *fpIntrfDesc;
+
+ fpIntrfDesc = (INTRF_DESC*)((UINT8*)fpDesc + wLength);
+
+ //
+ // Search the bad device table to get the structure for this device
+ //
+ for (fpBadDevice = gUsbBadDeviceTable;
+ fpBadDevice->wDID | fpBadDevice->wVID; fpBadDevice++) {
+
+ if ((fpBadDevice->wDID != fpDevInfo->wDeviceId) ||
+ (fpBadDevice->wVID != fpDevInfo->wVendorId)) {
+ continue;
+ }
+USB_DEBUG(DEBUG_LEVEL_3, "Found non-compatible device: DID=%x, VID=%x\n", fpBadDevice->wDID, fpBadDevice->wVID);
+ //
+ // Save the incompatibility flag into device info structure
+ //
+ fpDevInfo->wIncompatFlags = fpBadDevice->wFlags;
+
+ //
+ // Check which fields to update in the interface descriptor
+ //
+ // Check for base class field
+ //
+ if (fpBadDevice->bBaseClass) {
+ //
+ // Update base class field in the interface descriptor
+ //
+ fpIntrfDesc->bBaseClass = fpBadDevice->bBaseClass;
+ }
+ //
+ // Check for base sub class field
+ //
+ if (fpBadDevice->bSubClass) {
+ //
+ // Update sub class field in the interface descriptor
+ //
+ fpIntrfDesc->bSubClass = fpBadDevice->bSubClass;
+ }
+ //
+ // Check for protocol field
+ //
+ if (fpBadDevice->bProtocol) {
+ //
+ // Update protocol field in the interface descriptor
+ //
+ fpIntrfDesc->bProtocol = fpBadDevice->bProtocol;
+ }
+ break;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// PROCEDURE: USBIdentifyAndConfigureDevice
+//
+// Description: This routine invokes the device drivers 'check device type'
+// routine and identifies the device type.
+//
+// Output: pHCStruc HCStruc pointer
+// pDevInfo Device information structure pointer
+// pDesc Pointer to the descriptor structure
+// wStart Offset within interface descriptor
+// supported by the device
+// wEnd End offset of the device descriptor
+//
+// Output: Pointer to new device info. struc, NULL on error
+//
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+DEV_INFO*
+USBIdentifyAndConfigureDevice (
+ HC_STRUC* fpHCStruc,
+ DEV_INFO* fpDevInfo,
+ UINT8* fpDesc,
+ UINT16 wLength,
+ UINT16 wDescLength)
+{
+ UINT8 bBaseClass, bSubClass, bProtocol,
+ bIndex, bRetValue;
+ DEV_INFO* fpDevInfoLocal;
+ DEV_DRIVER* fpDevDriver;
+ INTRF_DESC* fpIntrfDesc;
+
+ //
+ // Check for non-compliant device. If non-compliant device found then
+ // the descriptor values will get updated depending on the need.
+ //
+ USBCheckNonCompliantDevice (
+ fpHCStruc,
+ fpDevInfo,
+ fpDesc,
+ wLength,
+ wDescLength);
+
+ USB_DEBUG(DEBUG_LEVEL_3, "USBIdentifyAndConfigureDevice...");
+
+ //
+ // Check whether device needs to be disable
+ //
+ if (fpDevInfo->wIncompatFlags & USB_INCMPT_DISABLE_DEVICE) {
+ USB_DEBUG(DEBUG_LEVEL_3, "not compatible device.\n");
+ return NULL;
+ }
+
+ fpIntrfDesc = (INTRF_DESC*)(fpDesc + wLength);
+
+//(EIP74609+)>
+ if(OEMSkipList(fpDevInfo->bHubDeviceNumber,fpDevInfo->bHubPortNumber,fpHCStruc->wBusDevFuncNum,fpIntrfDesc->bBaseClass,1)) {
+ USB_DEBUG(3, "Match the skip table ; skipping this device.\n"); //(EIP98145)
+ return NULL;
+ }
+//<(EIP74609+)
+ //
+ // Get the base, sub class & protocol values
+ //
+ bBaseClass = fpIntrfDesc->bBaseClass;
+ bSubClass = fpIntrfDesc->bSubClass;
+ bProtocol = fpIntrfDesc->bProtocol;
+
+ //
+ // Check for matching device driver
+ //
+ fpDevInfoLocal = NULL;
+ bRetValue = USB_ERROR;
+
+ //(EIP96616+)>
+ for (bIndex = 0; bIndex < MAX_DEVICE_TYPES; bIndex ++) {
+ fpDevDriver = &gUsbData->aDevDriverTable[bIndex];
+ //
+ // Check structure validity
+ //
+ if (!fpDevDriver->bDevType) {
+ continue; // Driver table not valid
+ }
+ //
+ // Verify presence of Check Device routine
+ //
+ if (fpDevDriver->pfnCheckDeviceType) {
+ //
+ // Check device type is implemented. Execute it!
+ //
+ bRetValue = (*fpDevDriver->pfnCheckDeviceType)(
+ fpDevInfo,bBaseClass,
+ bSubClass,bProtocol);
+ if (bRetValue != USB_ERROR)
+ break;
+ } else {
+ //
+ // Check device type is not implemented. Compare the class codes
+ //
+ if((fpDevDriver->bBaseClass == bBaseClass) ||
+ (fpDevDriver->bSubClass == bSubClass) ||
+ (fpDevDriver->bProtocol == bProtocol)) {
+ //
+ // If the class codes match set bRetValue with the bDevType from the Device Driver
+ //
+ bRetValue = fpDevDriver->bDevType;
+ break;
+ }
+ }
+ }
+ if(bRetValue != USB_ERROR){
+ //
+ // Check whether we reached the limit of devices of this type
+ //
+ //if (CheckDeviceLimit(bBaseClass) == TRUE) continue; //(EIP81761-)
+
+ //
+ // Set the device type in the Device Info structure
+ //
+ fpDevInfo->bDeviceType = bRetValue;
+
+ //
+ // Set Base Class, Subclass and Protocol information
+ //
+ fpDevInfo->bBaseClass = bBaseClass;
+ fpDevInfo->bProtocol = bProtocol;
+ fpDevInfo->bSubClass = bSubClass;
+
+ //
+ // Device identified. Issue common configure call
+ // Call a common routine to handle the remaining initialization that is done
+ // for all devices.
+ //
+ fpDevInfoLocal = USB_ConfigureDevice(
+ fpHCStruc,
+ fpDevInfo,
+ fpDesc,
+ wLength,
+ wDescLength);
+
+ if (fpDevInfoLocal == NULL) {
+ USB_DEBUG(DEBUG_LEVEL_3, "USB: Common configure failed.\n");
+ return fpDevInfoLocal;
+ }
+
+ if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) {
+ if (!(fpDevInfoLocal->Flag & DEV_INFO_IN_QUEUE)) {
+ USB_SmiQueuePut(fpDevInfoLocal);
+ fpDevInfoLocal->Flag |= DEV_INFO_IN_QUEUE;
+ }
+ }
+
+ fpDevInfoLocal->fpDeviceDriver = fpDevDriver;
+ fpDevInfoLocal = (*fpDevDriver->pfnConfigureDevice)(
+ fpHCStruc,
+ fpDevInfoLocal,
+ fpDesc,
+ wLength,
+ wDescLength);
+ if (!fpDevInfoLocal ||
+ !(fpDevInfoLocal->Flag & DEV_INFO_VALID_STRUC) )
+ {
+ fpDevInfoLocal = 0;
+ USB_DEBUG(DEBUG_LEVEL_3, "USB: Device specific configure failed.\n");
+ return fpDevInfoLocal;
+ }
+
+ //<(EIP96616+)
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_3, "%x\n", fpDevInfoLocal);
+
+ return fpDevInfoLocal;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: USB_InitFrameList
+//
+// Description: This routine initializes the frame list pointed by fpPtr
+// with the dValue provided
+//
+// Output: fpHCStruc Pointer to the Host Controller structure
+// dValue Value to be initialized with
+//
+// Output: Nothing
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+
+VOID
+USB_InitFrameList(
+ HC_STRUC* fpHCStruc,
+ UINT32 dValue)
+{
+ UINT16 wIndex;
+ UINT32 *fpPtr = (UINT32*)fpHCStruc->fpFrameList;
+
+ for (wIndex = 0; wIndex < fpHCStruc->wAsyncListSize; wIndex ++) {
+ fpPtr[wIndex] = dValue;
+ }
+ return;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBKeyRepeat
+//
+// Description: This function handles different key repeat related functions
+// depending on the input
+//
+// Input: fpHCStruc - pointer for the HC that implements the key repeat function
+// bAction - sub-function index:
+// 0 Install key repeat HCStruc
+// 1 Disable key repeat
+// 2 Enable key repeat
+// 3 Uninstall key repeat HCStruc
+//
+// Output: None
+//
+// Note: fpHCStruc is only relevant for sub-function 0.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBKeyRepeat(
+ HC_STRUC* HcStruc,
+ UINT8 Action
+)
+{
+
+//USB_DEBUG(DEBUG_LEVEL_3, "KR%d\n", bAction);
+ UINT8 i;
+
+ switch (Action) {
+ case 0: // Sub-function 0: Save the HCStruc value for later use
+ if (gKeyRepeatStatus == FALSE) {
+ gUsbData->fpKeyRepeatHCStruc = HcStruc;
+ }
+ break;
+ case 1: // Sub-function 0: Disable key repeat
+ if (gKeyRepeatStatus) {
+#if USB_HID_KEYREPEAT_USE_SETIDLE == 1
+ if (gUsbData->fpKeyRepeatDevInfo != NULL) {
+ //
+ // Set the HID SET_IDLE request to 0
+ //
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable[gUsbData->fpKeyRepeatDevInfo->bHCNumber - 1]->bHCType)].pfnHCDControlTransfer)
+ (gUsbData->HcTable[gUsbData->fpKeyRepeatDevInfo->bHCNumber - 1],
+ gUsbData->fpKeyRepeatDevInfo,(UINT16)HID_RQ_SET_IDLE, gUsbData->fpKeyRepeatDevInfo->bInterfaceNum, 0, 0, 0); //(EIP54782)
+ }
+#else
+ if (gUsbData->fpKeyRepeatHCStruc) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(
+ gUsbData->fpKeyRepeatHCStruc->bHCType)].pfnHCDDisableKeyRepeat)(
+ gUsbData->fpKeyRepeatHCStruc);
+ }
+#endif
+ gKeyRepeatStatus = FALSE;
+ }
+ break;
+ case 2: // Sub-function 0: Enable key repeat
+ if (!gKeyRepeatStatus) {
+#if USB_HID_KEYREPEAT_USE_SETIDLE == 1
+ if(gUsbData->fpKeyRepeatDevInfo != NULL) {
+ //
+ // Set the HID SET_IDLE request to 0x200 (8ms)
+ //
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable[gUsbData->fpKeyRepeatDevInfo->bHCNumber - 1]->bHCType)].pfnHCDControlTransfer)
+ (gUsbData->HcTable[gUsbData->fpKeyRepeatDevInfo->bHCNumber - 1],
+ gUsbData->fpKeyRepeatDevInfo,(UINT16)HID_RQ_SET_IDLE, gUsbData->fpKeyRepeatDevInfo->bInterfaceNum, 0x400, 0, 0); //(EIP54782)
+ }
+#else
+ if (gUsbData->fpKeyRepeatHCStruc) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(
+ gUsbData->fpKeyRepeatHCStruc->bHCType)].pfnHCDEnableKeyRepeat)(
+ gUsbData->fpKeyRepeatHCStruc);
+ }
+#endif
+ gKeyRepeatStatus=TRUE;
+ }
+ break;
+ case 3:
+ if (gUsbData->fpKeyRepeatHCStruc == HcStruc) {
+ gUsbData->fpKeyRepeatHCStruc = NULL;
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ if (gUsbData->HcTable[i] == NULL) {
+ continue;
+ }
+ if (gUsbData->HcTable[i] == HcStruc) {
+ continue;
+ }
+ if (gUsbData->HcTable[i]->dHCFlag & HC_STATE_RUNNING) {
+ gUsbData->fpKeyRepeatHCStruc = gUsbData->HcTable[i];
+ if (gKeyRepeatStatus) {
+ gKeyRepeatStatus = FALSE;
+ USBKeyRepeat(NULL, 2);
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: BusFillDriverEntries
+//
+// Description: Install drivers that redirects ...????
+//
+// Input: fpDevDriver - record that the routine can use to install the drive
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_bus_interrupt_handler (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Td,
+ UINT8 *Buffer,
+ UINT16 DataLength
+)
+{
+ USBHC_INTERRUPT_DEVNINFO_T *Idi = (USBHC_INTERRUPT_DEVNINFO_T *)DevInfo->pExtra;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ ASSERT(Idi);
+ if (Idi == NULL) {
+ return USB_SUCCESS;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)Idi, sizeof(USBHC_INTERRUPT_DEVNINFO_T));
+ if (EFI_ERROR(Status)) {
+ return USB_ERROR;
+ }
+#endif
+
+ USB_SmiQueuePutMsg(&Idi->QCompleted, Buffer, (int)Idi->DataLength);
+ return USB_SUCCESS;
+}
+
+VOID
+UsbBusDeviceInit(
+ VOID
+)
+{
+ USB_InstallCallBackFunction(USB_bus_interrupt_handler);
+ return;
+}
+
+DEV_INFO*
+USB_on_configDev(
+ HC_STRUC *fpHCStruc,
+ DEV_INFO *fpDevInfo,
+ UINT8 *fpDesc,
+ UINT16 wStart,
+ UINT16 wEnd
+)
+{
+ fpDevInfo->bDeviceType = (UINT8)BIOS_DEV_TYPE_USBBUS;
+ fpDevInfo->bCallBackIndex = USB_InstallCallBackFunction(USB_bus_interrupt_handler);
+ return(fpDevInfo);
+}
+
+UINT8
+USB_on_identifyDev(
+ DEV_INFO* fpDevInfo,
+ UINT8 bBaseClass,
+ UINT8 bSubClass,
+ UINT8 bProtocol
+)
+{
+ //(EIP96616+)>
+ if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI)
+ return BIOS_DEV_TYPE_USBBUS;
+ else
+ return USB_ERROR;
+ //<(EIP96616+)
+}
+
+UINT8
+USB_on_disconnectDev(
+ DEV_INFO* fpDevInfo
+)
+{
+ return USB_SUCCESS;
+}
+
+VOID
+BusFillDriverEntries(
+ DEV_DRIVER *fpDevDriver
+)
+{
+ fpDevDriver->bDevType = BIOS_DEV_TYPE_USBBUS;
+ fpDevDriver->bBaseClass = 0;
+ fpDevDriver->bSubClass = 0;
+ fpDevDriver->bProtocol = 0;
+ fpDevDriver->pfnDeviceInit = UsbBusDeviceInit;
+ fpDevDriver->pfnCheckDeviceType = USB_on_identifyDev;
+ fpDevDriver->pfnConfigureDevice = USB_on_configDev;
+ fpDevDriver->pfnDisconnectDevice = USB_on_disconnectDev;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USB_ReConfigDevice, USB_ReConfigDevice2
+//
+// Description: EFI code will call this function to give a chance for
+// SMI dev driver to complete the configuration of device
+//
+// Before call, USB device is connected, address is assigned
+// and configuration is set. DEV_INFO structure is initalized
+// from information parsed from descriptors and linked
+// to USBBUS dev driver. Device driver specific to the type
+// of USB device wasn't called on this device
+//
+// After the call returns, a specific device driver
+// initialization was performed by calling pfnCheckDeviceType
+// and pfnConfigureDevice functions of device driver. Parameters
+// to those functions are taken from descriptors downloaded from
+// the device. Device preserve old address and active configuration
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+int USB_ReConfigDevice2( HC_STRUC* fpHCStruc, DEV_INFO* fpDevInfo,
+ CNFG_DESC *fpCnfgDesc,
+ INTRF_DESC * fpIntrfDesc );
+
+int USB_ReConfigDevice( HC_STRUC* fpHCStruc, DEV_INFO* fpDevInfo )
+{
+ INTRF_DESC *fpIntrfDesc=NULL;
+
+ UINT8 iConfig;
+ int status = USB_SUCCESS; //(EIP90124)
+ UINT8* fpBuffer;
+ CNFG_DESC *fpCnfgDesc=NULL;
+ UINT16 OrgTimeOutValue;
+
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ gCheckUsbApiParameter = FALSE;
+
+ if (fpDevInfo->bDeviceType != 0 &&
+ fpDevInfo->bDeviceType != BIOS_DEV_TYPE_USBBUS) {
+ return USB_SUCCESS;
+ }
+
+ fpBuffer = USB_MemAlloc (GET_MEM_BLK_COUNT(MAX_CONTROL_DATA_SIZE));
+ if (fpBuffer == NULL) {
+ return USB_ERROR;
+ }
+ //
+ // Find configuration desc
+ //
+ for (iConfig = 0; iConfig < fpDevInfo->DevDesc.NumConfigs;++iConfig){
+
+ OrgTimeOutValue = gUsbData->wTimeOutValue;
+ gUsbData->wTimeOutValue = USB_GET_CONFIG_DESC_TIMEOUT_MS;
+
+ fpCnfgDesc = (CNFG_DESC*)USB_GetDescriptor(
+ fpHCStruc,
+ fpDevInfo,
+ fpBuffer,
+ (MAX_CONTROL_DATA_SIZE - 1),
+ DESC_TYPE_CONFIG,
+ iConfig);
+
+ gUsbData->wTimeOutValue = OrgTimeOutValue;
+
+ if (fpDevInfo->bEndpointSpeed == USB_DEV_SPEED_FULL) {
+ FixedDelay(1000);
+ }
+ if(fpCnfgDesc != NULL && fpCnfgDesc->bDescType == DESC_TYPE_CONFIG &&
+ fpDevInfo->bConfigNum == fpCnfgDesc->bConfigValue ){
+ break;
+ }
+
+ fpCnfgDesc = NULL;
+ }
+
+ if( fpCnfgDesc ){
+ UINT16 offset;
+ UINT16 wDescLength;
+ INTRF_DESC *pIntrf;
+
+ if(fpCnfgDesc->wTotalLength > MAX_CONTROL_DATA_SIZE - 1)
+ fpCnfgDesc->wTotalLength = MAX_CONTROL_DATA_SIZE - 1;
+ wDescLength = fpCnfgDesc->wTotalLength;
+ for(offset=(UINT16)fpCnfgDesc->bDescLength;offset <wDescLength ;offset = offset + (UINT16)pIntrf->bDescLength){
+ pIntrf = (INTRF_DESC*)((UINT8*)fpCnfgDesc + offset);
+ if(pIntrf->bDescLength == 0) {
+ break;
+ }
+ if (pIntrf->bDescType == DESC_TYPE_INTERFACE &&
+ fpDevInfo->bInterfaceNum == pIntrf->bInterfaceNum &&
+ fpDevInfo->bAltSettingNum == pIntrf->bAltSettingNum ) {
+ fpIntrfDesc =pIntrf;
+ break;
+ }
+ }
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_3,
+ "USB_reConfigDev:: CfgDsc=%x; IntrfDsc=%x\n",
+ fpCnfgDesc, fpIntrfDesc);
+
+ if (fpIntrfDesc && fpCnfgDesc) {
+ status = USB_ReConfigDevice2(fpHCStruc, fpDevInfo,
+ fpCnfgDesc, fpIntrfDesc);
+ } else {
+ status = USB_ERROR;
+ }
+
+ USB_MemFree(fpBuffer, (UINT8)(MAX_CONTROL_DATA_SIZE / sizeof(MEM_BLK)));
+
+ return status;
+}
+
+//----------------------------------------------------------------------------
+// USB_ReConfigDevice2
+//----------------------------------------------------------------------------
+int
+USB_ReConfigDevice2(
+ HC_STRUC *fpHCStruc,
+ DEV_INFO *fpDevInfo,
+ CNFG_DESC *fpCnfgDesc,
+ INTRF_DESC *fpIntrfDesc
+)
+{
+// int abort=0;
+ int bIndex;
+ UINT8 bRetValue = USB_ERROR;
+ DEV_DRIVER *fpDevDriver = NULL;
+ DEV_INFO *fpDevInfoLocal;
+ UINT8 bBaseClass, bSubClass, bProtocol;
+ EFI_STATUS EfiStatus;
+
+ USB_DEBUG(DEBUG_LEVEL_3, "USB_ReConfigDevice2.\n");
+
+
+ EfiStatus = UsbHcStrucValidation(fpHCStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(fpDevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+#if USB_RUNTIME_DRIVER_IN_SMM
+ if (gCheckUsbApiParameter) {
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpCnfgDesc, sizeof(CNFG_DESC));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpCnfgDesc, fpCnfgDesc->wTotalLength);
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ EfiStatus = AmiValidateMemoryBuffer((VOID*)fpIntrfDesc, sizeof(INTRF_DESC));
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+ gCheckUsbApiParameter = FALSE;
+ }
+#endif
+
+ //
+ // Check for non-compliant device. If non-compliant device found then
+ // the descriptor values will get updated depending on the need.
+ //
+ USBCheckNonCompliantDevice (
+ fpHCStruc,
+ fpDevInfo,
+ (UINT8*)fpCnfgDesc,
+ fpCnfgDesc->bDescLength,
+ fpCnfgDesc->wTotalLength);
+
+ //
+ // Check whether device needs to be disable
+ //
+ if (fpDevInfo->wIncompatFlags & USB_INCMPT_DISABLE_DEVICE)
+ {
+ return USB_ERROR;
+ }
+
+ //
+ // Get the base, sub class & protocol values
+ //
+ bBaseClass = fpIntrfDesc->bBaseClass;
+ bSubClass = fpIntrfDesc->bSubClass;
+ bProtocol = fpIntrfDesc->bProtocol;
+
+ //
+ // Check for matching device driver
+ //
+ fpDevInfoLocal = NULL;
+ for (bIndex = 0, bRetValue = USB_ERROR;
+ bIndex < MAX_DEVICE_TYPES && bRetValue == USB_ERROR; bIndex ++) {
+ fpDevDriver = &gUsbData->aDelayedDrivers[bIndex];
+ if (!fpDevDriver->bDevType)
+ continue;
+ if (fpDevDriver->pfnCheckDeviceType){
+ bRetValue = (*fpDevDriver->pfnCheckDeviceType)(
+ fpDevInfo,bBaseClass,bSubClass,bProtocol);
+ }else if((fpDevDriver->bBaseClass == bBaseClass) &&
+ (fpDevDriver->bSubClass == bSubClass) &&
+ (fpDevDriver->bProtocol == bProtocol)){
+ bRetValue = fpDevDriver->bDevType;
+ }
+ }
+ if(bRetValue == USB_ERROR)
+ return bRetValue;
+
+ //driver was found
+
+ fpDevInfo->bDeviceType = bRetValue;
+ fpDevInfo->fpDeviceDriver = fpDevDriver;
+ fpDevInfoLocal = (*fpDevDriver->pfnConfigureDevice)(
+ fpHCStruc,fpDevInfo,(UINT8*)fpCnfgDesc,
+ (UINT16)(UINTN)((char*)fpIntrfDesc - (char*)fpCnfgDesc),fpCnfgDesc->wTotalLength);
+ if (!fpDevInfoLocal)
+ {
+ USB_DEBUG(DEBUG_LEVEL_0, "USB_ReConfigDevice2: Device specific configure failed.\n");
+ return USB_ERROR;
+ }
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: hcnum2hcstruc
+//
+// Description: Search for the HC_STRUC with specified bHCNumber
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+HC_STRUC*
+hcnum2hcstruc(
+ UINT8 bHCNumber
+)
+{
+ return gUsbData->HcTable[bHCNumber - 1];
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: prepareForLegacyOS
+//
+// Description: Changes global state of USBSMI module to function properly
+// in non-EFI OS - without support from EFI drivers
+//
+// Before call USB BUS is a driver that handles all devices (
+// except hub) and rest of the drivers are delayed. Number of
+// devices are supported by SUBBUS driver and custom EFI driver
+//
+// After call returns, USBBUS driver is removed and all drivers
+// that where
+// delayed became active. All USBBUS devices are reconfigured.
+// Devices that are not supported by now active drivers are decon-
+// figured.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+prepareForLegacyOS()
+{
+ //(EIP96616)>
+ DEV_INFO* di;
+ HC_STRUC* fpHCStruc;
+ DEV_INFO* e = gUsbData->aDevInfoTable + COUNTOF(gUsbData->aDevInfoTable);
+ int status;
+
+ gCheckUsbApiParameter = FALSE;
+
+
+ //
+ //First Reconfigure all USBBUS device (while drivers are in delayed array)
+ //
+ for( di = &gUsbData->aDevInfoTable[1]; di != e; ++di ){ //(EIP34448)
+ if((di->Flag & DEV_INFO_VALIDPRESENT) == DEV_INFO_VALIDPRESENT &&
+ di->bDeviceType == BIOS_DEV_TYPE_USBBUS )
+ {
+ fpHCStruc = hcnum2hcstruc(di->bHCNumber);
+ status = USB_ReConfigDevice(fpHCStruc, di );
+ if(status == USB_ERROR){
+ //
+ // Release DEV_INFO
+ //
+ di->Flag &= ~DEV_INFO_VALIDPRESENT;
+ }
+ }
+ //di->Flag &= ~DEV_INFO_DEV_BUS;
+ }
+ //<(EIP96616)
+
+
+ USBKeyRepeat(NULL, 1); // Disable key repeat
+ //gUsbData->dUSBStateFlag |= USB_FLAG_RUNNING_UNDER_OS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USB_ResetAndReconfigDev
+//
+// Description: This routine resets and reconfigures the device.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+USB_ResetAndReconfigDev(
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo
+)
+{
+ DEV_INFO *Dev;
+ UINT32 Status;
+ UINT8 DevAddr;
+ UINT8 *Buffer;
+ DEV_DESC *DevDesc;
+ CNFG_DESC *CnfgDesc;
+ INTRF_DESC *IntrfDesc;
+ UINT8 ConfigIndx;
+ UINT8 IntrfIndx;
+ DEV_DRIVER *DevDriver;
+ UINT8 i;
+ UINT8 PortStatus;
+ UINT8 *DevMiscInfo;
+ UINT16 TotalLength;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ gCheckUsbApiParameter = FALSE;
+
+ for (i = 1; i < MAX_DEVICES; i++) {
+ Dev = &gUsbData->aDevInfoTable[i];
+ if ((Dev->Flag & (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT |
+ DEV_INFO_DEV_DUMMY)) != (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT)) {
+ continue;
+ }
+ if ((Dev->bHubDeviceNumber == DevInfo->bHubDeviceNumber) &&
+ (Dev->bHubPortNumber == DevInfo->bHubPortNumber) &&
+ (Dev->bDeviceType != BIOS_DEV_TYPE_USBBUS)) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(
+ HcStruc->bHCType)].pfnHCDDeactivatePolling)(HcStruc, Dev);
+ }
+ }
+
+ Status = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDDeinitDeviceData)
+ (HcStruc, DevInfo);
+ if (Status != USB_SUCCESS) {
+ return Status;
+ }
+
+ Status = USB_ResetHubPort(HcStruc, DevInfo->bHubDeviceNumber, DevInfo->bHubPortNumber);
+ if (Status != USB_SUCCESS) {
+ return Status;
+ }
+
+ Status = USB_EnableHubPort(HcStruc, DevInfo->bHubDeviceNumber, DevInfo->bHubPortNumber);
+ if (Status != USB_SUCCESS) {
+ return Status;
+ }
+
+ PortStatus = USB_GetHubPortStatus(HcStruc, DevInfo->bHubDeviceNumber, DevInfo->bHubPortNumber, TRUE);
+
+ if (PortStatus == USB_ERROR) {
+ return USB_ERROR;
+ }
+
+ if (!(PortStatus & USB_PORT_STAT_DEV_ENABLED)) {
+ return USB_ERROR;
+ }
+
+ // Initialize HC specific data before device configuration
+ Status = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDInitDeviceData)(
+ HcStruc, DevInfo, PortStatus, &DevMiscInfo);
+ if (Status != USB_SUCCESS) {
+ return Status;
+ }
+
+ DevInfo->DevMiscInfo = (VOID*)DevMiscInfo;
+
+ Buffer = USB_MemAlloc(GET_MEM_BLK_COUNT(sizeof(DEV_DESC)));
+ if (Buffer == NULL) {
+ return USB_ERROR;
+ }
+
+ DevAddr = DevInfo->bDeviceAddress;
+ DevInfo->bDeviceAddress = 0;
+
+ DevDesc = (DEV_DESC*)USB_GetDescriptor(HcStruc, DevInfo, Buffer, sizeof(DEV_DESC),
+ DESC_TYPE_DEVICE, 0);
+ if(DevDesc == NULL) {
+ USB_MemFree(Buffer, GET_MEM_BLK_COUNT(sizeof(DEV_DESC)));
+ return USB_ERROR;
+ }
+
+ Status = USB_SetAddress(HcStruc, DevInfo, DevAddr);
+ if (Status != USB_SUCCESS) {
+ USB_MemFree(DevDesc, GET_MEM_BLK_COUNT(sizeof(DEV_DESC)));
+ return Status;
+ }
+
+ DevInfo->bDeviceAddress = DevAddr;
+
+ Buffer = USB_MemAlloc(GET_MEM_BLK_COUNT(MAX_CONTROL_DATA_SIZE));
+ if (Buffer == NULL) {
+ USB_MemFree(DevDesc, GET_MEM_BLK_COUNT(sizeof(DEV_DESC)));
+ return USB_ERROR;
+ }
+
+ for (ConfigIndx = 0; ConfigIndx < DevDesc->NumConfigs; ConfigIndx++) {
+ CnfgDesc = (CNFG_DESC*)USB_GetDescriptor(HcStruc, DevInfo, Buffer,
+ 0xFF, DESC_TYPE_CONFIG, ConfigIndx);
+ if (CnfgDesc == NULL) {
+ continue;
+ }
+ TotalLength = CnfgDesc->wTotalLength;
+ if (TotalLength > 0xFF) {
+ if (TotalLength > (MAX_CONTROL_DATA_SIZE - 1)) {
+ TotalLength = MAX_CONTROL_DATA_SIZE - 1;
+ }
+ CnfgDesc = (CNFG_DESC*)USB_GetDescriptor(HcStruc, DevInfo, Buffer,
+ TotalLength, DESC_TYPE_CONFIG, ConfigIndx);
+ if (CnfgDesc == NULL) {
+ continue;
+ }
+ }
+
+ if (CnfgDesc->bDescType == DESC_TYPE_CONFIG) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDEnableEndpoints)(
+ HcStruc, DevInfo, (UINT8*)CnfgDesc);
+ }
+
+ USB_SetConfig(HcStruc, DevInfo, CnfgDesc->bConfigValue);
+
+ IntrfDesc = (INTRF_DESC*)CnfgDesc;
+ for (IntrfIndx = 0; IntrfIndx < CnfgDesc->bNumInterfaces; IntrfIndx++) {
+ do {
+ IntrfDesc = (INTRF_DESC*)((UINTN)IntrfDesc + IntrfDesc->bDescLength);
+ if ((UINTN)IntrfDesc > ((UINTN)CnfgDesc + CnfgDesc->wTotalLength) ||
+ (UINTN)IntrfDesc > ((UINTN)CnfgDesc + MAX_CONTROL_DATA_SIZE)) {
+ break;
+ }
+ } while (IntrfDesc->bDescType != DESC_TYPE_INTERFACE);
+
+ if (IntrfDesc->bDescType != DESC_TYPE_INTERFACE) {
+ break;
+ }
+
+ for (i = 1; i < MAX_DEVICES; i++) {
+ Dev = &gUsbData->aDevInfoTable[i];
+ if ((Dev->Flag & (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT |
+ DEV_INFO_DEV_DUMMY)) != (DEV_INFO_VALID_STRUC | DEV_INFO_DEV_PRESENT)) {
+ continue;
+ }
+ if ((Dev->bHubDeviceNumber == DevInfo->bHubDeviceNumber) &&
+ (Dev->bHubPortNumber == DevInfo->bHubPortNumber) &&
+ (Dev->bConfigNum == CnfgDesc->bConfigValue) &&
+ (Dev->bInterfaceNum == IntrfDesc->bInterfaceNum) &&
+ (Dev->bAltSettingNum == IntrfDesc->bAltSettingNum)) {
+ break;
+ }
+ }
+ if (i == MAX_DEVICES) {
+ continue;
+ }
+
+ Dev->wVendorId = DevDesc->VendorId;
+ Dev->wDeviceId = DevDesc->DeviceId;
+
+ if (Dev->bDeviceType != BIOS_DEV_TYPE_USBBUS) {
+ DevDriver = UsbFindDeviceDriverEntry(Dev->fpDeviceDriver);
+ if (DevDriver != NULL) {
+ (*DevDriver->pfnConfigureDevice)(HcStruc, Dev, (UINT8*)CnfgDesc,
+ (UINT16)((UINTN)IntrfDesc - (UINTN)CnfgDesc), CnfgDesc->wTotalLength);
+ }
+ }
+ }
+ }
+
+ USB_MemFree(DevDesc, GET_MEM_BLK_COUNT(sizeof(DEV_DESC)));
+ USB_MemFree(Buffer, GET_MEM_BLK_COUNT(MAX_CONTROL_DATA_SIZE));
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USB_DevDriverDisconnect
+//
+// Description:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT32
+USB_DevDriverDisconnect(
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo
+)
+{
+ DEV_DRIVER* DevDriver;
+ UINT8 Index;
+ EFI_STATUS EfiStatus;
+
+ EfiStatus = UsbHcStrucValidation(HcStruc);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ EfiStatus = UsbDevInfoValidation(DevInfo);
+
+ if (EFI_ERROR(EfiStatus)) {
+ return USB_ERROR;
+ }
+
+ gCheckUsbApiParameter = FALSE;
+
+ DevDriver = UsbFindDeviceDriverEntry(DevInfo->fpDeviceDriver);
+
+ if (DevDriver && DevDriver->pfnDisconnectDevice) {
+ DevDriver->pfnDisconnectDevice(DevInfo);
+
+ DevInfo->bDeviceType = 0;
+ DevInfo->fpDeviceDriver = NULL;
+
+ for (Index = 0; Index < MAX_DEVICE_TYPES; Index++) {
+ DevDriver = &gUsbData->aDevDriverTable[Index];
+
+ if (DevDriver->bDevType == BIOS_DEV_TYPE_USBBUS) {
+ DevInfo->bDeviceType = DevDriver->bDevType;
+ DevDriver->pfnConfigureDevice(HcStruc, DevInfo, NULL, 0, 0);
+ break;
+ }
+ }
+ } else {
+ if (DevInfo->IntInEndpoint) {
+ // Stop polling the device's interrupt endpoint
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDDeactivatePolling)
+ (HcStruc, DevInfo);
+ DevInfo->IntInEndpoint = 0;
+ }
+ }
+
+ return USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: VALID_DEVINFO
+//
+// Description: Checks if DEV_INFO is a valid connected device info
+// Due to hot-plug a DEV_INFO can become invalid in the
+// midle of configuration
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+int VALID_DEVINFO(DEV_INFO* pDevInfo)
+{
+ return (pDevInfo->Flag & DEV_INFO_VALIDPRESENT)!=0;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: USB_AbortConnectHubChildren
+//
+// Description: Mark DEV_INFO not valid for all the devices connected to a
+// given hub.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USB_AbortConnectHubChildren(
+ UINT8 HubAddr
+)
+{
+ UINT8 i;
+ DEV_INFO *Dev = &gUsbData->aDevInfoTable[1];
+
+ for (i=1; i<MAX_DEVICES; i++, Dev++) {
+ if ((Dev->bHubDeviceNumber == HubAddr) && (Dev->Flag & DEV_INFO_VALIDPRESENT)) {
+ Dev->Flag &= ~DEV_INFO_DEV_PRESENT;
+ if (!(Dev->Flag & DEV_INFO_MASS_DEV_REGD)) {
+ Dev->Flag &= ~DEV_INFO_VALID_STRUC;
+ }
+
+ USB_DEBUG(DEBUG_LEVEL_3, "USB: abort device [%x] connected to hub[%x]\n",
+ Dev->bDeviceAddress, HubAddr);
+
+ if (Dev->bDeviceType == BIOS_DEV_TYPE_HUB) {
+ USB_AbortConnectHubChildren(Dev->bDeviceAddress);
+ }
+ }
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: USB_FreeDeviceAddress
+//
+// Description: This routine releases the given device's address by
+// updating gUsbData->dDeviceAddressMap.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USB_FreeDeviceAddress(
+ DEV_INFO *DevInfo
+)
+{
+ UINT8 i;
+ UINT8 Found = 0;
+
+ if (DevInfo->bDeviceAddress)
+ {
+ for (i=1; i<MAX_DEVICES; i++) {
+ if (gUsbData->aDevInfoTable+i != DevInfo &&
+ gUsbData->aDevInfoTable[i].bDeviceAddress == DevInfo->bDeviceAddress)
+ {
+ Found++;
+ }
+ }
+ if (Found == 0){
+ //The DevInfo was the only function with allocated address -
+ // return the address to the pool
+ gUsbData->DeviceAddressMap |= Shl64(1, DevInfo->bDeviceAddress);
+ }
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USB_AbortConnectDev
+//
+// Description: Mark DEV_INFO not valid and release its device address
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USB_AbortConnectDev(
+ DEV_INFO* pDevInfo
+)
+{
+ USB_DEBUG(DEBUG_LEVEL_3, "USB: abort connect [%x].flag = %x\n",
+ pDevInfo, pDevInfo->Flag);
+
+ pDevInfo->Flag &= ~DEV_INFO_DEV_PRESENT;
+
+ if (!(pDevInfo->Flag & DEV_INFO_MASS_DEV_REGD)) {
+ pDevInfo->Flag &= ~DEV_INFO_VALID_STRUC;
+ if (pDevInfo->bDeviceAddress == 0) return;
+
+ USB_FreeDeviceAddress(pDevInfo);
+ }
+
+ // Remove children (if any) from aborted parent hub device.
+ // Assume the child device has not been connected since
+ // the hub has to be connected first.
+ if (pDevInfo->bDeviceType == BIOS_DEV_TYPE_HUB) {
+ USB_AbortConnectHubChildren(pDevInfo->bDeviceAddress);
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: USB_SmiQueuePut
+//
+// Description: Puts the pointer pointer into the queue for processing,
+// updates queue head and tail.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USB_SmiQueuePut(VOID * d)
+{
+ QUEUE_T* q = &gUsbData->QueueCnnctDisc;
+
+ while (q->head >= q->maxsize) {
+ q->head -= q->maxsize;
+ }
+
+ q->data[q->head++] = d;
+ if (q->head == q->maxsize) {
+ q->head -= q->maxsize;
+ }
+ if (q->head == q->tail) {
+ //Drop data from queue
+ q->tail++;
+ while (q->tail >= q->maxsize) {
+ q->tail -= q->maxsize;
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: QueuePutMsg
+//
+// Description: Add a variable size item to the queue
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USB_SmiQueuePutMsg( QUEUE_T* q, VOID * d, int sz )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (q->head + sz > q->maxsize) {
+ q->head = 0;
+ }
+#if USB_RUNTIME_DRIVER_IN_SMM
+ Status = AmiValidateMemoryBuffer((VOID*)((UINTN)q->data + q->head), sz);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+#endif
+ MemCopy((UINT8*)d, (UINT8*)((UINTN)q->data + q->head), sz);
+ q->head += sz;
+ if(q->head==q->maxsize) q->head = 0;
+ if(q->head==q->tail){
+ //Drop data from queue
+ q->tail+=sz;
+ if( q->tail >= q->maxsize ) q->tail = 0;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: CheckDeviceLimit
+//
+// Description: Verifies whether the number of initialized devices of a given
+// class has reached the limit.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+BOOLEAN
+CheckDeviceLimit(
+ UINT8 BaseClass
+)
+{
+ URP_STRUC Urp;
+ UINT8 DevNumber;
+
+ Urp.bFuncNumber = USB_API_CHECK_DEVICE_PRESENCE;
+ Urp.bSubFunc = 1;
+ Urp.ApiData.ChkDevPrsnc.fpHCStruc = NULL;
+ Urp.ApiData.ChkDevPrsnc.bDevType = BaseClass;
+
+ USBAPI_CheckDevicePresence(&Urp);
+
+ if (Urp.bRetValue == USB_SUCCESS)
+ {
+ DevNumber = Urp.ApiData.ChkDevPrsnc.bNumber;
+ if ((BaseClass == BASE_CLASS_HID)
+ && ((USB_DEV_HID_COUNT == 0) || (DevNumber == USB_DEV_HID_COUNT)))
+ {
+ USB_DEBUG(3, "Reached the limit of supported HIDs (%d); skipping this device.\n", USB_DEV_HID_COUNT);
+ return TRUE;
+ }
+
+ if ((BaseClass == BASE_CLASS_HUB)
+ && ((USB_DEV_HUB_COUNT == 0) || (DevNumber == USB_DEV_HUB_COUNT)))
+ {
+ USB_DEBUG(3, "Reached the limit of supported HUBs (%d); skipping this device.\n", USB_DEV_HUB_COUNT);
+ return TRUE;
+ }
+
+ if ((BaseClass == BASE_CLASS_MASS_STORAGE)
+ && ((USB_DEV_MASS_COUNT == 0) || (DevNumber == USB_DEV_MASS_COUNT)))
+ {
+ USB_DEBUG(3, "Reached the limit of supported Mass Storage Devices (%d); skipping this device.\n", USB_DEV_MASS_COUNT);
+ return TRUE;
+ }
+ if ((BaseClass == BASE_CLASS_CCID_STORAGE)
+ && ((USB_DEV_CCID_COUNT == 0) || (DevNumber == USB_DEV_CCID_COUNT+1)))
+ {
+ USB_DEBUG(3, "Reached the limit of supported CCID Devices (%d); skipping this device.\n", USB_DEV_CCID_COUNT);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbControlTransfer
+//
+// Description:
+//
+// Input:
+//
+// Output:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbControlTransfer(
+ HC_STRUC* HcStruc,
+ DEV_INFO* DevInfo,
+ DEV_REQ DevReq,
+ UINT16 Timeout,
+ VOID* Buffer)
+{
+ UINT16 Status;
+ UINT16 SavedTimeout;
+
+ SavedTimeout = gUsbData->wTimeOutValue;
+ gUsbData->wTimeOutValue = Timeout;
+
+ Status = (*gUsbData->aHCDriverTable[
+ GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDControlTransfer)(
+ HcStruc,
+ DevInfo,
+ DevReq.wRequestType,
+ DevReq.wIndex,
+ DevReq.wValue,
+ Buffer,
+ DevReq.wDataLength);
+
+ gUsbData->wTimeOutValue = SavedTimeout;
+
+ return DevReq.wDataLength && (Status == 0)? USB_ERROR : USB_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UsbInterruptTransfer
+//
+// Description: This function executes an interrupt transaction on the USB.
+//
+// Input:
+// HcStruc Pointer to HCStruc of the host controller.
+// DevInfo DeviceInfo structure (if available else 0).
+// EndpointAddress The destination USB device endpoint to which the device request
+// is being sent.
+// MaxPktSize Indicates the maximum packet size the target endpoint is capable
+// of sending or receiving.
+// Buffer Buffer containing data to be sent to the device or buffer to be
+// used to receive data.
+// Length Length request parameter, number of bytes of data to be transferred.
+// Timeout Indicates the maximum time, in milliseconds, which the transfer
+// is allowed to complete.
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+UsbInterruptTransfer (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 EndpointAddress,
+ UINT16 MaxPktSize,
+ VOID *Buffer,
+ UINT16 Length,
+ UINT16 Timeout
+)
+{
+ UINT16 SavedTimeout;
+ UINT16 BytesTransferred;
+
+ SavedTimeout = gUsbData->wTimeOutValue;
+ gUsbData->wTimeOutValue = Timeout;
+
+ BytesTransferred = (*gUsbData->aHCDriverTable[
+ GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDInterruptTransfer)(
+ HcStruc,
+ DevInfo,
+ EndpointAddress,
+ MaxPktSize,
+ Buffer,
+ Length);
+
+ gUsbData->wTimeOutValue = SavedTimeout;
+
+ if (BytesTransferred == 0) {
+ return USB_ERROR;
+ } else {
+ return USB_SUCCESS;
+ }
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: USB_EnableEndpointsDummy
+//
+// Description: Dummy HC API function used by the HC drivers that do not need
+// to implement enable endpoint function.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+USB_EnableEndpointsDummy (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 *Desc
+)
+{
+ return USB_SUCCESS;
+}
+
+UINT8
+USB_InitDeviceDataDummy (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo,
+ UINT8 PortStatus,
+ UINT8 **DeviceData
+)
+{
+ *DeviceData = NULL;
+ return USB_SUCCESS;
+}
+
+UINT8
+USB_DeinitDeviceDataDummy (
+ HC_STRUC *HcStruc,
+ DEV_INFO *DevInfo
+)
+{
+ return USB_SUCCESS;
+}
+
+ //(EIP54018+)>
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: LocatePwrCapOffset
+//
+// Description:
+// This function locate power management capability offset
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+UINT8
+LocatePwrCapOffset (
+ IN UINT16 BusDevFunc
+)
+{
+#if USB_RUNTIME_DRIVER_IN_SMM
+ UINT16 StatusReg;
+ UINT8 CapOffset;
+ EFI_PCI_CAPABILITY_HDR CapHeader;
+
+ // Check if device supports extended capabilities
+ StatusReg = (UINT16)ReadPCIConfig(BusDevFunc, PCI_STATUS_REGISTER_OFFSET);
+ if((StatusReg & PCI_STS_CAPABILITY) == 0) {
+ return 0;
+ }
+ // Get offset of first capability structure
+ CapOffset = (UINT8)ReadPCIConfig(BusDevFunc, EFI_PCI_CAPABILITY_PTR);
+ // Check capabilities until PMI is found or no more capabilities
+ while (CapOffset) {
+ CapHeader.CAP_HDR = (UINT16)ReadPCIConfig(BusDevFunc, CapOffset);
+ // If PMI block, return offset
+ if(CapHeader.CapabilityID == PCI_CAP_ID_PMI) {
+ return CapOffset;
+ }
+ // If not, check for next offset
+ CapOffset = CapHeader.NextItemPtr;
+ }
+#endif
+ return 0;
+}
+
+#if USB_S5_WAKEUP_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: ResumePciBridge
+//
+// Description:
+// This function resumed PciBridge
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+ResumePciBridge(
+ UINT16 BusDevFun
+)
+{
+ UINT32 PmStaCtlReg;
+ UINT32 PmCapReg;
+ UINT8 PwrCapPtr;
+ UINT8 PciCommand;
+
+ PwrCapPtr = LocatePwrCapOffset(BusDevFun);
+
+ if (PwrCapPtr) {
+ PmCapReg = ReadPCIConfig(BusDevFun, PwrCapPtr);
+ PmStaCtlReg = ReadPCIConfig(BusDevFun, PwrCapPtr + 0x04);
+ if (PmCapReg & (BIT31 | BIT30)) {
+ PmStaCtlReg |= BIT8;
+ }
+ if (PmStaCtlReg & (BIT0 | BIT1)) {
+ PmStaCtlReg &= ~(BIT0 | BIT1);
+ }
+ DwordWritePCIConfig(BusDevFun, PwrCapPtr + 0x04, PmStaCtlReg);
+ }
+
+ PciCommand = (UINT8)ReadPCIConfig(BusDevFun, PCI_COMMAND_REGISTER_OFFSET);
+ PciCommand |= (PCI_CMD_MEMORY_SPACE + PCI_CMD_BUS_MASTER);
+ ByteWritePCIConfig(BusDevFun, PCI_COMMAND_REGISTER_OFFSET, PciCommand);
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: StopPciBridge
+//
+// Description:
+// This function stopped PciBridge
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+StopPciBridge(
+ UINT16 BusDevFun
+)
+{
+ UINT32 PmStaCtlReg;
+ UINT8 PwrCapPtr;
+ UINT8 PciCommand;
+
+ PwrCapPtr = LocatePwrCapOffset(BusDevFun);
+
+ if (PwrCapPtr) {
+ PmStaCtlReg = ReadPCIConfig(BusDevFun, PwrCapPtr + 0x04);
+ PmStaCtlReg |= (BIT0 + BIT1);
+ DwordWritePCIConfig(BusDevFun, PwrCapPtr + 0x04, PmStaCtlReg);
+ }
+
+ PciCommand = (UINT8)ReadPCIConfig(BusDevFun, PCI_COMMAND_REGISTER_OFFSET);
+ PciCommand &= (~PCI_CMD_BUS_MASTER);
+ ByteWritePCIConfig(BusDevFun, PCI_COMMAND_REGISTER_OFFSET, PciCommand);
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: EnablePciBridge
+//
+// Description:
+// This function scaned PciBridge
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+ScanPciBridge(
+ UINT16 *BridgePciAddr
+)
+{
+ HC_STRUC *HcStruc;
+ UINT8 HcBus[256];
+ UINT16 HcBusIndex = 0;
+ UINT16 MaxHcBus = 0;
+ UINT16 i;
+ UINT16 PciAddr;
+ UINT16 PciBus;
+ UINT16 PciDev;
+ UINT16 PciFun;
+ UINT16 BridgeIndex = 255;
+ UINT16 DownstreamBus;
+
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ HcStruc = gUsbData->HcTable[i];
+ if (HcStruc == NULL) {
+ continue;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_USED)) {
+ continue;
+ }
+
+ if (HcStruc->dHCFlag & HC_STATE_EXTERNAL) {
+ HcBus[HcBusIndex] = (UINT8)(HcStruc->wBusDevFuncNum >> 8);
+ if(MaxHcBus < HcBus[HcBusIndex]) {
+ MaxHcBus = HcBus[HcBusIndex];
+ }
+ HcBusIndex++;
+ }
+ }
+
+ for (PciBus = 0; PciBus < MaxHcBus; PciBus++) {
+ for (PciDev = 0; PciDev < 0x20 ; PciDev++) {
+ PciAddr = (UINT16)((PciBus << 8) | (PciDev << 3) | 0);
+ if (ReadPCIConfig(PciAddr, PCI_VID) != 0xffffffff) {
+ PciFun = ((UINT8)ReadPCIConfig(PciAddr, PCI_HDR) & 0x80) ? 8 : 1;
+ do {
+ PciFun--;
+ PciAddr = (UINT16)((PciBus << 8) | (PciDev << 3) | PciFun);
+ if (PciFun != 0) {
+ if (ReadPCIConfig(PciAddr, PCI_VID) == 0xffffffff) {
+ continue;
+ }
+ }
+ if (ReadPCIConfig(PciAddr, PCI_SCC) == 0x0604) {
+ DownstreamBus = (UINT16)ReadPCIConfig(PciAddr, PCI_SBUS);
+ for (i = 0; i < HcBusIndex; i++) {
+ if ((HcBus[i] >= (UINT8)(DownstreamBus)) &&
+ (HcBus[i] <= (UINT8)(DownstreamBus >> 8))) {
+ ResumePciBridge(PciAddr);
+ BridgePciAddr[BridgeIndex] = PciAddr;
+ BridgeIndex--;
+ break;
+ }
+ }
+ }
+ } while (PciFun);
+ }
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Input: UsbSuspendHubPort
+//
+// Description: This function suspends the hub port
+//
+// Input: DevInfo Device info pointer
+//
+// Output: Status: EFI_SUCCESS = Success
+// EFI_DEVICE_ERROR = Failure
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+UsbSuspendHubPort (
+ DEV_INFO *DevInfo
+)
+{
+ UINT32 Index;
+ DEV_INFO *HubDevInfo;
+ HC_STRUC *HcStruc;
+ UINT16 OrgTimeOutValue;
+
+ if (DevInfo->bHubDeviceNumber & BIT7) {
+ return EFI_SUCCESS;
+ }
+
+ for (Index = 1; Index < MAX_DEVICES; Index++) {
+ HubDevInfo = &gUsbData->aDevInfoTable[Index];
+ if ((HubDevInfo->Flag & DEV_INFO_VALIDPRESENT) != DEV_INFO_VALIDPRESENT) {
+ continue;
+ }
+ if (DevInfo->bHubDeviceNumber == HubDevInfo->bDeviceAddress) {
+ HcStruc = gUsbData->HcTable[HubDevInfo->bHCNumber - 1];
+
+ OrgTimeOutValue = gUsbData->wTimeOutValue;
+ gUsbData->wTimeOutValue = USB_SUSPEND_HUB_PORT_TIMEOUT_MS;
+
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(
+ HcStruc->bHCType)].pfnHCDControlTransfer)(
+ HcStruc,
+ HubDevInfo,
+ (UINT16)HUB_RQ_SET_PORT_FEATURE,
+ DevInfo->bHubPortNumber,
+ (UINT16)PortSuspend,
+ 0, 0);
+
+ gUsbData->wTimeOutValue = OrgTimeOutValue;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_DEVICE_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbSuspendDevices
+//
+// Description:
+// This function suspends usb devices.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UsbSuspendDevices (
+ VOID
+)
+{
+ UINT32 Index;
+ DEV_INFO *DevInfo;
+
+ for (Index = MAX_DEVICES; Index > 0; Index--) {
+
+ DevInfo = &gUsbData->aDevInfoTable[Index];
+
+ if ((DevInfo->Flag & DEV_INFO_VALIDPRESENT) != DEV_INFO_VALIDPRESENT) {
+ continue;
+ }
+ UsbSuspendHubPort(DevInfo);
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbSuspend
+//
+// Description:
+// This function suspend USB
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+UsbSuspend(
+ VOID
+)
+{
+ HC_STRUC *HcStruc;
+ DEV_INFO *DevInfo;
+ CNFG_DESC *CnfgDesc;
+ UINT8 *Buffer;
+ UINT16 i;
+ UINT32 PmStaCtlReg;
+ UINT32 PmCapReg;
+ UINT16 BridgePciAddr[256];
+ UINT32 HcLowBaseAddress;
+ UINT32 HcHighBaseAddress;
+ UINT16 HcIoAddress;
+ UINT16 OrgTimeOutValue;
+
+ for (i = 0; i < 256; i++) {
+ BridgePciAddr[i] = 0;
+ }
+
+ ScanPciBridge(BridgePciAddr);
+
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ HcStruc = gUsbData->HcTable[i];
+ if (HcStruc == NULL) {
+ continue;
+ }
+
+ if (!(HcStruc->dHCFlag & HC_STATE_USED)) {
+ continue;
+ }
+
+ HcStruc->PwrCapPtr = LocatePwrCapOffset(HcStruc->wBusDevFuncNum);
+ if (HcStruc->PwrCapPtr) {
+ PmCapReg = ReadPCIConfig(HcStruc->wBusDevFuncNum,
+ HcStruc->PwrCapPtr);
+ PmStaCtlReg = ReadPCIConfig(HcStruc->wBusDevFuncNum,
+ HcStruc->PwrCapPtr + 0x04);
+ if (PmCapReg & (BIT31 | BIT30)) {
+ PmStaCtlReg |= BIT8;
+ }
+ if (PmStaCtlReg & (BIT0 | BIT1)) {
+ PmStaCtlReg &= ~(BIT0 | BIT1);
+ }
+ DwordWritePCIConfig(HcStruc->wBusDevFuncNum,
+ HcStruc->PwrCapPtr + 0x04, PmStaCtlReg);
+ }
+ if (HcStruc->bHCType == USB_HC_UHCI) {
+ HcIoAddress = (UINT16)ReadPCIConfig(HcStruc->wBusDevFuncNum, USB_IO_BASE_ADDRESS);
+ if (HcStruc->BaseAddress != HcIoAddress) {
+ WordWritePCIConfig(HcStruc->wBusDevFuncNum,
+ USB_IO_BASE_ADDRESS, (UINT32)HcStruc->BaseAddress);
+ }
+ ByteWritePCIConfig(HcStruc->wBusDevFuncNum,
+ PCI_CMD, PCI_CMD_IO_SPACE | PCI_CMD_BUS_MASTER);
+ } else {
+ HcLowBaseAddress = ReadPCIConfig(HcStruc->wBusDevFuncNum, PCI_BAR0);
+ if ((((UINT8)HcLowBaseAddress & (BIT1 |BIT2)) == BIT2) && ((sizeof(VOID*) / sizeof(UINT32)) == 2)) {
+ HcHighBaseAddress = ReadPCIConfig(HcStruc->wBusDevFuncNum, PCI_BAR1);
+ if(HcStruc->BaseAddress != ((UINTN)(HcLowBaseAddress & 0xFFFFFFF0)) +
+ (Shl64((UINTN)HcHighBaseAddress, 32))) {
+ DwordWritePCIConfig(HcStruc->wBusDevFuncNum,
+ PCI_BAR0, (UINT32)HcStruc->BaseAddress);
+ DwordWritePCIConfig(HcStruc->wBusDevFuncNum,
+ PCI_BAR1, (UINT32)(Shr64(HcStruc->BaseAddress, 32)));
+ }
+ } else {
+ if (HcStruc->BaseAddress != (HcLowBaseAddress & 0xFFFFFFF0)) {
+ DwordWritePCIConfig(HcStruc->wBusDevFuncNum,
+ PCI_BAR0, (UINT32)HcStruc->BaseAddress);
+ }
+ }
+ ByteWritePCIConfig(HcStruc->wBusDevFuncNum,
+ PCI_CMD, PCI_CMD_MEMORY_SPACE | PCI_CMD_BUS_MASTER);
+ }
+ }
+
+ // Remove the prsent flag of devices before we reenumerate.
+ for (i = 1; i < MAX_DEVICES; i++) {
+ DevInfo = &gUsbData->aDevInfoTable[i];
+ DevInfo->Flag &= ~DEV_INFO_DEV_PRESENT;
+ }
+
+ gUsbData->UsbSetupData.UsbMassDriverSupport = FALSE;
+ gUsbData->bHandOverInProgress = FALSE;
+
+ //Start XHCI
+ StartControllerType(USB_HC_XHCI);
+ //Start EHCI
+ StartControllerType(USB_HC_EHCI);
+ //Start UHCI
+ StartControllerType(USB_HC_UHCI);
+ //Start OHCI
+ StartControllerType(USB_HC_OHCI);
+
+ //Wait for the usb devices connect.
+ FixedDelay(50 * 1000);
+
+ USB_EnumerateRootHubPorts(USB_HC_XHCI);
+ USB_EnumerateRootHubPorts(USB_HC_EHCI);
+ USB_EnumerateRootHubPorts(USB_HC_UHCI);
+ USB_EnumerateRootHubPorts(USB_HC_OHCI);
+
+ Buffer = USB_MemAlloc(sizeof(CNFG_DESC));
+
+ OrgTimeOutValue = gUsbData->wTimeOutValue;
+ gUsbData->wTimeOutValue = 500;
+
+ for (i = 1; i < MAX_DEVICES; i++) {
+
+ DevInfo = &gUsbData->aDevInfoTable[i];
+
+ if ((DevInfo->Flag & DEV_INFO_VALIDPRESENT) != DEV_INFO_VALIDPRESENT) {
+ continue;
+ }
+
+ if (DevInfo->bDeviceType == BIOS_DEV_TYPE_HUB) {
+ continue;
+ }
+
+ HcStruc = gUsbData->HcTable[DevInfo->bHCNumber - 1];
+
+ CnfgDesc = (CNFG_DESC*)USB_GetDescriptor(
+ HcStruc,
+ DevInfo,
+ Buffer,
+ sizeof(CNFG_DESC),
+ DESC_TYPE_CONFIG,
+ 0);
+
+ if (CnfgDesc == NULL) {
+ continue;
+ }
+
+ //Check the device have the capable of remote wakeup
+ if (CnfgDesc ->bConfigFlags & BIT5) {
+ //Send device wakeup command to the device
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(
+ HcStruc->bHCType)].pfnHCDControlTransfer)(
+ HcStruc,
+ DevInfo,
+ (UINT16)USB_RQ_SET_FEATURE,
+ 0,
+ (UINT16)USB_FSEL_DEV_REMOTE_WAKEUP,
+ 0, 0);
+
+ }
+
+ }
+
+ gUsbData->wTimeOutValue = OrgTimeOutValue;
+
+ USB_MemFree(Buffer, sizeof(CNFG_DESC));
+
+ UsbSuspendDevices();
+
+ for (i = 0; i < gUsbData->HcTableCount; i++) {
+ HcStruc = gUsbData->HcTable[i];
+ if (HcStruc == NULL) {
+ continue;
+ }
+
+ //Global suspend host
+ if (HcStruc->dHCFlag & HC_STATE_RUNNING) {
+ (*gUsbData->aHCDriverTable[GET_HCD_INDEX(
+ HcStruc->bHCType)].pfnHCDGlobalSuspend)(HcStruc);
+ if (HcStruc->PwrCapPtr) {
+ PmStaCtlReg = ReadPCIConfig(HcStruc->wBusDevFuncNum,
+ HcStruc->PwrCapPtr + 0x04);
+ PmStaCtlReg |= (BIT0 + BIT1);
+ DwordWritePCIConfig(HcStruc->wBusDevFuncNum,
+ HcStruc->PwrCapPtr + 0x04, PmStaCtlReg);
+ }
+ }
+ }
+
+ for (i = 0; i < 256; i++) {
+ if (BridgePciAddr[i] != 0) {
+ StopPciBridge(BridgePciAddr[i]);
+ }
+ }
+
+ UsbSbEnablePme();
+
+}
+
+#endif
+ //<(EIP54018+)
+UINT8
+UsbGetDataToggle(
+ DEV_INFO *DevInfo,
+ UINT8 EndpointAddr
+)
+{
+ DEV_INFO *DevInfoToToggle;
+ UINT8 ToggleBit = (EndpointAddr & 0xF) - 1;
+ UINT16 *DataSync;
+ EFI_STATUS Status;
+
+ if (DevInfo->fpLUN0DevInfoPtr) {
+ Status = UsbDevInfoValidation(DevInfo->fpLUN0DevInfoPtr);
+ if (EFI_ERROR(Status)) {
+ return 0;
+ }
+ DevInfoToToggle = DevInfo->fpLUN0DevInfoPtr;
+ } else {
+ DevInfoToToggle = DevInfo;
+ }
+
+ if (EndpointAddr & BIT7) {
+ DataSync = &DevInfoToToggle->wDataInSync;
+ } else {
+ DataSync = &DevInfoToToggle->wDataOutSync;
+ }
+
+ return (UINT8)((*DataSync) >> ToggleBit) & 0x1;
+}
+
+VOID
+UsbUpdateDataToggle(
+ DEV_INFO *DevInfo,
+ UINT8 EndpointAddr,
+ UINT8 DataToggle
+)
+{
+ DEV_INFO *DevInfoToToggle;
+ UINT8 ToggleBit = (EndpointAddr & 0xF) - 1;
+ UINT16 *DataSync;
+ EFI_STATUS Status;
+
+ if (DevInfo->fpLUN0DevInfoPtr) {
+ Status = UsbDevInfoValidation(DevInfo->fpLUN0DevInfoPtr);
+ if (EFI_ERROR(Status)) {
+ return;
+ }
+ DevInfoToToggle = DevInfo->fpLUN0DevInfoPtr;
+ } else {
+ DevInfoToToggle = DevInfo;
+ }
+
+ if (EndpointAddr & BIT7) {
+ DataSync = &DevInfoToToggle->wDataInSync;
+ } else {
+ DataSync = &DevInfoToToggle->wDataOutSync;
+ }
+
+ *DataSync &= (UINT16)~(1 << ToggleBit);
+ *DataSync |= (UINT16)(DataToggle << ToggleBit);
+ return;
+}
+
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+//** **
+//** Phone (770)-246-8600 **
+//** **
+//****************************************************************************
+//****************************************************************************