diff options
Diffstat (limited to 'Core/EM/usb/rt/amiusb.c')
-rw-r--r-- | Core/EM/usb/rt/amiusb.c | 3402 |
1 files changed, 3402 insertions, 0 deletions
diff --git a/Core/EM/usb/rt/amiusb.c b/Core/EM/usb/rt/amiusb.c new file mode 100644 index 0000000..89a2975 --- /dev/null +++ b/Core/EM/usb/rt/amiusb.c @@ -0,0 +1,3402 @@ +//**************************************************************************** +//**************************************************************************** +//** ** +//** (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/amiusb.c 121 10/16/16 10:11p Wilsonlee $ +// +// $Revision: 121 $ +// +// $Date: 10/16/16 10:11p $ +// +//**************************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/amiusb.c $ +// +// 121 10/16/16 10:11p 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 +// +// 120 7/29/16 3:13a 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 +// +// 119 7/29/16 3:09a Wilsonlee +// [TAG] EIP277810 +// [Category] Improvement +// [Description] Validate the memory buffer is entirely outside of SMM. +// [Files] usbsb.c, amiusb.c, ehci.c, ohci.c, uhci.c, usbCCID.c, +// usbdef.h, usbmass.c, xhci.c, amiusbhc.c, efiusbccid.c, efiusbmass.c, +// uhcd.c, uhcd.h, usbmisc.c +// +// 117 7/07/16 1:09a Wilsonlee +// [TAG] EIP277810 +// [Category] Improvement +// [Description] Validate the memory buffer is entirely outside of SMM. +// [Files] usbsb.c, amiusb.c, ehci.c, ohci.c, uhci.c, usbCCID.c, +// usbdef.h, usbmass.c, xhci.c, amiusbhc.c, efiusbccid.c, efiusbmass.c, +// uhcd.c, uhcd.h, usbmisc.c +// +// 116 10/16/15 3:34a Wilsonlee +// [TAG] EIP241977 +// [Category] Improvement +// [Description] Improve UsbKbcAccessControl api function. +// [Files] amiusb.c +// +// 115 4/10/15 3:12a Wilsonlee +// [TAG] EIP207413 +// [Category] Improvement +// [Description] Install UsbApiTable and UsbMassApitTable in +// AmiUsbSmmProtocol. +// [Files] amiusbhc.c, AmiUsbController.h, usbdef.h, usbCCID.c, uhci.c, +// ehci.c, amiusbrtCCID.h, amiusb.h, amiusb.c, uhcd.c +// +// 114 2/10/15 12:20a Wilsonlee +// Fixed build error in non-smm projects. +// +// 113 12/03/14 9:36p Wilsonlee +// [TAG] EIP193805 +// [Category] Improvement +// [Description] Security Enhancement for SMIHandler in USB module. +// [Files] amiusb.c, uhcd.c, usbrt.mak, usbdef.h, usbsb.c +// +// 112 11/23/14 10:10p Wilsonlee +// [TAG] EIP189293 +// [Category] Improvement +// [Description] Implement XHCI key repeat function. +// [Files] usb.c, xhci.c , xhci.h, amiusb.c +// +// 111 6/05/14 9:15p Wilsonlee +// [TAG] EIP171837 +// [Category] Bug Fix +// [Severity] Critical +// [Symptom] When use afuwin update BIOS or read ROMID under pure Win8.1 +// OS, sometimes the system will blue screen. +// [RootCause] UsbData->EfiKeyboardBuffer is EfiBootServicesData. This +// memory isn't reserved in OS. We can't write data to this memory in OS. +// [Solution] We clear the buffer at USBKBDProcessKeyboardData function +// if the system is under EFI. +// [Files] amiusb.c +// +// 110 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 +// +// 109 4/07/14 1:28a Wilsonlee +// [TAG] EIP157193 +// [Category] Improvement +// [Description] Stop the usb host controllers at AcpiModeEnable if they +// art extend cards or don't support HW SMI. +// [Files] amiusb.c +// +// 108 2/10/14 1:19a Ryanchou +// [TAG] EIP149929 +// [Category] Improvement +// [Description] Stop all external EHCI HCs in ACPI enable call. +// [Files] amiusb.c +// +// 107 12/15/13 10:16p Wilsonlee +// [TAG] EIP136594 +// [Category] New Feature +// [Description] Support 64 bits LBA of usb mass storages. +// [Files] Bfiusb.asm, Bfiusb.equ, UsbInt13.c, UsbInt13.h, amiusb.c, +// usbdef.h, usbmass.c, UsbMass.h, efiusbmass.c, UI13.bin +// +// 106 11/05/13 4:46a Ryanchou +// [TAG] EIP135636 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] NumLock LED cannot be on/off properly. +// [RootCause] It is the side effect of EIP #107429 changes, the +// keyboard does not generate break code when pressing NumLock. +// [Solution] Remove the EIP #107429 changes. +// [Files] amiusb.c, usbkbd.c, efiusbkb.c +// +// 105 10/19/13 7:06a Ryanchou +// [TAG] EIP138257 +// [Category] Improvement +// [Description] Correct USB HID device type. +// [Files] amiusb.c, usbdef.h, usbhid.c, efiusbhid.c, uhcd.c +// +// 104 8/06/13 4:21a Wilsonlee +// [TAG] EIP128970 +// [Category] Improvement +// [Description] UsbInstallHwSmiHandler returns EFI_UNSUPPORTED if +// HCType is invalid. +// [Files] amiusb.c +// +// 103 6/02/13 11:43p Wilsonlee +// [TAG] EIP123235 +// [Category] Improvement +// [Description] Stop the usb host controller at ExitBootService if it +// is an extend card or it doesn't support HW SMI. +// [Files] xhci.c, ehci.c, uhci.c, ohci.c, amiusb.c, usbdef.h, usbsb.c, +// uhcd.c +// +// 102 4/10/13 9:29p Wilsonlee +// [TAG] EIP120573 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] Afuwinx64/Safuwinx64 hang up issue. +// [RootCause] EfiZeroMem is a boot service function, we can't use it +// during runtime. +// [Solution] Use MemFill function to clear the KBC buffers. +// [Files] amiusb.c +// +// 101 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 +// +// 100 1/23/13 4:15a Ryanchou +// [TAG] EIP111280 +// [Category] Improvement +// [Description] Add USB APIs for external driver. +// [Files] amiusb.c, amiusb.h, usbdef.h +// +// 99 1/22/13 3:09a Wilsonlee +// [TAG] EIP112938 +// [Category] Improvement +// [Description] Create a header file for usb mass storage driver. +// [Files] UsbMass.h, usbmass.c, usbdef.h, amiusb.c, efiusbmass.c +// +// 98 12/21/12 5:02a Ryanchou +// [TAG] EIP71730 +// [Category] New Feature +// [Description] Added OHCI handoff support. +// [Files] usb.sdl, usbport.c, amiusb.c, usbdef.h, UsbPolicy.h, usb.sd, +// usb.uni +// +// 97 12/09/12 12:12a Wilsonlee +// [TAG] EIP107429 +// [Category] Improvement +// [Description] Process the make code even if there is no break code. +// [Files] efiusbkb.c, amiusb.c +// +// 96 12/02/12 10:23p Roberthsu +// [TAG] EIP102150 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Push key and unplug KB , character repeat can not. +// stop +// [RootCause] Because repeat key does not clear when usb keyboard +// unplug. +// [Solution] When keyboard disconnrct, clear keyboard device id with +// device id buffer and scancode buffer. +// [Files] amiusb.c,syskbc.c,uhcd.c,usbkbd.c +// +// 95 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 +// +// 94 8/29/12 8:10a 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 +// +// 93 8/07/12 9:39p Wilsonlee +// [TAG] EIP96366 +// [Category] New Feature +// [Description] Add the token "DEFAULT_USB_EMUL6064_OPTION" that +// control the default value of the I/O port 60h/64h emulation support +// option. +// [Files] usb.sd, usb.sdl, amiusb.c, amiusb.h +// +// 92 6/13/12 7:31a Lavanyap +// [TAG] EIP89825 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] System get's hangs inside the SMI handler while flashing +// the Bios. +// [RootCause] Port 60/64 access SMI will not be generated immediately +// if accessed inside an SMI handler when KbcEmulation is enabled. +// [Solution] Emulation is disabled while accessing the Port 60/64. +// [Files] amiusb.c +// +// 91 5/22/12 10:03a Ryanchou +// [TAG] EIP90154 +// [Category] Improvement +// [Description] Remove the USBSB_EnableSmmPeriodicSmi and +// USBSB_DisableSmmPeriodicSmi hooks. +// [Files] amidef.h, amiusb.c, usb.c, usbsb.c +// +// 90 5/04/12 6:37a 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 +// +// 89 5/04/12 5:21a Wilsonlee +// [TAG] EIP89307 +// [Category] Improvement +// [Description] Modify incorrect #pragma pack directive. +// [Files] amidef.h, amiusb.c, ehci.c, ohci.c, ohci.h, uhci.h, usb.c, +// usbdef.h, xhci.h, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, +// UsbIo.h +// +// 88 5/03/12 5:50a Roberthsu +// [TAG] EIP84455 +// [Category] Improvement +// [Description] Implement usb hid device gencric. +// [Files] amiusb.c,amiusbhc.c,efiusbhid.c,efiusbkb.c,ehci.c,ohci.c,uhc +// d.c,uhci.c,usbdef.h,usbhid.c,usbhub.c,usbkbd.c,usbkbd.h,usbms.c,usbsb.c +// ,usbsrc.sdl +// +// 87 1/16/12 6:01a Ryanchou +// [TAG] EIP81132 +// [Description] Add core version check for EIP80609 solution. +// [Files] amiusb.c, usbrt.mak, usbsb.c +// +// 86 1/14/12 4:09a Ryanchou +// [TAG] EIP80609 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] If to enable debug mode and set launch CSM is "Never" in +// setup, system will hang at 0xB1 +// [RootCause] The pointer AmiUsb is invalid if CSM is not launched, +// that may cause CPU exception. +// [Solution] Added USB smm protocol, and use SmmLocateProtocol to get +// the pointer. +// [Files] amiusb.c, AmiUsbController.h, usbrt.mak, usbsb.c +// +// 85 1/13/12 4:23a 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 +// +// 84 12/09/11 3:09p Ryanchou +// [TAG] EIP7768 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] USB mass storage can't work after unplug and plug under DOS +// [RootCause] The SW SMI handler checks USB_FLAG_RUNNING_UNDER_EFI flag +// to get the URP from USB global data area or EBDA. Legacy boot event +// clears the flag, and UsbPrepareForLegacyOS will not be invoked. +// [Solution] Check the URP in USB global data area, if it is not empty, +// get it in USB global data area, or get it in EBDA. +// [Files] amiusb.c +// +// 83 11/08/11 8:22a 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 +// +// 82 11/08/11 1:41a Ryanchou +// [TAG] EIP63188 +// [Category] Improvement +// [Description] External USB controller support. +// [Files] amidef.h, amiusb.c, ehci.c, ohci.c, uhcd.c, uhcd.h, uhci.c, +// usbdef.h, usbmisc.c, usbsb.c, xhci.c +// +// 81 11/05/11 3:26a Ryanchou +// [TAG] EIP70094 +// [Category] Improvement +// [Description] Microsoft CSM Opt-Out feature implementation. +// [Files] amiusb.c, uhcd.c +// +// 80 10/17/11 2:24a Ryanchou +// [TAG] EIP69136 +// [Category] Improvement +// [Description] Remove the dependency of EBDA in USB module for CSM +// disabling. +// [Files] amiusb.c, uhcd.c, usbport.c, usbsb.c +// +// 79 9/28/11 10:45a Ryanchou +// [TAG] EIP66064 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] System hangs when waiting for finger swipe +// [RootCause] USB driver save the URP pointer to EBDA in function +// UsbSmiCore and UsbSmiHc, the pointer will be destroyed if someone also +// invoke the two functions. +// [Solution] Save the URP pointer before generate SW SMI and restore it +// after return from SMI. +// [Files] amiusb.c, amiusbhc.c, usbport.c +// +// 78 8/08/11 6:57a 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 +// +// 77 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 +// +// 76 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 +// +// 75 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 +// +// 74 5/03/11 8:44a Ryanchou +// [TAG] EIP57521 +// [Category] Improvement +// [Description] Enumerate root hub ports after start host controllers +// in USB_StartLegacy. +// [Files] amiusb.c +// +// 73 3/30/11 9:02a Ryanchou +// [TAG] EIP41483 +// [Category] Improvement +// [Description] Stop timer SMI after legacy shutdown. +// [Files] amiusb.c, AmiUsbController.h, ohci.c +// +// 72 3/29/11 10:07a 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 +// +// 71 12/24/10 5:02a Tonylo +// [TAG] EIP48323 +// [Category] Improvement +// [Description] Reflush USB keyboard data buffer to avoid junk data +// sent after enable USB keyboard data throughput. +// [Files] AMIUSB.C +// +// 70 11/22/10 8:42a Ryanchou +// [TAG] EIP48064 +// [Category] Improvement +// [Description] The SB template implemented elink +// AcpiEnableCallbackList, the XHCI/EHCI hand off function should be +// invoked via the elink AcpiEnableCallbackList. +// [Files] amidef.h, amiusb.c, amiusb.dxs, amiusb.h, +// AmiUsbController.h, usb.sdl, usbrt.mak, usbsb.c +// +// 69 10/07/10 9:32a Ryanchou +// EIP42986: Remove the retry loop in UsbHwSmiHandler. +// +// 68 8/31/10 8:57a Tonylo +// Remove user tags for coding standard. +// +// Description: Remove user tags for coding standard. +// +// 67 8/18/10 4:22p Olegi +// Klockwork related fixes; EIP37978 +// +// 66 7/27/10 9:11a Ryanchou +// EIP41216: Return correct error code when device isn't present. +// +// 65 7/15/10 4:33a Tonylo +// EIP21649 - USB mass storage device still appear in BBS menu when USB +// legacy support is disabled. +// +// 64 6/07/10 8:56a Ryanchou +// EIP38547: Fixed system halt when installing FreeBSD. +// +// 63 3/31/10 6:26p Olegi +// +// 62 3/25/10 9:45a Olegi +// +// 61 3/19/10 10:05a Olegi +// +// 60 1/27/10 5:19p Olegi +// Added chipset porting hook to initialize timers. +// +// 59 12/01/09 10:06a Olegi +// EIP31535: RWV error code corrected. +// +// 58 11/25/09 8:05a Olegi +// EIPEIP29733: Added KBC access control API +// +// 57 10/30/09 5:47p Olegi +// +// 56 10/02/09 10:49a Olegi +// Code cleanup. +// +// 54 9/15/09 10:21a Olegi +// Added USB_INCMPT_HID_DATA_OVERFLOW incompatibility type. +// +// 53 8/26/09 11:41a Olegi +// Changes that prevent collision of keyboard activity and mass storage +// access. EIP#22808 +// +// 52 5/22/09 1:46p Olegi +// Added the special treatment for in-built hubs. +// +// 51 5/21/09 5:11p Olegi +// Added checking for hotplug fake drives in Read/Write/Verify functions. +// +// 50 1/29/09 2:31p Olegi +// USB API CheckDevicePresence is extended with USB_SRCH_DEVBASECLASS_NUM +// search key. +// +// 49 1/23/09 4:28p Olegi +// Added EXTRA_CHECK_DEVICE_READY condition for the fix to EIP#15037. +// +// 48 1/05/09 9:40a Olegi +// Changes for EIP#15037. Extra CheckDeviceReady call added to read/write +// functions. +// +// 46 10/06/08 3:33p Olegi +// EHCI change ownership testing in DOS fix (EIP#14855). +// +// 44 9/24/08 4:01p Olegi +// Modified USBAPI_ChangeOwner so that it allows multiple calls to +// acquiring the ownership without releasing it. +// +// 43 7/04/08 1:07p Olegi +// Device "Ultra-X, Inc.: Ultra-X QTP USB HD 1.01" is removed from +// incompatible device list. +// +// 42 6/27/08 5:52p Olegi +// Added incompatible devices. +// +// 41 5/16/08 12:01p Olegi +// Compliance with AMI coding standard. +// +// 40 12/17/07 4:04p Olegi +// KBC emulation support added. +// +// 39 12/05/07 4:36p Olegi +// Modification in USBSWSMIHandler() related to the 64/32-bit pointers. +// +// 36 7/09/07 2:11p Olegi +// Changed the maximum data size of the BulkTransfer from 1kB to 64kB. +// +// 34 6/11/07 2:53p Olegi +// Bugfix in device read/write routine: do not issue RWV command if there +// is no media present. +// +// 32 3/20/07 12:16p Olegi +// SMITHUNK removed. +// +// 28 10/18/06 9:40a Andriyn +// Fix: race condition on hot-plug in / plug-off +// +// 27 10/12/06 4:41p Olegi +// Modified the method of passing arguments into USBSWSMIHandler: it is +// done through memory location, not using CPU register. This change is +// only valid for CSM16 versions 31 and later. +// +// 26 4/14/06 6:39p Olegi +// Conversion to be able to use x64 compiler. +// +// 24 3/20/06 3:37p Olegi +// Version 8.5 - x64 compatible. +// +// 23 3/06/06 6:22p Olegi +// Lun devices support modifications: supported using the index in +// DEV_INFO table, not through dedicated massLun table. +// +// 21 1/11/06 11:51a Olegi +// LegacyUsbSupport setup question functionality added. +// +// 18 10/20/05 3:08p Olegi +// ReadDevice correction (EST change). +// +// 14 8/25/05 7:19p Andriyn +// USB Keyboard and mouse to use EMUL 60/64 for passing data to KBC. +// Fall-back when EMUL 60/64 is not present +// +// 13 8/23/05 5:50p Olegi +// USBMassGetDeviceParameters function added. +// +// 12 8/11/05 9:53a Olegi +// 60/64 port emulation related fixes for EMU6064 driver. +// +// 11 8/04/05 5:58p Andriyn +// Legacy over LegacyFree +// +// 10 6/20/05 8:55a Olegi +// .NET compiler with highest warning level and warning-as-error +// modification. +// +// 9 6/15/05 1:59p Andriyn +// Comments were changed +// +// 6 6/03/05 6:06p Olegi +// UsbHwSmiHandler modified to be called individually from UHCI, OHCI and +// EHCI drivers. +// +// 5 6/03/05 9:28a Olegi +// ATA Error reporting is corrected in USBWrapGetATAErrorCode. +// +// 4 6/01/05 5:21p Olegi +// Debug message shortened. +// +// 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: AMIUSB.C +// +// Description: AMI USB API implementation. The following code will be +// copied to SMM; only RT functions can be used. gUsbData +// is obtained from AMIUHCD in the entry point and can be +// used afterwards. +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include <AmiDxeLib.h> +#include "amiusb.h" +#include "amidef.h" +#include <UsbDevDriverElinks.h> //(EIP71750+) +#if USB_RUNTIME_DRIVER_IN_SMM +#include <AmiBufferValidationLib.h> +#include <AmiUsbSmmGlobalDataValidationLib.h> +#endif + +#if USB_DEV_KBD +#include "usbkbd.h" +#endif +#include "UsbMass.h" + + //(EIP54018+)> +#if USB_S5_WAKEUP_SUPPORT +#include <Protocol\SmmSxDispatch.h> +#include <Protocol\SmmPowerButtonDispatch.h> +#endif + //<(EIP54018+) +//#pragma warning (disable: 4152) + +extern UINT8 IsKbcAccessBlocked; //(EIP29733+) +EFI_EMUL6064MSINPUT_PROTOCOL* gMsInput = 0; +EFI_EMUL6064KBDINPUT_PROTOCOL* gKbdInput = 0; +EFI_EMUL6064TRAP_PROTOCOL* gEmulationTrap = 0; + +USB_GLOBAL_DATA *gUsbData; +//USB_BADDEV_STRUC *gUsbBadDeviceTable; //(EIP60706-) + +AMI_USB_SMM_PROTOCOL gUsbSmmProtocol = {0}; + +BOOLEAN gLockSmiHandler = FALSE; +BOOLEAN gLockHwSmiHandler = FALSE; +BOOLEAN gCheckUsbApiParameter = FALSE; + +VOID StopControllerType(UINT8); +VOID StartControllerType(UINT8); +UINT8 USB_StopDevice (HC_STRUC*, UINT8, UINT8); +UINT8 USB_EnumerateRootHubPorts(UINT8); //(EIP57521+) +VOID StopControllerBdf(UINT16); //(EIP74876+) + +VOID FillHcdEntries(); + //(EIP71750+)> +typedef VOID USB_DEV_DELAYED_DRIVER_CHECK (DEV_DRIVER*); +extern USB_DEV_DELAYED_DRIVER_CHECK USB_DEV_DELAYED_DRIVER EndOfUsbDevDelayedDriverList; +USB_DEV_DELAYED_DRIVER_CHECK* UsbDevDelayedDrivers[]= {USB_DEV_DELAYED_DRIVER NULL}; + +typedef VOID USB_DEV_DRIVER_CHECK (DEV_DRIVER*); +extern USB_DEV_DRIVER_CHECK USB_DEV_DRIVER EndOfUsbDevDriverList; +USB_DEV_DRIVER_CHECK* UsbDevDrivers[]= {USB_DEV_DRIVER NULL}; + //<(EIP71750+) + //(EIP54018+)> +#if USB_S5_WAKEUP_SUPPORT +VOID UsbSuspend(VOID); +#endif + +#if USB_S5_WAKEUP_SUPPORT +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: UsbS5SmiCallback +// +// Description: +// This function enter usb s5 callback. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +UsbS5SmiCallback( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext +) +{ + EFI_STATUS Status = EFI_SUCCESS; +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B) + Status = AmiUsbSmmGlobalDataValidation(gUsbData); + + ASSERT_EFI_ERROR(Status); + + if (EFI_ERROR(Status)) { + return; + } +#endif + UsbSuspend(); +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: UsbPowerButtonSmiCallback +// +// Description: +// This function enter s5 callback if press power button. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +UsbPowerButtonSmiCallback( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_POWER_BUTTON_DISPATCH_CONTEXT *DispatchContext +) +{ + EFI_STATUS Status = EFI_SUCCESS; +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B) + Status = AmiUsbSmmGlobalDataValidation(gUsbData); + + ASSERT_EFI_ERROR(Status); + + if (EFI_ERROR(Status)) { + return; + } +#endif + UsbSuspend(); +} +#endif + //<(EIP54018+) + +//<AMI_THDR_START> +//---------------------------------------------------------------------------- +// Name: aUsbApiTable - USB API Function Dispatch Table +// +// Type: Function Dispatch Table +// +// Description: This is the table of functions used by USB API +// +// Notes: This functions are invoked via software SMI +// +//---------------------------------------------------------------------------- +//<AMI_THDR_END> + +API_FUNC aUsbApiTable[] = { + USBAPI_CheckPresence, + USBAPI_Start, + USBAPI_Stop, + USBAPI_DisableInterrupts, + USBAPI_EnableInterrupts, + USBAPI_MoveDataArea, + USBAPI_GetDeviceInfo, + USBAPI_CheckDevicePresence, + USBAPI_MassDeviceRequest, + USBAPI_PowerManageUSB, + USBAPI_PrepareForOS, + USBAPI_SecureInterface, + USBAPI_LightenKeyboardLEDs, + USBAPI_ChangeOwner, + USBAPI_HC_Proc, + USBAPI_Core_Proc, + USBAPI_LightenKeyboardLEDs_Compatible, + USBAPI_KbcAccessControl, + USBAPI_LegacyControl, + USBAPI_GetDeviceAddress, + USBAPI_ExtDriverRequest, + USBAPI_CCIDRequest, + USBAPI_UsbStopController, //(EIP74876+) + USBAPI_HcStartStop +}; + +//<AMI_THDR_START> +//---------------------------------------------------------------------------- +// Name: USBMassAPITable - USB Mass Storage API Function Dispatch Table +// +// Type: Function Dispatch Table +// +// Description: This is the table of functions used by USB Mass Storage API +// +//---------------------------------------------------------------------------- +//<AMI_THDR_END> + +API_FUNC aUsbMassApiTable[] = { + USBMassAPIGetDeviceInformation, // USB Mass API Sub-Func 00h + USBMassAPIGetDeviceGeometry, // USB Mass API Sub-Func 01h + USBMassAPIResetDevice, // USB Mass API Sub-Func 02h + USBMassAPIReadDevice, // USB Mass API Sub-Func 03h + USBMassAPIWriteDevice, // USB Mass API Sub-Func 04h + USBMassAPIVerifyDevice, // USB Mass API Sub-Func 05h + USBMassAPIFormatDevice, // USB Mass API Sub-Func 06h + USBMassAPICommandPassThru, // USB Mass API Sub-Func 07h + USBMassAPIAssignDriveNumber, // USB BIOS API function 08h + USBMassAPICheckDevStatus, // USB BIOS API function 09h + USBMassAPIGetDevStatus, // USB BIOS API function 0Ah + USBMassAPIGetDeviceParameters // USB BIOS API function 0Bh +}; + +EFI_DRIVER_ENTRY_POINT(USBDriverEntryPoint) + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: USBDriverEntryPoint +// +// Description: USB Driver entry point +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +USBDriverEntryPoint( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable +) +{ + EFI_STATUS Status; + + InitAmiLib(ImageHandle, SystemTable); + +#if USB_RUNTIME_DRIVER_IN_SMM + Status = InitSmmHandler(ImageHandle, SystemTable, InSmmFunction, NULL); +#else + Status = InstallUsbProtocols(); + InitializeUsbGlobalData(); +#endif + ASSERT_EFI_ERROR(Status); + + return Status; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: InitializeUsbGlobalData +// +// Description: This function initializes the USB global data. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +InitializeUsbGlobalData( + VOID +) +{ + EFI_STATUS Status; + UINT8 bDriverIndex; + UINT8 bDelayedIndex; + + // + // Initialize host controller drivers + // + FillHcdEntries(); // This routine is implemented in $(BUILD_DIR)\dummyusbrt.c + + // + // Initialize the device driver pointers + // + bDriverIndex = 0; + bDelayedIndex = 0; + //(EIP71750)> + while(UsbDevDelayedDrivers[bDelayedIndex]) { + UsbDevDelayedDrivers[bDelayedIndex](&gUsbData->aDelayedDrivers[bDelayedIndex]); + if (gUsbData->aDelayedDrivers[bDelayedIndex].pfnDeviceInit) { + (*gUsbData->aDelayedDrivers[bDelayedIndex].pfnDeviceInit)(); + } + if (gUsbData->aDelayedDrivers[bDelayedIndex].bDevType) { + bDelayedIndex++; + } + } + + while(UsbDevDrivers[bDriverIndex]) { + UsbDevDrivers[bDriverIndex](&gUsbData->aDevDriverTable[bDriverIndex]); + if (gUsbData->aDevDriverTable[bDriverIndex].pfnDeviceInit) { + (*gUsbData->aDevDriverTable[bDriverIndex].pfnDeviceInit)(); + } + if (gUsbData->aDevDriverTable[bDriverIndex].bDevType) { + bDriverIndex++; + } + } + + // + // Allocate a block of memory to be used as a temporary + // buffer for USB mass transfer + // + Status = pBS->AllocatePool (EfiRuntimeServicesData, MAX_CONSUME_BUFFER_SIZE, + &gUsbData->fpUSBMassConsumeBuffer); + ASSERT_EFI_ERROR(Status); + pBS->SetMem(gUsbData->fpUSBMassConsumeBuffer, MAX_CONSUME_BUFFER_SIZE, 0); + + // + // Allocate a block of memory for the temporary buffer + // + Status = gBS->AllocatePool (EfiRuntimeServicesData, MAX_TEMP_BUFFER_SIZE, + &gUsbData->fpUSBTempBuffer); + ASSERT_EFI_ERROR(Status); + pBS->SetMem(gUsbData->fpUSBTempBuffer, MAX_TEMP_BUFFER_SIZE, 0); + + // + // Allow to enumerate ports + // + gUsbData->bEnumFlag = FALSE; + + return USB_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: UsbApiHandler +// +// Description: +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +UsbApiHandler(VOID* Param) +{ + URP_STRUC *fpURP = (URP_STRUC*)Param; + UINT8 bFuncIndex; + UINT8 bNumberOfFunctions; + + if (fpURP == NULL) { + return; + } + + bFuncIndex = fpURP->bFuncNumber; + bNumberOfFunctions = sizeof aUsbApiTable / sizeof (API_FUNC *); + + // + // Make sure function number is valid; if function number is not zero + // check for valid extended USB API function + // + if (bFuncIndex && ((bFuncIndex < USB_NEW_API_START_FUNC ) || + bFuncIndex > (bNumberOfFunctions + USB_NEW_API_START_FUNC))) { + //fpURP->bRetValue = USBAPI_INVALID_FUNCTION; + USB_DEBUG(3, "UsbApiHandler Invalid function#%x\n", bFuncIndex); + return; + } + + if (bFuncIndex) { + bFuncIndex = (UINT8)(bFuncIndex - USB_NEW_API_START_FUNC + 1); + } + + aUsbApiTable[bFuncIndex](fpURP); // Call the appropriate function + +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: InstallUsbProtocols +// +// Description: This function initializes the USB global data. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +InstallUsbProtocols( + VOID +) +{ + EFI_STATUS Status; + EFI_USB_PROTOCOL *UsbProtocol; + + Status = pBS->LocateProtocol(&gEfiUsbProtocolGuid, NULL, &UsbProtocol); + if (EFI_ERROR(Status)) { + return Status; + } + gUsbData = UsbProtocol->USBDataPtr; + + UsbProtocol->UsbRtKbcAccessControl = UsbKbcAccessControl; + + //Hook USB legacy control function for shutdown/init USB legacy support + UsbProtocol->UsbLegacyControl = USBRT_LegacyControl; + UsbProtocol->UsbStopUnsupportedHc = USB_StopUnsupportedHc; +#if !USB_RUNTIME_DRIVER_IN_SMM + UsbProtocol->UsbInvokeApi = UsbApiHandler; +#endif + + return Status; +} + +#if USB_RUNTIME_DRIVER_IN_SMM +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: InSmmFunction +// +// Description: SMM entry point of AMIUSB driver +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +InSmmFunction( + EFI_HANDLE ImageHandle, + EFI_SYSTEM_TABLE *SystemTable +) +{ + EFI_STATUS Status; + + EFI_SMM_SW_DISPATCH_CONTEXT SwSmiContext; + EFI_HANDLE SwSmiHandle = NULL; + EFI_SMM_SW_DISPATCH_PROTOCOL *SwSmiDispatch; + + UINT32 KbcEmulFeature = 0; + VOID *ProtocolNotifyRegistration; + EFI_EVENT Emul6064Event = NULL; + + //(EIP54018+)> +#if USB_S5_WAKEUP_SUPPORT + EFI_SMM_SX_DISPATCH_CONTEXT S5DispatchContext; + EFI_SMM_SX_DISPATCH_PROTOCOL *SxDispatchProtocol; + EFI_SMM_POWER_BUTTON_DISPATCH_CONTEXT PbDispatchContext; + EFI_SMM_POWER_BUTTON_DISPATCH_PROTOCOL *PbDispatchProtocol; + EFI_HANDLE S5DispatchHandle; + EFI_HANDLE PbDispatchHandle; +#endif + //<(EIP54018+) +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B) + EFI_HANDLE UsbSmmProtocolHandle = NULL; + + Status = InitAmiSmmLib(ImageHandle, SystemTable); + if (EFI_ERROR(Status)) return Status; +#endif + + InitAmiBufferValidationLib(ImageHandle, SystemTable); + + InstallUsbProtocols(); + InitializeUsbGlobalData(); + + + Status = pBS->LocateProtocol (&gEmul6064TrapProtocolGuid, NULL, &gEmulationTrap); + if (EFI_ERROR(Status)) { + Status = RegisterProtocolCallback(&gEmul6064TrapProtocolGuid, + Emul6064TrapCallback, + NULL, + &Emul6064Event, + &ProtocolNotifyRegistration); + } + + if(!gUsbData->kbc_support) { + Status = gBS->LocateProtocol (&gEmul6064MsInputProtocolGuid, NULL, &gMsInput); + pBS->LocateProtocol (&gEmul6064KbdInputProtocolGuid, NULL, &gKbdInput); + + if (Status == EFI_SUCCESS) { + gUsbData->dUSBStateFlag |= USB_FLAG_6064EMULATION_ON; + if(gEmulationTrap) + KbcEmulFeature = gEmulationTrap->FeatureSupported(gEmulationTrap); + if(KbcEmulFeature & IRQ_SUPPORTED) { + gUsbData->dUSBStateFlag |= USB_FLAG_6064EMULATION_IRQ_SUPPORT; + } + } else { + InitSysKbc( &gKbdInput, &gMsInput ); + } + } else { + // + //Init Fake Emulation interface + // + InitSysKbc( &gKbdInput, &gMsInput ); + } + + Status = USBSB_InstallSmiEventHandlers(); + + USB_DEBUG(DEBUG_LEVEL_3,"AMIUSB global data at 0x%x\n", gUsbData); + + // + // Register the USB SW SMI handler + // + Status = pBS->LocateProtocol (&gEfiSmmSwDispatchProtocolGuid, NULL, &SwSmiDispatch); + + if (EFI_ERROR (Status)) { + USB_DEBUG(DEBUG_LEVEL_0, "SmmSwDispatch protocol: %r\n", Status); + return Status; + } + + SwSmiContext.SwSmiInputValue = USB_SWSMI; + Status = SwSmiDispatch->Register (SwSmiDispatch, USBSWSMIHandler, &SwSmiContext, &SwSmiHandle); + + USB_DEBUG(DEBUG_LEVEL_3, "AMIUSB SW SMI registration:: %r\n", Status); + +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B) + gUsbSmmProtocol.UsbStopUnsupportedHc = USB_StopUnsupportedHc; + gUsbSmmProtocol.UsbApiTable = aUsbApiTable; + gUsbSmmProtocol.UsbMassApiTable = aUsbMassApiTable; + gUsbSmmProtocol.GlobalDataValidation.ConstantDataCrc32 = 0; + gUsbSmmProtocol.GlobalDataValidation.Crc32Hash = (UINT32)GetCpuTimer(); + + Status = pSmst->SmmInstallProtocolInterface( + &UsbSmmProtocolHandle, + &gAmiUsbSmmProtocolGuid, + EFI_NATIVE_INTERFACE, + &gUsbSmmProtocol + ); + + USB_DEBUG(DEBUG_LEVEL_3, "AMIUSB SMM protocol: %r\n", Status); +#endif + +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B) + InitAmiUsbSmmGlobalDataValidationLib(ImageHandle, SystemTable); + UpdateAmiUsbSmmGlobalDataCrc32(gUsbData); +#endif + + //(EIP54018+)> +#if USB_S5_WAKEUP_SUPPORT + Status = pBS->LocateProtocol( + &gEfiSmmSxDispatchProtocolGuid, + NULL, + &SxDispatchProtocol + ); + + if (EFI_ERROR(Status)) { + return Status; + } + + S5DispatchContext.Type = SxS5; + S5DispatchContext.Phase = SxEntry; + Status = SxDispatchProtocol->Register( + SxDispatchProtocol, + UsbS5SmiCallback, + &S5DispatchContext, + &S5DispatchHandle + ); + + if (EFI_ERROR(Status)) { + return Status; + } + + // Locate Power Button Dispatch Protocol + Status = pBS->LocateProtocol( + &gEfiSmmPowerButtonDispatchProtocolGuid, + NULL, + &PbDispatchProtocol + ); + + if (EFI_ERROR(Status)) { + return Status; + } + + // Register the handler for power button presses + PbDispatchContext.Phase = PowerButtonEntry; + Status = PbDispatchProtocol->Register( + PbDispatchProtocol, + UsbPowerButtonSmiCallback, + &PbDispatchContext, + &PbDispatchHandle + ); +#endif + //<(EIP54018+) + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBSWSMIHandler +// +// Description: Invoked on reads from SW SMI port with value USB_SWSMI. This +// function dispatches the USB Request Packets (URP) to the +// appropriate functions. +// +// Input: EBDA:USB_DATA_EBDA_OFFSET - Pointer to the URP (USB Request +// Packet structure) +// DispatchHandle - EFI Handle +// DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT +// +// Output: bRetValue Zero on successfull completion +// Non-zero on error +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBSWSMIHandler ( + EFI_HANDLE DispatchHandle, + EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext +) +{ + URP_STRUC *UsbUrp; + UINT16 EbdaSeg; + EFI_STATUS Status; + + if (gLockSmiHandler == TRUE) { + return; + } +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B) + Status = AmiUsbSmmGlobalDataValidation(gUsbData); + + ASSERT_EFI_ERROR(Status); + + if (EFI_ERROR(Status)) { + gLockHwSmiHandler = TRUE; + gLockSmiHandler = TRUE; + return; + } +#endif + + if (gUsbData->fpURP) { // Call from AMIUSB C area + Status = AmiValidateMemoryBuffer((VOID*)gUsbData->fpURP, sizeof(URP_STRUC)); + if (EFI_ERROR(Status)) { + USB_DEBUG(3, "UsbApiHandler Invalid Pointer, the address is in SMRAM.\n"); + return; + } + UsbUrp = gUsbData->fpURP; + gUsbData->fpURP = 0; // Clear the switch + } else { + if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_OS) { + return; + } + // + // Get the fpURP pointer from EBDA + // + EbdaSeg = *((UINT16*)0x40E); + UsbUrp = *(URP_STRUC**)(UINTN)(((UINT32)EbdaSeg << 4) + USB_DATA_EBDA_OFFSET); + UsbUrp = (URP_STRUC*)((UINTN)UsbUrp & 0xFFFFFFFF); + Status = AmiValidateMemoryBuffer((VOID*)UsbUrp, sizeof(URP_STRUC)); + if (EFI_ERROR(Status)) { + USB_DEBUG(3, "UsbApiHandler Invalid Pointer, the address is in SMRAM.\n"); + return; + } + } + + if (UsbUrp == NULL) { + return; + } + + gCheckUsbApiParameter = TRUE; + + UsbApiHandler(UsbUrp); + + gCheckUsbApiParameter = FALSE; + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: UsbHwSmiHandler +// +// Description: USB Hardware SMI handler. +// +// Input: Host controller type. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +UsbHwSmiHandler (UINT8 HcType) +{ + UINT8 Index; + HC_STRUC *HcStruc; + EFI_STATUS Status; + + if (gLockHwSmiHandler == TRUE) { + return; + } + +#if defined(PI_SPECIFICATION_VERSION)&&(PI_SPECIFICATION_VERSION>=0x0001000A)&&(CORE_COMBINED_VERSION >= 0x4028B) + Status = AmiUsbSmmGlobalDataValidation(gUsbData); + + ASSERT_EFI_ERROR(Status); + + if (EFI_ERROR(Status)) { + gLockHwSmiHandler = TRUE; + gLockSmiHandler = TRUE; + return; + } +#endif + + for (Index = 0; Index < gUsbData->HcTableCount; Index++) { + HcStruc = gUsbData->HcTable[Index]; + if (HcStruc == NULL) { + continue; + } + if (!(HcStruc->dHCFlag & HC_STATE_USED)) { + continue; + } + if (HcStruc->bHCType == HcType) { // Process appropriate interrupt + (*gUsbData->aHCDriverTable + [GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDProcessInterrupt)(HcStruc); + } + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: xhciHWSMIHandler +// +// Description: USB Hardware SMI handler. +// +// Input: DispatchHandle - EFI Handle +// DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT +// +// Output: Nothing +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +UhciHWSMIHandler ( + EFI_HANDLE DispatchHandle, + EFI_SMM_USB_DISPATCH_CONTEXT *DispatchContext + ) +{ + UsbHwSmiHandler(USB_HC_UHCI); +} +VOID +OhciHWSMIHandler ( + EFI_HANDLE DispatchHandle, + EFI_SMM_USB_DISPATCH_CONTEXT *DispatchContext + ) +{ + UsbHwSmiHandler(USB_HC_OHCI); +} +VOID +EhciHWSMIHandler ( + EFI_HANDLE DispatchHandle, + EFI_SMM_USB_DISPATCH_CONTEXT *DispatchContext + ) +{ + UsbHwSmiHandler(USB_HC_EHCI); +} + +VOID +XhciHwSmiHandler ( + EFI_HANDLE DispatchHandle, + VOID *DispatchContext + ) +{ + UsbHwSmiHandler(USB_HC_XHCI); +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: USBInstallHwSmiHandler +// +// Description: +// This function registers USB hardware SMI callback function. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +UsbInstallHwSmiHandler( + HC_STRUC *HcStruc +) +{ + EFI_STATUS Status; + EFI_SMM_USB_DISPATCH_CONTEXT UsbContext; + EFI_SMM_USB_DISPATCH_PROTOCOL *UsbDispatch; + EFI_SMM_USB_DISPATCH UsbCallback; + EFI_HANDLE Handle = NULL; + + if (HcStruc->HwSmiHandle != NULL) { + return EFI_SUCCESS; + } + + Status = gBS->LocateProtocol( + &gEfiSmmUsbDispatchProtocolGuid, + NULL, + &UsbDispatch); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR(Status)) { + return Status; + } + + switch (HcStruc->bHCType) { + case USB_HC_UHCI: + UsbCallback = UhciHWSMIHandler; + break; + + case USB_HC_OHCI: + UsbCallback = OhciHWSMIHandler; + break; + + case USB_HC_EHCI: + UsbCallback = EhciHWSMIHandler; + break; + + case USB_HC_XHCI: + UsbCallback = XhciHwSmiHandler; + break; + + default: + return EFI_UNSUPPORTED; + } + + UsbContext.Type = UsbLegacy; + UsbContext.Device = HcStruc->pHCdp; + + Status = UsbDispatch->Register( + UsbDispatch, + UsbCallback, + &UsbContext, + &Handle); + + USB_DEBUG(DEBUG_LEVEL_3, "AMIUSB HC type %x HW SMI registation status:: %r\n", HcStruc->bHCType, Status); + + if (!EFI_ERROR(Status)) { + HcStruc->HwSmiHandle = Handle; + } + + return Status; +} +#endif + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: Emul6064TrapCallback +// +// Description: +// Update the KbcEmul feature when the Emul6064Trap Protocol becomes available. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +Emul6064TrapCallback ( + EFI_EVENT Event, + VOID *Context +) +{ + EFI_STATUS Status; + UINT32 KbcEmulFeature = 0; + + Status = gBS->LocateProtocol( + &gEmul6064TrapProtocolGuid, + NULL, + &gEmulationTrap); + + if(!gUsbData->kbc_support) { + Status = gBS->LocateProtocol( + &gEmul6064MsInputProtocolGuid, + NULL, + &gMsInput); + + gBS->LocateProtocol( + &gEmul6064KbdInputProtocolGuid, + NULL, + &gKbdInput); + + if (Status == EFI_SUCCESS) { + gUsbData->dUSBStateFlag |= USB_FLAG_6064EMULATION_ON; + if(gEmulationTrap) + KbcEmulFeature = gEmulationTrap->FeatureSupported(gEmulationTrap); + if(KbcEmulFeature & IRQ_SUPPORTED) { + gUsbData->dUSBStateFlag |= USB_FLAG_6064EMULATION_IRQ_SUPPORT; + } + } else { + InitSysKbc( &gKbdInput, &gMsInput ); + } + } else { + // + //Init Fake Emulation interface + // + InitSysKbc( &gKbdInput, &gMsInput ); + } +} + +////////////////////////////////////////////////////////////////////////////// +// +// USB API Functions +// +////////////////////////////////////////////////////////////////////////////// + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBAPI_MassDeviceRequest +// +// Description: This routine services the USB API function number 27h. It +// handles all the mass storage related calls from the higher +// layer. Different sub-functions are invoked depending on +// the sub-function number +// +// Input: fpURPPointer Pointer to the URP structure +// fpURPPointer.bSubFunc Subfunction number +// 00 Get Device Information +// 01 Get Device Parameter +// 02 Reset Device +// 03 Read Device +// 04 Write Device +// 05 Verify Device +// 06 Format Device +// 07 Request Sense +// 08 Test Unit Ready +// 09 Start Stop Unit +// 0A Read Capacity +// 0B Mode Sense +// 0C Device Inquiry +// 0D Send Command +// 0E Assign drive number +// +// Output: URP structure is updated with the relevant information +// +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBAPI_MassDeviceRequest (URP_STRUC *fpURP) +{ + UINT8 bMassFuncIndex = fpURP->bSubFunc; + UINT8 bNumberOfMassFunctions = sizeof aUsbMassApiTable / sizeof (API_FUNC *); + + // + // Make sure function number is valid + // + if (bMassFuncIndex >= bNumberOfMassFunctions) { + //fpURP->bRetValue = USBAPI_INVALID_FUNCTION; + USB_DEBUG(3, "UsbApi MassDeviceRequet Invalid function#%x\n", bMassFuncIndex); + return; + } + gUsbData->bUSBKBC_MassStorage = 01; + // + // Function number is valid - call it + // + aUsbMassApiTable[bMassFuncIndex](fpURP); + gUsbData->bUSBKBC_MassStorage = 00; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBAPI_CheckPresence +// +// Description: This routine services the USB API function number 0. It +// reports the USB BIOS presence, its version number and +// its current status information +// +// Input: fpURPPointer - Pointer to the URP structure +// +// Output: URP structure is updated with the following information +// CkPresence.wBiosRev USB BIOS revision (0210h means r2.10) +// CkPresence.bBiosActive 0 - if USB BIOS is not running +// CkPresence.bNumBootDev Number of USB boot devices found +// CkPresence.bNumHC Number of host controller present +// CkPresence.bNumPorts Number of root hub ports +// CkPresence.dUsbDataArea Current USB data area +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBAPI_CheckPresence (URP_STRUC *fpURP) +{ + fpURP->bRetValue = USB_SUCCESS; + fpURP->ApiData.CkPresence.bBiosActive = 0; + + fpURP->ApiData.CkPresence.bNumBootDev = 0; // Number of USB boot devices found + fpURP->ApiData.CkPresence.bNumKeyboards = 0; // Number of USB keyboards present + fpURP->ApiData.CkPresence.bNumMice = 0; // Number of USB mice present + fpURP->ApiData.CkPresence.bNumPoint = 0; // Number of USB Point present //(EIP38434+) + fpURP->ApiData.CkPresence.bNumHubs = 0; // Number of USB hubs present + fpURP->ApiData.CkPresence.bNumStorage = 0; // Number of USB storage devices present + + fpURP->ApiData.CkPresence.wBiosRev = (USB_DRIVER_MAJOR_VER << 4) + USB_DRIVER_MINOR_VER; + fpURP->ApiData.CkPresence.bBiosActive = USB_ACTIVE; // Set USB BIOS as active + if (!(gUsbData->dUSBStateFlag & USB_FLAG_DISABLE_LEGACY_SUPPORT)) { + fpURP->ApiData.CkPresence.bBiosActive |= USB_LEGACY_ENABLE; + } + if (gUsbData->dUSBStateFlag & USB_FLAG_6064EMULATION_ON) { + fpURP->ApiData.CkPresence.bBiosActive |= USB_6064_ENABLE; + } + USBWrap_GetDeviceCount(fpURP); // Get active USB devices +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBAPI_Start +// +// Description: This API routine configures the USB host controllers and +// enumerate the devices +// +// Input: fpURPPointer URP structure with input parameters +// StartHc.wDataAreaFlag Indicates which data area to use +// +// Output: StartHc.wDataAreaFlag Returns current data area pointer +// bRetValue - USB_SUCCESS on success, USB_ERROR on error. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID USBAPI_Start (URP_STRUC *fpURP) +{ + USB_DEBUG(DEBUG_LEVEL_3, "USBSMI: Start\n"); + USB_DEBUG(DEBUG_LEVEL_3, "\tUSBAPI_HC_Proc:%x\n", &USBAPI_HC_Proc); + USB_DEBUG(DEBUG_LEVEL_3, "\tUSBAPI_Core_Proc:%x\n", &USBAPI_Core_Proc); + USB_DEBUG(DEBUG_LEVEL_3, "\tUSB_ReConfigDevice:%x\n", &USB_ReConfigDevice); + fpURP->bRetValue = USB_StartHostControllers (gUsbData); + USB_DEBUG(DEBUG_LEVEL_3, "USB_StartHostControllers returns %d\n", fpURP->bRetValue); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBAPI_Stop +// +// Description: This routine stops the USB host controllers +// +// Input: fpURPPointer Pointer to the URP structure +// +// Output: bRetValue USB_SUCCESS on success +// USB_ERROR on error +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID USBAPI_Stop (URP_STRUC *fpURP) +{ + gCheckUsbApiParameter = FALSE; + fpURP->bRetValue = USB_StopHostControllers (gUsbData); + USB_DEBUG(DEBUG_LEVEL_3, "USB_StopHostControllers returns %d\n", fpURP->bRetValue); + gUsbData->dUSBStateFlag &= ~(USB_FLAG_DRIVER_STARTED); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBAPI_PowerManageUSB +// +// Description: This routine suspends the USB host controllers +// +// Input: fpURPPointer Pointer to the URP structure +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID USBAPI_PowerManageUSB (URP_STRUC *fpURP) +{ + fpURP->bRetValue = USB_NOT_SUPPORTED; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBAPI_PrepareForOS +// +// Description: This routine updates data structures to reflect that +// POST is completed +// +// Input: fpURPPointer Pointer to the URP structure +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID USBAPI_PrepareForOS (URP_STRUC *fpURP) +{ + fpURP->bRetValue = USB_NOT_SUPPORTED; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBAPI_SecureInterface +// +// Description: This routine handles the calls related to security device +// +// Input: fpURPPointer Pointer to the URP structure +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID USBAPI_SecureInterface (URP_STRUC *fpURP) +{ + fpURP->bRetValue = USB_NOT_SUPPORTED; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBAPI_DisableInterrupts +// +// Description: This routine stops the USB host controllers interrupts +// +// Input: fpURPPointer Pointer to the URP structure +// +// Output: bRetValue USB_SUCCESS on success +// USB_ERROR on error (Like data area not found) +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID USBAPI_DisableInterrupts (URP_STRUC *fpURP) +{ + fpURP->bRetValue = USB_NOT_SUPPORTED; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBAPI_EnableInterrupts +// +// Description: This routine re-enable the USB host controller interrupts +// +// Input: fpURPPointer Pointer to the URP structure +// +// Output: bRetValue USB_SUCCESS on success +// USB_ERROR on error (Like data area not found) +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID USBAPI_EnableInterrupts (URP_STRUC *fpURP) +{ + fpURP->bRetValue = USB_NOT_SUPPORTED; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBAPI_MoveDataArea +// +// Description: This routine stops the USB host controllers and moves +// the data area used by host controllers to a new area. +// The host controller is started from the new place. +// +// Input: fpURPPointer URP structure with input parameters +// StartHc.wDataAreaFlag Indicates which data area to use +// +// Output: bRetValue USB_SUCCESS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID USBAPI_MoveDataArea(URP_STRUC *fpURP) +{ + fpURP->bRetValue = USB_NOT_SUPPORTED; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBAPI_GetDeviceInfo +// +// Description: This routine returns the information regarding +// a USB device like keyboard, mouse, floppy drive etc +// +// Input: fpURPPointer URP structure with input parameters +// GetDevInfo.bDevNumber Device number (1-based) whose +// information is requested +// +// Output: URP structure is updated with the following information +// GetDevInfo.bHCNumber - HC number in which the device is found +// GetDevInfo.bDevType - Type of the device +// bRetValue will be one of the following value +// USB_SUCCESS on successfull completion +// USB_PARAMETER_ERROR if bDevNumber is invalid +// USB_ERROR on error +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID USBAPI_GetDeviceInfo (URP_STRUC *fpURP) +{ + DEV_INFO* fpDevInfo; + + // + // Initialize the return values + // + fpURP->ApiData.GetDevInfo.bHCNumber = 0; + fpURP->ApiData.GetDevInfo.bDevType = 0; + fpURP->bRetValue = USB_ERROR; + + // + // Check for parameter validity + // + if ( !fpURP->ApiData.GetDevInfo.bDevNumber ) return; + + fpURP->bRetValue = USB_PARAMETER_ERROR; + + // + // Get the device information structure for the 'n'th device + // + fpDevInfo = USBWrap_GetnthDeviceInfoStructure(fpURP->ApiData.GetDevInfo.bDevNumber); +// if (!wRetCode) return; // USB_PARAMETER_ERROR + + // + // Return value + // + fpURP->ApiData.GetDevInfo.bDevType = fpDevInfo->bDeviceType; + fpURP->ApiData.GetDevInfo.bHCNumber = fpDevInfo->bHCNumber; + fpURP->bRetValue = USB_SUCCESS; + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBAPI_CheckDevicePresence +// +// Description: This routine checks whether a particular type of USB device +// is installed in the system or not. +// +// Input: fpURPPointer URP structure with input parameters +// ChkDevPrsnc.bDevType Device type to find +// ChkDevPrsnc.fpHCStruc Pointer to HC being checked for device +// connection; if NULL then the total number of devices +// connected to ANY controller is returned. +// ChkDevPrsnc.bNumber Number of devices connected +// +// Output: bRetValue will be one of the following value +// USB_SUCCESS if device type present, ChkDevPrsnc.bNumber <> 0 +// USB_ERROR if device type absent, ChkDevPrsnc.bNumber returns 0 +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBAPI_CheckDevicePresence (URP_STRUC *fpURP) +{ + UINT8 bSearchFlag; + UINTN dData; + + bSearchFlag = USB_SRCH_DEV_NUM; + if (fpURP->bSubFunc == 1) + { + bSearchFlag = USB_SRCH_DEVBASECLASS_NUM; + } + // + // The total number of devices connected to ANY controller has been requested + // + dData = (UINTN) USB_GetDeviceInfoStruc( bSearchFlag, + 0, fpURP->ApiData.ChkDevPrsnc.bDevType, fpURP->ApiData.ChkDevPrsnc.fpHCStruc); + + fpURP->ApiData.ChkDevPrsnc.bNumber = (UINT8)dData; + fpURP->bRetValue = (UINT8)((fpURP->ApiData.ChkDevPrsnc.bNumber)? + USB_SUCCESS : USB_ERROR); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBMassAPIGetDeviceInformation +// +// Description: This function is part of the USB BIOS MASS API. This function +// returns the device information of the mass storage device +// +// Input: fpURPPointer Pointer to the URP structure +// bDevAddr USB device address of the device +// +// Output: bRetValue Return value +// fpURPPointer Pointer to the URP structure +// dSenseData Sense data of the last command +// bDevType Device type byte (HDD, CD, Removable) +// bEmuType Emulation type used +// fpDevId Far pointer to the device ID +// dInt13Entry INT 13h entry point +// +// Notes: Initially the bDevAddr should be set to 0 as input. This +// function returns the information regarding the first mass +// storage device (if no device found it returns bDevAddr as +// 0FFh) and also updates bDevAddr to the device address of +// the current mass storage device. If no other mass storage +// device is found then the routine sets the bit7 to 1 +// indicating current information is valid but no more mass +// device found in the system. The caller can get the next +// device info if bDevAddr is not 0FFh and bit7 is not set +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBMassAPIGetDeviceInformation (URP_STRUC *fpURP) +{ + fpURP->bRetValue = USBMassGetDeviceInfo (&fpURP->ApiData.MassGetDevInfo); +} + +VOID +USBMassAPIGetDeviceParameters (URP_STRUC *fpURP) +{ + DEV_INFO *DevInfo; + EFI_STATUS Status; + + DevInfo = fpURP->ApiData.MassGetDevParms.fpDevInfo; + + Status = UsbDevInfoValidation(DevInfo); + + if (EFI_ERROR(Status)) { + return; + } + +#if USB_RUNTIME_DRIVER_IN_SMM + if (gCheckUsbApiParameter) { + Status = AmiValidateMemoryBuffer((VOID*)fpURP->ApiData.MassGetDevParms.fpInqData, sizeof(MASS_INQUIRY)); + if (EFI_ERROR(Status)) { + return; + } + gCheckUsbApiParameter = FALSE; + } +#endif + + fpURP->ApiData.MassGetDevParms.fpInqData = USBMassGetDeviceParameters(DevInfo); + fpURP->bRetValue = (fpURP->ApiData.MassGetDevParms.fpInqData == NULL)? USB_ERROR : USB_SUCCESS; +} + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Procedure: USBMassAPIGetDevStatus +// +// Description: This function returns the drive status and media presence +// status +// +// Input: fpURPPointer Pointer to the URP structure +// fpURP->ApiData.fpDevInfo - pointer to USB device that is +// requested to be checked +// +// Output: Return code USB_ERROR - Failure, USB_SUCCESS - Success +// +//------------------------------------------------------------------------------; +//<AMI_PHDR_END> + +VOID +USBMassAPIGetDevStatus(URP_STRUC *fpURP) +{ +#if USB_DEV_MASS + fpURP->bRetValue = USBMassGetDeviceStatus (&fpURP->ApiData.MassGetDevSts); +// USB_DEBUG(DEBUG_LEVEL_3, "USBMassAPIGetDevStatus ... check function call correct?\n"); +#endif +} + + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBMassAPIGetDeviceGeometry +// +// Description: This function is part of the USB BIOS MASS API. +// +// Input: fpURPPointer Pointer to the URP structure +// bDevAddr USB device address of the device +// +// Output: bRetValue Return value +// fpURPPointer Pointer to the URP structure +// dSenseData Sense data of the last command +// bNumHeads Number of heads +// wNumCylinders Number of cylinders +// bNumSectors Number of sectors +// wBytesPerSector Number of bytes per sector +// bMediaType Media type +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBMassAPIGetDeviceGeometry(URP_STRUC *fpURP) +{ + fpURP->bRetValue = USBMassGetDeviceGeometry (&fpURP->ApiData.MassGetDevGeo); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBMassAPIResetDevice +// +// Description: This function is part of the USB BIOS MASS API. +// +// Input: fpURPPointer Pointer to the URP structure +// +// Output: bRetValue Return value +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBMassAPIResetDevice (URP_STRUC *fpURP) +{ + UINT8 bDevAddr; + DEV_INFO *fpDevInfo; + UINT16 wResult; + + bDevAddr = fpURP->ApiData.MassReset.bDevAddr; + + // + // Get the device info structure for the matching device address + // + fpDevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, 0, bDevAddr, 0); + if((fpDevInfo == NULL)|| (!(fpDevInfo->Flag & DEV_INFO_DEV_PRESENT))) { + fpURP->bRetValue = USB_ATA_TIME_OUT_ERR; + return; + } + // + // Send Start/Stop Unit command to UFI class device only + // + fpURP->bRetValue = USB_SUCCESS; + if(fpDevInfo->bSubClass == SUB_CLASS_UFI) { + wResult = USBMassStartUnitCommand (fpDevInfo); + if (wResult) { + fpURP->bRetValue = USBWrapGetATAErrorCode(fpURP->ApiData.MassReset.dSenseData); + } + } +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBMassAPIReadDevice +// +// Description: This function is part of the USB BIOS MASS API. +// +// Input: fpURPPointer Pointer to the URP structure, it contains the following: +// bDevAddr USB device address of the device +// dStartLBA Starting LBA address +// wNumBlks Number of blocks to read +// wPreSkipSize Number of bytes to skip before +// wPostSkipSize Number of bytes to skip after +// fpBufferPtr Far buffer pointer +// +// Output: fpURPPointer Pointer to the URP structure +// bRetValue Return value +// dSenseData Sense data of the last command +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBMassAPIReadDevice ( + URP_STRUC *Urp +) +{ + DEV_INFO *DevInfo; + UINT8 DevAddr; + UINT16 Result; + UINT32 Data = 0; + UINT8 OpCode; + + DevAddr = Urp->ApiData.MassRead.DevAddr; + + if (((DevAddr == USB_HOTPLUG_FDD_ADDRESS) && + ((gUsbData->dUSBStateFlag & USB_HOTPLUG_FDD_ENABLED) == FALSE)) || + ((DevAddr == USB_HOTPLUG_HDD_ADDRESS) && + ((gUsbData->dUSBStateFlag & USB_HOTPLUG_HDD_ENABLED) == FALSE)) || + ((DevAddr == USB_HOTPLUG_CDROM_ADDRESS) && + ((gUsbData->dUSBStateFlag & USB_HOTPLUG_CDROM_ENABLED) == FALSE))) { + Urp->bRetValue = USB_ATA_DRIVE_NOT_READY_ERR; + return; + } + + // + // Get the device info structure for the matching device address + // + DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, 0, DevAddr, 0); + if ((DevInfo == NULL)|| (!(DevInfo->Flag & DEV_INFO_DEV_PRESENT))) { + Urp->bRetValue = USB_ATA_TIME_OUT_ERR; + return; + } + + //(EIP15037+)> +#if EXTRA_CHECK_DEVICE_READY + // + // Check device ready + // + Data = USBMassCheckDeviceReady(DevInfo); + if (Data) { + Urp->ApiData.MassRead.dSenseData = Data; + Urp->bRetValue = USBWrapGetATAErrorCode(Urp->ApiData.MassRead.dSenseData); //(EIP31535) + return; + } +#endif + //<(EIP15037+) + + // + // Issue read command + // + if (Shr64(DevInfo->MaxLba, 32)) { + OpCode = COMMON_READ_16_OPCODE; + } else { + OpCode = COMMON_READ_10_OPCODE; + } + Result = USBMassRWVCommand(DevInfo, OpCode, &Urp->ApiData.MassRead); + //USB_DEBUG(DEBUG_LEVEL_3, " wr(%x):%x %x", DevAddr, Result, Urp->ApiData.MassRead.dSenseData); + if (Result) { + Urp->bRetValue = USB_SUCCESS; + return; + } + Urp->bRetValue = USBWrapGetATAErrorCode(Urp->ApiData.MassRead.SenseData); + //USB_DEBUG(DEBUG_LEVEL_3, " er(%x):%x", DevAddr, Urp->bRetValue); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBMassAPIWriteDevice +// +// Description: This function is part of the USB BIOS MASS API. +// +// Input: fpURPPointer Pointer to the URP structure +// bDevAddr USB device address of the device +// dStartLBA Starting LBA address +// wNumBlks Number of blocks to write +// wPreSkipSize Number of bytes to skip before +// wPostSkipSize Number of bytes to skip after +// fpBufferPtr Far buffer pointer +// +// Output: fpURPPointer Pointer to the URP structure +// bRetValue Return value +// dSenseData Sense data of the last command +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBMassAPIWriteDevice( + URP_STRUC *Urp +) +{ + DEV_INFO *DevInfo; + UINT8 DevAddr; + UINT16 Result; + UINT32 Data = 0; + UINT8 OpCode; + + DevAddr = Urp->ApiData.MassWrite.DevAddr; + + if (((DevAddr == USB_HOTPLUG_FDD_ADDRESS) && + ((gUsbData->dUSBStateFlag & USB_HOTPLUG_FDD_ENABLED) == FALSE)) || + ((DevAddr == USB_HOTPLUG_HDD_ADDRESS) && + ((gUsbData->dUSBStateFlag & USB_HOTPLUG_HDD_ENABLED) == FALSE)) || + ((DevAddr == USB_HOTPLUG_CDROM_ADDRESS) && + ((gUsbData->dUSBStateFlag & USB_HOTPLUG_CDROM_ENABLED) == FALSE))) { + Urp->bRetValue = USB_ATA_DRIVE_NOT_READY_ERR; + return; + } + + // + // Get the device info structure for the matching device address + // + DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, 0, DevAddr, 0); + if((DevInfo == NULL)|| (!(DevInfo->Flag & DEV_INFO_DEV_PRESENT))) { + Urp->bRetValue = USB_ATA_TIME_OUT_ERR; + return; + } +/* + if (!(DevInfo->bLastStatus & USB_MASS_MEDIA_PRESENT)) { + Urp->bRetValue = USB_ATA_NO_MEDIA_ERR; + return; + } +*/ + //(EIP15037+)> +#if EXTRA_CHECK_DEVICE_READY + // + // Check device ready + // + Data = USBMassCheckDeviceReady(DevInfo); + if (Data) { + Urp->ApiData.MassRead.dSenseData = Data; + Urp->bRetValue = USBWrapGetATAErrorCode(Urp->ApiData.MassWrite.dSenseData); //(EIP31535) + return; + } +#endif + //<(EIP15037+) + + // + // Issue write command + // + if (Shr64(DevInfo->MaxLba, 32)) { + OpCode = COMMON_WRITE_16_OPCODE; + } else { + OpCode = COMMON_WRITE_10_OPCODE; + } + Result = USBMassRWVCommand(DevInfo, OpCode, &Urp->ApiData.MassWrite); + if (Result) { + Urp->bRetValue = USB_SUCCESS; + return; + } + + Urp->bRetValue = USBWrapGetATAErrorCode(Urp->ApiData.MassWrite.SenseData); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBMassAPIVerifyDevice +// +// Description: This function is part of the USB BIOS MASS API. +// +// Input: fpURPPointer Pointer to the URP structure +// bDevAddr USB device address of the device +// dStartLBA Starting LBA address +// wNumBlks Number of blocks to write +// wPreSkipSize Number of bytes to skip before +// wPostSkipSize Number of bytes to skip after +// fpBufferPtr Far buffer pointer +// +// Output: fpURPPointer Pointer to the URP structure +// bRetValue Return value +// dSenseData Sense data of the last command +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBMassAPIVerifyDevice( + URP_STRUC *Urp +) +{ + DEV_INFO *DevInfo; + UINT8 DevAddr; + UINT16 Result; + UINT32 Data = 0; + UINT8 OpCode; + + DevAddr = Urp->ApiData.MassVerify.DevAddr; + + if (((DevAddr == USB_HOTPLUG_FDD_ADDRESS) && + ((gUsbData->dUSBStateFlag & USB_HOTPLUG_FDD_ENABLED) == FALSE)) || + ((DevAddr == USB_HOTPLUG_HDD_ADDRESS) && + ((gUsbData->dUSBStateFlag & USB_HOTPLUG_HDD_ENABLED) == FALSE)) || + ((DevAddr == USB_HOTPLUG_CDROM_ADDRESS) && + ((gUsbData->dUSBStateFlag & USB_HOTPLUG_CDROM_ENABLED) == FALSE))) { + Urp->bRetValue = USB_ATA_DRIVE_NOT_READY_ERR; + return; + } + + // + // Get the device info structure for the matching device address + // + DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, 0, DevAddr, 0); + if ((DevInfo == NULL)|| (!(DevInfo->Flag & DEV_INFO_DEV_PRESENT))) { + Urp->bRetValue = USB_ATA_TIME_OUT_ERR; + return; + } + //(EIP15037+)> +#if EXTRA_CHECK_DEVICE_READY + // + // Check device ready + // + Data = USBMassCheckDeviceReady(DevInfo); + if (Data) { + Urp->ApiData.MassRead.dSenseData = Data; + Urp->bRetValue = USBWrapGetATAErrorCode(Urp->ApiData.MassVerify.dSenseData); //(EIP31535) + return; + } +#endif + //<(EIP15037+) + + // + // Issue write command + // + if (Shr64(DevInfo->MaxLba, 32)) { + OpCode = COMMON_VERIFY_16_OPCODE; + } else { + OpCode = COMMON_VERIFY_10_OPCODE; + } + Result = USBMassRWVCommand(DevInfo, OpCode, &Urp->ApiData.MassVerify); + if (Result) { + Urp->bRetValue = USB_SUCCESS; + return; + } + + Urp->bRetValue = USBWrapGetATAErrorCode(Urp->ApiData.MassVerify.SenseData); + +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBMassAPIFormatDevice +// +// Description: This function is part of the USB BIOS MASS API. +// +// Input: fpURPPointer Pointer to the URP structure +// +// Output: bRetValue Return value +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBMassAPIFormatDevice(URP_STRUC *fpURP) +{ + fpURP->bRetValue = USB_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBMassAPICommandPassThru +// +// Description: This function is part of the USB BIOS MASS API. This +// function can be used to pass raw command/data sequence to +// the USB mass storage device +// +// Input: fpURPPointer Pointer to the URP structure +// +// Output: bRetValue Return value +// +// Modified: Nothing +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBMassAPICommandPassThru (URP_STRUC *fpURP) +{ + UINT8 Result; + MASS_CMD_PASS_THRU *MassCmdPassThru; + EFI_STATUS Status = EFI_SUCCESS; + + MassCmdPassThru = &fpURP->ApiData.MassCmdPassThru; + +#if USB_RUNTIME_DRIVER_IN_SMM + if (gCheckUsbApiParameter) { + Status = AmiValidateMemoryBuffer((VOID*)MassCmdPassThru->fpCmdBuffer, MassCmdPassThru->wCmdLength); + if (EFI_ERROR(Status)) { + return; + } + Status = AmiValidateMemoryBuffer((VOID*)MassCmdPassThru->fpDataBuffer, MassCmdPassThru->wDataLength); + if (EFI_ERROR(Status)) { + return; + } + gCheckUsbApiParameter = FALSE; + } +#endif + + Result = USBMassCmdPassThru(MassCmdPassThru); + + fpURP->bRetValue = Result; +} + + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Procedure: USBMassAPIAssignDriveNumber +// +// Description: This function is part of the USB BIOS MASS API. This function +// assigns the logical drive device according to the information of the +// mass storage device +// +// Input: fpURPPointer Pointer to the URP structure +// bDevAddr USB device address of the device +// bLogDevNum Logical Drive Number to assign to the device +// +// Output: Return code USB_ERROR - Failure, USB_SUCCESS - Success +// +//------------------------------------------------------------------------------; +//<AMI_PHDR_END> + +VOID +USBMassAPIAssignDriveNumber (URP_STRUC *fpURP) +{ + fpURP->bRetValue = USB_SUCCESS; // No errors expected after this point +} + + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Procedure: USBMassAPICheckDevStatus +// +// Description: This function is part of the USB BIOS MASS API. This function +// invokes USB Mass Storage API handler to check whether device +// is ready. If called for the first time, this function retrieves +// the mass storage device geometry and fills the corresponding +// fpDevInfo fields. +// +// Input: fpURPPointer Pointer to the URP structure +// fpURP->ApiData.fpDevInfo - pointer to USB device that is +// requested to be checked +// +// Output: Return code USB_ERROR - Failure, USB_SUCCESS - Success +// +//------------------------------------------------------------------------------; +//<AMI_PHDR_END> + +VOID +USBMassAPICheckDevStatus(URP_STRUC *fpURP) +{ +#if USB_DEV_MASS + UINT32 Result; + DEV_INFO *DevInfo; + EFI_STATUS Status; + + DevInfo = fpURP->ApiData.MassChkDevReady.fpDevInfo; + + Status = UsbDevInfoValidation(DevInfo); + + if (EFI_ERROR(Status)) { + return; + } + + gCheckUsbApiParameter = FALSE; + + Result = USBMassCheckDeviceReady(fpURP->ApiData.MassChkDevReady.fpDevInfo); + fpURP->bRetValue = (UINT8)Result; +#endif +} + + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Procedure: USBAPI_LightenKeyboardLEDs +// +// Description: This function is part of the USB BIOS API. This function +// controls LED state on the connected USB keyboards +// +// Input: fpURP Pointer to the URP structure +// +// Output: Return code USB_ERROR - Failure, USB_SUCCESS - Success +// +//------------------------------------------------------------------------------; +//<AMI_PHDR_END> + +VOID +USBAPI_LightenKeyboardLEDs(URP_STRUC *fpURP) +{ +#if USB_DEV_KBD + + gCheckUsbApiParameter = FALSE; + + if(fpURP->ApiData.KbLedsData.fpLedMap) { + gUsbData->bUSBKBShiftKeyStatus = 0; + if(((LED_MAP*)fpURP->ApiData.KbLedsData.fpLedMap)->NumLock) { + gUsbData->bUSBKBShiftKeyStatus |= KB_NUM_LOCK_BIT_MASK; + } + if(((LED_MAP*)fpURP->ApiData.KbLedsData.fpLedMap)->CapsLock) { + gUsbData->bUSBKBShiftKeyStatus |= KB_CAPS_LOCK_BIT_MASK; + } + if(((LED_MAP*)fpURP->ApiData.KbLedsData.fpLedMap)->ScrLock) { + gUsbData->bUSBKBShiftKeyStatus |= KB_SCROLL_LOCK_BIT_MASK; + } + } + //USB_DEBUG(DEBUG_LEVEL_3," LEDs: %d\n", gUsbData->bUSBKBShiftKeyStatus); + USBKB_LEDOn(); + + fpURP->bRetValue = USB_SUCCESS; + return; +#else + fpURP->bRetValue = USB_NOT_SUPPORTED; +#endif + +} + +VOID +USBAPI_LightenKeyboardLEDs_Compatible(URP_STRUC *fpURP) +{ + USBAPI_LightenKeyboardLEDs(fpURP); +} + + //(EIP29733+)> +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Procedure: USBAPI_KbcAccessControl +// +// Description: This function is part of the USB BIOS API. This function +// is used to control whether KBC access in USB module +// should be blocked or not. +// +// Input: fpURP Pointer to the URP structure +// +// Output: Return code USB_ERROR - Failure, USB_SUCCESS - Success +// +// Notes: +// +//------------------------------------------------------------------------------; +//<AMI_PHDR_END> + + +VOID +UsbKbcAccessControl( + UINT8 ControlSwitch +) +{ + UINT8 Index; + HC_STRUC *HcStruc; +#if USB_RUNTIME_DRIVER_IN_SMM + EFI_STATUS Status = EFI_SUCCESS; + + Status = AmiUsbSmmGlobalDataValidation(gUsbData); + + ASSERT_EFI_ERROR(Status); + + if (EFI_ERROR(Status)) { + gLockHwSmiHandler = TRUE; + gLockSmiHandler = TRUE; + return; + } +#endif + + gCheckUsbApiParameter = FALSE; + + IsKbcAccessBlocked = (ControlSwitch != 0)? TRUE : FALSE; + + for (Index = 0; Index < gUsbData->HcTableCount; Index++) { + HcStruc = gUsbData->HcTable[Index]; + if (HcStruc == NULL) { + continue; + } + if (HcStruc->dHCFlag & HC_STATE_RUNNING) { + break; + } + } + + if (Index == gUsbData->HcTableCount) { + return; + } +/* + // + // Check if the USB access in Legacy mode. If it's legacy mode enable/disable + // the Kbcemulation based on the ControlSwitch + // + if(!(gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI)) { + + if(IsKbcAccessBlocked) { + if(gEmulationTrap) { + // + // Keyboard access blocked. Disable the Emulation + // + gEmulationTrap->TrapDisable(gEmulationTrap); + } + } else { + if(gEmulationTrap) { + // + // Keyboard access enabled. Enable the KbcEmulation + // + gEmulationTrap->TrapEnable(gEmulationTrap); + } + } + } +*/ + //(EIP48323+)> + //Reflush USB data buffer if intend to disable usb keyboard data throughput. + if (IsKbcAccessBlocked) { + USBKeyRepeat(NULL, 1); // Disable Key repeat + gUsbData->RepeatKey = 0; + + // Clear Legacy USB keyboard buffer + MemFill(gUsbData->aKBCCharacterBufferStart, sizeof(gUsbData->aKBCCharacterBufferStart), 0); + gUsbData->fpKBCCharacterBufferHead = gUsbData->aKBCCharacterBufferStart; + gUsbData->fpKBCCharacterBufferTail = gUsbData->aKBCCharacterBufferStart; + + MemFill(gUsbData->aKBCScanCodeBufferStart, sizeof(gUsbData->aKBCScanCodeBufferStart), 0); + gUsbData->fpKBCScanCodeBufferPtr = gUsbData->aKBCScanCodeBufferStart; + + MemFill(gUsbData->aKBCDeviceIDBufferStart, sizeof(gUsbData->aKBCDeviceIDBufferStart), 0); + MemFill(gUsbData->aKBCShiftKeyStatusBufferStart, sizeof(gUsbData->aKBCShiftKeyStatusBufferStart), 0); + + MemFill(gUsbData->aKBInputBuffer, sizeof(gUsbData->aKBInputBuffer), 0); + } + //<(EIP48323+) +} + + +VOID +USBAPI_KbcAccessControl(URP_STRUC *fpURP) +{ + UsbKbcAccessControl(fpURP->ApiData.KbcControlCode); +} + //<(EIP29733+) +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Procedure: USB_StopLegacy +// +// Description: This function is part of the USB BIOS API. This function init USB +// legacy support. +// +// Input: fpURP Pointer to the URP structure +// +// Output: None +// +// Notes: +// +//------------------------------------------------------------------------------; +//<AMI_PHDR_END> +VOID +USB_StopLegacy(URP_STRUC *fpURP) +{ + //shutdown device first + UINT8 bIndex; + DEV_INFO *fpDevInfo; + HC_STRUC *fpHCStruc; + + for (bIndex = 1; bIndex < MAX_DEVICES; bIndex ++){ + fpDevInfo = gUsbData->aDevInfoTable +bIndex; + if ((fpDevInfo->Flag & + (DEV_INFO_VALID_STRUC |DEV_INFO_DEV_PRESENT) ) == + (DEV_INFO_VALID_STRUC |DEV_INFO_DEV_PRESENT) ){ + // + fpHCStruc = gUsbData->HcTable[fpDevInfo->bHCNumber - 1]; + // + USB_StopDevice (fpHCStruc, fpDevInfo->bHubDeviceNumber, fpDevInfo->bHubPortNumber); + } + } + + StopControllerType(USB_HC_XHCI); //(EIP57521+) + StopControllerType(USB_HC_EHCI); + StopControllerType(USB_HC_UHCI); + StopControllerType(USB_HC_OHCI); + + //return as success + fpURP->bRetValue = USB_SUCCESS; + +} + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Procedure: USB_StartLegacy +// +// Description: This function is part of the USB BIOS API. This function init USB +// legacy support. +// +// Input: fpURP Pointer to the URP structure +// +// Output: None +// +// Notes: +// +//------------------------------------------------------------------------------; +//<AMI_PHDR_END> +VOID +USB_StartLegacy(URP_STRUC *fpURP) +{ + //(EIP57521)> + gUsbData->bHandOverInProgress = FALSE; + //Start XHCI + StartControllerType(USB_HC_XHCI); + USB_EnumerateRootHubPorts(USB_HC_XHCI); + //Start EHCI + StartControllerType(USB_HC_EHCI); + USB_EnumerateRootHubPorts(USB_HC_EHCI); + //Start UHCI + StartControllerType(USB_HC_UHCI); + USB_EnumerateRootHubPorts(USB_HC_UHCI); + //Start OHCI + StartControllerType(USB_HC_OHCI); + USB_EnumerateRootHubPorts(USB_HC_OHCI); + //<(EIP57521) + //return as success + fpURP->bRetValue = USB_SUCCESS; +} + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Procedure: USBAPI_LegacyControl +// +// Description: This function is part of the USB BIOS API. This function +// is used to shutdown/init USB legacy support. +// +// Input: fpURP Pointer to the URP structure +// +// Output: None +// +// Notes: +// +//------------------------------------------------------------------------------; +//<AMI_PHDR_END> +VOID USBAPI_LegacyControl (URP_STRUC *fpURP) +{ + UINT8 bSubLegacyFunc = fpURP->bSubFunc,i; //(EIP102150+) + UINT8 Count = (UINT8)(gUsbData->fpKBCScanCodeBufferPtr - + (UINT8*)gUsbData->aKBCScanCodeBufferStart); //(EIP102150+) + + gCheckUsbApiParameter = FALSE; + + USB_DEBUG(DEBUG_LEVEL_3, "USBAPI_LegacyControl %d\n", fpURP->bSubFunc); + if(bSubLegacyFunc==STOP_USB_CONTROLLER){ //(EIP43475+)> + USB_StopLegacy (fpURP); + //(EIP102150+)> + for(i = Count; i > 0; i--) + USBKB_DiscardCharacter(&gUsbData->aKBCShiftKeyStatusBufferStart[i-1]); + //<(EIP102150+) + if(gEmulationTrap) + gEmulationTrap->TrapDisable(gEmulationTrap); + } + + if(bSubLegacyFunc==START_USB_CONTROLLER){ + USB_StartLegacy (fpURP); + if(gEmulationTrap) + gEmulationTrap->TrapEnable(gEmulationTrap); + } //<(EIP43475+) + USB_DEBUG(DEBUG_LEVEL_3, "Result %d\n", fpURP->bRetValue); +} + //(EIP74876+)> +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Procedure: USBAPI_UsbStopController +// +// Description: This function is part of the USB BIOS API. This function stops +// the USB host controller. +// +// Input: fpURP Pointer to the URP structure +// +// Output: None +// +// Notes: +// +//------------------------------------------------------------------------------; +//<AMI_PHDR_END> +VOID USBAPI_UsbStopController (URP_STRUC *fpURP) +{ + gCheckUsbApiParameter = FALSE; + StopControllerBdf(fpURP->ApiData.HcBusDevFuncNum); +} + //<(EIP74876+) +//----------------------------------------------------- +// +//----------------------------------------------------- +EFI_STATUS USBRT_LegacyControl (VOID *fpURP) +{ +#if USB_RUNTIME_DRIVER_IN_SMM + EFI_STATUS Status = EFI_SUCCESS; + + Status = AmiUsbSmmGlobalDataValidation(gUsbData); + + ASSERT_EFI_ERROR(Status); + + if (EFI_ERROR(Status)) { + gLockHwSmiHandler = TRUE; + gLockSmiHandler = TRUE; + return EFI_SUCCESS; + } +#endif + // + USBAPI_LegacyControl ((URP_STRUC *)fpURP); + // + return((EFI_STATUS)(((URP_STRUC *)fpURP)->bRetValue)); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBAPI_GetDeviceAddress +// +// Description: +// +// Input: +// +// Output: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBAPI_GetDeviceAddress( + URP_STRUC *Urp +) +{ + UINT8 i; + DEV_INFO *DevInfo = NULL; + + for (i = 1; i < MAX_DEVICES; i++) { + if (!(gUsbData->aDevInfoTable[i].Flag & DEV_INFO_VALID_STRUC)) { + continue; + } + if ((gUsbData->aDevInfoTable[i].wVendorId == Urp->ApiData.GetDevAddr.Vid) && + (gUsbData->aDevInfoTable[i].wDeviceId == Urp->ApiData.GetDevAddr.Did)) { + DevInfo = &gUsbData->aDevInfoTable[i]; + } + } + if (DevInfo == NULL) { + Urp->bRetValue = USB_ERROR; + return; + } + + Urp->ApiData.GetDevAddr.DevAddr = DevInfo->bDeviceAddress; + Urp->bRetValue = USB_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBAPI_ExtDriverRequest +// +// Description: +// +// Input: +// +// Output: +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBAPI_ExtDriverRequest ( + URP_STRUC *Urp +) +{ + DEV_INFO *DevInfo = NULL; + DEV_DRIVER *DevDriver; + + DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_ADDR, 0, Urp->ApiData.DevAddr, 0); + if (DevInfo == NULL) { + Urp->bRetValue = USB_ERROR; + return; + } + + DevDriver = UsbFindDeviceDriverEntry(DevInfo->fpDeviceDriver); + + if (DevDriver != NULL) { + DevDriver->pfnDriverRequest(DevInfo, Urp); + } +} + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Procedure: USB_StopUnsupportedHc +// +// Description: This routine is called, from host controllers that supports +// OS handover functionality, when OS wants the BIOS to hand-over +// the host controllers to the OS. This routine will stop HC that +// does not support this functionality. +// +// Input: None +// +// Output: None +// +// Notes: +// +//------------------------------------------------------------------------------; +//<AMI_PHDR_END> + +VOID +USB_StopUnsupportedHc() +{ + +#if USB_RUNTIME_DRIVER_IN_SMM + UINT8 Index; + HC_STRUC* HcStruc; + EFI_STATUS Status; + + Status = AmiUsbSmmGlobalDataValidation(gUsbData); + + ASSERT_EFI_ERROR(Status); + + if (EFI_ERROR(Status)) { + gLockHwSmiHandler = TRUE; + gLockSmiHandler = TRUE; + return; + } + + USBSB_UninstallTimerHandlers(); + + USB_DEBUG(DEBUG_LEVEL_3, "Stopping all external HCs"); + for (Index = 0; Index < gUsbData->HcTableCount; Index++) { + HcStruc = gUsbData->HcTable[Index]; + if (HcStruc == NULL) { + continue; + } + if (HcStruc->HwSmiHandle != NULL) { + continue; + } + if (HcStruc->dHCFlag & HC_STATE_RUNNING) { + (*gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDStop)(HcStruc); + USB_DEBUG(DEBUG_LEVEL_3, "."); + } + } + + USB_DEBUG(DEBUG_LEVEL_3, "\n"); + +#endif + + if(gUsbData->UsbXhciHandoff) { + StopControllerType(USB_HC_XHCI); + } + if(gUsbData->UsbEhciHandoff) { + gUsbData->bHandOverInProgress = TRUE; + StopControllerType(USB_HC_EHCI); + } + if(gUsbData->UsbOhciHandoff) { + StopControllerType(USB_HC_OHCI); + } +} + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Procedure: USBAPI_ChangeOwner +// +// Description: This function is part of the USB BIOS API. This function +// updates the global variables according to the new owner +// +// Input: fpURP Pointer to the URP structure +// +// Output: Return code USB_ERROR - Failure, USB_SUCCESS - Success +// +// Notes: It is a caller responsibility to release the keyboard only if it +// was previously acquired. +// +//------------------------------------------------------------------------------; +//<AMI_PHDR_END> + +VOID +USBAPI_ChangeOwner(URP_STRUC *fpURP) +{ +//USB_DEBUG(DEBUG_LEVEL_3, "USBAPI_ChangeOwner.."); + + if(fpURP->ApiData.Owner) { // Changing to Efi driver +//USB_DEBUG(DEBUG_LEVEL_3, "fpURP->ApiData.Owner=%d\n", fpURP->ApiData.Owner); + if(gEmulationTrap) { + gEmulationTrap->TrapDisable(gEmulationTrap); + } + gUsbData->dUSBStateFlag |= USB_FLAG_RUNNING_UNDER_EFI; + } else { // Acquiring - check the current condition first +//USB_DEBUG(DEBUG_LEVEL_3, "fpURP->ApiData.Owner=%d...", fpURP->ApiData.Owner); + if(gEmulationTrap) { + gEmulationTrap->TrapEnable(gEmulationTrap); + } + + if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) { +//USB_DEBUG(DEBUG_LEVEL_3, "USB_FLAG_RUNNING_UNDER_EFI\n"); + gUsbData->dUSBStateFlag &= ~USB_FLAG_RUNNING_UNDER_EFI; + } else { +//USB_DEBUG(DEBUG_LEVEL_3, "not USB_FLAG_RUNNING_UNDER_EFI\n"); + } + } + fpURP->bRetValue = USB_SUCCESS; +} + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Procedure: USBAPI_HcStartStop +// +// Description: This function is part of the USB BIOS API. This function +// starts/stops the USB host controller. +// +// Input: fpURP Pointer to the URP structure +// +// Output: None +// +// Notes: +// +//------------------------------------------------------------------------------; +//<AMI_PHDR_END> + +VOID +USBAPI_HcStartStop(URP_STRUC *Urp) +{ + HC_STRUC* HcStruc; + EFI_STATUS Status; + + HcStruc = Urp->ApiData.HcStartStop.HcStruc; + + Status = UsbHcStrucValidation(HcStruc); + + if (EFI_ERROR(Status)) { + return; + } + + if ((HcStruc->bHCType != USB_HC_UHCI) && (HcStruc->bHCType != USB_HC_OHCI) && + (HcStruc->bHCType != USB_HC_EHCI) && (HcStruc->bHCType != USB_HC_XHCI)) { + return; + } + + gCheckUsbApiParameter = FALSE; + + if (Urp->ApiData.HcStartStop.Start) { + Urp->bRetValue = UsbHcStart(HcStruc); + } else { + Urp->bRetValue = UsbHcStop(HcStruc); + } +} + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Procedure: USBAPI_invoke_in_frame +// +// Description: Invokes procedure passing parameters supplied in the buffer +// It replicates the stack frame so that target procedure can +// see the parameters passed to the stub. +// +// Output: Returns result of invoked proc +// +//------------------------------------------------------------------------------ +//<AMI_PHDR_END> + +// +// The following typedef corresponds to the min width type that can be passed +// into function call as a parameter without padding +// +typedef UINTN STACKWORD; + +UINTN +USBAPI_invoke_in_frame( + VOID* pProc, + VOID* buffer, + UINT32 paramSize ) +{ + STACKWORD* params = (STACKWORD*)buffer; + + switch(paramSize/sizeof(STACKWORD)){ + case 0: return ((STACKWORD (*)())pProc)(); + case 1: return ((STACKWORD (*)(STACKWORD))pProc)(params[0]); + case 2: return ((STACKWORD (*)(STACKWORD,STACKWORD))pProc)(params[0], + params[1]); + case 3: return ((STACKWORD (*)(STACKWORD,STACKWORD,STACKWORD))pProc)( + params[0],params[1],params[2]); + case 4: return ((STACKWORD (*)(STACKWORD,STACKWORD,STACKWORD, + STACKWORD))pProc)( + params[0],params[1],params[2],params[3]); + case 5: return ((STACKWORD (*)(STACKWORD,STACKWORD,STACKWORD,STACKWORD, + STACKWORD))pProc)( + params[0],params[1],params[2],params[3],params[4]); + case 6: return ((STACKWORD (*)(STACKWORD,STACKWORD,STACKWORD,STACKWORD, + STACKWORD,STACKWORD))pProc)( + params[0],params[1],params[2],params[3],params[4],params[5]); + case 7: return ((STACKWORD (*)(STACKWORD,STACKWORD,STACKWORD,STACKWORD, + STACKWORD,STACKWORD,STACKWORD))pProc)( + params[0],params[1],params[2],params[3],params[4],params[5], + params[6]); + default: + ASSERT(paramSize/sizeof(STACKWORD) < 4); + return 0; + } +/* kept for reference + __asm { + push ecx + push esi + pushf + //Copy stak frame + std + mov esi, buffer + mov ecx, paramSize + add esi, ecx + sub esi, 4 + shr ecx, 2 +loop1: + lodsd //DWORD PTR ds:edi + push eax + loop loop1 + //Call proc + mov eax, pProc + cld + call eax + //Read return value + mov retVal, eax + + //Restore stack and registers + add esp, paramSize + popf + pop esi + pop ecx + } + return retVal;*/ +} + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Procedure: USBAPI_HC_Proc +// +// Description: Bridge to a number of procedures supplied by HC driver +// +// +// Input: fpURP Pointer to the URP structure +// +// Output: Return code USB_ERROR - Failure, USB_SUCCESS - Success) +// +// Notes: +// Assumes that buffer has a correct image of the stack that +// corresponding function reads argument from +// Size of the buffer can be biger than actually used. +// +// Following code copies the buffer (some stack frame) into new +// stack frame such that invoked dirver proc can read parametes +// supplied by buffer +//------------------------------------------------------------------------------; +//<AMI_PHDR_END> + +VOID USBAPI_HC_Proc(URP_STRUC *fpURP) +{ + VOID* buffer = fpURP->ApiData.HcProc.paramBuffer; + UINT32 paramSize = // align size on DWORD + (fpURP->ApiData.HcProc.paramSize + 3) & ~0x3; + UN_HCD_HEADER* pHdr; + + ASSERT( GET_HCD_INDEX(fpURP->ApiData.HcProc.bHCType) < + sizeof(gUsbData->aHCDriverTable)/sizeof(HCD_HEADER)); + ASSERT( fpURP->bSubFunc < sizeof(pHdr->asArray.proc)/sizeof(VOID*)); + + pHdr = (UN_HCD_HEADER*)(gUsbData->aHCDriverTable + + GET_HCD_INDEX(fpURP->ApiData.HcProc.bHCType)); + fpURP->ApiData.HcProc.retVal = USBAPI_invoke_in_frame( + pHdr->asArray.proc[fpURP->bSubFunc],buffer,paramSize); + fpURP->bRetValue = USB_SUCCESS; +} + + +//<AMI_PHDR_START> +//----------------------------------------------------------------------------- +// Procedure: USBAPI_Core_Proc +// +// Description: Bridge to a number of procedures supplied by Core proc table +// +// Input: fpURP Pointer to the URP structure +// +// Output: Return code USB_ERROR - Failure, USB_SUCCESS - Success +// +// Notes: +// Assumes that buffer has a correct image of the stack that +// corresponding function reads argument from +// Size of the buffer can be biger than actually used. +// +// Following code copies the buffer (some stack frame) into new +// stack frame such that invoked proc can read parametes +// supplied by buffer +//------------------------------------------------------------------------------; +//<AMI_PHDR_END> + + +VOID* core_proc_table[] = { + USB_GetDescriptor, + USB_ReConfigDevice, + USB_ReConfigDevice2, + UsbAllocDevInfo, + prepareForLegacyOS, + USB_ResetAndReconfigDev, + USB_DevDriverDisconnect, +// USB_GetDataPtr, +// MemCopy, + }; + +VOID USBAPI_Core_Proc(URP_STRUC *fpURP) +{ + VOID* buffer = fpURP->ApiData.CoreProc.paramBuffer; + UINT32 paramSize = // align size on DWORD + (fpURP->ApiData.CoreProc.paramSize + 3) & ~0x3; + + ASSERT( fpURP->bSubFunc < COUNTOF(core_proc_table)); + + fpURP->ApiData.CoreProc.retVal = USBAPI_invoke_in_frame( + core_proc_table[fpURP->bSubFunc],buffer,paramSize); + + fpURP->bRetValue = USB_SUCCESS; +} + + +//---------------------------------------------------------------------------- +// USB API Procedures Ends +//---------------------------------------------------------------------------- + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBWrapGetATAError +// +// Description: This routine converts the sense data information into +// ATAPI error code +// +// Input: dSenseData Sense data obtained from the device +// +// Output: BYTE - ATAPI error code +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 USBWrapGetATAErrorCode (UINT32 dSenseData) +{ + UINT8 sc = (UINT8)dSenseData; // Sense code + UINT8 asc = (UINT8)(dSenseData >> 16); // Additional Sense Code (ASC) + UINT8 ascq = (UINT8)(dSenseData >> 8); // Additional Sense Code Qualifier (ASCQ) + + if (ascq == 0x28) return USB_ATA_DRIVE_NOT_READY_ERR; + if (sc == 7) return USB_ATA_WRITE_PROTECT_ERR; + if ((asc == 0x80) && (ascq == 0x80)) return USB_ATA_TIME_OUT_ERR; + if (ascq == 0x18) return USB_ATA_DATA_CORRECTED_ERR; + if ((ascq==6) && (asc == 0)) return USB_ATA_MARK_NOT_FOUND_ERR; + if ((ascq==0x3a) && (asc == 0)) return USB_ATA_NO_MEDIA_ERR; + if ((ascq==0x11) && (asc == 0)) return USB_ATA_READ_ERR; + if ((ascq==0x11) && (asc == 6)) return USB_ATA_UNCORRECTABLE_ERR; + if (ascq==0x30) return USB_ATA_BAD_SECTOR_ERR; + if ((ascq<0x20) || (ascq>0x26)) return USB_ATA_GENERAL_FAILURE; + + return USB_ATA_PARAMETER_FAILED; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBWrap_GetnthDeviceInfoStructure +// +// Description: This routine finds the 'n'th device's DeviceInfo entry. +// +// Input: bDevNumber Device number (1-based) +// +// Output: DeviceInfo structure +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +DEV_INFO* +USBWrap_GetnthDeviceInfoStructure(UINT8 bDevNumber) +{ + return &gUsbData->aDevInfoTable[bDevNumber]; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: USBWrap_GetDeviceCount +// +// Description: This routine searches through the device entry table +// and returns number of active USB devices configured +// by the BIOS. +// +// Input: fpURPPointer Pointer to the URP +// +// Output: Following fields in the URP are modified +// CkPresence.bNumBootDev Number of USB boot devices found +// CkPresence.bNumKeyboards Number of USB keyboards present +// CkPresence.bNumMice Number of USB mice present +// CkPresence.bNumHubs Number of USB hubs present +// CkPresence.bNumStorage Number of USB storage devices present +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +USBWrap_GetDeviceCount(URP_STRUC *fpURP) +{ + DEV_INFO *fpDevInfo; + UINT8 i; + + for (i=1; i<MAX_DEVICES; i++) { + fpDevInfo = &gUsbData->aDevInfoTable[i]; + + if ( (fpDevInfo->Flag & DEV_INFO_VALID_STRUC) && + (fpDevInfo->Flag & DEV_INFO_DEV_PRESENT)) { + fpURP->ApiData.CkPresence.bNumBootDev++; + + switch (fpDevInfo->bDeviceType) { + case BIOS_DEV_TYPE_HID: + if (fpDevInfo->HidDevType & HID_DEV_TYPE_KEYBOARD) { + fpURP->ApiData.CkPresence.bNumKeyboards++; + } + if (fpDevInfo->HidDevType & HID_DEV_TYPE_MOUSE) { + fpURP->ApiData.CkPresence.bNumMice++; + } + if (fpDevInfo->HidDevType & HID_DEV_TYPE_POINT) { + fpURP->ApiData.CkPresence.bNumPoint++; + } + break; + //<(EIP84455+) + case BIOS_DEV_TYPE_HUB: + fpURP->ApiData.CkPresence.bNumHubs++; + break; + case BIOS_DEV_TYPE_STORAGE: + fpURP->ApiData.CkPresence.bNumStorage++; + break; + case BIOS_DEV_TYPE_SECURITY: + break; + } + } + } +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MemFill +// +// Description: This routine fills the given memory range with the given value. +// +// Input: +// fpPtr - Pointer to the memory region to fill. +// wSize - Size in bytes of the area to be filled. +// Value - Byte value to fill the given range with. +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +MemFill ( + UINT8* fpPtr, + UINT32 dSize, + UINT8 Value) +{ + UINT32 dCount; + + if (fpPtr) { // Check for pointer validity + for(dCount = 0; dCount < dSize; dCount++) { + fpPtr[dCount] = Value; + } + } +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MemCopy +// +// Description: This routine copies data from source to destination. +// +// Input: +// fpSrc - Pointer to the source. +// fpDest - Pointer to the destination. +// wSize - Number of bytes to copy. +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +MemCopy ( + UINT8* fpSrc, + UINT8* fpDest, + UINT32 dSize) +{ + UINT32 dCount; + + // + // Check for pointer validity + // + if ((fpSrc) && (fpDest)) { + for(dCount = 0; dCount < dSize; dCount++) { + fpDest[dCount] = fpSrc[dCount]; + } + } +} + + +UINTN DevicePathSize ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Start; + + if (DevicePath == NULL) { + return 0; + } + + // + // Search for the end of the device path structure + // + Start = DevicePath; + while (!EfiIsDevicePathEnd (DevicePath)) { + DevicePath = EfiNextDevicePathNode (DevicePath); + } + + // + // Compute the size and add back in the size of the end device path structure + // + return ((UINTN)DevicePath - (UINTN)Start) + sizeof(EFI_DEVICE_PATH_PROTOCOL); +} + + +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *Src1, + IN EFI_DEVICE_PATH_PROTOCOL *Src2 + ) +{ + EFI_STATUS Status; + UINTN Size; + UINTN Size1; + UINTN Size2; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath; + + // + // Allocate space for the combined device path. It only has one end node of + // length EFI_DEVICE_PATH_PROTOCOL + // + Size1 = DevicePathSize (Src1); + Size2 = DevicePathSize (Src2); + Size = Size1 + Size2; + + if (Size1 != 0 && Size2 != 0) { + Size -= sizeof(EFI_DEVICE_PATH_PROTOCOL); + } + + Status = gBS->AllocatePool (EfiBootServicesData, Size, (VOID **)&NewDevicePath); + + if (EFI_ERROR(Status)) { + return NULL; + } + + gBS->CopyMem (NewDevicePath, Src1, Size1); + + // + // Over write Src1 EndNode and do the copy + // + if (Size1 != 0) { + SecondDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)((CHAR8 *)NewDevicePath + (Size1 - sizeof(EFI_DEVICE_PATH_PROTOCOL))); + } + else { + SecondDevicePath = NewDevicePath; + } + gBS->CopyMem (SecondDevicePath, Src2, Size2); + return NewDevicePath; +} + +//**************************************************************************** +//**************************************************************************** +//** ** +//** (C)Copyright 1985-2016, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** +//** ** +//** Phone (770)-246-8600 ** +//** ** +//**************************************************************************** +//**************************************************************************** |